There’s a lot of information on the Interweb about how to write a functional specification (FS for short, aka software requirements specification, system specification, product specification.
What I have struggled to find, though, is a good, detailed description of what should actually go in an FS and, in particular, to what level of detail. When asked this question, most BAs answer, “it depends”. Whilst this is true, I think we can improve on it by drawing some clear boundaries around how much detail is allowed, and how much is too much.
Therefore, I present a specification for a functional specification. This my own view and by no means an industry standard, but it works for me.
Let’s be clear. I’m not talking here about a high-level business requirements document or a wish-list of stakeholder needs that may or may not be achievable, and which might even conflict with one another. The document I’m talking about here is the result of the synthesis of those needs into a coherent view of what the system will actually be.
This is the document that you:
- Give to the developers so they know what to build
- Give to the testers so they know what tests to run
- Give to the stakeholders (and get them to approve) so they know what they are getting
Now before you start getting all agile on me…no, I’m not advocating a “throw it over the wall” approach to delivery, and I’ll talk later about the various forms that an FS can take. I just want to be sure we are all talking about the same thing.
Oh, and whilst we’re at it, let’s not call it a document. It might not be a single monolithic text-and-diagrams epic. So let’s just call it a thing, or even better, let’s go plural: things.
I’m also primarily talking about the specification for a system that is to be built. Such a specification is not generally appropriate for a system that is to be bought off the shelf.
A Simple Definition of a Functional Specification
OK, now we have the preamble out of the way, here’s my simple definition of a functional specification:
A Functional Specification of a (computer) system describes the externally-visible behaviour of that system.
That definition might sound a little too simple to be true. Surely there’s more to a system than just what the users see. You’re right, there is. And once I elaborate on my definitions of system and externally-visible behaviour (specifically, I don’t mean just use cases), hopefully you will agree with me that the definition is both complete and precise.
What is a System?
I like to think of a (computer) system as a black box. The black box has two interesting features:
- Interfaces, through which external entities can interact with the system via a series of inputs and outputs. There are two types of external entities – humans and other systems (also collectively referred to as actors of the system), and we need to worry about them both.
- State, which changes as a result of interactions with the actors. Think of this as the system’s memory, in which it remembers (or stores) data - usually implemented as a database.
This simple definition applies to pretty much any system you can think of. All systems have interfaces – without any interfaces, a system is just a rather uninteresting black box! Most systems have (human) user interfaces, but I’ve also worked on plenty of data processing systems with no UIs – they just take data from one system, process it, and pass it on to another system. Some systems do not have any system interfaces, but in these days of end-to-end integration, most systems do. Some very simple systems do not have any state, although most interesting systems do (any system that manages data has state).
One of the most important things to get clear for a system under design is where the system boundary lies, and you can do that easily by identifying its interfaces with the outside world.
Here’s a simple diagram of a system (called eShop), showing its interfaces and the actors that use those interfaces. I call this a context diagram.
Two Key Elements – Functions and Data
Armed with my definition of a system, I can now say that there are two key elements to a functional specification:
- Functions – a description of the interactions between the system and its (human and system) actors
- Data – a description of the state of the system
Once you have described all the functions and all the data (to the right level of detail), you are done – simple as that!
The functions of a system are the interactions that can occur between the system and its actors (through the interfaces). An interaction is a sequence of actor inputs (e.g. a user clicking a mouse button) and system outputs (e.g. displaying some data on the user’s screen). Typically the actor is trying to achieve some objective (log in, search for data, update data, perform a calculation etc.).
I like to use use cases as the main anchor for describing a system’s functions. They are, to my mind, the perfect format for describing interactions between an actor and the system. Laura Brandenberg has a similar love affair with use cases. I’m not going to explain use cases in full (you can click here to read what a use case is), but just in case you’re new to this game, a use case looks something like this:
Use Case 1: User Logs On
- User launches the application
- System prompts user for log-on details (user name and password)
- User enters log-on details and submits them
- System requests user’s log-on details from the external single-sign on directory
- System validates that user’s entered log-on details match those from the directory
- System displays the main menu
Alternative Flow 4a: Incorrect log-on details
- System tells user their log-on has failed
- Return to Main Flow step 2
Alternative Flow 4b: User account locked
- System tells user their account is locked and they should call the helpline
- Return to Main Flow step 2
I’ve omitted some of the key parts of my use case for brevity (e.g. pre- and post-conditions), but you should be able to see that it describes the sequence of inputs (by the user) and outputs (by the system) for a given function. For more info on use cases, read Writing Effective Use Cases by Alistair Cockburn.
Note that the example use case shows interactions both with a human user and also an external system (the single-sign on directory). In order for your use cases to be complete, you need to cover all the interactions through all the interfaces, whether they be human user interfaces or system interfaces, in particular including any “back-end” systems.
It’s also important to understand that use cases do not give a fully-detailed description of the system’s functions. Rather, they are the anchor for the functions, around which the other details can be added. Adriana Beal has some additional comments on this topic in this article.
Functions – How Much Detail is Allowed?
OK, we’ve done the easy part – most people agree that use cases rock, and all I’ve been doing so far is setting the scene. The tricky part is deciding how much detail to include either within the use cases or alongside them.
Here’s my simple answer:
- You are allowed to include full detail of any externally-visible behaviour of the system (including behaviour through system interfaces).
- You are not allowed to include any details on the internal workings of the system.
For example, you are absolutely allowed to include:
- User interface details, right down to the very last pixel and colour shade
- Size and allowable contents of data input fields
- Whether a specific input control is implemented as radio buttons or a drop-down menu
- Exact text of error messages
- Complex business rules and algorithms
- Supported web browsers, client operating systems, screen sizes
Some people will argue that some of the above examples are aspects of the design, and have no place in a requirements specification. There’s a long debate on this topic in my previous article, Requirements Versus Design: It’s All Design. But whatever terminology we use, my experience is that business stakeholders, developers and testers care about these details, and thus they have every right to be included.
In particular, the UX design might be put in a separate document, maybe even produced by a separate person (a UX designer), but in my world-view, it is still part of the externally-visible behaviour and thus part of this “thing” or “things” that I am calling a Functional Specification.
Here are some more things you are allowed to include:
- Exact format of a system log
- Physical format of a system interface
These are slightly more controversial because they are of little interest to our primary business stakeholders, and certainly have a “technical” aspect to them. Nevertheless, they are externally-visible behaviours of the system and are of interest to other stakeholders – a sys admin, or the developers of an external system.
Also allowed are the externally-visible qualities of the system, such as:
- Performance (system response times)
- Volumetrics (number of concurrent users) – current and future
- Concurrency characteristics
- Security characteristics (notoriously difficult to specify effectively)
Such qualities are commonly referred to as non-functional requirements – a term which I really dislike because they are so obviously not non-functional. But the term is pretty-much ubiquitous, so I guess we’re stuck with it.
First of all, let’s resolve a contradiction. I’ve said that the FS should describe the externally-visible behaviour of the system. But the system’s state isn’t externally visible (unless you go poking around in the database), so why include it? The answer is that the system’s state has an important effect on its functions. A function which updates the system’s state has a delayed effect in that it affects any other function which outputs the same data. Functions and data are intertwined and you can’t really describe one without the other.
The usual way to describe system data is in terms of (logical) data entities. An entity is a “thing” of interest (a customer, an address, an order, a product). Entities have attributes (a customer has a first name, a last name, a date of birth etc.). Entities also have relationships with one another (a customer has one or more delivery addresses; a customer has zero or more orders; an order consists of one or more products).
Data – How Much Detail is Allowed?
Here’s what detail I consider to be allowable for data:
- Entity name (so that it can be unambiguously referred to)
- Entity description (explaining what the entity actually is – not always obvious)
- Description (again, not always obvious)
- Type and allowable values, such as:
- String, max 50 characters
- Integer from 0 to 60,000 or blank
- One of Male, Female or Not Specified
- Relationships with other entities:
- Meaning of relationship (e.g. home address, delivery address)
- Multiplicity (one-to-one, one-to-many, zero-or-one-to-one etc.)
Note that the above are logical, rather than physical, definitions. For example, a logical type of “Male, Female or Not Specified” might be implemented as a NUMBER where 1=Male, 2=Female, 0=Not Specified, or it might be implemented as a nullable VARCHAR where “M”=Male, “F”=Female and NULL=Not Specified
- Physical database definitions (table names, column names, column types)
- “Entities” that are actually database tables implementing many-to-many relationships
OK, So How Much Detail Do I Actually Include?
So far, I have stated the level of detail that, in my view, is allowed in an FS. The obvious next question is whether you actually need to write down all that detail. And here’s where we get back to the original answer – “it depends”.
It depends on a variery of factors, such as:
- How much your business stakeholders care about the details
- How much detail your developers want you to give (or alternatively how much you trust the developers to do something sensible in the absence of detail!)
- How much detail your testers want you to give
- Whether you are specifying a new system or enhancements to an existing system – an existing system has existing patterns which can be assumed to apply to enhancements, such as look & feel, data validation rules and so on
- How much you rely on non-written communication
My own experience is that every organisation is different, and for each new assignment I need to find the appropriate level of detail that needs to be written down. Here’s what happens when I get it wrong:
- I give too little detail and the developers makes a “wrong” assumption
- I give too much detail and I spend more time than necessary writing it all down
- I give too little detail and the testers keep coming back for more detail
- I give too much detail and the developers and testers work exactly to spec instead of challenging its deficiencies
However much detail I decide to include in, or omit from, my written specification, I am always clear where the boundary of my accountability lies – I am accountable for all externally-visible behaviour of the system – so if I choose to leave some detail out, I accept that I am giving the developers some free reign, but that it’s my problem if the stakeholder doesn’t like it!
And What Format Do I Write It Down In?
So far I have talked about a thing called a Functional Specification, and you might have assumed that I am thinking of a single, “traditonal” text-and-diagrams document (such as might be authored in Microsoft Word). But of course there are many alternatives, especially when you start looking at agile approaches. Here are a few options:
- A formal requirements management tool, such as Rational Rose
- Use cases in a spreadsheet combined with an HTML prototype (see my previous article, An Agile Functional Specification)
- Use cases, data and business rules in one document, UX design in a separate document (perhaps produced by a separate UX designer)
- User stories and acceptance criteria scribbled on index cards (as per XP)
- A graphical format using a drawing tool such as Microsoft Visio (something I am experimenting with at the moment)
A Curveball or Two
So far I have said that a functional specification should only describe externally-visible behaviour. I have already made a minor exception to this rule by including the system state, which is kind of internal.
There are some other exceptions, and they apply in cases where it is important constrain the (internal/technical) design of the system. Here are a couple of common examples:
- For a software product, defining the platform(s) on to which it must be possible to deploy the software (e.g. “compatible with Windows Vista and Windows 8 with 2GB of RAM”)
- Extensibility requirements – how easy it must be to extend or alter the system. This is a whole topic in itself.
I try to treat these very much as exceptions to the rule and only include them where they are absolutely necessary.
To summarise then:
- If a system is a black box with (human and system) actors interacting with it through interfaces, then…
- A functional specification describes the externally-visible behaviour of the system
- There are two key elements – functions and data
- Functions are commonly anchored around use cases
- The theoretical scope includes all externally-visible behaviour, right down to the last pixel…
- But as to how much detail you actually include…it depends…
- And you are still accountable for all the details that you omit