Sponsored Link •
Design monkeys on your back
In the real world, as you work to design software, you have several concerns to keep in mind -- several "monkeys on your back." Each monkey competes with the others for your attention, trying to convince you to take its particular concern to heart as you work. One large, heavy monkey hangs on your back with its arms around your neck and repeatedly yells, "You must meet the schedule!" Another monkey, this one perched on top of your head (as there is no more room on your back), beats its chest and cries, "You must accurately implement the specification!" Still another monkey jumps up and down on top of your monitor yelling, "Robustness, robustness, robustness!" Another keeps trying to scramble up your leg crying, "Don't forget about execution speed!" And every now and then, a small monkey peeks timidly at you from beneath the keyboard. When this happens, the other monkeys become silent. The little monkey slowly emerges from under the keyboard, stands up, looks you in the eye, and says, "You must make the code easy to read and easy to change." With this, all the other monkeys scream and jump onto the little monkey, forcing it back under the keyboard. With the little monkey out of sight, the other monkeys return to their positions and resume their activities.
As you sit there in your cubicle and work on your software, to which monkey should you listen? Alas, in most cases you must listen to all of them. To do a "good job," you will need to find a way to keep all these monkeys happy -- to strike a proper balance between these often conflicting concerns.
The first monkey: Meeting the schedule
In my experience, the most important way to keep management happy during a software development project is to meet the schedule. The schedule is critical, of course, because commercial software development is done for commercial reasons. It's a business.
Although there is often pressure to dive into implementation as soon as possible in an effort to finish a project faster, developing a well-thought-out specification and a thorough design from the start can help prevent unforeseen schedule catastrophes during the implementation phase. Having real specification and design phases before implementation gives you milestones that can help you manage your project schedule. In addition, the people for whom you are developing the end product (the people for whom schedule is the most important concern) will feel more comfortable if you give them intermediate milestones along the path to project completion. Early milestones can be the completion and sign-off of the specification, the completion and sign-off of the user interface prototype, and the completion and peer review of the design.
Once you have a design that includes all the classes populated with fields and methods without bodies, you have a good inventory of the work that remains. By making estimates for the time it will take to implement each method body, you should be able to come up with a reasonably accurate schedule for the implementation phase.
This is how a solid specification and design phase before implementation can help prevent major schedule slips during implementation: By the time you implement, you know what you are aiming for, and you know what you have to do to get there.
The second monkey: Correctly implementing the specification
To appease the second monkey, the most important thing is to do the work up front to figure out and communicate a clear, sufficiently detailed vision of the end target. If you don't know where you are going, you'll likely end up somewhere you never intended. To produce a product that matches and satisfies the customer's expectations, all those involved in developing the software must have a clear understanding of what they are supposed to produce.
The third monkey: Robustness
If you meet your milestones during the specification, design, and implementation phases but then require two more years to get the system to work reliably, you have a problem. Bugs are inevitable, but there is a threshold beyond which a product becomes unusable or at least less marketable. This threshold varies depending on the application. Software that helps commercial jetliners navigate likely has a higher robustness threshold than the browser software you are using to read this article. In all cases, however, there is some level of robustness that you must deliver.
In my experience, robustness has arisen out of good, solid designs and good coding practices. With the advent of Java, with its garbage collection and limitations on pointers, robustness became much easier to deliver. But even without memory problems, bad design and bad coding can still yield programs that lack robustness.
One coding technique I've found especially useful in achieving robustness is unit testing methods just after I implement them. After implementing a method, I walk through it with a debugger to make sure it is doing what I intended it to do.
The fourth monkey: Performance
Performance -- execution speed, resource usage, and so on -- is something you should usually keep in mind as you design and implement software. But often, programmers try to solve performance problems their programs don't actually have. The right approach typically is to keep performance in the back of your mind as you develop. In the front of your mind, keep "good object-oriented, thread safe" design. During integration and testing, if you discover you do indeed have a performance problem, that is the time to analyze and address it.
The fifth monkey: Flexibility
There is more than one path to correct implementation of a specification. Different teams of programmers can produce drastically different designs and implementations, all of which fulfill the requirements set forth by the specification. Some versions, however, may take longer to write and debug. As they execute, some versions may be slower than others. And over time, as the program evolves from release to release, some versions may turn out to be less flexible than others.
Flexibility, the ease with which a program can be changed, is important because source code usually evolves over time. As bugs are fixed and enhancements made for new releases, programmers must return to already-existing source code, understand it, and make changes to it.
When you write a program, you are communicating. Most obviously, you are communicating with a machine. You are telling a computer what you want it to do. But there is another, less obvious, form of communication that you perform when you write a program: communication with other programmers. Through your source code, you communicate your design to any programmers who, in the future, ever need to fix a bug, make an enhancement, or simply reuse your code. You are telling programmers how your code is supposed to work, how it should be used, and how best to go about changing it.
One of the most important aspects of program flexibility is source code readability. Readable source code is important because it helps future programmers (possibly including your future self) understand what you were trying to do. In many cases in the real world, a program's source code is the documentation. When others work on your source code, either to add new features or to fix bugs, they read your source code to understand what it does.