GUIDELINES TO ACHIEVE GOOD PROGRAMMING

This document is intended to help you in writing well-developed and neat programs. If you follow the guidelines below, it will be very useful both for you (as the program coders and developers) and for us (to grade your programs at best).

First of all, you should not forget that writing a program is a self-discipline. You should bear in your minds that you are not the only person who will deal with your programs. Moreover, properly written programs would be very helpful to you, as well, in debugging, and also in checking for the control flow.

Steps in a Programming Project

In CMPE150, the importance of a clear, structured programming style has been emphasized. Because of the importance of these principles, it is worth reviewing them here before we start the main part of CMPE160.

Any programming project, no matter how simple, should be divided into several main sections:

  1. Make sure you understand the problem you are trying to solve. This may seem obvious, but many later problems in coding can be traced back to your lack of a complete understanding of just what it is the program is supposed to do. In particular, when you are doing CMPE160 lab questions, make sure you understand what the question is asking. If you are at all unsure, ask someone, or mail the instructor (akin@boun.edu.tr) or TA.
  2. Once you have a clear picture in your mind of the problem, you should write out the specifications that the program is to satisfy. As a simple example, suppose you wish to write a program that sorts a list of numbers into ascending order. Even for such a simple program, you need to consider the specifications before you put finger to keyboard. For example, how are the numbers to be input into the program? Will they be typed in from the keyboard or read from a file? Will the quantity of numbers be known in advance, or should this quantity be requested from the user before the numbers are read, or should the program count the numbers as they are read in? Where is the sorted list to be output (on screen or in a file)? If files are used for input and/or output, are the filenames to be constant, or should the program request the filenames from the user? Should the program be able to sort integers or real numbers as well? You should have made up your mind on all these points before you even sit down in front of the computer. Failing to think things through at this stage can mean a lot of chopping and changing in the program later, which leads to jumbled code that is full of errors, and difficult to debug, as well as a lot of wasted time.
  3. Having decided exactly what the specifications of the program are, you must now consider the coding of it. There are two aspects to be solved here. First, you must decide what data structures are to be used to represent the entities in the program. Second, you must decide what algorithm you are going to use to do the calculations.
Example: In coding a sorting program, for example, you must decide how you are going to store the numbers to be sorted. If the maximum quantity of numbers is known in advance, an array may be the best way. If the quantity varies a lot from one run to the next, a linked list (a data structure in which space is allocated for data as it is needed, not reserved in advance as in an array) may be more appropriate. If the numbers are associated with other data, it might be better to use an array or linked list of records, in which one field represents the number which is used as the sorting key. If you have considered the specifications properly, the choice of data structure is usually a lot easier. The choice of which algorithm to use is often closely linked with the specifications and the choice of data structures. There are a great many sorting algorithms around (insertion sort, bubble sort, quicksort, mergesort, etc. etc.). Different algorithms work best in different situations-some sorting algorithms are more efficient when the list to sort is short, others are better when the list is long. Some algorithms move the data around less than others, so if each chunk of data is fairly large, meaning that moving it is expensive in computer time, it would be better to use one of the former algorithms. If each datum is only a single integer, so that moving it is fairly cheap, one of the other algorithms may be better. If the program will be handling lists of different sizes, it may even be worthwhile to include more than one sorting algorithm, and choose the right one for the length of list currently being sorted.
  1. The steps up to now could all be done away from the computer, but you must now write the actual code. There are many guidelines which are appropriate here, but we will consider these in a moment. Overall, the goal is to write clear, well documented, easy to read code that will be easy for both you and someone else to understand and update at some time in the future.
  2. Once the program is written, it must be tested against its specifications. Actually, it is a good idea to make testing an integral part of the code writing process. Since properly written code uses the top-down (stepwise refinement) process, you will be writing individual functions and procedures to do separate tasks. You should test each of these modules as you write it. If a module calls other modules which you haven't written yet, create a dummy or stub module with a simple writeln statement in it so that your module has something to call. If you make sure that each module works as you write it, you ease the task of debugging things later on. Once the entire program is complete, though, you must perform a set of comprehensive tests on it to make sure it lives up to its specifications. Try it first with all forms of acceptable input for which it was designed and make sure it behaves correctly. However, one aspect (the most difficult one) of testing is to try to anticipate all the forms of incorrect input that users will feed your program. For example, suppose your array sorting program is only designed to handle lists of up to 100 numbers. What will it do if someone feeds in 200? Or, if the program is designed to read a fixed quantity of numbers from a file with a fixed name, what will the program do if the file contains too few numbers, or if the file doesn't exist at all? In most cases like this, the program will just crash with an obscure error message, like 'Segmentation fault' or 'Trace-trap error', which will mean nothing to a naive user. You should try to anticipate as many of these problems as you can, and write your program to catch these errors and print out friendly error messages that let the user know exactly what is wrong. One of the best ways of doing this is have a friend (preferably a sadistic one) consciously try to break your program by feeding it all sorts of garbage input. You will find that there are quite a few input errors that you haven't thought of. Although this sort of testing is very important when you write programs in a commercial or industrial environment, you won't have enough expertise at present to be able to correct all the possible incorrect input situations. (For example, how do you guard against someone entering text characters when your program expects numbers?) To trap all these cases requires some fairly sophisticated techniques which you aren't expected to know at this stage. However, you should be thinking about making your program as user-friendly as possible by allowing for simple errors that you do know how to fix. Unfortunately, putting in all these error traps can considerably lengthen the code for an otherwise simple program. Most of the programming examples we will consider in CMPE160 are designed to illustrate the implementation of certain data structures in Pascal, so we don't want them to get too complicated. In order to emphasize the data structures, we will often not bother putting in all the error checks that a fully developed program should have. Although, the programs in these notes may not be of a standard where they could be released into the world, they do provide some good practice for you in attempting to find input that can cause them to crash. When you read through the programming examples, you should be on the lookout for things that could be done to improve them. A check list that can be used for testing:
Programming Style

The actual style used in writing programs is often a matter of personal taste, but there are certain guidelines that should be followed within your own style in order to make programs easy to maintain and understand by both yourself and others.

while i < 1000 {
  while j < 1000 {
    while k < 1000 {
      various statements;
      if (disaster occurs) goto (escape);
      various statements;
    }
  }
}
c = 6.283185 * r;
const double PI = 3.141592;
 
circum = 2*pi*radius;
        i = i+1;  //increment i by 1
        //Horse string length into correctitude
do
  cout<<"Enter n (0 <= n <= 100): ";
  cin>>n;
  if ((n < 0) ||(n  100))
    cout<<"Number outside acceptable range. Please try again."<<endl;
while (n > 100) || (n < 0);
Keep in mind that the programs you hand in during CMPE160 will be marked partially on how well you have observed these criteria.

SUMMARY