Writing A Good Program

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 10

Writing a GOOD Program

[The following guidelines use the word program but hold true just as well for code pieces, i.e.,
functions, classes, etc.]

Programs should, optimally, be functional, elegant, efficient, user-friendly, and self-documenting.

Why bother with programming style? Lots of reasons.


 ease in debugging
 to enable other programmers to follow your logic and the way it was carried through in the
program. A program is usually used many times, by many different people.
 You may want to use your program again yourself in the future. A poorly written /
documented program is hard to understand and does not lend itself to reuse.
 A well-written program is often more efficient and economical than a poorly written one.
 Modifications may be called for in the future. An unintelligible program is a monster to
modify and debug.

A. Functional - The program should do what it is called upon to do. It should be error-free and
produce output that is correct.

B. Elegant - The program should do it in the best possible way. Avoid convoluted logic and
awkward control mechanisms. break, continue, and goto statements are occasionally
useful - employ them only when absolutely necessary.

C. Efficient - The program should not be unnecessarily wasteful of computer resources, namely,
time and space (memory). Avoid the use of extra variables and/or operations that are not
needed for the functionality or readability of the program.

D. User-friendly - The program should make as few assumptions as possible about the
capabilities of the user.
This means giving interactive user screens and printed reports a “natural” style and
appearance. As always, we are trying to bring the machine up to the level of the human
user (rather than the other way around). We use prompts to let the user know what kind of
data is expected and in what format. Whenever possible we provide the user with a menu
of options or possible data values to input. We validate the input data and provide helpful
error messages (and a chance to enter the data again) if the input data is not in the correct
range, format, etc.

E. Self-documenting - The program should contain within the source code as much
documentation information as possible.

The program should be structured to highlight the major processes involved. Use
descriptive names for variables, constants, functions, classes, objects, etc. Employ a
recognized and consistent indenting scheme. Avoid unnecessary variables - too many
variables not only waste memory but they also make programs harder to understand.
Liberal use of comments: to explain what each variable name stands for; to clarify
complicated calculations; to give information regarding the data needed by the program:
data format, type, files used, etc. Comment block at the beginning of the program can

497747298.doc.doc 1 of 10
contain: descriptive name for the program, author’s name, date written, date last
modified, purpose of program.

Assignment: Redo a programming assignment of your choice to make it as user-


friendly and as self-documenting as possible. Submit together with your previous
version of the assignment.

Some Notes on Program Design

A good program is not an accident. Programming is not accomplished by luck, coincidence,


or happenstance. Good programming is by design.

Programming by design requires some forethought with regard to the structure and outcome
of the programming effort. What sort of software product will result? Who will use it? Is it
expected to change over time? Programming by design encompasses a large variety of techniques
that have been developed since the 1960s, beginning with modular programming up to the current
interest in automated program design environments.

What Is A Good Program?

Before examining techniques for constructing a good program, it is reasonable to try to


identify the species. Over the years, our conception of what makes a program "good" has
undergone some radical changes. A case in point: FORTRAN programs were considered "good"
if they produced efficient, executable code. While this is a valid objective, it is not sufficient
today.

A good program does what it is supposed to do in the best possible way. Now, as a
definition, this is altogether too vague, especially the part about "the best possible way." Several
desirable program characteristics have been identified. A "good" program ought to be valid,
readable, modifiable, efficient with regard to programmer time, and efficient with regard to
storage space and processing time. These are general criteria that can be applied to any program.
Other criteria may be more specialized and application dependent, such as the real-time
constraints built into an on-line query system.

Validity. First and foremost, a program must be correct-that is, it should do what it is supposed to
do without error. We can distinguish two kinds of validity, internal validity and external
validity. Internal validity refers to the verifiability of the program. A program with
internal validity meets the specifications and design goals that have been set down for it
and does not contain "bugs." This is usually the objective when a program is tested for
correctness. Of course, while a program may be proved to contain errors, it is impossible
to prove that a program is correct.

External validity refers to the usefulness of the program. A program with external validity
solves the problem that motivated its design in the first place. After all, there is no value in
constructing a perfect program for the wrong problem. These two types of program
validity can be expressed by the questions:
497747298.doc.doc 2 of 10
 Is the program right (internal validity)?
 Is it the right program (external validity)?

