In a UML activity diagram, why must a decision node's outgoing guards cover every case?
answer
- Look at the edges, not the node
- Ask what happens when nothing matches
- Two properties: nothing missing, nothing overlapping
- The else edge is the catch-all
basics
~20 sA decision node routes the arriving token down the single outgoing edge whose guard is true. If no guard holds, the token stops there and the path dies silently; if two hold, the model permits either path and no longer has one meaning.
solid answer
~40 sGuards live on the *edges* leaving a decision node, not in the diamond, and they are what turns a branch point into a specification. A correct guard set has two properties: it is **complete**, so every reachable case matches at least one outgoing edge, and it is **mutually exclusive**, so no case matches two. Incompleteness is a silent dead end — the token has nowhere to go and the notation reports nothing, so the gap is found in production. Overlap is ambiguity: the diagram now describes two behaviours and which one gets built depends on who reads it. The cheap fix for completeness is an **else** edge, taken when no other guard on that node is true, and it must lead to a real action rather than trailing off the page.
code
pseudocode · 5 linesDIAMOND on outstanding balance
edge 1 [balance = 0] -> close account
edge 2 [balance > 0 and <= 250] -> send reminder
edge 3 [balance > 250] -> escalate for review
-- no edge matches a negative balance: the set is incompletego deeper
Know that a guard is the condition in square brackets on an edge leaving a decision node, that it is written on the edge and not in the diamond, and that only one of those edges is taken.
Explain the two properties a guard set needs — complete and mutually exclusive — and say what an else edge buys you when the cases cannot all be enumerated in advance.
Demonstrate reviewing guard sets against boundary values, empty collections and absent values. A diagram that silently strands a token at a diamond is the defect you are expected to find before anyone codes it.
Take a position on how much conditional logic belongs in the picture at all. Past a handful of cases, a decision table beside a simple diagram serves the team better than a fan of guarded edges nobody can check.
## Where a guard lives A **guard** is a condition written in square brackets on a **control flow edge** — not inside the node the edge leaves. In an activity diagram the guards that matter sit on the outgoing edges of a **decision node**, the diamond that picks one path. A token arrives at the diamond, the guards on the outgoing edges are evaluated, and the token departs along the single edge whose guard holds. The node carries no logic at all; every bit of the logic is on the edges. That is why writing the condition inside the diamond is a reading error: the diamond marks *where* the choice happens, and the edges say *what* the choice is. Two properties make a guard set correct: - **Complete** — for every state of the world reachable at that point, at least one outgoing guard is true. - **Mutually exclusive** — for every such state, at most one outgoing guard is true. Miss the first and the flow can dead-end. Miss the second and the diagram stops having a single meaning. ## What each failure does to the model | Guard-set defect | What the model now says | What a reader does with it | |---|---|---| | A case matches no guard | The token stops at the diamond and that path makes no further progress | Invents a default, or finds the gap in production | | A case matches two guards | Either path is permitted and neither is preferred | Two implementers build two behaviours, both defensible | | Condition written inside the node | Nothing at all; the outgoing edges are unlabelled | Cannot tell which edge is the affirmative one | | No catch-all edge | Every case nobody enumerated is undefined | Adds one silently, in code, undocumented | An **incomplete** guard set is a silent dead end. Nothing on the page looks wrong and the notation reports no error; the diagram is simply mute about one case. It surfaces in review as the question 'and what happens when the balance is exactly zero?', and if nobody in the room can answer, the picture has failed at the one job it had. An **overlapping** guard set fails more quietly still, because both paths look deliberate. A diagram whose token could legally go two ways is not one specification — it is two, and which one gets built is decided by whoever reads it first. ## The catch-all edge The notation predefines an **else** guard for exactly this problem: an edge marked else is taken when no other outgoing guard on that decision node is true. It buys completeness cheaply — enumerate the cases you genuinely care about, then route everything else down one labelled edge. Two things else is not: 1. **It is not 'do nothing'.** The else edge has to lead somewhere real — a rejection action, a compensating step, an exception path, a final node. An else edge that trails off the page restores exactly the dead end you drew it to remove. 2. **It is not a substitute for thinking.** If most of the real traffic ends up on the else path, the guard set is naming the exceptions and hiding the rule, and the diagram is describing a process nobody actually follows. ## Boundaries are where guard sets rot Almost every guard-set defect found in review sits on a numeric or empty-value boundary, and the two failure modes are mirror images: - `[amount < 250]` beside `[amount > 250]` leaves exactly 250 unrouted — an incomplete set that exactly one input value exposes. - `[amount <= 250]` beside `[amount >= 250]` routes 250 down both — an overlapping set that the same single input exposes. - Guards over a collection routinely forget the empty case: `[all items approved]` beside `[some item rejected]` says nothing about a collection with no items. - Guards over an optional value forget the absent case, which is neither the true nor the false side of a condition about its content. The habit that fixes all four is to write guards that *partition* the input rather than describe it, then read them back as a sentence — 'zero, above zero up to the limit, above the limit, anything else' — and check the seams between the phrases. ## Reviewing a guard set in ninety seconds 1. Read the outgoing edges of every diamond aloud, as a list of cases. 2. Name one input for each edge, then name one input you believe reaches none of them. 3. Name one input you believe reaches two of them; if you can, the set overlaps. 4. Confirm the catch-all edge exists and lands on a real action rather than on white space. 5. Check that each guarded edge eventually reaches a rejoin or a final node, so no case has a shorter life than the others. A guard set that survives that pass is worth more than the rest of the diagram, because it is the part a reader can get *wrong* while believing they read it right.
- Where should an else edge lead?To a real action — a rejection, a compensating step, an exception path or a final node — never off the page. The point of a catch-all is that every input has a modelled outcome, and an else edge that trails off restores the dead end it was drawn to remove. If most traffic ends up on it, the guard set is naming exceptions and hiding the rule.
- How do you keep a guard set correct over a numeric range?Partition the range instead of describing it. Two edges reading below the limit and above the limit leave the limit itself unrouted, and making both comparisons inclusive routes it twice. Pick one side to own the boundary, add explicit edges for zero or empty when those are meaningful, and read the whole set back as a list of cases to check the seams.
saying these in an interview costs you the question
- Leaves the negative or empty case off the diagram entirely
- Writes overlapping ranges on two outgoing edges of one diamond
- Puts the condition inside the diamond instead of on its edges
- Assumes an unmatched token falls through to the next action
- Treats the else edge as meaning nothing happens
- Believes two true guards mean both paths are taken