You use a UML state machine in MDriven Designer to define which lifecycle states an object may occupy and which business actions may move it between those states.
Model an object's lifecycle
A UML class diagram describes the relatively stable structure of a domain: classes, attributes, and associations. A UML state machine describes its dynamics: the allowed states of an instance object and the rules for changing state.
For example, a Car can be created, put into production, and later scrapped. A state machine makes the allowed lifecycle explicit. Instead of relying on several unrelated attributes or checks, you state that a car follows a defined flow.
| Term | Meaning | Car example |
|---|---|---|
| State | A named situation in the lifecycle of one object. | Created, InProduction, or Scrapped.
|
| Transition | A directed move from one state to another. | The move from Created to InProduction.
|
| Trigger | A method on the class that initiates a transition. | StartProduction.
|
| Guard | An OCL expression that must evaluate to true before a transition is allowed. | self.DepositPaid.
|
| Entry action | An action that runs when the object enters a state. | Record or perform the work required when the car enters InProduction.
|
| Exit action | An action that runs when the object leaves a state. | Perform the work required before the car leaves Created.
|
Create a state machine
Create the state machine for the class whose objects have the lifecycle you want to control.
- Select the class in MDriven Designer. In this example, select
Car. - Open the class's state diagram.
- Create a state attribute for the lifecycle. Name it for the perspective that it represents, such as
LifeTimeState. - Add the states that are valid for that perspective. For example:
Created,InProduction, andScrapped. - Add a transition from
CreatedtoInProductionand give it the triggerStartProduction. - Add further transitions and triggers for the actions your domain permits. For example, use
Scrapfor a transition toScrapped. - Save the model and test that each trigger is available only where its transition permits it.
A newly created object starts from the state machine's initial path. In a state machine with an initial state leading to Created, a new Car enters Created unless a guard prevents progress.
Use one state attribute per lifecycle perspective
The current state is stored in the state attribute. A class can have more than one state attribute when the same object has independent lifecycle perspectives.
For example, a Car may have:
LifeTimeState, with states such asCreated,InProduction, andScrapped.CleanlinessState, with states such asDirtyandClean.
Keep these perspectives separate when their rules are separate. Starting production is a lifecycle decision; cleaning the car is a different concern. Giving each concern its own state attribute prevents one large state machine from mixing unrelated rules.
Control transitions with triggers
A transition is not an unrestricted assignment of a state value. You follow the transition by executing its trigger, which is a method on the class. The trigger performs the work associated with moving from the source state to the destination state.
For the production flow, the object must be in Created before StartProduction can move it to InProduction. If the car is already Scrapped, that transition is not available unless you have explicitly modeled one.
This makes the allowed business actions visible in the model. A user or developer can inspect the state diagram and see which actions are meaningful in each state.
Add guards for business conditions
Use a guard when a transition is allowed only if a business condition is true. A guard is written in OCL (Object Constraint Language), which lets the rule use the names of attributes and associations in your model.
Consider the rule: Do not start production until the deposit is paid. Add a guard to the StartProduction transition:
self.DepositPaidWith this guard, a car in Created can move to InProduction only when its DepositPaid value is true.
You can combine conditions. If the car must have a paid deposit and a brand before production starts, use:
self.DepositPaid and self.TheBrandOfTheCar->notEmptyHere, self means the current Car. TheBrandOfTheCar is an association end, and ->notEmpty verifies that it has a value.
Write guards in domain language. A guard is easiest to review when readers can recognize the business terms directly from the class diagram.
Run work on entry and exit
Add entry and exit actions when work belongs to arriving in or leaving a state.
For example:
- Put an entry action on
InProductionfor work that must occur whenever a car enters production. - Put an exit action on
Createdfor work that must occur whenever a car leaves the created state.
Use these actions for behavior that is part of the state change itself. Keep the transition and its guard focused on the business decision: the trigger requests the move, and the guard determines whether the move is permitted.
Example: production lifecycle
The following lifecycle expresses the deposit rule as a modelled process:
| Current state | Trigger | Guard | Next state |
|---|---|---|---|
Created
|
StartProduction
|
self.DepositPaid and self.TheBrandOfTheCar->notEmpty
|
InProduction
|
InProduction
|
Scrap
|
None | Scrapped
|
A concrete sequence is:
- Create a car. It enters
Created. - Set its deposit as paid, and relate it to a brand.
- Execute
StartProduction. - The guard evaluates to true, so the car enters
InProductionand its entry action runs, if one is defined. - Execute
Scrapwhen the car must leave production permanently.
If the deposit has not been paid, step 3 cannot take the car into production because the guard evaluates to false. The rule is therefore expressed where the lifecycle decision is made.
Choose state machines and constraints deliberately
Use a state machine when the rule governs a sequence of allowed lifecycle steps, such as when a car may start production only from Created. Use constraints for rules that must hold independently of a particular transition, including delete-specific rules. Association cardinalities also create implicit constraints.
For example, "a car must not start production until its deposit is paid" is naturally a guard on StartProduction. A rule about whether an object may be deleted belongs in a delete constraint when it is not primarily a lifecycle transition.
Keep state machines understandable
- Name states as stable business situations, such as
InProduction, rather than names of user-interface buttons. - Name triggers as business actions, such as
StartProduction. - Put the condition on the transition as a guard instead of expecting users to remember it.
- Split independent perspectives into separate state attributes rather than combining them into every possible state combination.
- Use the diagram to review the process with domain experts. It shows both the flow and the rules that govern it.