Readability. In addition to providing a means by which a programmer communicates instructions


to a machine, a program ought to be understandable by human beings. This requirement
becomes increasingly important as the programming function becomes increasingly more
managerial and less technical. This changing role of programming may be seen in several
trends: larger programming efforts, programming teams, auditing of programs, separation
of analysis and design, maintenance programming.

Modifiability. There no longer exists the concept of a "throw-away" program. If it ever did exist,
it was tied to the image of the lone scientist/theoretician, working out of a closet
somewhere, who writes a long, unintelligible program in order to solve a terribly
complicated mathematical problem and, once solved, the program is no longer needed. If
this sort of programmer ever did exist outside of the collective imagination of the science
fiction community, it was a short-lived existence.

The reality is that software is now treated as an asset of the firm that owns and uses it.
Programs are no longer coded-they are designed. Programs are no longer executed they
are implemented. Programs are no longer "thrown away" --they are maintained.
Maintenance programming accounts for much of a firm's programming effort. This means
that most programming time is spent modifying programs as opposed to creating new
applications. It is only sensible that some of that effort be put into a program right at the
start to make it easy to modify later on.

Efficiency. It is indicative of the way that programming has changed over the last several decades
that, while in 1954 the designers of FORTRAN put machine efficiency at the top of their
list of requirements (although not before program correctness!), nowadays it comes last.
This is not to minimize the importance of efficiency in programming. Efficiency
considerations should permeate the entire programming effort. However, efficiency ought
to be sacrificed in favor of modifiability or readability.

Efficiency concerns lie in two arenas: the human and the machine. If a program is
programmer-efficient, then human time has been optimized; if it is machine- efficient, then
CPU time and storage space have been optimized. Which would you suppose should have
higher priority? Consider the following trends:
1. Computers are faster, more powerful, contain more storage space, and cost less.
2. Programs are larger, more complex, and take longer to write.
3. Programmers work slowly (due to 2) and cost a lot.

Given these trends, it is clear why programmer efficiencies have taken precedence over
machine efficiencies.

In addition, there is the concept of an elegant program. This does not, as some would have
you believe, apply to a program that employs clever tricks or to single-statement programs.
(These are sometimes called "write-only" programs since that is all you can really do with
them.) An elegant program goes beyond simply meeting the specifications. It is composed of
clear, simple, readable code. It gets the job done in the best possible way.

497747298.doc.doc 3 of 10
The Well-Written Program

What does it take to write a good program? A measure of problem solving, skill, certainly.
Beyond that, it is unclear.

If we look at people whom we identify as good programmers, we would find a host of


different skills and, probably, very few common characteristics. One problem with this, of course,
is that we might identify the good programmers incorrectly. Someone who works very hard on a
project and lets you know about it may not be as good at the job as someone who works quickly,
quietly, and efficiently - but the latter may appear to be someone who gets easy assignments
rather than a good programmer. Beyond having problem-solving ability, then, what can we say
about a good programmer? There is one common characteristic that comes up repeatedly-the
ability to communicate.

The fact is that a person who is capable of writing English can write a program. And
someone who is capable of writing well is capable of writing a good program. In fact, this has
been identified repeatedly as a major factor in the design of a good program. According to some it
is the major factor. The myth of the semi-illiterate hacker is just that - a myth.

Writing and Programming

How is writing a program similar to "just plain writing"?

Communication. First of all, the primary activity in both writing and programming is the same.
This activity is communication. Human beings use writing to communicate with each
other, sometimes across vast distances, or over great spans of time. Similarly, a program is
a medium of communication between programmer and machine, between programmer and
programmer and, sometimes, between programmer and nontechnical personnel. The
communication skills that you acquire in one spoken and written language can usually be
transferred and put to good use when you communicate in another language. In other
words, a good communicator has skills that transcend the syntax of any one particular
language. The same is true for computer programming languages. A good programmer
can communicate in FORTRAN or C++ as well as in MODULA-2 or Ada because it is
not the language that imparts this skill, it is simply an ability to communicate in a
programming context.

Reading. Many people think that to be a good programmer you simply start writing programs,
using brute force if necessary to accomplish the task. The truth is more civilized. A good
programmer, like a good writer, ought to begin by reading the work of others. This gives
you a chance to see what is being done and, perhaps, adapt it to your own problem.

