How to Use Include and Extend Without Overcomplicating
To master include vs extend UML relationships, distinguish between mandatory reusable behavior and optional conditional flows. Use include to eliminate redundant code in common steps like authentication. Use extend only for optional logic that activates under specific conditions. Apply these rules strictly to prevent your diagrams from becoming tangled messes that confuse stakeholders.
Understanding the Core Distinction in include vs extend UML
Business analysts often struggle to draw clean diagrams because they over-engineer the relationships between use cases. The primary confusion usually stems from misapplying the include and extend relationships. These two constructs serve fundamentally different purposes in the Unified Modeling Language (UML).
The include relationship represents mandatory behavior. It means that if you use Case A, you must also execute Case B. There is no decision point; it is a requirement. Conversely, the extend relationship represents optional or conditional behavior. It means Case B might execute, but only if a specific condition is met.
Confusing these two leads to bloated diagrams. Analysts frequently use include when they should use extend, or vice versa, creating models that are difficult to understand and maintain. We must clarify exactly when to apply each relationship in the include vs extend UML debate.
Define the Scope of Common Behavior
The first step in mastering these relationships is defining the scope of the behavior you are modeling. Ask yourself: “Is this part of the main success scenario, or is it an exception?” If the behavior is a mandatory step required for the use case to function, it belongs in the main flow or uses include.
For example, a use case named “Place Order” usually requires “Authenticate User.” You cannot place an order without authentication. In this scenario, “Authenticate User” is a dependency that is always invoked.
If you factor this out into a separate use case and link it with an include relationship, you are essentially saying: “Place Order” pulls in “Authenticate User” every single time. This keeps your main scenario focused on the high-level flow without getting bogged down in repetitive details.
Identify Conditional Logic for Extension
The second step involves identifying behavior that is not mandatory. Ask: “Does this step happen only sometimes? Does it depend on a guard condition?” If the answer is yes, you are looking at an extend relationship.
Consider the “Place Order” use case again. What if a user wants to add an item from a wishlist? This action is optional. The main flow does not require it, but it is a valid alternative path. This is the perfect candidate for an extend relationship.
In an extend relationship, the extending use case (e.g., “Add Wishlist Item”) specifies a set of points where it can be inserted into the base use case. The base use case remains valid without the extension, but the extension adds value under specific circumstances.
Deep Dive: The Include Relationship
The include relationship is the tool for breaking down complexity. It allows you to create a “template” for common behavior that multiple use cases might share. This is crucial for maintaining consistency in large system models.
When to Force a Split Using Include
You should use an include relationship when a sequence of steps appears in multiple different use cases. If you find yourself copying and pasting the same steps into three different use cases, that is a red flag. You need to extract that behavior into a base use case.
Common examples of extractable behavior include:
- Authentication and Authorization
- Logging out
- Generating a standard report PDF
- Validating a credit card format
By extracting these into separate use cases, you reduce the cognitive load on the reader. The main use case diagram remains high-level, showing the big picture without unnecessary detail.
Structuring the Flow Correctly
When structuring an include, the flow is strictly linear. The base use case calls the included use case, executes it, and then resumes its own flow. The included use case cannot branch off or return data arbitrarily; it must execute to completion.
The arrow of dependency points from the base use case (the caller) to the included use case (the callee). This visual cue is critical for interpreting the model correctly.
Do not use include to model alternative flows that are mutually exclusive. If a system can do “A” or “B,” but not both, do not use include. Use separate branches or extend relationships instead.
Deep Dive: The Extend Relationship
The extend relationship offers flexibility. It is the primary mechanism for modeling optional features, error handling, or special cases that might arise during the execution of a main scenario.
The Role of Guard Conditions
A defining characteristic of the extend relationship is the guard condition. This is a specific requirement or state that must be true for the extension to trigger. Without a clear guard condition, the extend relationship becomes ambiguous.
For instance, in a banking system, the “Transfer Money” use case might extend to “Notify Fraud Department.” This extension only happens if the transfer amount exceeds a certain threshold. The guard condition protects the user from unnecessary alerts.
If you omit the guard condition, the diagram becomes difficult to read because the reader does not know why the extension occurs. Always document the trigger explicitly in the diagram or its accompanying text.
Placement of Extension Points
You must explicitly define extension points in the base use case. These are specific locations in the main flow where the system is prepared to hand control over to an extension.
Analysts often struggle with where to place these points. The rule is simple: place the extension point at the logical boundary where an optional step would naturally occur.
- Before a step that might be skipped.
- After a decision point that leads to a special case.
- At the end of a transaction for post-processing tasks.
The arrow for the extend relationship points from the extending use case to the base use case. This reverses the direction of the include relationship, highlighting that the extension is supplementary.
Common Pitfalls in include vs extend UML
Even experienced analysts make mistakes when modeling complex systems. These errors often stem from trying to force relationships into the diagram where they do not belong.
Overusing Include for Everything
A common mistake is to extract every step into a separate use case and link them with include. This results in a “use case spaghetti” where the main flow is just a long list of references to other boxes.
This approach kills the readability of the diagram. If a use case includes ten other use cases, the user must navigate through many screens to understand a single transaction.
Reserve include for significant chunks of behavior that are shared across many use cases. If a step is unique to one use case, keep it in the narrative flow or the use case description. Do not create a separate use case for it.
Ignoring the Direction of the Arrow
Confusion often arises regarding the direction of the arrows in the diagram. The arrow direction indicates the dependency, not the flow of execution.
- Include: The base use case calls the included one. Arrow points to the included use case.
- Extend: The extending use case adds to the base. Arrow points to the base use case.
Always double-check your arrows. Reversing them can completely change the semantics of your model and mislead developers and stakeholders.
Decision Guide for Analysts
Use the following checklist to decide between include, extend, or simple inclusion in the main flow. This guide simplifies the include vs extend UML decision process.
-
Is the behavior mandatory?
If yes, and it is repetitive across multiple use cases, use Include. If it is unique to this use case, write it in the main flow. -
Is the behavior optional or conditional?
If yes, use Extend. Ensure you specify the guard condition clearly. -
Is this behavior a side effect or error handling?
Use Extend for error handling and exceptional flows that do not prevent the main use case from succeeding. -
Does this create a loop?
Check for circular dependencies. If Use Case A includes Use Case B, and B includes A, you have a design error. Break the cycle by factoring out the common behavior into a third, independent use case.
Visual Examples of Correct vs Incorrect Usage
Consider a “Purchase Product” scenario.
Incorrect: You create an “Include” relationship for “Select Payment Method” simply because you have many payment options. This implies the user must choose a payment method every single time in a way that feels mandatory and rigid, potentially confusing the flow.
Correct: If “Select Payment Method” is a standard step required for all purchases, it is a valid candidate for Include if it appears in many other use cases like “Return Goods” or “Cancel Order.”
Alternative Correct: If “Select Payment Method” depends on the user’s preference or the type of product, use Extend. The main flow is “Purchase Product,” and the extension is “Select Credit Card Payment” or “Select Cash Payment.”
Refining the Use Case Model
A clean use case diagram is the foundation of good requirements engineering. By correctly applying include and extend relationships, you create a model that is both comprehensive and easy to understand.
Remember that the goal is clarity, not complexity. If a diagram requires a legend to explain the arrows, you have likely over-complicated the model.
Iterate on your diagrams. Ask stakeholders to walk through the flow with you. If they get confused by the arrows or the relationships, simplify the diagram. Remove unnecessary includes or consolidate extensions.
Use the diagram to drive the conversation, not to replace it. The visual model should support the detailed requirements in the use case descriptions, not replace them.
Maintaining Consistency Across Teams
In large organizations, consistency is key. Ensure all analysts use the same notation for include vs extend UML. Define a standard naming convention for extension points and guard conditions.
Review models regularly to ensure that relationships have not drifted from their original intent. Technical debt accumulates in models just as it does in code. Refactor your diagrams as the system evolves.
Key Takeaways
- Include is for mandatory, reusable behavior that every instance of a use case must perform.
- Extend is for optional, conditional behavior that only happens under specific circumstances.
- Use guard conditions explicitly in extend relationships to clarify when the extension triggers.
- Avoid overusing include relationships; keep the main flow high-level and readable.
- Ensure arrow direction correctly reflects the dependency (Base points to Include; Extension points to Base).