Software design begins when one knows what one is supposed to accomplish with software. There is more than one way to do it, but there is no way to do it until you know what you will be designing.

It is common for a software design to include:
  • A data model (any number of objects)
  • A process model (one or more processes)
  • A description of the major components of the system and their behavior as well as the business rules that influence that behavior
  • A description of how the major components interact to deliver the service or functionality called for in the functional specifications
  • A description of life cycles of the major objects in the system: how they get created, managed over time, and what happens at their end-of-life
  • How the system integrates with other systems
  • How the software is configured
  • A description of the administration faciities and what can be done with them
  • A description of permissions or access restrictions or privileges for different classes of users or roles
  • A description of how multiuser/simultaneous use is handed
  • APIs for internal use when building applications within the system
  • APIs for external use when integrating with other systems
  • A description of how notifications and/or events are to be handled (emailed, logged, displayed, etc.)

Most of these deserve to be their own section of the software design. Some products or services won’t need every last one of these.

Designing software before it is written feels harder than just diving in and coding. But, by contrast, completing a software design is far easier than completing a software project that was implemented without design. The first 90% of the work takes the first 90% of the time. The remaining 10% of the project takes the other 90% of the time. Finishing poorly planned projects is elusive and problematic, because the problems caused by inadequate design tend to show up only at the end of the project.

Imagine building bridge across a river, starting from each side. Would you say the project suffered a sudden and unexpected failure if the two sides don’t align? No. The project was poorly planned if the two sides don’t align. It just wasn’t apparent until the end.

This is the essence of why software design is required: it is the only way to have visibility into the future of the project.

If you are building a one-room shack, and you have the materials, you can pretty much do it any way you want. You can run the plumbing on the outside of the building. You can cut a window out of a wall, etc. But, would you build house that way? Maybe… how about an apartment complex? A sky scraper? A city?

Software projects can range in scale from a shack to a city. An adhoc approach may work for smaller projects, but it is inadequate for larger ones.

It comes down to risk. While it is possible that an engineer might sit down and create exactly the right system without designing it first, it is unlikely to say the least. And, anyone capable of such a feat would probably be the first to agree that such an approach is the most risky way to develop software. Chances are that if you think a brilliant engineer succeeds without a software design phase, you are mistaken and the engineer is merely not sharing their design process with you. Even if they are capable of designing in their head, they still have a design in mind. The danger comes when people who lack that degree of software design experience try to emulate it. How could they?

Unless those with software design experience provide examples of good software design for others, how can it be learned?
The hard way. Those with experience might not need the documentation they produce nearly as much as those around them, so it is tempting for an expert to simply do the work without documenting it. This is not a sign of maturity or excellence in my opinion. Yet, it is a sure sign of expediency necessary to survive in an environment where design is presumed to be a problem only for the programmer and its cost is solely shouldered by the programmer. What can be done to improve this state of affairs?
  • Make essential requirements a required deliverable
  • Make the functional spec a required deliverable
  • Make each of the elements of the software design a required deliverable
  • Insist upon peer-review of requirements, functional specs and software designs
  • Do not allow development on a project to begin on any portion of the project that is not covered by requirements and functional specifications.

It is ok to break a large project up along its orthogonal parts and even to design them consecutively, but it is probably NOT ok to proceed without an understanding of the essential requirements or one may find that even perfectly engineered systems that met all their own requirements still cannot be of use when incorporated into the complete system.

When choosing a peer review team, I like to follow Hewlett Packard’s Document Review suggestion, which happens also to be how to choose a wedding gift:
Something old, something new, something borrowed, something blue.

What it means for peer review is this:
  • Something old: someone with a lot of experience with the project
  • Something new: someone new to the project if not the company
  • Something borrowed: someone from a different department, but who has a lot of experience
  • Something blue: someone “out of the blue” -- someone who is completely unrelated to the project

The point of such diversity is to collect the widest possible set of perspectives and interests without involving a huge number of people and driving review costs through the roof.

If you think that 1 hour of time from four people is too much to review a functional specification and provide comments, you must believe that the mistakes caused by lack of review will take less than four hours to solve once they occur. I do not believe that is the case, so I favor peer review as a
good investment.