Keep it simple. We have all seen written work that is unintelligible, but uses such nice big words
and technical jargon that you think, "This must be good work." This syndrome is
especially evident in student projects and articles in scholarly journals. This sort of work is
designed to impress the reader so much that she will not bother reading it too critically. It
is bad writing masquerading as good. On the other hand, we sometimes wrongly label a
written work as bad if is it written simply, using clear language within a good
organizational structure. We may think, "If I can understand it so easily, it must be trivial."
This problem too has an exact counterpart in the realm of programming. An unintelligible
497747298.doc.doc 4 of 10
program may impress us, while a simple and elegant one may appear to be "easy." As a
writer or reader of programs, be careful of this pitfall.

Outline. In class, we saw that a control hierarchy chart representing a top-down program is
strikingly similar to an outline. A composition, term project, or piece of fiction lacking a
solid organizational structure is just as unreadable as a disorganized program.

Plan ahead. In both writing and programming, you have to have a plan. You think ahead, not
only when you make up the outline but also when you approach each new paragraph. This
enables you to control the complexity of the product regardless of the complexity of the
original problem. For example, the structured constructs - sequence, selection, iteration -
with which we build programs help us to plan ahead in a formalized manner.

In fact, research in the area of cognitive behavior has shown that experts in many different
fields-including writing and programming-store information in meaningful and relevant
"chunks." Looking specifically at programming experts, researchers have shown that a
program can be decomposed into a set of interrelated goals, and each goal is realized by a
particular plan-that is, a chunk of programming knowledge.

Cohesion. We all remember learning that a paragraph should contain only a single thought.
Paragraphs, sections, and chapters share the requirement of program modules: They must
be cohesive.

Esthetics. In much written work, "white space" is important. It enhances the readability of the
finished product even if it does not change its meaning. For instance, in "action" novels,
there is often a lot of dialogue and short paragraphs. The page is more pleasing to the eye
and you end up turning pages faster in keeping with the pace of the story. As another
example, in print advertising, advertisements with a lot of copy are less likely to be read
even if they provide valuable information. Similarly, in order to enhance program
readability, we use a number of techniques that come under the heading of "esthetics."
These include such devices as the use of blank spaces and blank lines, indentation, and the
placement of borders around blocks of comments.

Read it through. Finally, just as you would ask a friend or colleague to review a piece of writing
you have just finished - whether it is a composition, article, story, or novel - programmers
submit their finished work to structured walkthroughs by a committee of their peers.

Structured Programming Methodology

The term structured programming refers to a collection of programming techniques for


implementing program and control abstractions in a hierarchical manner. The use of structured
programming methodology in program design increases the likelihood of producing a program
that is correct, readable, modifiable, and efficient. The techniques of structured programming may
be used with any of the computer programming languages on the software ladder, from the lowest
machine code to the highest machine-independent languages.

The term structured programming has come to represent different things to different people.
We use it here to represent a body of techniques that may be applied to a large and complex
program design task in order to produce programs that are logically manageable, well-structured,
and easily tested for correctness. Structured programming methodology dictates that correctness
497747298.doc.doc 5 of 10
be incorporated into the design of the program at the outset rather than having to "debug" errors
out of it after the program has been completed.

Structured programming methodology encompasses three techniques:


1. the modular decomposition of programs into collections of modules, or subprograms
2. the top- down or hierarchical ordering of these modules
3. the use of structured control constructs at the detailed logic flow level.

The development of a program's structures utilizes the techniques of modular decomposition


and top-down design to design a program in hierarchical levels of program abstraction. These
techniques have already been discussed fully in Chapter 5. The statement-level control structures
are drawn from the structured control constructs that are abstractions of control. These have
already been discussed in Chapter 6. In order to pull these three techniques together under the
umbrella of structured programming, we briefly review them here.

Modular Decomposition. Modularization of a program involves the identification, definition,


and construction of relatively independent blocks of program code, called modules. These
may be external subprograms, internal subprograms, or simply groups of statements
within a program unit, in order of decreasing independence. Each module performs a
clearly defined task and is characterized by a single entry point and a single exit point.
Thus the module can represent a single action and is a means of building abstraction into a
program.

