My sister (call her Jane) and I are both software contractors.
She’s on the east coast and I’m in Minneapolis.
Every few weeks we call and trade war stories.
Her tales are almost always the same. They go something like this.
Jane arrives on the scene at a software project and receives her three-month assignment.
She starts by carefully gathering her requirements,
taking a system-wide view and doing her best to understand the interfaces between her stuff
and the rest of the product.
She asks a lot of questions of others, who would mostly prefer that she stop bothering them.
After a week of this everyone expects Jane to jump in and start coding immediately,
but what she does instead is to start writing a design for the code she’s going to write.
She does it in two phases.
The first phase is a high-level design in which all the major components and their internal and external relationships
are laid out in detail.
Once she’s certain that her bases are covered she moves on to the second phase,
which is to produce a very detailed design consisting of the pseudo-code for each component.
As part of this she also designs the tests she’s going to write,
which she regards as an integral part of the application.
They will facilitate her in writing the app code,
since the tests define the interfaces with which her application code must mesh.
It’s sort of like taking the time to figure out what your customers want before you bring a product to market.
Jane knows that her tests will come in handy soon for other reasons as well.
Management is not encouraged by her seemingly time-wasting approach.
By now they were expecting to see some demonstration of some visible features,
but Jane has nothing to show but her design documents.
She assures her managers that she’s on schedule but they’re having trouble buying it.
They’re looking at her peers and all of them are coding features day in and day out.
In fact that’s all they do - code - except of course that once each day they spend fifteen minutes
doing a “stand up” in which they report their progress (as is now the custom seemingly everywhere).
Six weeks into a three-month project Jane’s management is relieved to learn that she’s done with design,
and Jane starts coding the application. Since she’s not designing as she’s coding, the coding goes quickly.
She doesn’t do much rewriting or “refactoring” (piecewise rewriting)
because she knew what the code would look like before she wrote it,
and because her unit tests help her to define her app code’s interfaces.
In two weeks she is done coding, much to everyone’s surprise and relief.
Her peers meanwhile are also declaring themselves “code complete” after spending as much time coding as she spent designing,
writing tests, and coding.
For two to three weeks Jane performs unit tests, which are tests of just her individual components.
These tests can execute and test her application code independently of the rest of the application.
Finally, perhaps one to two weeks short of the due date, Jane updates her design documentation
with any minor modifications that were needed as a result of unit testing.
Now comes the system test phase.
Jane’s peers didn’t write any unit tests,
so the only way to test their code is to put the whole system together and try to run it
in the same manner that a user would run it. It’s sort of like creating an airplane from scratch,
component by untested component, and then testing all the components together at once by actually flying the plane.
Thus begins the next phase of the project, one that invariably wasn’t scheduled.
It’s the fixing of the long, long bug list.
There are plenty of bugs, and they’re hard to find because you can’t isolate them easily using system-wide tests.
All you know that some externally visible feature isn’t working,
but the problem could be in any of a dozen components that were never tested individually.
The additional frustration with system-testing-only is that once you’ve fixed one bug,
you tend to uncover at least one more, and in fixing one bug you may create another.
It’s hard to get control of a system with dozens or hundreds of components that can’t be tested separately.
The exception, of course, is Jane’s code. When the problem seems to point in her direction,
she has unit tests to demonstrate that her code meets specifications.
Soon it becomes apparent to everyone that Jane’s code contains few if any bugs,
so she is reassigned. Her job now is to fix everyone else’s bugs.
In the end, she will spend more time fixing others’ bugs than she spent designing, writing, and testing her own code.
After they've extended her contract, that is.
Even after the bug list is conquered, there will be a huge difference in the confidence level of Jane’s code
vs. the rest of the code.
In order to avoid getting technical here let’s use an analogy.
Would you have more trust in a product that had been delivered to you the first time in working order,
or in another one that the maker had managed to remedy by eventually fixing it after you had returned it a dozen times?
There are two types of code (software) in this industry.
There’s designed code, which is reliable by virtue of the fact that the designer knew what he/she was doing
and took the time to design it.
Then there is diddled code, which is code that was just written off the top of one’s head and eventually
diddled, diddled, and diddled again until it managed to pass its system tests,
probably under very controlled circumstances.
Well-designed code is inherently reliable because the code is written such that the vast majority
of undesirable outcomes are inherently impossible.
Well-designed code needs only a fraction of the testing of poorly designed code,
since the well-designed code cannot possibly produce most bad outcomes, i.e. there isn’t even a way to test for them.
Diddled code is, well, something you just end up diddling forever, usually at tremendous expense.
At the end of the day you are either going to get a product that was designed well or you aren’t.
If you’re buying software development services and you don’t know what constitutes great design,
you are almost certainly heading for serious disappointment.
So in our next several articles we’ll focus on the essence of great software design.