Design-of-Record
Week 7 · The last document before the code
Week 7 · The last document before the code
Who got a Project Pulse reminder this term for something they had already submitted?
flowchart LR S[Specification] --> A[Agent] --> C[Code]
What does your use case not decide?
You review decisions you did not know were made, after they were built. Ask twice, get two designs.
The code says what it does. Only the design says why.
You can use an eraser on the drafting table or a sledgehammer on the construction site.
Attributed to Frank Lloyd Wright, American architect
| Architecture-of-record | Design-of-record | |
|---|---|---|
| Covers | The whole system | One use case area |
| Stops at | Each component's job | What the agent can safely derive |
| How many | One | One per area |
| Written | Before any code | Before this area's code |
Weeks of coding can save you hours of planning.
Industry: the RFC
A proposal, reviewed and approved before it is built. IETF, Rust, Sourcegraph, Oxide.
Here: the design-of-record
Usually drafted by the agent, after your sketch. Reviewed by you. The review is the skill.
The design's header names every use case it realizes. The traceability matrix's Design column points back.
Six things the reminder's use case did not settle.
| Finding | The fix went to |
|---|---|
| Two definitions that disagree | A new business rule |
| Scheduler checks the wrong week | The amended FR |
| Emails students who cannot submit | The business rule |
| Which week the WAR covers | The use case |
| Half-finished peer evaluations | The business rule |
| Foundation calls a feature | The design |
| Where | Decides "has not submitted" as |
|---|---|
| Instructor's WAR page, in the browser | No activity that week |
| Peer evaluation report, on the server | Evaluated nobody that week |
Two places, two definitions. What could go wrong?
Nobody wrote down the answer.
Most of what the challenge loop finds belongs in the specification, not the design.
There are two hard things in computer science: cache invalidation and naming things. Project Pulse had two names for one fact, which is both.
classDiagram
direction LR
class ReminderController {
<<new>>
}
class SubmissionStatusService {
<<new>>
}
class ReminderService {
<<new>>
}
class WeeklyReminderScheduler {
<<moved>>
}
class ActivityService {
<<reused>>
}
class EvaluationService {
<<reused>>
}
class EmailService {
<<reused>>
}
class SectionService {
<<reused>>
}
ReminderController --> SubmissionStatusService
ReminderController --> ReminderService
WeeklyReminderScheduler --> SectionService
WeeklyReminderScheduler --> SubmissionStatusService
WeeklyReminderScheduler --> ReminderService
SubmissionStatusService --> ActivityService
SubmissionStatusService --> EvaluationService
ReminderService --> EmailService| Notation | Means |
|---|---|
| Solid arrow | A call; the caller waits |
| Dashed arrow | A return |
| alt / else | Exactly one branch happens |
| opt | Happens only if its condition holds |
| loop | Repetition |
The rule this course adds: label each interaction with the use case step it implements.
sequenceDiagram
actor I as Instructor
participant RC as ReminderController
participant SS as SubmissionStatusService
participant RS as ReminderService
participant EM as EmailService
I->>RC: choose the item (steps 1 to 3)
RC->>SS: who owes it, previous week
SS-->>RC: students who owe it
RC-->>I: list by team, and weekActive (step 4)
alt week inactive (4a)
Note over I: "Only for an active week", no send button
else week active
I->>RC: confirm (step 5)
RC->>RS: remind them
loop each student (step 6)
RS->>EM: send
end
RS-->>RC: sent, and who failed
RC-->>I: sent, and who failed (step 7)
endMost objects do not need one.
Draw it where the lifecycle is where the bugs live.
stateDiagram-v2
direction LR
[*] --> Editable: submit
Editable --> Editable: edit
Editable --> ReadOnly: week endsSession A builds the browser side.
Session B builds the server side.
They never see each other's code. What do they both read?
| Endpoint | POST /sections/{sectionId}/reminders |
| Who may | The course section's instructor, or the course admin |
| Request | the item only |
| Success | 200: number sent, who failed |
| Errors | 403 anyone else; 400 week inactive (4a) |
Why does the request not carry the week?
Where "has not submitted" lives. One service, used by the scheduler, the reminder, and both reports. Rejected: each page computing its own list. Rejected: the report calling the new service, which makes a cycle.
Gold-plating. Ask what problem it solves in this area.
When all you have is the Gang of Four, everything looks like an AbstractSingletonProxyFactoryBean. (That is a real Spring class.)
Show only what this area adds: tables, columns, the migration.
Link the domain model; never redraw it.
The reminder adds nothing.
Rejected: a reminder log. A table, a migration, and seed data, to guard a double send the confirmation and a disabled Confirm button already guard.
"No change", with a reason, is a decision. A blank section is not.
| Flow | Asserts |
|---|---|
| Main, peer evaluation | Rated two of three: reminded. Rated all: not. |
| 4a | Week inactive: 400, no email |
| 6a | One failed send stops nothing |
| Last active week | Its reminder still goes out |
Change the architecture in the same pull request. Two maps, and the agent follows whichever it reads last.
Ready when nothing on the list could break a requirement.
| Found | Answer |
|---|---|
| 3 contradictions in the design | All fixed |
| 7 guesses worth pinning | Fixed: 6 in the design, 1 in the spec |
| 9 guesses that break nothing | Kept, each with a reason |
The author reads what they meant. A fresh reader reads what is on the page.
It found what you missed: it goes in. You knew what it could not: fix the specification too.
Yours, or already in the spec
Check the use case and its rules. Then answer.
The client's
Do not pick. Fix the use case, or OPEN-ISSUES.md.
The options are its guesses. Read every one; Other is always there.
LGTM: Let's Gamble, Trust Me.
A long, polished, agent-drafted design invites approval on sight.
A design's sequence diagram has an arrow "send analytics event". No use case step mentions analytics. What do you write in the review?
Build one use case all the way through, from the screen to the database, before building the rest. Its job is to test the architecture.
Good slice
Touches the external system you are least sure of, crosses the trust boundary, or carries your hardest quality attribute.
Bad slice
The login page. A list screen. Nothing your architecture was unsure of.
The first 90 percent of the code takes the first 90 percent of the time. The remaining 10 percent takes the other 90 percent. Build the risky 10 percent first.
What the design leaves open, the agent decides. Decide it first, and get someone else to check.