How does history state work in UML?
A history state in a UML state machine acts as a “bookmark” within a composite state. When a state machine enters a region with a history vertex, it restores the previous configuration exactly as it existed before the region was left. This eliminates the need to return to default start points, ensuring that complex workflows resume precisely where the process was interrupted.
Core Concept: The State Machine Bookmark
Definition and Purpose
The history state is a specialized UML pseudostate designed to preserve state information. It serves as a memory mechanism for composite states. Without this feature, every time a machine re-enters a complex state, it would reset to the initial sub-state, losing all context.
When a transition leads out of a composite state and eventually leads back, the history state directs the machine. It remembers the last active sub-state. This is critical for systems where the current context matters more than the entry point.
In the context of history state UML modeling, this feature reduces the complexity of transition logic. You do not need to draw separate transitions for every sub-state to re-enter them. The history vertex handles the logic automatically.
Visual Representation
UML specifies a distinct symbol for the history state. It appears as a circle containing an uppercase “H”. This symbol is placed inside a composite state box.
The connection from the history state to a target state is a regular transition. The direction of the arrow indicates that the history state has “resolved” its memory to a specific target.
When the diagram is interpreted, the software engine sees the H and looks for the saved context. It then activates the transition from the memory address stored in that state.
Distinguishing Shallow vs. Deep History
Shallow History Mechanism
A shallow history state restores the most recently active direct sub-state. It does not look inside that sub-state. It simply points to the top-level state that was active before leaving the parent.
Consider a configuration state with options A, B, and C. If you were in option B and left, a shallow history will resume at option B. However, if option B contains nested sub-states, the history will land at the initial state of B.
This behavior is suitable for states where the initial configuration is always the safe entry point for the sub-state. It provides a balance between memory and simplicity.
Deep History Mechanism
A deep history state goes one step further. It remembers the entire nested hierarchy of the composite state. It restores the exact state of the sub-states as they were before the parent was exited.
If you are deep inside a configuration tree, a deep history will navigate all the way down to that specific leaf node. It effectively restores the entire state stack of the composite state.
Using deep history is essential for complex lifecycles where the position within the hierarchy determines the system’s behavior. It is the preferred method for history state UML applications in financial or medical software.
Comparison Table
| Attribute | Shallow History | Deep History |
|---|---|---|
| Memory Depth | One level only | All nested levels |
| Resume Point | Initial state of sub-state | Last active sub-state |
| Complexity | Low | High |
| Use Case | Simple reset contexts | Complex workflow contexts |
Modeling Scenarios and Implementation
Scenario: Resume a Shopping Cart
Imagine an e-commerce system where a user leaves a shopping cart to process a payment. The cart state is composite with sub-states like Item Selection, Shipping, and Review.
If the user leaves the Review sub-state and later returns, you want them to see the items they selected, not the default empty state. You use a deep history state for this.
The transition from “Payment Process” back to the “Cart” state points to the deep history vertex. The state machine reconstructs the “Review” state and restores the specific items selected.
This ensures a seamless user experience without requiring the developer to save and pass multiple variables manually for every sub-state.
Scenario: Resume a Machine Idle State
In industrial automation, a machine might have a composite state called “Operational Mode”. This contains sub-states like “Calibration”, “Running”, and “Maintenance”.
If the machine enters “Running” and then a fault occurs, the system might pause. When the operator clears the fault, the machine needs to return to “Running”.
Using a shallow history might restart the calibration if “Running” was the parent of the current context. A deep history ensures the machine resumes exactly in the “Running” state with its previous parameters intact.
Configuring the Pseudostate
To implement this, you must place the history vertex inside the composite state box. It is drawn as a circle with an H inside.
You draw a transition arrow from the history vertex to the specific sub-state you want it to point to. If you want a deep history, you draw the arrow to the deepest level required.
Some modeling tools allow you to set a property directly on the state to define the depth. This simplifies the visual clutter of the diagram.
Common Troubleshooting and Misconceptions
Root Cause: Resetting Instead of Resuming
A frequent error in history state UML modeling is the accidental resetting of the state. This happens when the transition from the parent state points to the initial state, not the history vertex.
If you draw a line from the entry point to a sub-state directly, the machine ignores the memory. It always enters the initial state every time.
To fix this, ensure the transition arrow points to the H symbol. Verify that the transition logic triggers when the machine re-enters the parent composite state.
Root Cause: Shallow vs. Deep Confusion
Designers often assume all history states behave the same. If you need deep resumption but configure a shallow one, the system will land in the initial state of the sub-state.
This results in lost data or incorrect context for the user. Always check the depth requirement of the workflow before drawing the transition.
If the sub-state is simple, shallow is sufficient. If it contains nested machines, deep is required.
Misconception: History vs. Variables
Some developers believe they need variables to store the state ID. In UML state machines, the history state handles this internally.
The state machine runtime maintains the stack. You do not need external databases or custom code to track which state was active.
This reduces the code footprint and minimizes bugs related to state synchronization.
Advanced Considerations and Validation
Handling Initial State Entry
When a state machine starts, the history state is not active. It has no data. You must define a default entry for the first time the state is entered.
The history state effectively becomes a “cold start” until the composite state has been visited at least once. Ensure your logic handles this first-entry case gracefully.
Often, the initial state acts as a fallback if the history is empty. This is a standard behavior in most UML tools.
Concurrency and History
When using orthogonal regions (concurrent states), each region has its own history context. A history state in one region does not affect another.
Modeling complex lifecycles often involves parallel processing. Ensure that your history states are defined within their respective regions to avoid conflicts.
Validation checks should confirm that concurrent transitions do not create circular dependencies with the history state.
State Validation Rules
Before deploying the model, run a validation check. Ensure that the history target state is valid within the current composite state.
If the history points to a state that was removed or renamed, the machine may crash or hang. Regular refactoring requires updating the history targets.
Check that the history state does not create cycles that prevent the state machine from terminating or reaching a terminal state.
Summary of Benefits
Reduced Code Complexity
Using history state UML reduces the number of explicit transitions required in your codebase. You remove the need to manually set state variables.
This leads to cleaner logic and easier maintenance. Developers can focus on the transitions rather than the data persistence of the current state.
Improved User Experience
Users benefit from systems that remember their position. This is vital for mobile applications or web interfaces where connectivity might be unstable.
The system resumes exactly where the user left off, providing a seamless and professional experience without requiring re-configuration.
Key Takeaways
- Purpose: A history state acts as a bookmark to save and restore context.
- Types: Shallow stops at the immediate sub-state; deep navigates the full hierarchy.
- Visuals: Represented by an uppercase “H” inside a circle.
- Configuration: Ensure the transition points to the history vertex, not the initial state.
- Usage: Essential for state machines that need to resume complex, nested workflows.