First, a brief example:
Imagine that you have been hired to build a digital version of a classic board game. You spend days finding the right graphical assets. You spend even longer researching different AI methods for the CPU opponent. You read rule book after rule book, making sure that even the most random corner case of your gameplay is covered.
After months of hard work, you finally show your finished game to the client: Chess Master 3000. You beam with pride as the boot it up for the first time.
The client… looks less than enthusiastic. “Where is the game you built for me?” they ask.
You blink at them, confused. “It’s… right there? Don’t you like it?”
The client sits back and takes a deep breath. “Well… it’s a very nice chess game. But I asked for checkers.”
Okay, I realize that this is a bit overdramatic. But still, while you might not build a completely different program than what the client wants, it is entirely possible to get some aspects wrong. Perhaps you aren’t familiar with their domain knowledge and you implemented something incorrectly because you simply didn’t know that something wasn’t allowed, like programming SIS to allow a student to take two classes at the same time.
Requirements engineering is the subfield of software engineering completely focused on making sure that we can turn the plain-language explanation of what a software need is into something that is actionable by a development team. The process is typically broken into two broad categories:
Before we get into elicitation vs. specification, let’s define some different types of requirements.
A functional requirement is a statement of what the system should specifically “do.” It represents a feature of the system that is:
These are often expressed in a form kind of like this:
The system shall //do something// because //important reasons// for //these types of users//
So anything like the following for a to-do list app:
The system shall allow a user to add a new to-do list item by tapping the plus icon on the home screen.
The system shall mark an item as “Completed” if the user taps on the checkbox beside the item.
The system shall allow the user to sort to-do items by their due date, with the earliest date first.
A non-fuctional requirement (or NFR for short) is a statement regarding an overall condition of the system and is not directly tied to a single function or feature. NFRs often fall under one of these categories:
No one feature in a system is responsible for it’s security, for example. It is an aspect of the system that has to be taken into consideration with every feature. Thus there has to be some sort of centralized, concerted effort among all developers to ensure that NFRs are completed
A constraint is a limitation put on the “solution set” of possible systems that could be developed. For example, a client may say that the software you build for them must run on iOS. If this is the case, they have created an implementation limitation on all the possible ways that you could build something. Another example could be that you have to utilize some particular API or third-party service due to contractual obligations. These are all constraints and not functional or non-functional requirements.