CS 3358 (Data Structures and Algorithms) by Lee S. Koh

Advice on Programming Assignments
Programming assignments are an integral part of the course. Some students in the past commented that programming assignments should carry a much heavier weight because they devoted a lot of time to them, and I tend to agree with them. The main reason why programming assignments don't weigh as much as they should is that there is no sure way to ensure that students truly and wholly do the programming assignments themselves. Nevertheless, programming assignments still carry a significant weight. Perhaps more importantly, and many past students would attest to this, if you don't do the programming assignments or don't do them yourself, you will most likely not able to do well in the tests. Having said that, following are some advice to help you do well in the programming assignments and learn well by doing them - click here to first read a quotable quote about some psychological aspects of working in computer science.
Start early

Don't make the common mistake that many students tend to make, which is to underestimate the complexity of the programming assignments and the time required to complete them.

Allow yourself plenty of time and opportunity to seek clarification and/or help.

Don't be one of those who have to wait in long lines that tend to form near the due dates.

Don't be one of those who have to say, "I have finished everything but I cannot turn in my work on time because the print queue is four hours long."

Take the following line to heart: "Cramming simply will not work or will at best not work well."

Quotable quote:



Programming is not an activity that can be reliably scheduled to take a predetermined amount of time. Even programs that look like they should be doable in 2 hours will often take 4 or 5 hours to complete. The best thing you can do for yourself is to say, "I have no idea how long this will take; I'd better get started right away."
Don't skip class to gain some extra time for doing assignment

Trust me, "skipping class to gain some extra time for doing assignment" will never be a good idea in my class.


Remember that lecture notes can only assist you in following lectures, not replacing them.


Remember that not all things covered in class are in lecture notes.


Remember that lecture notes may be corrected, updated, expanded, etc. during lectures.


Remember that, where appropriate, assignment due dates may be extended or relaxed.

The best way to not have to deal with the "skipping class to gain some extra time for doing assignment" temptation is to start work early and finish it on time.
Do according to specifications

Most programming assignments require you to do them in some specific ways because they are meant to be exercises on certain concepts covered in class. Many times they are not the best ways to solve the associated problems. If you don't do them in the specified ways, however, you will defeat the intended purpose in part or in whole and will receive partial or no credits.

Be sure to first carefully and fully read the descriptions and thoroughly understand them.

Be sure to ask me if you are in doubt about a description or requirement; you risk losing points if you resolve it by simply assuming or guessing, by taking a vote with some fellow classmates, by believing in what someone else (besides me) interprets it, etc. (Recall what I said about starting early and allowing plenty of time and opportunity to seek clarification.)

NOTE: You will not be penalized for doing more than what is required (but you will be penalized if you don't do what is required).
Use systematic (scientific) approach

Do conceptual problem solving (analyzing problem and designing solution) before programming (implementing and testing solution design)


Use the top-down stepwise refinement technique to help design the solution.


The "problem of problem solving": Attempting to code the program right away (with little or no prior analysis of the problem and planning for the solution) and hoping that the program that is haphazardly put together will somehow work (perhaps after some trial and error)!

Quotable quote:



Learning to program the computer to solve problems requires two skills:



You need to know how to develop a plan for solving a particular problem - this plan, or algorithm, is a sequence of steps that, when followed, will lead to a solution of the problem;



You need to know how to use a programming language to implement your algorithm (translate the algorithmic steps into specific instructions that the machine can understand and execute).



Initially, you may think that learning a programming language is the more difficult task because the problems that you will be solving will have rather easy solutions. Nothing could be further from the truth! The single most important thing you can do as a student of computer science is to develop the skill to formulate algorithms to solve problems. Once you have this skill, you can learn to write programs in several different languages.
Develop programs progressively (incrementally)

Don't attempt to implement and test an entire program all at once.

Rather implement and test the program in small pieces.

Start by implementing only the simplest components of the program and using "stubs" for the harder components.



NOTE: A "stub" is a "placeholder" for something that is yet to be implemented or fully implemented. For example, a function "stub" is the implementation of a function with the function body omitted - the function body is empty if the function is a void function and the function body contains only a single return statement that returns a "phony" value if the function is a value returning function. As another example, a "stub" for a complicated segment of code to be filled in later may simply be a comment.)


This mostly skeletal version of the program should successfully compile and run, although it will not give the full and/or correct results. Test and debug the components that are already fully implemented. Once you have done that, add the implementation of one of the "stub" components and test and debug the augmented version of the program - any errors arising should now be localized to the component you just implemented because you have already tested and debugged the other components that were implemented earlier. Continue this process until the entire program is fully implemented.

Don't take this advice lightly: Experience tells me that many students like to try to write their programs all at once. You can get away with it on small programs, but as the amount of code increases, you're asking for headaches if you don't write a little at a time, and test each section as you write it.


CAUTION: If you seek my help in debugging your code and I see that you are not following this advice, I will send you away to start over and follow the advice.
Follow good programming style and practice

You won't go wrong if you follow my style guide.

Take heed of additional good and bad programming practices mentioned in the lecture notes and during lectures.

Don't attempt to first write a "sloppy" version during implementation and testing and later re-write a "pretty" version for submission; rather, write only the "pretty" version and take advantage of the "pretty" quality to help you avoid and discover errors.


CAUTION: If you seek my help in debugging your code and I see that your code lacks readability, I will send you away to "pretty" it up first.
Adequately test your programs and demonstrate that you have done so

One method for finding good test cases: boundary value testing.


Identify and test input values that are boundary values.


A boundary value of a problem is an input that is one step away from a different kind of behavior.


For example, consider a problem that involves using a variable called hour, where the valid range for hour is given by 0 <= hour <= 23. Two boundary values for the problem are 0 (since one step below 0 will make hour invalid) and 23 (since one step above 23 will make hour invalid). If the nature of the problem differs between morning hours (0 <= hour <= 11) and afternoon hours (12 <= hour <= 23), then 11 and 12 are also boundary values. If hour == 0 is dealt with in some special way in the problem, then 1 is also a boundary value.

Another method for finding good test cases: fully exercising code.


One aspect of the idea is to have each line of code executed at least once by some test cases. For example, there might be a portion of the code that is only handling a rare situation; this rare situation should be covered by the test cases.


Another aspect of the idea is that, if there is some part of the code that is sometimes skipped altogether, then there should be at least one test case that actually does skip that part of the code. For example, there might be a loop where the body is sometimes never execuated; there should at least be a test case for which the loop body is not executed.

In submitting your work, be sure to include all your test data (required for both printed version and e-mail version) and all associated test run results (required for printed version, optional for e-mail version).
Minimize your chances of losing points

In general, make it as easy as possible for me (or grader) to grade your work.


Nicely organize and present your work.


Maximize the readability and understandability of your work.


Highest grade for a program that doesn't compile/run is typically 30%.


Highest grade for a program that compiles/runs but contains major "runtime error" (segmentation fault, aborted execution, ...) is typically 60%.


You may lose up to 30% for not following good programming style and practices.


You risk losing up to 100% under one or more of the following circumstances:



If your work does not fulfill the requirements (meet the specifications);



If you turn in your work late;



If you include fake test data/results;



If you copy somebody else's work, or let somebody else copy your work.