One of the most important aspects of software design is having well defined requirements.
When I was just out of school, I didn’t fully understand what that statement means. Two and a half years later I probably still don’t, but I am at least to the point where I am beginning to know what I don’t know. As I get more responsibility at work, I’ve been getting more opportunities to practice my writing skills in the form of functional specs and design documents. One of the major components of any good functional spec is a description of the requirements that the software must follow. This means more than just having a bulleted list of vague requirements. A statement like, “The feature will be configured by a single configuration file” doesn’t cut it. Go deeper into what that requirement what really means. How will you parse the contents of the file? What library will be used or will you write one by hand? Is the file stored on disk or in memory? Is a database like MySQL used?
Questions like these are just the basic ones, technical details about how the software will work. They need to be answered before you can begin to write and test your code. Getting the above information down in writing or in pictures is crucial to avoiding costly mistakes which often come at the expense of half-baked designs. I personally work best with words, preferring to use diagrams sparingly. I know others that rely solely on PowerPoint slides. Do what works best for you. Once you’ve covered the above questions, you can implement your software. If your answers are relatively sane, your resulting software should work well.
This is where I am at right now, just thinking about the basic function of the app. Luckily I have some great role models to learn from and am setting a goal to improve my requirement writing. Using the above example of a configuration file, we can get into more detail with our questions. Will it be backwards compatibile? How exactly does that work? Who will be editing the file, and what will they have to do to add/edit a parameter? How easy is it to automate the process? What types of validation are there? What will be visible in the resulting UI?
In contrast to the first questions which deal with the operation of the software, these speak to usability. For software to truly be successful, the designer must not design something which just accomplishes the desired function, but it must do so in the manner which best meets the needs of its users. I recently wrote a document for a new feature which would be used by three different customers. We gathered input from one of the customers- it was designed with them in mind so we knew it would meet their requirements. The second customer was still in the pre-sales phase, so we used our design to influence their expectations. Not surprisingly, the third customer turned out to be more troublesome. In making sure our requirement met the needs of the first two customers, we naively assumed that they would meet the needs of the third. While mostly true, a closer look turned up a few cases about how our software would be used by the third customer. These were the base for more than a few discussions between myself and a the other engineers I work with. We are still ironing out the last of the details, but in the interest of avoiding these troubles in the future, it is important to realize how I ended up in the position- by not being thorough enough with my requirements.
Many of the software design methodologies include ways to create requirements, be it through brainstorming, user stories, or use cases. In the absence of one of these design methodologies, the responsibility officially falls to marketing to define the requirements. Often though, for reasons of time or simplicity, marketing defers to the engineers. When this happens, I must take the extra time to think not just about how the software will work, but how it will be used as well.