White paper ·
UML: The Boxes Were Right and the Lines Were Wrong
How to build a model, which four diagrams pay for themselves, and what changes when a machine draws one
Contents10 sections
The diagram that read as correct
Hand a page of requirements to a language model and ask for a class diagram. What comes back looks finished. Every noun in the requirement has a rectangle: Order, Customer, LineItem, Payment. The attributes underneath them are plausible. The whole thing renders clean enough that a reviewer nods and scrolls on.
The lines between the boxes are where it comes apart.
Somebody has now measured that gap rather than complaining about it, which is the part worth reading twice, because a complaint about machine-written documentation ages badly and a number attached to a named evaluation does not. In the NOMAD evaluation out of the University of Manchester, a single-prompt baseline scored 0.82 on class extraction against 0.46 on strict relationship extraction. Lines come back a little over half as good as boxes. Both numbers describe the same diagram, generated in the same pass, and only one of the two is visible to a reader skimming a rendered picture at the speed people actually review documents.
The diagram got accepted because it looked like a diagram. That was an error in reading what a picture proves. A rendered box carries no claim that survives inspection; it says a thing exists and stops there. A line does more work, because it carries multiplicity, direction, ownership and lifetime, which is to say it states how many of one thing may attach to another and what dies when the parent dies. Checking the nouns and calling the diagram reviewed skips every part of the artifact that could have been wrong. Nobody read the multiplicities.
This is the argument for knowing the notation. A machine draws the picture in under a minute now, and it is competent at the half of the work a reader checks by glancing. Whatever a reader has to check deliberately is the half that stayed hard, and it is the half the notation exists to make checkable.
What a model is, and what the standard says
UML, the Unified Modeling Language, is a specification owned by the Object Management Group. That is the industry consortium behind CORBA and BPMN as well. The current version is 2.5.1, filed as formal/17-12-05 and published in December 2017. Nothing has superseded it in the nine years since. That makes UML unusual in this industry: it stopped moving, and the tooling caught up. Nine years is a long freeze.
A second copy of the standard carries a different number. ISO/IEC 19505, parts 1 and 2, was published in 2012; its text is identical to OMG UML 2.4.1. That version shipped in July 2011, one revision behind the current one. ISO confirmed it as current again in 2025, so the gap now runs fifteen years. A procurement document citing the ISO number is asking for a UML older than the free PDF on the OMG site. That gap matters exactly once, at the moment somebody writes a contract clause naming the standard by its ISO reference, in a room where nobody notices that the version behind that reference stopped tracking the specification the tooling was actually built against.
One idea inside the spec does more work than the rest of it combined. It is also the one most often missed. A model is the set of elements: classes, associations, states, messages. Any diagram is a view onto that set, allowed to show a fraction of it. Two diagrams that contradict each other are not two opinions; they are one broken model that nobody reconciled. Once that lands, the question stops being which diagram to draw and becomes what the model has to be true about, which is a question a domain expert can answer and a notation cannot.
Fourteen diagrams, and the four that pay for themselves
The specification defines fourteen diagram types, split evenly into seven that describe structure and seven that describe behaviour.
| # | Diagram | Group | The question it answers |
|---|---|---|---|
| 1 | Class | Structure | What is the domain made of, and how do the parts relate |
| 2 | Object | Structure | What does one concrete snapshot of those parts look like |
| 3 | Package | Structure | How is the model grouped, and what depends on what |
| 4 | Composite structure | Structure | What is inside one classifier, and how are its parts wired |
| 5 | Component | Structure | What are the replaceable units, and what do they offer |
| 6 | Deployment | Structure | What runs where, on which node, in which artifact |
| 7 | Profile | Structure | How is UML itself extended for this domain |
| 8 | Use case | Behaviour | Who uses the system, and for what goal |
| 9 | Activity | Behaviour | What is the flow of work, including its branches and joins |
| 10 | State machine | Behaviour | Which transitions are legal, and which are refused |
| 11 | Sequence | Behaviour | Who calls whom, in what order, over time |
| 12 | Communication | Behaviour | Who is connected to whom, with the ordering de-emphasised |
| 13 | Interaction overview | Behaviour | How do several interactions compose into one flow |
| 14 | Timing | Behaviour | How does state change against a clock |
Table 1. The fourteen UML 2.5.1 diagram types and the question each one is built to answer.
Reading the right-hand column straight down is the fastest way to see what the notation is for, since each row names a question about the system that somebody eventually has to answer out loud, and the diagram type beside it is the shape that answer takes on paper. Most projects need four. A class diagram states what the domain is made of and how the pieces relate. Draw it and a wrong noun gets caught before it becomes a wrong table. A sequence diagram states who calls whom in what order; ordering faults and missing timeouts become visible on paper. Only the state machine diagram says what the system must refuse. A deployment diagram states what runs where. It earns its hour the first time somebody asks whether the database sits in the same region as the service.
Ten of them are not wasted. They are specialised. A team that draws all fourteen for every feature has confused thoroughness with modelling, which costs a sprint and produces a folder of pictures nobody opens twice.
Building a class diagram, step by step
Take a small clinic scheduler. A provider publishes slots; a patient books an appointment against a slot; the visit produces an encounter record.
Write the invariant first, in one sentence. For this domain it's "a slot holds at most one active appointment." That sentence is the reason the diagram exists. Every decision below gets checked against it.
Turn the nouns into candidates, then strike most of them. Provider, Slot, Appointment, Patient, Encounter survive. Confirmation number does not: it belongs to Appointment as an attribute. A class carrying one field and no behaviour is a field wearing a rectangle.
Name each association with a verb, read in one direction. A bare line between Patient and Appointment says nothing; "Patient books Appointment" says something a clinic scheduler can agree or disagree with. An association nobody can name in a verb is usually two associations that got merged by accident.
Put multiplicity on both ends, then argue about it. Slot to Appointment is 1 to 0..1. That pair of numbers is the invariant from step one, written in notation a tool can check. Patient to Appointment is 1 to many, as is Provider to Slot. This step is the diagram; the rest is drawing.
Mark composition where lifetime is shared. An Encounter cannot outlive its Appointment, so that relationship takes the filled diamond. Slot survives a cancelled Appointment, so it does not.
Read the finished diagram back as sentences. "One provider publishes many slots. One slot holds at most one active appointment. One appointment produces at most one encounter." Read those aloud to a clinic scheduler, and if the person who books appointments all day disagrees with any one of them, the model has already paid for itself before anybody opened an editor. That conversation is the point.
Fourteen lines of text hold the whole model, and they render to Figure 1.
@startuml
class Provider { npi : string }
class Slot { starts_at : datetime }
class Appointment { confirmation : string }
class Patient { mrn : string }
class Encounter { signed_at : datetime }
Provider "1" -- "0..*" Slot : publishes
Slot "1" -- "0..1" Appointment : holds
Patient "1" -- "0..*" Appointment : books
Appointment "1" *-- "0..1" Encounter : produces
@enduml
What practitioners actually do
The honest picture of UML adoption is smaller than the textbooks suggest. Somebody measured it.
Marian Petre interviewed fifty professional software engineers at fifty companies across Europe, North America, Brazil, India and Japan. She published the counts at ICSE 2013. Thirty-five of the fifty used no UML at all. Eleven used it selectively. Three used it to generate code. Not one described wholehearted use of the notation as current practice, against eleven who described picking two or three diagrams and ignoring the rest.
A second study from the same year gets quoted far more often. It measures something else. Reggio and colleagues counted how often each diagram type appears across thirty books, twenty tools, twenty-two university courses and eighteen tutorials. Class diagrams appear in 100 percent of those sources, activity in 98, sequence in 97, use case and state machine in 96, profile diagrams in 11. That is a real result about what the industry teaches and what tools ship. It says nothing about what engineers draw, and the authors say so plainly, noting that a survey of actual practitioners was still ahead of them. A number that answered a neighbouring question is worth reporting with its question attached.
Put the two together and the useful finding is the middle category. Selective use is what survives contact with a deadline: two or three diagrams that carry a thought somebody needed to have. What that group has in common is that a diagram got drawn because a decision was stuck, and it got put down again as soon as the decision came unstuck, which is a very different relationship to the notation than a textbook chapter describes.
The model as context a machine can read
Here is what changed. It has nothing to do with drawing.
Source code tells an agent what the system does. It is close to silent about what the system is allowed to do. A repository can show that book_appointment writes a row; it rarely shows that a slot may hold one active appointment, because that rule lives in a unique index and a service-layer check, plus a comment somebody deleted in 2023. An agent reading that repository infers the rule from whatever it can see. A plausible wrong inference is exactly the failure mode nobody catches.
A model states the constraint directly. Multiplicity is a machine-readable sentence about how many. A state machine is a machine-readable sentence about what is refused. An agent cannot derive either one reliably from implementation, and both are cheap enough to write down once and then keep in the repository beside the code they constrain.
That makes an architecture model something more useful than documentation. It is context, in the specific sense that word has acquired: material an agent reads before it acts. The loop in Figure 2 runs requirement to model to code, then back from code to a drift check against the model, and that last leg is the one most teams skip.
What the measurements say about generated models
The generation half of that loop is measurable now. The numbers say something specific about where to spend review time.
NOMAD, from Polydoros Giannouris and Sophia Ananiadou at the University of Manchester, splits UML class-model generation across five specialised agents rather than one prompt: concept extraction, relationship comprehension, model integration, code articulation, and validation. Across eight supplementary use cases, overall F1 moved from 0.66 to 0.70. The class-level score moved from 0.82 to 0.86. Names are easy. Strict relationship extraction moved from 0.46 to 0.50, leaving relationships at roughly half the accuracy of the class names above them.
Relationships are the hard half. Depth is where that shows. On the Northwind case study, twenty-one classes, overall F1 went from 0.74 to 0.84 and strict relationship F1 went from 0.52 to 0.92. Adding a verification agent lifted the overall figure again, from 0.84 to 0.89. Decomposition and a checker between them nearly doubled the score on the exact part of the diagram that a skimming reviewer never checks. A generated model is still not trustworthy on its own. What the numbers do say is where review effort belongs: on the associations, rather than spread evenly across a picture whose easy half a model already handles.
| Evaluation | Measure | Baseline | NOMAD |
|---|---|---|---|
| Breadth, 8 use cases | Overall F1 | 0.66 | 0.70 |
| Breadth, 8 use cases | Class F1 | 0.82 | 0.86 |
| Breadth, 8 use cases | Attribute F1 | 0.71 | 0.77 |
| Breadth, 8 use cases | Relationship F1, strict | 0.46 | 0.50 |
| Depth, Northwind, 21 classes | Overall F1 | 0.74 | 0.84 |
| Depth, Northwind, 21 classes | Relationship F1, strict | 0.52 | 0.92 |
| Depth, Northwind, 21 classes | Overall F1 with verification agent | 0.84 | 0.89 |
Table 2. Reported F1 scores from the NOMAD evaluation, where the relationship rows move furthest.
Work published in March 2026 by Jackson Nguyen and colleagues points the same direction from a different angle. They generated class models from requirements with four current models, then validated the output twice. Two language models acted as judges; human experts confirmed across completeness, correctness, standards conformance, comprehensibility and terminology alignment. The generated models held up as structurally coherent. Worth keeping is the shape of the setup: the model is both the thing assessed and one of the instruments doing the assessing. Somebody has to hold that conflict in view.
Diagrams that live in the repository
None of this works if the diagram is a PNG in a wiki.
PlantUML takes nine UML diagram types as plain text and renders through Graphviz. A class diagram becomes a file that diffs and merges like any other. Mermaid covers thirty-plus diagram types, class, sequence, state and C4 among them. GitHub has rendered it inside markdown files since February 2022, which put a diagram inside a pull request with no tool to install. C4 sits a level above both, offering four zoom levels from system down to code, notation independent and tooling independent by design. Structurizr DSL expresses it when a team wants one source generating several views.
What they share is the property that matters for the loop above. A text-source diagram is readable by the same agent that reads the code, in the same pass, with no image handling in between. A picture of an architecture is worth roughly what a screenshot of a table is worth, which is to say it is evidence that somebody once knew.
The model that drifts
A stale model is worse than no model. It fails the same way a stale index does: it answers confidently and cites itself. A reader cannot separate a diagram that describes the system from one that describes the system as of a refactor two quarters ago. Both of them render.
So a model earns its place by being checked rather than by being pretty. Generate the class diagram from the schema in continuous integration and fail the build when a multiplicity in the source contradicts one in the model. Pin the diagram to a commit the way a code index gets pinned, so a reader knows what it was true about. The other ten diagram types can stay out of the repository until somebody needs one.
Lines were always the expensive part. A machine draws them in seconds now, at roughly half the accuracy of the names it puts in the boxes. The review that catches the difference is a person reading multiplicity out loud to somebody who knows the domain.
Glossary
| Term | Definition |
|---|---|
| Aggregation | A relationship marking one class as a container for another, drawn with a hollow diamond. The contained object survives the container, which is what separates it from composition. |
| Association | A line between two classes stating that instances of them are related. It carries a name, a direction, and a multiplicity at each end. |
| C4 model | A way of organising architecture diagrams into four zoom levels: system context, container, component, and code. It prescribes the levels and leaves the notation and tooling open. |
| Class diagram | The UML structure diagram showing classes, their attributes and operations, and the associations between them. It is the most used of the fourteen types. |
| Composition | A relationship where the contained object cannot outlive its container, drawn with a filled diamond. Deleting the whole deletes the part. |
| Drift | The gap that opens between a model and the system it describes once the code changes and the model does not. A drifted model still renders, which is why it needs a check rather than a glance. |
| F1 score | A single accuracy figure combining precision and recall, running from 0 to 1. In model generation it is computed separately for classes, attributes, and relationships, and those three numbers usually disagree. |
| Mermaid | A text-to-diagram tool covering more than thirty diagram types, including several UML ones. GitHub renders it inside markdown files natively. |
| Multiplicity | The numbers at the end of an association saying how many instances may participate, written as 1, 0..1, or 0..*. It is where a domain invariant becomes checkable notation. |
| Object Management Group | The standards consortium that owns UML, along with BPMN, CORBA, and related specifications. It publishes the specification documents free of charge. |
| PlantUML | A text language for UML diagrams covering nine diagram types, rendered through Graphviz and other layout engines. Its source files diff and merge like code. |
| Sequence diagram | The UML behaviour diagram showing messages exchanged between participants in time order. It is where ordering faults and missing timeouts become visible. |
| State machine diagram | The UML behaviour diagram showing the states an object may occupy and the transitions between them. It is the diagram that says what the system must refuse. |
| Structurizr DSL | A text language for describing a C4 model once and generating several views from that single description. |
| UML | The Unified Modeling Language, a standard graphical notation for specifying and documenting software systems, currently at version 2.5.1. |
Keep reading
More field notes
This piece is part of the MAX Research Collective library. Browse the rest, or connect on LinkedIn.