inse - lecture 10 programming practice & style u control constructs u layout & names u...
TRANSCRIPT
INSE - Lecture 10
Programming practice & style
Control constructsLayout & NamesInitialization
To bear in mind while “coding”
A key target is readability of the code,because that
leads to understandability; and learnability.
Control Constructs
"Those things in the language that determine in which order instructions are obeyed."
Control constructs - sub-topics:
“Stucturedness” Linear sequence ("too obvious" - and not
much to say anyway); Loop constructs; Choice constructs (if , case/switch, etc.); Subroutine constructs (?recursive); Labels and goto ("unstructured"); Other? (e.g. error-handling; parallelism...)
What does “structured” mean?
1960's - “programs must be 'structured'.”
(With at least two inconsistent definitions of the term!)
1970's -(1) “What's that?”
-- please define it better!
(2) It's a straitjacket.
-- what forms of structure do we really want?
(3) "The 60's doctrine is fine forbeginners."
Example: input, skipping
spaces, buffering non-spaces: the first character can be either space or non-space: stop at end of input.
Can this be made structured?
Not a chance!
“Structured” loop constructs
These are “natural” loop constructs for many applications, but there are situations where the need goes beyond either of these… e.g. ...
Another “natural” loop need:
“Copy characters from an input file to an output file, up to (but excluding output of) the first ‘@’.”
(Assume there will be a ‘@’ before end of file.)
Copy up to but excluding… That “naturally” calls for
the flow diagram on the left.
This flow diagram is of a “N-and-a-half-loop”.
Note that it is structured in the sense of “one entry, one exit”.
Coding that in (say) Java - try 1
do
// read C
if (C!=‘@’)
// write C
while(C!=‘@’);
The duplicated condition makes it hard to understand
Testing the condition twice each time round the loop is inefficient
Prone to mis-maintenance?
Coding that in (say) Java - try 2
// read C
while(C!=‘@’)
{
// write C
// read C
}
More understand-able?
Safe? What if the “read” is
many lines of code? - a maintenance problem...
Coding that in (say) Java - try 3
boolean stop=false;
while(!stop)
{
// read C
if (C==‘@’)
stop = true;
else
// write C
}
Obscures the real flow Longer than it needs
to be Somewhat inefficient
Coding that in (say) Java - try 4
do
// read C
if (C==‘@’)
break;
// write C
while(true);
Understandable, because it “says what we mean” by the N-and-a-half flow diagram
Efficient Hard to mis-maintain
Other special loops...
There are other special design situations calling for special control flows…
… the one on the left is a search loop
it’s one-entry one-exit.
It’s a special case of...
...
… a multi-exit loop
(still “one entry, one exit”)
An unavoidable goto - even in Ada
procedure Sort(X:Arr) is
Old : Element;
begin
<<Restart>>
for I in X’First+1..X’Last loop
if X(I-1) > X(I) then
Old:=X(I-1); X(I-1):=X; X(I):=Old;
goto Restart;
end if;
end loop;
end Sort;
Exceptions
Another unstructured situation … when something in the program goes
catastrophically wrong…e.g.– arithmetic overflow or underflow;– over-running the bounds of an array or other
fixed-size container;– hitting end-of-file but needing more data from the
file;– communications line errors ...
Especially for reliable programs – we can’t let them crash, or run amok!
Where to handle the abort?
Often the handling can only be done many levels of call back from the site of the problem.
So any aborting mechanism needs to be (potentially) back to the call, often repeatedly.
Traditional solution
Pass some error flag out of each call; after every call of every procedure test
all flags for all possible kinds of abort until a “handler” is met for a particular abort...
Problems with that solution
How do we guarantee some handler will be met for every possible abort in every possible call sequence? (especially in a compiled program - i.e. impossible to test exhaustively).
In languages without return, how do we abort from the middle of a procedure?
How do with abort without a value from the middle of a function? ...
In Ada, C++, Java The languages provide exceptions … ...with statements to “raise” (or “throw”) an
exception aborting the current set of instructions…
…there is syntax to “handle” (or “catch”) particular exceptions…
… when an exception is raised, it is “propagated” out of blocks and calls until a handler is found for it.
Subroutines...… or “subprograms”… or “procedures and functions”… or “PERFORMable paragraphs and sections”… or OO “methods”… or ...
How functions return their results
Some older languages tended to try return function results without any special syntax -– hard to “spot” when reading the program;– sometimes made it possible to exit a
function without defining a value.
In Ada C++ & Java
an explicit “return” instruction to define the result;
if execution tries to leave the function’s instructions by “falling off the end”, then an exception is raised.
Recursion
not often needed - but when it is needed, it can make otherwise-nasty code very simple;
easy when you know the trick -– at the place of a recursive call, think of the call as “seen from the outside” - just as you would for a call of any other subroutine.
from the programming units, you should know all about it?
Backtracking
for “brute-force search” programs
Example - in “extended” Adafor all I in 1..8 loop -- statements which might include -- instructions like success and -- failureend loop;
Backtracking is build into Prolog as the basis of the flow-of-control mechanism.
“Others” - many! e.g. ... co-routines for pseudo-parallelism:
– really only one program counter - but it “jumps” between co-routines (usually at controlled places in the source - e.g. semicolons);
parallelism/concurrency: – multiple program counters in a single program, one
per process» problems of synchronization» problems of intercommunication» problems of conflict & deadlock
A personal conclusion
[but one that many other people came to in the 1970’s]
We need adequate programming language constructs: they should give us the ability to state disciplined structures in forms which are– not concealed; and– understandable.
Layout
I.e. prudent use of blank lines; indentation; blanks within a line; placement of comments.
Purpose of layout
LEGIBILITY!
1/ by separation into “natural units” - usually by blank lines; visible boundaries to the “natural unit”
remove one uncertainty when thinking about it;
good for different granularities of “natural unit”.
Purpose of layout… legibility!!
2/ by drawing attention to “local structure”:
usually by indentation;
used to help us see where constructs start & end;
also to see which construct.
for
Purpose of layout… legibility!!
3/ by “phrasing” within the line: e.g. by spaces within the line:
= - the spaces make it very clear that the line represents an assignment.
Consistency of layout
It helps to have rules of thumb; habits; “house style”.
Know when to break the rules: e.g.
rule 1: “one instruction per line”;
rule 2: space either side of the assignment operator“;
butint OldA=A;A=B;B=OldA;
Postscript to “layout”
Objective: to help the reader So consistently-applied rules avoid the reader
having to adapt to changing style; But deviations from the rules might be useful to
attract the reader’s attention.Having a style is more important than exactly
what it is…“Adding layout and comments later” is false
economy.
Names
Choosing them for understandability
Names ...
… should be thoughtfully chosen to be– as short as possible; but also– to say as much as possible.
… we need to find a trade-off between these usually-conflicting objectives.
?standard abbreviations ?
? influence of the programming language?
!! inspiration !!
Initialization and...
[Avoiding too-obvious bugs…]
General program form
Many programs & program-components are of form
– do some setting up; then– do the real work; then– do some wrapping up.
The setting up is easy to forget…– especially uninitialized variables => bugs;– most especially uninitialized pointer variables.
Easy to forget...
The setting up is easy to forget…– especially uninitialized variables => bugs;– most especially uninitialized pointer variables.
The wrapping up (“finalization”) is very easy to forget…
– many diverse and subtle forms of this error…» e.g. omitted CLOSEs on some operating systems.
After this lecture (1) look at the loops in your past
programming efforts – – how easy to read were they?– how prone to mis-maintenance?
read the notes – especially– for the problems of coding a search loop;– for choice constructs (un-lectured);– for Boehm-Jacopini theorem (un-lectured).
After this lecture (2) From here out, compare constructs in
programming languages you meet for their strengths and weaknesses.
think about your past programming efforts - how good was the layout & naming?
do better in future - thoughtfully!!
be more alert for initialization & finalization issues.
© C Lester 1997-2014