Loading content...
So far, we've modeled actors connecting to use cases with simple association lines. But real systems have more complex relationships between their functionalities. Some use cases always require other use cases to complete. Some use cases optionally extend others under certain conditions. These dependencies are not mere implementation details—they reveal fundamental architectural relationships.
The «include» and «extend» relationships in UML provide the vocabulary to express these dependencies. Mastered correctly, they enable powerful modeling of shared behavior, optional functionality, and use case decomposition. Misused, they create confusing diagrams that obscure rather than clarify requirements.
By the end of this page, you will understand the precise semantics of «include» and «extend» relationships, when to use each, and how to avoid common modeling mistakes. You'll learn to recognize patterns where these relationships add clarity versus patterns where they add unnecessary complexity.
When modeling use cases, you'll quickly encounter situations where functionalities overlap or depend on each other. Without a vocabulary for these relationships, you face unpleasant choices:
Option 1: Duplicate Description Write the same steps in multiple use case specifications. When something changes, you must update multiple places—inevitably leading to inconsistencies.
Option 2: Vague References Write 'see other use case' without formal connection. This creates implicit dependencies that are easy to miss and hard to trace.
Option 3: Monolithic Use Cases Combine related functionality into huge use cases. These become unmaintainable and obscure the true structure of requirements.
Use case relationships solve these problems by providing explicit, visual connections between use cases that have dependencies. They make shared behavior visible and optional extensions clear.
The Three Relationship Types:
UML defines three relationship types between use cases:
| Relationship | Symbol | Direction | Purpose |
|---|---|---|---|
| «include» | Dashed arrow with «include» label | From base use case to included use case | Base always uses the included behavior |
| «extend» | Dashed arrow with «extend» label | From extending use case to base use case | Extension optionally adds to base behavior |
| Generalization | Solid line with hollow triangle | From specialized use case to general use case | Specialized use case inherits and modifies |
This page focuses on «include» and «extend», as they are the most commonly used and most frequently misunderstood.
The arrow direction for «include» and «extend» is opposite to what many people expect. «Include» points FROM the base TO the included. «Extend» points FROM the extension TO the base. Getting this wrong reverses the semantic meaning. Pay attention to the arrow direction in all examples.
The «include» relationship indicates that a base use case always incorporates the behavior of another use case. Think of it as mandatory delegation—every time the base use case executes, it necessarily executes the included use case.
Formal Definition:
An «include» relationship is a directed dependency from a base use case to an included use case. The base use case is incomplete without the behavior of the included use case.
Key Characteristics:
In This Example:
When to Use «include»:
| Scenario | Example |
|---|---|
| Shared precondition behavior | Multiple use cases require authentication |
| Common subprocess | Logging, auditing, or notification across use cases |
| Reusable functional units | Payment processing included by Purchase, Subscribe, Renew |
| Extracted complexity | A complex step that deserves separate documentation |
While «include» resembles subroutine calls in programming, included use cases should still represent meaningful, potentially standalone functionality. 'Authenticate User' is valuable on its own (an admin might use it). If the 'included' behavior only makes sense as part of other use cases, reconsider whether it should be a separate use case.
The Included Use Case Should:
How «include» Appears in Use Case Specifications:
In the base use case specification, you reference the included use case at the point where its behavior occurs:
Use Case: Transfer Funds
Main Success Scenario:
1. Customer initiates transfer
2. System includes 'Authenticate User'
3. Customer enters transfer details
4. System validates recipient account
5. System processes transfer
6. System confirms completion
The included use case has its own complete specification.
The «extend» relationship indicates that an extending use case may optionally add behavior to a base use case under certain conditions. Think of it as a plugin or hook—the base use case works without it, but when specific conditions are met, the extension activates.
Formal Definition:
An «extend» relationship is a directed dependency from an extending use case to a base use case. The extending use case specifies a condition under which it inserts its behavior at a defined extension point in the base use case.
Key Characteristics:
In This Example:
When to Use «extend»:
| Scenario | Example |
|---|---|
| Optional features | Gift wrapping extends checkout |
| Conditional behavior | Fraud check extends high-value orders |
| Exception handling | Escalate to manager extends disputed transaction |
| Upgrades/premiums | Premium support extends standard support (for premium users) |
Extension Points:
For «extend» relationships, the base use case should define extension points—named locations where extensions can plug in. This makes the relationship explicit and controlled.
Use Case: Place Order
Extension Points:
- apply_promotions: After items are added, before total calculated
- add_options: After total calculated, before payment
Main Success Scenario:
1. Customer adds items to cart
2. Extension point: apply_promotions
3. System calculates total
4. Extension point: add_options
5. Customer provides payment
6. System processes order
The extending use case references which extension point it uses:
Use Case: Apply Discount Code
Extends: Place Order at apply_promotions
Condition: Customer enters a discount code
Main Success Scenario:
1. Customer enters discount code
2. System validates code
3. System applies discount to eligible items
A well-designed base use case defines extension points like a plugin system defines hooks. The base works without plugins, but plugins can enhance it at predefined points. This mindset helps you design extensible systems that accommodate future requirements without modifying base functionality.
The distinction between «include» and «extend» confuses even experienced modelers. The key differentiators are mandatory vs optional and who knows about whom.
| Aspect | «include» | «extend» |
|---|---|---|
| Execution | Always executes | Conditionally executes |
| Base completeness | Base is incomplete without included | Base is complete without extension |
| Knowledge direction | Base knows about included | Extension knows about base; base doesn't know about extensions |
| Arrow direction | From base to included | From extension to base |
| Analogy | Subroutine call | Plugin/hook |
| Question answered | 'What always happens as part of this?' | 'What might optionally happen during this?' |
| Modification impact | Changing included affects all bases | Adding extension doesn't change base |
The Knowledge Direction is Key:
This is the most important distinction and the easiest to get wrong:
«include»: The base use case explicitly references the included use case. The base knows it needs the included behavior. Dependency flows from base to included.
«extend»: The extending use case references the base use case, but the base doesn't need to know about extensions. The base is designed with extension points, but doesn't reference specific extensions. Dependency flows from extension to base.
Why This Matters Architecturally:
With «include», adding a new base that includes an existing use case doesn't change the included use case. But the new base explicitly depends on the included.
With «extend», adding a new extension doesn't change the base at all. The base remains blissfully unaware of its extensions. This enables open/closed principle—the base is closed for modification but open for extension.
Ask: 'Can the base use case complete successfully without this behavior?' If YES, use «extend». If NO, use «include». Additionally: 'Does the base need to explicitly invoke this behavior, or does it just need to allow it?' If explicit invocation, use «include». If allowing at defined points, use «extend».
«include» and «extend» are among the most misused UML constructs. Understanding common mistakes helps you avoid them.
The Functional Decomposition Trap in Detail:
This is the most common mistake. Consider this misuse:
Bad: Login «includes» Enter Username
Login «includes» Enter Password
Login «includes» Validate Credentials
Login «includes» Create Session
This treats «include» like program structure—breaking login into sequential steps. But these aren't separate use cases; they're steps within 'Login'. No other use case reuses 'Enter Username' alone.
Correct approach:
Login is one use case with steps in its specification:
1. User enters username
2. User enters password
3. System validates credentials
4. System creates session
Better «include» example:
- Login «includes» Authenticate User
- Password Reset «includes» Authenticate User
- View Profile «includes» Authenticate User
Now 'Authenticate User' is genuinely shared behavior—multiple use cases truly need it.
Before creating an «include» relationship, ask: 'Would this included behavior be used by at least two different base use cases?' If not, the behavior probably belongs inside the single use case that needs it, not as a separate included use case.
While «include» and «extend» are the most common use case relationships, UML also supports generalization between use cases. This models inheritance-like relationships where specialized use cases share structure with a general use case.
When Use Case Generalization Applies:
Generalization is appropriate when you have multiple use cases that share a common structure but differ in specific details:
How Generalization Works:
Generalization vs «include»:
| Aspect | Generalization | «include» |
|---|---|---|
| Relationship type | IS-A (specialized is a kind of general) | HAS-A (base has the included behavior) |
| Behavior sharing | Specialized inherits and may override | Base always uses included exactly as defined |
| Actor interaction | Typically with specialized use cases | With the base use case |
| Common use | Variations of the same goal | Reusable sub-functionality |
Use case generalization is less common than «include» and «extend». It's most useful when you have genuinely polymorphic behaviors—multiple ways to achieve the same goal with significantly different steps. If the variations are minor, document them as alternative flows in a single use case rather than creating a generalization hierarchy.
Let's model a comprehensive example that uses all relationship types appropriately. Consider an online banking system with various transaction capabilities.
Identified Use Cases and Relationships:
| Use Case | Relationship | Related Use Case | Justification |
|---|---|---|---|
| Transfer Funds | «includes» | Authenticate User | Every transfer requires authentication |
| Pay Bill | «includes» | Authenticate User | Every bill payment requires authentication |
| View Balance | «includes» | Authenticate User | Every balance check requires authentication |
| Transfer Funds | «includes» | Select Account | Must choose source and destination accounts |
| Send Large Transfer | «extends» | Transfer Funds | Additional verification for transfers over $10,000 |
| Add Payee | «extends» | Transfer Funds | Optional during first transfer to new recipient |
| Pay with Credit Card | generalizes | Make Payment | Specific payment method inheriting payment structure |
| Pay with Bank Transfer | generalizes | Make Payment | Alternative payment method |
Analysis of This Model:
«include» Relationships (Mandatory Shared Behavior):
«extend» Relationships (Optional Enhancements):
Generalization (Specialized Variants):
For each relationship, ask: (1) For «include»: 'Is this always required, and is it reused?' (2) For «extend»: 'Is the base complete without this? Is this truly optional/conditional?' (3) For generalization: 'Are these truly different ways to achieve the same goal?' If answers don't match, reconsider the relationship.
We've explored the relationships that connect use cases to each other. Let's consolidate the key insights:
What's Next:
Now that we understand how to model actors, use cases, boundaries, and relationships, we need to see how these concepts come together for requirement gathering. The final page explores how use case diagrams function as living requirements documents—how to create them collaboratively with stakeholders, evolve them as understanding grows, and ensure they drive effective software development.
You now understand «include», «extend», and generalization relationships between use cases. You can model mandatory shared behavior, optional extensions, and specialized variants. You know the common anti-patterns to avoid and how to validate your relationship choices. Next, we'll explore how use case diagrams drive requirements gathering.