[comp.software-eng] How will your code look to the hot-shots of 1993?

bks@ALFA.berkeley.edu (Brad Sherman) (07/22/88)

Everyone seems to have a plan for producing good software, but could we
have some discussion of how to go about fixing and modifying existing code?

For example, given a working software system that began its life-cycle, say,
5 years ago. That has been through patches, bug-fixes and customer
requested feature additions.  That was written using the state-of-the-craft
design methods of an above average programmer of 1983.  In other words,
it works most of the time and no one is going to give you the luxury of
a complete rewrite using the design methods of 1988 and your own peculiar
idioms.  Unfortunately, the original programmer is now designing graphics
boards for the Estonian division of MegaCorp.  System consists of 8 programs
written in C ( remember, 1983 style ) about 20000 lines total. Documentation
is sparse and out of date.

Your job is to make it work on the new improved and almost compatible hardware
and revised O.S., and oh yes, please add these 4 features while you're at it.

I think that this task is more typical than most that have been discussed in
this group.  How should a programmer go about internalizing enough of the
workings of the system to have a shot at succesful completion?

		--Brad Sherman

shebs%defun.utah.edu@utah-cs.UUCP (Stanley T. Shebs) (07/23/88)

In article <12398@agate.BERKELEY.EDU> bks@ALFA.berkeley.edu (Brad Sherman) writes:

>Everyone seems to have a plan for producing good software, but could we
>have some discussion of how to go about fixing and modifying existing code?
>[...]  How should a programmer go about internalizing enough of the
>workings of the system to have a shot at succesful completion?

Seems like I've spent half my programming career doing this, with everything
from old and crufty Fortran to old and crufty Lisp.

My preferred practice is to start by making one attempt to read through the
code to understand it.  If this succeeds, then the code is good.  If not,
then I start adding comments for the bits I do understand, with lots of
questions.  At the same time, I start doing local transformations on the
code - changing into a more modern dialect/usage, flushing fragments that
aren't really used, moving things in and out of loops, being careful all
the while to make sure that correctness is preserved.  At this point, only
local understanding is needed.  As time goes on, larger patterns start to
appear, I understand more of the total program, can revise the comments
to reflect that improved understanding, and can make more sweeping changes.
In several cases, I've ended up with a nearly total rewrite that is easier 
to understand, better commented, faster, and more general than the original.
This process has also uncovered long-hidden bugs on more than one occasion!

Caveats:  This is harder to do if the code must be left alone - the comments
and transformations have to be somewhere else.  It also requires care and
backups and frequent testing to make sure that things haven't gotten broken
by the apparently innocuous change.  The time and effort is substantial,
so it's more practical for individual routines than major systems.

One way to look at this is that it's the application of hacking energy to
reverse program entropy...

							stan shebs
							shebs@cs.utah.edu

hollombe@ttidca.TTI.COM (The Polymath) (07/26/88)

In article <12398@agate.BERKELEY.EDU> bks@ALFA.berkeley.edu (Brad Sherman) writes:
}Everyone seems to have a plan for producing good software, but could we
}have some discussion of how to go about fixing and modifying existing code?

}I think that this task is more typical than most that have been discussed in
}this group.  How should a programmer go about internalizing enough of the
}workings of the system to have a shot at succesful completion?

Probably most of us have done more of this than almost anything else
during our time in the D.P. biz.  My last experience with it involved over
4,000 lines of C so crufty the original authors refused to touch it.
Here's how I went about it:

Step zero:  Keep multi-generation backups.  Be able to fall back to the
original code, if necessary. (Sounds trite, I know, but I've seen
self-styled "Real(tm) Programmers" happily go in and modify the only
existing version of a major system's source code with no backups.  I get
the shakes just thinking about it).

Step one:  Reformat the code to something readable.  Do it by hand, not
with a pretty printer.  In the two days I spent doing this I uncovered and
fixed six major bugs that had been obscured by incorrect indentation and
general cruft.  The STR's on some of them were over 18 months old.

Step two:  Eliminate the unnecessary (but make _sure_ it's unnecessary).
I wound up deleting over 1,000 lines of code that either did nothing or
did nothing necessary.  Much of it was debug left over from the original
creation of the beast.

Step three:  Add comments.  In particular, make sure every declared
constant and variable has a comment description.  Likewise for functions
and subroutines.  Exceptionally tricky or crufty code should be commented
line by line, if necessary.  This will give you a fair idea of what the
program is doing and how it does it.  (My personal commenting standard:
All comments are delimited line by line.  This makes accidentally
including live code in a comment much less likely).

Step four:  This is a quick and dirty trick I occasionally have use for.
If your system doesn't have a program trace capability, you can add a
rough one by putting

#ifdef TRACE
     printf ("PROGRAM_NAME:  Function_name() \n");
     fflush (stdout);
#endif

at the start of each function.  The fflush() makes it more likely you'll
get the last line out if something crashes.

Step five:  Document.  If documentation doesn't exist, write it.  If it
exists, update it.  If it's up to date, keep it that way.

Step six:  Now you're ready to start making changes.  After you've
designed them (you do design before you code, don't you?) try to implement
and test as modularly possible.  Debugging is much more of an adventure if
you try to change everything at once.  (Adventure: n., Someone else having
a hard time, very far away).

End result:  What started out as a buggy and much distrusted system hasn't
had a valid STR written against it in over a year.  Its capabilities have
been enhanced to do things the original authors thought were impossible or
too complex to bother with (or never thought of at all).  People are
starting to realize the beast is maintainable, after all.  I'm getting a
lot of requests for more enhancements and upgrades.

-- 
The Polymath (aka: Jerry Hollombe, hollombe@ttidca.tti.com)  Illegitimati Nil
Citicorp(+)TTI                                                 Carborundum
3100 Ocean Park Blvd.   (213) 452-9191, x2483
Santa Monica, CA  90405 {csun|philabs|psivax}!ttidca!hollombe

orr@cs.glasgow.ac.uk (Fraser Orr) (07/26/88)

In article <5623@utah-cs.UUCP> shebs%defun.utah.edu.UUCP@utah-cs.UUCP (Stanley T. Shebs) writes:
>In article <12398@agate.BERKELEY.EDU> bks@ALFA.berkeley.edu (Brad Sherman) writes:
>
>>Everyone seems to have a plan for producing good software, but could we
>>have some discussion of how to go about fixing and modifying existing code?
>>[...]  How should a programmer go about internalizing enough of the
>>workings of the system to have a shot at succesful completion?
>
>My preferred practice is to start by making one attempt to read through the
>code to understand it.  If this succeeds, then the code is good.  If not,
>then I start adding comments for the bits I do understand, with lots of

Anyone interested in this approach might like to read Elshoff and Marcotty's
paper on this very subject :-
     Elshoff, James L. and Michael Marcotty, "Improving Computer Program
	      Readability to Aid Modification," CACM, vol. 25, no. 8,
	      pp. 512-521, August 1982.
It is an interesting and worthwhile read for anyone unfortunate enough to have
to maintain other people's programs.

==Fraser Orr ( Dept C.S., Univ. Glasgow, Glasgow, G12 8QQ, UK)
UseNet: {uk}!cs.glasgow.ac.uk!orr       JANET: orr@uk.ac.glasgow.cs
ARPANet(preferred xAtlantic): orr%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk