A simple sequence always moves to the next action.
Real programs often need to choose among possible paths.
Consider a soccer process:
A player reports whether they are available for the match.
The next action depends on a true/false condition.
If the player is available, the system may add the player to the available list.
If the player is not available, the system may leave the player off that list.
The process now contains a decision.
In a UML activity diagram, a decision node represents a point where one incoming flow can continue along different outgoing paths.
Conceptually:
┌─ [available] ─→ Add player to available list
Read status ──◇
└─ [not available] ─→ Continue without adding player
The diamond represents the decision point.
The outgoing paths represent possible results.
Only the path whose condition is satisfied should be followed.
The labels on the outgoing paths are often called guards.
They tell the reader when each path applies.
For the soccer example:
[available][not available]A reader should be able to understand why one path is followed instead of the other.
Without path conditions, a decision diamond with two arrows would leave the choice unexplained.
A decision often depends on a condition that can be understood as true or false.
Suppose the model tracks:
isAvailable
The process asks:
Is the player available?
If the condition is true, follow the available path.
If it is false, follow the other path.
This is the same Boolean reasoning from the previous activity, now represented visually.
Consider:
Is player available?
/ \
yes no
↓ ↓
Add to list Continue
The diagram should make the consequence of the decision visible.
A decision whose two paths immediately do exactly the same thing may not be useful.
The point of branching is that the condition affects what happens next.
Two paths do not have to remain separate forever.
For example:
┌─ [available] ─→ Add to available list ─┐
Read availability ──◇ ├─→ Display roster
└─ [not available] ─────────────────────┘
Both paths eventually continue to Display roster.
The difference is that only the available path performs the extra action first.
This helps you see the difference between:
A beginner diagram becomes difficult to read when one decision tries to answer several unrelated questions at once.
Instead of:
Is the player available, on the correct team, eligible, and wearing the right jersey?
begin with the specific condition the current process actually needs.
For example:
Is the player available?
Additional decisions can be modeled separately when the requirements call for them.
A useful decision flow includes enough context to understand:
For example:
Start
↓
Read player availability
↓
Decision: available?
├─ [yes] → Add player to available list
└─ [no] → Skip addition
↓
Display roster
↓
End
The exact UML rendering may use standardized shapes rather than this text layout, but the meaning should remain the same.
The decision asks a question.
The path condition identifies which result applies.
The next action performs work.
For example:
Decision: Is the player available?
Path: [yes]
Action: Add player to available list.
Keeping those roles separate makes both UML and later C# conditional logic easier to understand.
When reading a decision diagram, choose a specific state.
Suppose:
isAvailable = true
Begin at the start node and trace only the path that applies to that state.
Then imagine:
isAvailable = false
Trace the other path.
This lets you treat the activity diagram as a description of possible execution paths rather than as a picture where everything happens at once.
An activity diagram gives you a visual model of a choice.
C# later expresses the same kind of choice with conditional statements.
The syntax will look different, but the reasoning remains:
Evaluate a condition → select the matching path → continue execution
For now, focus on reading and creating that logic visually.