| UML Element | Mermaid Shape | Meaning |
|---|---|---|
| Initial node | ((●)) filled circle |
The single entry point of the activity. Every diagram has exactly one. |
| Activity final node | (((end))) bullseye circle |
Terminates the entire activity, canceling all concurrent flows. |
| Flow final node | circle with X | Terminates one concurrent flow without ending the activity. |
| Action node | [action text] rounded rectangle |
A single step: a computation, a call, an I/O operation. Named as a verb phrase. |
| Decision / merge node | {condition?} diamond |
Decision: one incoming flow, two or more outgoing flows with guard labels. Merge: two or more incoming flows, one outgoing flow. Same shape for both. |
| Fork / join bar | thick horizontal bar | Fork: one incoming flow splits into concurrent flows. Join: all concurrent flows must complete before the single outgoing flow continues. Mermaid approximates these as unlabeled nodes with multiple edges. |
| Swimlane | subgraph partition |
A labeled column or row that groups all actions performed by one actor or component. Actions in the same swimlane share responsibility. |
[matched],
[no match], [queue empty]. Every outgoing edge of a decision
node must carry a guard, and the guards must be mutually exclusive and collectively
exhaustive - otherwise the diagram is ambiguous.
flowchart TD
I(( )) --> parse["parse input"]
parse --> valid{"input valid?"}
valid -->|"[yes]"| process["process item"]
valid -->|"[no]"| err["report error"]
err --> done(((end)))
process --> more{"more items?"}
more -->|"[yes]"| parse
more -->|"[no]"| fork[ ]
style fork fill:#333,stroke:#333
fork --> t1["concurrent task A"]
fork --> t2["concurrent task B"]
t1 --> join[ ]
t2 --> join
style join fill:#333,stroke:#333
join --> done
Figure 1. Core notation.
flowchart TD
I(( )) --> argv["parse argv via CommandLine"]
argv --> cfgout["set regex on Output"]
cfgout --> cfgdn["set extension pattern on DirNav"]
cfgdn --> search["begin directory traversal"]
search --> hasdir{"next directory?"}
hasdir -->|"[yes]"| dodir["do_dir: record current directory"]
dodir --> hasfile{"next file?"}
hasfile -->|"[yes]"| dofile["do_file: build fully qualified path"]
dofile --> apply["apply regex to file content"]
apply --> hit{"regex match?"}
hit -->|"[yes]"| print["print directory and filename"]
print --> hasfile
hit -->|"[no]"| hasfile
hasfile -->|"[no]"| hasdir
hasdir -->|"[no]"| done(((end)))
Figure 2. TextFinder activity diagram.
hasdir; the inner is hasfile. The conditional action
(print) is inside the inner loop - it fires at most once per file. A reader can
confirm the depth of nesting and the placement of the conditional without reading
any code.
begin directory traversal, every action has exactly one incoming and
one outgoing edge. There are no decisions and no loops in startup. That linearity
is a design property, not an accident - it means startup always succeeds or throws
immediately; it cannot partially configure and then stall.
[yes] and [no],
or [match] and [no match]. A diagram with an unguarded
edge or a gap in guards signals an incomplete or ambiguous design.
apply regex, with edges to error-reporting actions.
The diagram makes the absence of error handling visible.
flowchart TD
subgraph EP["EntryPoint"]
argv["parse argv"]
cfgout2["set regex on Output"]
cfgdn2["set extension pattern on DirNav"]
end
subgraph DN["DirNav"]
search2["begin traversal"]
hasdir2{"next directory?"}
hasfile2{"next file?"}
end
subgraph TF["TfAppl / Output"]
dodir2["do_dir: record directory"]
dofile2["do_file: build path"]
apply2["apply regex"]
hit2{"match?"}
print2["print path"]
end
I2(( )) --> argv
argv --> cfgout2
cfgout2 --> cfgdn2
cfgdn2 --> search2
search2 --> hasdir2
hasdir2 -->|"[yes]"| dodir2
dodir2 --> hasfile2
hasfile2 -->|"[yes]"| dofile2
dofile2 --> apply2
apply2 --> hit2
hit2 -->|"[yes]"| print2
print2 --> hasfile2
hit2 -->|"[no]"| hasfile2
hasfile2 -->|"[no]"| hasdir2
hasdir2 -->|"[no]"| done2(((end)))
Figure 3. TextFinder activity diagram with swimlanes.
| Concern | Activity diagram | Sequence diagram |
|---|---|---|
| Primary question | What is the flow of control? | Who sends what message, in what order? |
| Strength | Decisions, loops, parallel branches, and algorithmic structure. | Message ordering, return values, activation lifetimes. |
| Weakness | Does not show which participant sends each message. | Complex branching quickly becomes unreadable. |
| Best fit | Algorithms, workflows, use-case realizations with multiple paths. | Protocols, API call sequences, callback chains. |
| TextFinder fit | Shows the search algorithm: nested loops, match decision, print action. | Shows the callback protocol: DirNav fires do_dir and do_file on TfAppl. |
| Resource | Description |
|---|---|
| Project Story: TextFinder | Architecture, CLI, performance, and code metrics for all five implementations. |
| UML Sequence Diagrams | The companion behavioral view showing the callback message protocol rather than the algorithm flow. |
| UML Class Diagrams | The structural view showing the types whose methods appear as action nodes in this diagram. |
| Mermaid flowchart syntax | Full syntax reference for Mermaid flowchart, the notation used to render activity diagrams on this page. |
| UML Activity Diagrams Overview | Formal UML notation reference covering all node types, edge notation, swimlanes, and exception regions. |