Top-Down Design. Although modularization dictates that the program be decomposed into
blocks of code, it doesn't say anything about how this decomposition ought to proceed.
The top-down program-design technique assumes a modular program and organizes these
modules into a hierarchical structure. Much like the outline you create before embarking
on a term project, top-down design is characterized by stepwise refinement and delayed
decision. An overview of a modular, hierarchical program is depicted in the figure below.

At any level in the hierarchy, the program can be regarded as complete and tested for
correctness. We can do this by assuming an underlying abstract machine that contains
operations corresponding to the lower level modules as yet uncoded. This is a boon to the
management of complexity in programming but, of course, at the next level we are rudely
awakened and forced to resume our coding. In this way, quite a bit of programming work
is done while we defer lower level decisions to a later time. Of course, this design
technique should not be used to justify procrastination-endlessly deferring critical
decisions so that the abstract machine stays abstract.

497747298.doc.doc 6 of 10
Software Engineering

We have come a long way from the octal-coded programs and open subroutines of the 1950s.
Computers are more powerful. Programs have become bigger and more complex. The technology
of program design is aimed at managing this complexity.

Software engineering encompasses techniques for analysis, design, testing, validation, and
maintenance of software. The discipline of software engineering can probably be traced back to
the advent of structured programming techniques of the early 1970s.

Structured programming was a huge improvement over trial-and-error and spaghetti code. In
fact, we can say that it has been a definite success. However, structured programming only goes
so far. For very large and complex software systems, structured programming methodology
breaks down. That is why other techniques have been developed, not to replace structured
programming methods but to enhance them. These other techniques include data abstraction,
information hiding, structured system analysis, database methods, database-centered
fourth-generation tools (4GTs), object-oriented programming, object-oriented design, editing
environments, rapid prototyping, and automatic documentation.

Software Engineering Concepts

The following are some of the important concepts of software engineering. All share the
same objective: reducing the complexity of the problem, thereby making the resulting
programming task more manageable.

Modularity. Modularity is probably the oldest software engineering concept, dating back to the
early 1960s. It predates and provides a solid basis for the ideas of structured programming.
High cohesion and low coupling are considered critical qualities for modules.

Structure. Modular programs may be structured in some way using one of a number of design
methods-for example, functional decomposition, data flow, by data structure design, etc.
The structure of a program is designed by specifying well-defined relationships among the
modules. For example, the modules of a program may be related in a network of
relationships or in a hierarchy-that is, a tree structure. A modular program constructed
using top-down design results in a hierarchical structure. The resulting structure diagram
is in tree form. Hierarchy is good at reducing the complexity of a problem, but not very
good at encouraging "reusable code." This is because the rigid tree structure does not
provide for common modules.

Information hiding. When modules are well designed, they are relatively independent. They
communicate with each other only through well-defined interfaces. A "user" module does
not require access to all the implementation details-such as local variables, algorithms-of
the "used" module. This unnecessary information may be hidden from the user, protecting
the integrity of individual modules and reducing the confusion that comes along with too
much information.

Abstraction. All abstraction uses the concept of information hiding. Any abstraction allows one
to ignore the tedious details (at least temporarily) involved in building a system and
concentrate on the larger picture. Abstraction is the major concept used in bottom-up
design: the construction of a large program by building layers upon layers of abstraction.
497747298.doc.doc 7 of 10
As we have seen throughout this text, abstraction comes in many forms. As it relates to
software engineering, we can consider data abstraction, program abstraction, and control
abstraction.

Data abstraction involves the encapsulation and hiding of variables and operations needed
to implement a data object. Program abstraction is the guiding concept underlying
modularity. Control abstraction involves the use of high-level control structures such as
the selection and iteration constructs, monitors, coroutines, exception handlers, parallel
processing-without concern for how they are actually implemented on a sequential
machine.

CONTROL STRUCTURE
Structured Control Constructs. Structured control constructs are statement-level control
structures that may be described as either (low-level) stylized sequences of instructions or
high-level language statements, each with a single entry point and a single exit point,
which fall into one of the following three categories: simple sequence, selection, iteration.
A construct is a building block. In this case, these are the building blocks from which the
program is constructed, piece by piece.

