|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 7 of 7
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.
What constitutes a "good object-oriented, thread-safe" design? The answer depends on whether you are talking about object orientation or thread safety.
Thread safety primarily is about robustness (monkey number three). If you forget to synchronize methods that really need to be synchronized, you can end up with intermittent data corruption. Creating thread-safe designs involve understanding multithreading in general, understanding the multithreaded needs of your particular programs, and programming accordingly.
Good object-oriented design also plays a part in robustness. As I said earlier in this article, my experience has shown me that robustness arises out of good design and coding practices.
In addition, a good object-oriented design can play a role in keeping a project on schedule (monkey number one). As part of a solid overall software development process, a thorough design phase can help a team avoid unforeseen schedule slips. A thorough design gives the team a clear and detailed view of the work that will be required by the implementation phase.
The primary benefit, however, of a good object-oriented design is flexibility, the concern of monkey number five. A good object-oriented design can give you code that is easy to understand and easy to change. And the greater the flexibility of a body of code, the quicker (and cheaper) will be enhancements and bug fixes to that code.
The guidelines put forth in this column primarily will help you achieve program flexibility. When I talk about object design, building class hierarchies, interfaces, polymorphism, choosing composition vs. inheritance, and so on, my main focus will be to give insights that will help you make your programs easier to understand and easier to change.
Software design is subjective. Your idea of a well-designed program may be your colleague's maintenance nightmare. In light of this fact, I hope to make this column as interactive as possible.
I encourage your comments, criticisms, suggestions, flames -- yep, every kind of feedback -- about the material presented in this column. If you disagree with something, or have something to add, please let me know. As part of each month's column (after the first one), I will include some reader feedback about the previous month's article.
With next month's Design Techniques I'll begin a mini-series of articles that focus on designing classes and objects. Next month's article, the first of this mini-series, will give design guidelines in the area of class initialization.
Read more about Core Java in JavaWorld's Core Java section.