Back to table of contents

Credit: public domain


Andrew J. Ko

Once you have a problem, a solution, and a design specification, it's entirely reasonable to start thinking about code. What libraries should we use? What platform is best? Who will build what? After all, there's no better way to test the feasibility of an idea than to build it, deploy it, and find out if it works. Right?

It depends. This mentality towards product design works fine with building and deploying something is cheap and getting feedback has no consequences. Simple consumer applications often benefit from this simplicity, especially early stage ones, because there's little to lose. But what if a beta isn't cheap to build? What if your product only has one shot at adoption? What if you're building something for a client and they want to define success? Worse yet, what if your product could kill people if it's not built properly? In these settings, software teams take an approach of translating a design into a specific explicit set of goals that must be satisfied in order for the implementation to be complete. We call these goals requirements and we call this process of requirements engineering (Sommerville & Sawyer 1997).

The relationship between requirements and design is somewhat murky. In design disciplines, designers tend to express requirements in the form of prototypes and mockups. These implicitly state requirements, because they suggest what the software is supposed to do without saying it directly. For some types of requirements, they actually imply nothing. For example, how responsive should a web page be to be? A prototype doesn't really say; an explicit requirement of an average page load time of less than 1 second is quite explicit. Requirements can therefore be thought of more like an architect's blueprint: they provide explicit definitions and scaffolding of project success.

And yet, like design, requirements come from the world and the people in it and not from software (Jackson 2001). Therefore, the methods that people use to do requirements engineering are quite similar to design methods. Requirements engineers do interviews, conduct user research, create prototypes, and iteratively converge toward requirements (Lamsweerd 2008). The big difference between design and requirements engineering is that requirements engineers take the process one step further than designers, enumerating in detail every property that the software must satisfy. They sometimes even use formal methods to specify requirements, allowing them to automatically identify conflicting requirements, so they don't end up proposing a design that can't possibly exist. Some even use systems to make requirements "traceable", meaning the high level requirement can be linked directly to the code that meets that requirement (Mader & Egyed 2015). All of this formality has tradeoffs: not only does it take more time to be so precise, but it can negatively effect creativity in concept generation as well (Mohanani et al. 2014).

Expressing requirements in natural language can mitigate these effects, at the expense of precision. They just have to be complete, precise, non-conflicting, and verifiable. For example, consider a design for a simple to do list application. It's requirements might be something like the following:

Let's review these requirements against the criteria for good requirements that I listed above:

Now, the flaws above don't make the requirements "wrong". They just make them "less good." The more complete, precise, non-conflicting, and testable your requirements are, the easier it is to anticipate risk, estimate work, and evaluate progress, since requirements essentially give you a to do list for building and testing your code.

Next chapter: Architecture

Further reading

Jackson, Michael (2001). Problem Frames. Addison-Wesley.

Axel van Lamsweerde. 2008. Requirements engineering: from craft to discipline. In Proceedings of the 16th ACM SIGSOFT International Symposium on Foundations of software engineering (SIGSOFT '08/FSE-16). ACM, New York, NY, USA, 238-249.

Mäder, P., & Egyed, A. (2015). Do developers benefit from requirements traceability when evolving and maintaining a software system? Empirical Software Engineering, 20(2), 413-441.

Rahul Mohanani, Paul Ralph, and Ben Shreeve. 2014. Requirements fixation. In Proceedings of the 36th International Conference on Software Engineering (ICSE 2014). ACM, New York, NY, USA, 895-906.

Sommerville, I., & Sawyer, P. (1997). Requirements engineering: a good practice guide. John Wiley & Sons, Inc.