Three types of control structure:-

1. Sequential Program Control


All of the RAPTOR programs you have seen in previous readings have used sequential program control.
By sequential we mean "in sequence," one-after-the-other. Sequential logic is the easiest to construct and
follow. Essentially you place each statement in the order that you want them to be executed and the
program executes them in sequence from the Start statement to the End statement.
As you can see by the example program to the right, the arrows linking the statements
depict the execution flow. If your program included 20 basic commands then it would
execute those 20 statements in order and then quit.

When you are solving a problem as a programmer, you must determine what statements Statement 1
are needed to create a solution to the problem and the order in which those statements
must be executed. Writing the correct statements is one task. Determining where to
place those statements in your program is equally important. For example, when you
want to get and process data from the user you have to GET the data before you can use Statement 2
it. Switching the order of these statements would produce an invalid program.

Sequential control is the "default" control in the sense that every statement
Statement 3
automatically points to the next statement in the flowchart diagram. You do not need to
do any extra work to make sequential control happen. However, using sequential
control alone will not allow the development of solutions for most real-world problems.
Most real world problems include "conditions" that determine what should be done
next. For example, "If it is after taps, then turn your lights out," requires a decision to
be made based on the time of day. The "condition" (i.e., the current time of day)
determines whether the action should be executed or not executed. This is called "selection control" and is
introduced next.

497747298.doc.doc 8 of 10
2. Selection Control
It is common that you will need to make a decision about some condition of
your program's data to determine whether certain statements should be
executed. For example, if you were calculating the slope of a line using the
assignment statement, slope ← dy / dx, then you need to make sure that the value of dx is not zero
(because division by zero is mathematically undefined and will produce a run-time error). Therefore, the
decision you would need to make is, "Is dx zero?"

A selection-control statement allows you to make "decisions" in your code about the current state of your
program's data and then to take one of two alternative paths to a "next" statement. The RAPTOR code on
the right illustrates a selection-control statement, which is
always drawn as a diamond. All decisions are stated as
"yes/no" questions. When a program is executed, if the
answer to a decision is "yes" (or true), then the left branch of
control is taken. If the answer is "no" (or false), then the right
branch of control is taken. In the example to the right, either
Statement 1
statement 2a or statement 2b will be executed, but never both.
Note that there are two possible executions of this example
program:
Possibility 1 Possibility 2 Decision
Statement 1 Statement 1
Statement 2a Statement 2b
Statement 3 Statement 3

Also note that either of the two paths of a selection-control Statement 2a Statement 2b
statement could be empty or could contain several statements.
It would be inappropriate for both paths to be empty or for
both paths to have the exact same statements, because then
your decision, Yes or No, would have no effect during Statement 3
program execution (since nothing different would happen
based on the decision).

Start
3. Selection Control Examples
To help clarify selection-control "Enter your PGA"GET GPA
statements, please study the following
examples. In the first example to the
right, if a student has made the Dean's
List, then a congratulations message Yes
GPA >= 3.0
Start No
will be displayed - otherwise nothing
is displayed (since the "no" branch is
empty). "Enter your PGA"GET GPA
PUT "Congratulations for making the Dean's list!"¶

In the next example, one line of text is GPA >= 3.0


Yes No
always displayed, with the value of the End
PGA variable determining which one.

497747298.doc.doc PUT "Congratulations for making the Dean's list!"¶


PUT "Sorry, you did not make the Dean's
9 oflist."¶
10
Start

"Enter your PGA"GET GPA

GPA >= 3.0


In the next example, if the student does Yes Start No
not make the Dean's list then two lines
of text are displayed, but only one line
is displayed if they do. "Enter your PGA"GET GPA
PUT "Congratulations for making the Dean's list!"¶
PUT "Sorry, you did not make the Dean's list."¶

PUT "Please study harder next semester"¶


GPA < 3.0
In the last example to the right, the Yes No
logic of the decision expression has
been inverted. This is perfectly
acceptable as long as you make sure
PUT cases.
the inversion covers all possible "Sorry, you did not make the Dean's list."¶
PUT "Congratulations for making the Dean's list!"¶
Note that the inversion of "greater End
than or equal to" is simply "less than."

End

497747298.doc.doc 10 of 10

You might also like