rules of software engineering. A rule that is so important, I’ll repeat it later in the book:
The longer a bug remains undetected, the harder it is to fi x.
Some people think of testing as something you do after the fact to verify that the code you wrote is correct. Actually, testing is critical at every stage of development to ensure the resulting application is usable.
DEPLOYMENT
Ideally, you roll out your software, the users are overjoyed, and everyone lives happily ever after. If you’ve built a new variant of Tetris and you release it on the Internet, your deployment may actually be that simple.
Often, however, things don’t go so smoothly. Deployment can be difficult, time-consuming, and expensive. For example, suppose you’ve written a new billing system to track payments from your company’s millions of customers. Deployment might involve any or all of the following:
● New computers for the back-end database
● A new network
● New computers for the users
● User training
● On-site support while the users get to know the new system
● Parallel operations while some users get to know the new system and other users keep using the old system
● Special data maintenance chores to keep the old and new databases synchronized
● Massive bug fixing when the 250 users discover dozens or hundreds of bugs that testing didn’t uncover
● Other nonsense that no one could possibly predict
WHO COULD HAVE PREDICTED?
I worked on one project that assigned repair people to fix customer problems for a phone company. Twice during live testing the system assigned someone to work at his ex-wife’s house. Fortunately, the repair people involved recognized the address and asked their supervisors to override the assignments.
If psychics were more consistent, it would be worth adding one to every software project to anticipate these sorts of bizarre problems. Failing that or a working crystal ball, you should allow some extra time in the project schedule to handle these sorts of completely unexpected complications.
MAINTENANCE
As soon as the users start pounding away on your software, they’ll find bugs. (This is another software axiom. Bugs that were completely hidden from testers appear the instant users touch the application.)
Of course, when the users find bugs, you need to fix them. As mentioned earlier, fixing a bug sometimes leads to another bug, so now you get to fix that one as well.
If your application is successful, users will use it a lot, and they’ll be even more likely to find bugs. They also think up a slew of enhancements, improvements, and new features that they want added immediately.
This is the kind of problem every software developer wants to have: customers that like an application so much, they’re clamoring for more. It’s the goal of every software engineering project, but it does mean more work.
WRAP-UP
At this point in the process, you’re probably ready for a break. You’ve put in long hours of planning, design, development, and testing. You’ve found bugs you didn’t expect, and the users are keeping you busy with bug reports and change requests. You want nothing more than a nice, long vacation.
There’s one more important thing you should do before you jet off to Cancún: You need to perform a post-mortem. You need to evaluate the project and decide what went right and what went wrong. You need to figure out how to make the things that went well occur more often in the future. Conversely, you need to determine how to prevent the things that went badly in the future.
Right after the project’s completion, many developers don’t feel like going through this exercise, but it’s important to do right away before everyone forgets any lessons that you can learn from the project.
EVERYTHING ALL AT ONCE
Several famous people have said, “Time is nature’s way to keep everything from happening all at once.” Unfortunately, time doesn’t work that way in software engineering. Depending on how big the project is and how the tasks are distributed, many of the basic tasks overlap – and sometimes in big ways.
Suppose you’re building a huge application that’s vital to national security interests. For example, suppose you want to optimize national energy drink ordering, distribution, and consumption. This is a big problem. (Really, it is.) You might have some ideas about how to start, but there are a lot of details that you’ll need to work out to build the best possible solution. You’ll probably need to spend quite a while studying existing operations to develop the user requirements.
You could spend several weeks peppering the customers with questions while the rest of the development team plays Mario Cart and consumes the drinks you’re studying, but that would be inefficient.
A better use of everyone’s time would be to put people to work with as much of the project that is ready to roll at any given moment. Several people can work with the customers to define the requirements. This takes more coordination than having a single person gather requirements, but on big projects it can still save you a lot of time.
After you think you understand some of the requirements, other team members can start working on high-level designs to satisfy them. They’ll probably make more mistakes than they would if you waited until the requirements are finished, but you’ll get things done sooner.
As the project progresses, the focus of work moves down through the basic project tasks. For example, as requirements gathering nears completion, you should finalize the high-level designs, so team members can move on to low-level designs and possibly even some development.
Meanwhile, throughout the entire project, testers can try to shoot holes in things. As parts of the application are finished, they can try different scenarios to make sure the application can handle them.
Depending on the testers’ skills, they can even test things such as the designs and the requirements. Of course, they can’t run the requirements through a compiler to see if the computer can make sense of them. They can, however, look for situations that aren’t covered by the requirements. (“What if a shipment of Quickstart Energy Drink is delayed, but the customer is on a cruise ship and just crossed the International Date Line! Is the shipment still considered late?”)
Sometimes tasks also flow backward. For example, problems during development may discover a problem with the design or even the requirements. The farther back a correction needs to flow, the greater its impact. Remember the earlier example where every problem caused two more? The requirements problem you discovered during development could lead to a whole slew of other undiscovered bugs. In the worst case, testing of “finished” code may reveal fundamental flaws in the early designs and even the requirements.
REQUIREMENT REPAIRS
The first project I worked on was an inventory system for NAVSPECWARGRU (Navy Special Warfare Group, basically the Navy SEALs). The application let you define equipment packages for various activities and then let team members check out whatever was necessary. (Sort of the way a Boy Scouts quartermaster does this. For this campout, you’ll need a tent, bedroll, canteen, cooking gear, and M79 grenade launcher.)
Anyway, while I was building one of the screens, I realized that the requirements specifications and high-level design didn’t include any method for team members to return equipment when they were done with it. In a matter of weeks, the quartermaster’s warehouse would be empty and the barracks would be packed to the rafters with ghillie suits and snorkels!
This was a fairly small project, so it was easy to fix. I told the project manager, he whipped up a design for an inventory return screen, and I built it. That kind of quick correction isn’t possible for every project, particularly not for large ones, but in this case the whole fix took approximately