There is a great book called Software Requirements written by Karl Wiegers about, well, software requirements. Itās a must read for every software engineer, in my opinion. Thereās no need for me to repeat what it says, but there are a few very simple and very typical mistakes we keep making in our specs. I see them in our documents again and again, which is why Iāve decided to summarize them. So here they are, the ten most critical and typical of them, from the point of view of a programmer reading a specification document.
Chapter 4.3 of a famous standard IEEE 830-1998 says that a good specification should be correct, unambiguous, complete, consistent, ranked, verifiable, modifiable, and traceable. Eight qualities in total. Then, the standard explains them one by one in pretty simple English. But do we have time to read those boring standards? They are for university professors and certification boards. We are practitioners, for goodness sake! ⦠Hold on, Iām joking.
No matter how small the project is and how practical we are, there is always a document that explains what needs to be done, and it may be called the āsoftware requirements specification,ā or āspecification,ā or just āspec.ā Of course, there is a lot of space for creativity, but weāre engineers, not artists. We must follow rules and standards, mostly because they make our communication easier.
Now, Iām getting to my point. The specs I usually see violate pretty much all eight principles mentioned earlier. Below is a summary of how exactly they do it. By the way, all examples are taken from real documents in real commercial software projects.
No Glossary or a Messy One
How about this:
UUID is set incrementally to make sure there
are no two users with the same account number.
What is the difference between UUID and account number? Is it the same thing? It seems so, right? Or maybe they are different ⦠it would be great to know what UUID stands for. Is it āunique user IDā or maybe āunified user identity descriptor?ā I have no idea. Iām lost, and I want to find the author of this text and do something bad to him ⦠or her.
Iāve written already that the worst technical specifications have no glossaries. In my experience, this is the biggest problem in all requirement documents. Itās not prose! Itās not a love letter! Itās technical documentation. We canāt juggle words for the sake of fun. We should not use product specs just to express ourselves. Weāre writing in order to be understood, not to impress the reader. And the rule is the same here as with diagrams: if I donāt understand you, itās your fault.
Here is how that text would look after a proper re-writing:
UUID is user unique ID, a positive 4-bytes integer.
UUID is set incrementally to make sure there
are no two users with the same UUID.
Better now?
Thus, the first and biggest problem is a frivolous use of terms and just words, without having them pre-defined in a glossary.
Questions, Discussions, Suggestions, Opinions
Iāve seen this very recently in a product spec:
I believe that multiple versions of the API
must be supported. What options do we have? I'd
suggest we go with versioned URLs. Feel free to
post your thoughts here.
Yes, this text exists verbatim in a requirements document. First, the author expresses his personal opinion about the subject. Then, the author asks me what possible options are out there. Then, he suggests I consider something, and after that, he invites me for a talk.
Impressive, right? Obviously, the author has a very creative personality. But we should keep this person as far away from project documentation as possible. This is not what a requirements document appreciates. Well, we appreciate creativity, but these four things are strictly prohibited: questions, discussions, suggestions, and opinions.
Specifications canāt have any questions in them. Who are these questions addressed to? Me, a programmer? Am I supposed to implement the software or answer your questions? Iām not interested in brainstorming with you. I expect you, a requirements author, to tell me what needs to be done. Find all your answers before writing the document. Thatās what youāre paid for. If you donāt have the answers, put something like TBD (āto be determinedā) there. But donāt ask questions. Itās annoying.
A requirements document is not a discussion board. As a reader of the spec, I expect to see exactly what needs to be done without any āmaybeā or āwe could do it differently.ā Of course you need to discuss these issues, but do it before documenting it. Do it somewhere else, like in Skype, on Slack, or by email. If you really want to discuss in the document, use Google Docs or Word with version tracking. But when the discussion is over, remove its history from the document. Its presence only confuses me, a programmer.
Thereās no need to format requirements as suggestions either. Just say what needs to be done and how the software has to work without fear of being wrong. Usually, people resort to suggestion when they are afraid to say it straight. Instead of saying āthe app must work on Android 3.x and higher,ā they say āI would suggest making the app compatible with Android 3.x and higher.ā See the difference? In the second sentence, the author is trying to avoid personal responsibility. Heās not saying āexactly Android 3.x;ā heās just suggesting. Donāt be a coward; say it straight. If you make a mistake, weāll correct you.
And, of course, opinions are not appreciated at all. Itās not a letter to a friend; itās a formal document that belongs to the project. In a few months or weeks, you may leave the project, and somebody else will work with your document. The spec is a contract between the project sponsor and project team. The opinion of a document author doesnāt make any difference here. Instead of noting āit seems Java would be fasterā and suggesting āwe should use it,ā say āJava is faster, so we must use it.ā Obviously you put it there because you thought so. But once itās there, we donāt care who it came from and what you thought about this problem. The information would just confuse us more, so skip it. Just facts, no opinions.
Donāt get me wrong, Iām not against creativity. Programmers are not robots, quietly implementing what the document says. But a messy document has nothing to do with creativity. If you want me to create, define the limits of that creativity and let me experiment within them; for example:
Multiple versions of the API must be supported. How exactly
that is done doesn't really matter.
This is how you invite me to be creative. I realize that the user of the product doesnāt really have any justifications or expectations for the versioning mechanisms in the API. Iām free to do whatever I can. Great, Iāll do it my way.
But again, let me reiterate: A specification is not a discussion board.
Mixing Functional and Quality Requirements
This is how it looks:
User must be able to scroll down through
the list of images in the profile smoothly and fast.
Itās a typical mistake in almost every spec Iāve seen. Here, we mix together a functional requirement (āto scroll imagesā) and and a non-functional one (āscrolling is smooth and fastā). Why is it bad? Well, there is no specific reason, but it exhibits a lack of discipline.
Such a requirement is difficult to verify or test, difficult to trace, and difficult to implement. As a programmer, I donāt know what is more important: to scroll or to make sure the scrolling is fast.
Also, it is difficult to modify such a statement. If tomorrow we add another functional requirementāscrolling a list of friends, for exampleāweāll want to require this scrolling to also be smooth and fast. Then, a few days later, weāll want to say that āfastā means less than 10 milliseconds of reaction time. Weāll then have to duplicate this information in two places. See how messy our document may become eventually?
Thus, I would strongly recommend you always document functional and non-functional requirements separately.
Mixing Requirements and Supplementary Docs
This is similar to a previous problem and may look like this:
User can download a PDF report that includes a full
list of transactions. Each transaction has ID,
date, description, account, and full amount. The report
also contains a summary and a link to the user account.
Itās obvious there are two things described in this paragraph. First is that a user can download a PDF report. Second is how this report should look. The first thing is a functional requirement, and the second one must be described in a supplementary document (or appendix).
In general, functional requirements must be very short: āuser downloads,ā āuser saves,ā āclient requests and receives,ā etc. If your text gets any longer, there is something wrong. Try to move part of it to a supplementary document.
Un-measurable Quality Requirements
This is what Iām talking about:
Credit card numbers must be encrypted.
The app should launch in less than 2 seconds.
Each web page must open in less than 500 milliseconds.
User interface must be responsive.
I can find many more examples just by opening requirement specs in many projects Iāve seen over the past few years. They all look the same. And the problem is always the same: It is very difficult to define a truly testable and measurable non-functional requirement.
Yes, itās difficult. Mostly because there are many factors. Take this line, for example: āThe app must launch in 2 seconds.ā On what equipment? With what amount of data in the user profile? What does ālaunchā mean; does it include profile loading time? What if there are launching problems? Do they count? There are a lot of questions like that.
If we answer all of them, the requirement text will fill an entire page. Nobody wants that, but having un-measurable requirements is a greater evil.
Again, itās not easy, but itās necessary. Try to make sure all quality requirements are complete and without ambiguity.
Implementation Instructions
This example illustrates a very common pitfall:
User authenticates via Facebook login button
and we store username, avatar, and email in the
database.
This is micromanagement, and itās something a requirements analyst should never do to a programmer. You shouldnāt tell me how to implement the functionality you desire. You want to give a user the ability to login via Facebook? Say so. Do you really care whether itās going to happen through a button click or somehow else? Do you really care what I store in the database? What if I use files instead of a database? Is that important to you?
I donāt think so. Only in very rare cases will it matter. Most of the time, itās just micromanagement.
The spec should only require what really matters for the business. Everything else is up to us, the programmers. We decide what database to use, where the button will be placed, and what information will be stored in the database.
If you really care about that because there are certain higher-level limitationsāsay so. But again, not as implementation instructions to us programmers, but rather as non-functional requirements like this:
Login page must look like this (screenshot attached).
We must store user email locally for future needs.
The point is that I have nothing against requirements, but Iām strongly against implementation instructions.
Lack of Actor Perspective
The text may look like:
PDF report is generated when required. It is
possible to download a report or save it
in the account.
The problem here is that there is no āactorā involved. This functionality is more or less clear, but itās not clear who is doing all this. Where is the user? It is just a story of something happening somewhere. Thatās not really what programmers need in order to implement it.
The best way to explain functionality is through user stories. And a good user story always has, guess what ⦠a user. It always starts with āthe user ā¦,ā followed by a verb. The user downloads, the user saves, the user clicks, prints, deletes, formats, etc.
Itās not necessary for the user to be a human. It may be a system, a RESTful API client, a database, anything. But always someone. āIt is possible to download ā¦ā is not a user story. Itās possible for who?
Noise
How about this:
Our primary concern is performance and an attractive
user interface.
This is noise. As the reader of this document, Iām neither an investor nor a user. Iām a programmer. I donāt care what your āprimary concernā is in this project. My job is to implement the product so that it matches the specs. If performance is your primary concern, create measurable and testable requirements for me. I will make sure the product satisfies them. If you canāt create a requirement, donāt spam me with this irrelevant information.
I donāt want to share your concerns, your beliefs, or your intentions. Thatās your business. And youāre paid to properly and unambiguously translate all that into testable and measurable requirements. If you canāt do this, itās your problem and your fault. Donāt try to make it mine.
Very often ⦠wait. Very, very often. No. Almost always. Wrong again. Always! Thatās right, spec documents are always full of noise. Some of them have a bit less; some have more. I believe this is a symptom of lazy and unprofessional document authors. In most cases, just lazy.
They donāt want to think and translate their concerns, ideas, thoughts, intentions, and objectives into functional and non-functional requirements. They just put them into the document and hope the programmers will somehow find the right solution. Good programmers should figure out what good performance means, right? Letās just tell them that performance is a concern for us, and they will figure something out.
No! Donāt do that. Do your job right and let programmers do theirs.
And we, programmers, should never accept such documents. We should just reject them and ask requirements authors to re-work and remove noise. I would recommend not even starting to work on a product if there is a lot of noise in its specs.
Will Work, Needs to Work, Must Work
This is yet another very typical mistake:
The API will support JSON and XML. Both formats
must fully support all data items. XML needs to
be validated by XSD schema.
See how messy it sounds? There are three different points of view, and none of them are suitable for a specification document. A spec must describe a product as if it already exists. A spec must sound like a manual, a tutorial, or a reference. This text must be re-written like this:
The API supports JSON and XML. Both formats
fully support all data items. XML is validated
by XSD schema.
See the difference? All the āmust,ā āneed,ā and āwillā words are just adding doubt to the document. For a reader of this spec, āthe API will supportā sounds like āsome time in the future, maybe in the next version, it will support.ā This is not what the author had in mind, right? There should be no doubt, no double meaning, no maybe. The API supports. Thatās it.
I may have forgotten something important, but these issues are so obvious and so annoying ⦠Iām going to use this post as a simple guide for our system analysts. Feel free to share your experience with requirements documents below in the comments.
