The goal of this multi-part series is to get back to basics and help make modeling more practical and useful for you. The Unified Modeling Language (UML) has been around formally for more than a decade. The UML superstructure specification is more than 700 pages long and quite complex. Many texts have been written to try to explain what it all means. And yet many modelers still struggle with the UML, often falling into the same pitfalls as their colleagues. These articles will approach this topic from a pragmatic, practical (instead of theoretical) point of view. Other articles in the series include "Useful UML Modeling: The Goldilocks Conundrum," "Don't Rewrite the UML"
, and "Ten Misunderstandings About UML Modeling
The sword is one of the most ubiquitous crafted weapons across civilizations worldwide. They come in many different shapes, sizes, and materials. An attribute they all have in common is a sharp edge. Some multiply their offensive capability by being sharpened on both edges, i.e., the double-edged sword. These are more deadly because they can cut both ways.
In common usage, the phrase "cuts both ways" often refers to something that can negatively affect all parties involved or something that has both advantages and disadvantages. Who would have expected that the innocent use case would introduce a double-edged sword into the UML? These two useful, but dangerous edges are the <<include>> and <<extend>> relationships.
The include relationship is used to show that certain behavior (specified by the "included" use case) is contained by the "including" use case. The extend relationship indicates that a use case may be "extended" by the behavior specified in another (i.e. the "extending") use case. A simple example is shown in Figure 1.
Include and Extend.
This use case diagram is saying that when the Driver (actor) takes a trip, fueling the vehicle is part of taking the trip (included use cases are mandatory behavior). However, the Driver may or may not take photos and/or eat a meal (extending used cases are optional behavior) as part of taking a trip.
So where is the danger? Recall the adage: "When all you have is a hammer, every problem looks like a nail". In this case, when all you have is a sword, every problem looks like the answer is to slice further.
Consider the <<extend>> relationship. It is intended to add behavior to a use case (e.g. adding a feature or a variation point in a product line). But some people use it to slice every use case into its individual flows, even down to the level of making every conditional path (e.g. IF statements) of a flow its own use case. This quite often leads to people performing a functional decomposition of use cases. This is so common it is acknowledged as a well known industry anti-pattern. When use cases are hacked to pieces in this manner, understanding what value the use case is to provide is severed, architectural considerations are missing, and consideration for non-functional requirements is lost, among other problems.
The <<include>> relationship is intended to capture reusable behavior. Unfortunately, the UML specification draws an analogy between an <<include>> and a subroutine call. The confusion is that a subroutine is an artifact of software architecture, whereas a use case is a requirements artifact. So some people take that analogy too far and use <<include>> relationships to carve up a use case into the equivalent of a software "call tree."
I have even seen a case where a person slashed every use case into its (assumed) operations and made each operation its own use case! Use case diagrams are not intended to show the structure of the software. Use cases do not "call" other use cases. And why would you try to prematurely specify the detailed software architecture when you are still discovering what the requirements (i.e. use cases) are?
So be careful. Avoid premature use, overuse, and misuse of the <<include>> and <<extend>> relationships. And remember what Mom always warned you -- don't run with sharp things.