Rule 11 – Don’t abuse «include»
A use case contains all the steps (transactions) needed to describe how the actor (our stakeholder) achieves their goal (or doesn’t; depending on the particular conditions of the scenario). Therefore a use case is a stand-alone entity – it encapsulates all the behaviour necessary to describe all the possible scenarios connected to achieving a particular end result. That’s what makes use cases such a powerful analysis tool – they give the system’s requirements context. Use case are also an extremely useful project management tool. By implementing a single use case you can deliver something complete, and of value, to the customer. The system may do nothing else, but at least the customer can solve one problem with it.
Occasionally, two use cases contain a sequence of transactions common to both sets of scenarios. This sequence may not necessarily occur at the same point in each use case (for example, the beginning) but will always be in the same order.
UML provides a mechanism for extracting this common information into its own use case. The mechanism is called the «include» relationship. The semantics of the «include» relationship mean that the base use cases are only complete if they fully, and completely, contain the contents of the included use case.
Included use cases (if you must use them)
This relationship can sometimes be useful, particularly if a sequence of transactions is repeated many times.
However, misunderstanding of «include» tends to lead to a very common abuse: functional decomposition of use cases.
Many use case modellers use the «include» relationship to split a complex use case into a number of smaller, simpler use cases. This can lead, in extreme cases, to an explosion of use cases, with leaf-node use cases capturing trivial functional requirements (for example “Capture button press”).
These trivial use cases often have no meaning to stakeholders, who should be focussed on what they want to happen, rather than how it happens. Also, there is a huge overhead is creating, reviewing and maintaining this vast number of use cases.
I call this approach “Design Cases” to differentiate it from a use case.
Design cases in action
Rather worryingly, several organisations actively promote Design Cases for requirements analysis. The appeal is obvious: functional decomposition is a familiar concept with most developers (and if it isn’t they really shouldn’t be developing software!); and it allows the developer to settle back into the comfortable territory of solving problems (rather than defining them)
Remember, use cases are an analysis tool for understanding the system. A simple, coherent set of use cases, reflecting the usage of the system from the customer’s perspective is far more effective than demonstrating, to the n-th level, how the system will operate. That’s what design verification is for.
My advice is to avoid «include» wherever possible. Prefer repetition of text within the use case description, over trying to identify and extract commonality. In this way each use case remains separate and complete; and there is no temptation to fall into the functional decomposition trap. That way lies madness (or at least analysis paralysis).
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.
He specialises in C++, UML, software modelling, Systems Engineering and process development.