Explaining a design
On This Lesson 11 topics
Lesson Overview
You can now turn requirements into classes, give each behavior a home, and split an overloaded class. The last skill in this module is one that no compiler checks: explaining your design to another person. In a job you will rarely make a design alone. A teammate reviews it, a lead asks why, and months later you must remember why you did it that way.
Explaining a design does not mean reading code aloud or showing a diagram in silence. It means saying what problem you solved, which classes cooperate, which choices you made, which alternatives you rejected, and why. In the staffing a small shop picture, it is the owner explaining the staffing plan: who does what, and why not hire someone else for that job.
This lesson gives you a compact structure for a half-page rationale and for a spoken walk-through, a model answer for the library design from this module, and a way to take review comments well. The scenario output below comes from the library classes of lesson 2, compiled and run with JDK 21.
It builds on lessons 1 to 3 of this module and on the UML sketches of BEG-025. The module's lab asks you to write a half-page rationale and to complete a peer review, so this lesson also prepares those.
Learning Objectives
By the end of this lesson you will be able to:
- Write a half-page design rationale with five parts: problem, main classes, key decisions with trade-offs, risks, and next steps.
- State a decision together with the alternative you rejected and the reason.
- Walk a reviewer through one scenario using your diagram.
- Name the weaknesses of your own design honestly.
- Respond to a review comment by discussing it and deciding what to change.
- Give a useful comment when you review someone else's design.
Written Explanation
Why explain at all
A design is a set of decisions. Code shows what you chose, but not why, and not what you did not choose. Without the reasons, the next reader either guesses or undoes your decision by accident. Writing the reasons also tests the design: if you cannot say why a class exists, it may not need to.
The five parts of a rationale
A half page is enough. Use these headings.
| Part | Answers | Length |
|---|---|---|
| Problem | What does the system have to do? Which rules matter most? | 1 to 2 sentences |
| Main classes | Which classes exist and how do they cooperate? | 3 to 5 lines |
| Key decisions and trade-offs | What did I choose, what did I reject, and why? | 2 to 3 decisions |
| Risks and weaknesses | Where is this design weak or incomplete? | 1 to 3 lines |
| Next steps | What would I do with more time? | 1 to 2 lines |
A decision needs a rejected alternative
"I made the fee a separate class" is a statement. "I made the fee a separate policy rather than a method on Loan, because the rate may differ by member type and change independently; the cost is one more class and one more argument to pass" is a decision. It has four parts: choice, alternative, reason, cost.
Naming the rejected option does three things. It shows the choice was deliberate. It lets the reviewer check your reasoning instead of guessing it. And it records the cost, since every choice has one. Almost every design choice is a trade-off: you gain something and give something up. A design with no stated costs sounds either naive or defensive.
Typical trade-offs you can name from this module:
| Choice | Gain | Cost |
|---|---|---|
| Behavior on the data owner | Rule in one place, easy to test | The data class grows |
| Separate policy class | Rule changes alone | One more class, an extra argument |
| Interface for notifications | Replace the channel without touching callers | An extra abstraction to read |
| No superclass yet | Simpler, nothing to maintain | May need refactoring when a second kind appears |
Coordinator class Library | One place for the sequence of steps | Risk of it growing into a god class |
Walk through one scenario
A diagram shows structure; a scenario shows behavior. Pick one typical case and follow the objects: "Lina borrows Dune on day 1; the library asks Lina whether she may borrow, marks the book, creates the loan with due day 15, and gives it to Lina. On day 18 she returns it; the loan reports three days late, so the fine is 75." A scenario catches design holes quickly: if you cannot narrate who calls whom, the responsibilities are unclear.
Choose one normal scenario and one failure scenario (for example, a third book refused because of the limit). Two scenarios are more convincing than ten.
Be honest about weaknesses
State what you know is weak: "Library.lend is not atomic if the member's list fails after the book is marked", or "the due date is an int, which is a shortcut". A reviewer who finds a flaw you listed trusts you more, and one that you hid, less. This is not about self-criticism for its own sake; it is information the next person needs.
Receiving a review
A reviewer's comment is about the design, not about you. A good response has three steps:
- Listen to the whole comment and, if needed, ask a question to understand it.
- Discuss it: restate it, give your reasoning, and check the facts against the code or the requirements.
- Decide and write down the outcome: change it, keep it with a stated reason, or note it as a risk.
A bad response ignores the comment, defends without listening, or changes everything immediately without understanding. Sometimes the reviewer is right and sometimes you are; the discussion decides, not who is more senior. If you review, make comments that are specific ("Library checks the limit; should Member own it?") rather than vague ("this feels wrong"), and say what you would try.
Examples
Example 1: a three-line rationale (simple)
The coffee loyalty card from lesson 1.
Problem: a customer collects stamps; every tenth coffee is free. Classes:
Customerholds aLoyaltyCard; the card guards "0 to 9 stamps" and says when a coffee is free. Decision: stamps are a plainintinside the card, not aStampclass, because a stamp has no behavior. If stamps ever carry dates or shops, they would become a class.
One decision, one rejected alternative, and the condition that would change my mind.
Example 2: the library rationale and walk-through (practical)
Problem. A library lends books to members, each loan has a due date, late loans pay a fine, and a member holds at most two books.
Main classes.
Librarycoordinates lending.Memberowns its loans and the limit.Bookowns whether it is available.Loanowns its due day and computes its fine.Decisions and trade-offs.
- Behavior sits on the class with the data (
Loan.fine,Member.canBorrow). I rejected aLoanManagerthat reads getters, because the rules would scatter. Cost: the data classes are larger.- No
Itemsuperclass. The text mentions only books. Cost: adding DVDs later may require a refactoring.- Due dates are day numbers. Cost: not realistic; a date class would replace them.
Risks.
Library.lendmarks the book before adding the loan to the member: if a step were added after the marking and failed, the book would stay marked as lent.Next steps. Return of books, renewals, and moving the fine rate into a policy if rates vary.
The walk-through, with the output of the real code:
- Lina borrows Dune on day 1.
Librarycallsmember.canBorrow()(yes),book.markLent(), and buildsnew Loan(book, 15). - On day 18
loan.fine(18)returns75: three late days at 25 cents. - Failure case: Lina already holds two books, and the third
lendthrows.
fine on day 18: 75
Lina has reached the loan limitNote how the risk in the rationale is a real property of the code from lesson 2, not a decoration.
Example 3: a review conversation (realistic)
Reviewer: "Why does Library not check the limit itself? That is where lending happens."
Weak reply: "That is just how I did it."
Better reply: "The limit is information that Member already has, via its loan list. If Library checked it too, the number two would live in two places. The cost is that you have to look at Member to see the rule. Would a comment on lend help?"
Reviewer: "Fine. But Library.lend is the only place that creates loans, and nothing stops a caller from calling member.addLoan directly, bypassing the check."
That is a valid weakness. The honest response is "you are right; addLoan should check canBorrow itself, or be package-private (BEG-027) so only Library can call it." Decide, write it in the rationale under Risks or change the code, and move on. The review improved the design, which is the point.
Backend Insight
In professional teams, design explanations appear as pull request descriptions, design documents, and architecture decision records. The common idea is the same as here: state the context, the decision, the alternatives, and the consequences. Reviewers in backend teams often ask the same questions you practiced: where does this rule live, what happens when this fails, and how hard will it be to change. A short rationale written next to the code saves hours later, when nobody remembers why a policy class exists. In interviews, a design question is almost always testing this skill: can you choose, justify, and name the cost?
Common Mistakes
Mistake 1: Reading the code aloud
A reviewer can read code. Explain the decisions, the shape, and the reasons.
Mistake 2: Presenting only the happy path
If every scenario succeeds, the reviewer will find the failure case for you. Show one failure.
Mistake 3: Hiding the rejected alternatives
- Incorrect: "I used a policy class because it is best practice."
- Correct: "I used a policy class rather than a method on
Loan, because rates may vary. The cost is one more class."
Mistake 4: Defending instead of discussing
Replying "it works" to a structural comment misses the question. Ask what the reviewer expects to break.
Mistake 5: Over-long rationales
Two pages of prose are not read. A half page with a diagram and one scenario is.
Exercises
Try each exercise yourself before opening the solutions.
Level A: Foundation
A1. List the five parts of a half-page design rationale.
Show solution A1
A1. Problem; main classes; key decisions and trade-offs; risks; next steps.
A2. Rewrite as a real decision: "I used an interface for the notifier." Include choice, alternative, reason, and cost.
Show solution A2
A2. For example: "I used a Notifier interface rather than a concrete EmailSender in the coordinator, because the channel may change to SMS. Cost: one more type to read and a constructor argument."
A3. Why should you pick one normal and one failure scenario for a walk-through?
Show solution A3
A3. The normal case shows the structure working; the failure case tests the rules and the error handling. Together they reveal missing responsibilities with little time.
Level B: Application
B1. Write a five-line rationale for the bike-sharing design from lesson 1 (Station, Dock, Rider, Bike, Ride). Include at least one rejected alternative.
Show solution B1
B1. For example: "Problem: riders unlock bikes from docks and return them to any dock. Classes: Station owns docks; Dock holds at most one bike; Ride records start dock, end dock, and times; Rider owns its rides. Decision: Ride is a class, not a field of Rider, because it carries its own facts; I rejected storing times on Bike, because a bike has many rides. Risk: no rule yet for a rider holding two bikes. Next: pricing as a separate policy."
B2. A reviewer says: "Bike and ElectricBike should be two classes." The only difference in the requirements is the battery level. Write a reply that discusses the comment and states what you would decide.
Show solution B2
B2. For example: "If only the battery level differs, a field batteryLevel (or nullable) on Bike does the job, and a subclass would only carry data. I would keep one class for now and revisit if electric bikes get different behavior, such as charging rules. Is there a rule in the requirements I missed?" It discusses, gives the reasoning, and states a decision with the condition for changing.
B3. Give a specific, useful review comment on this fragment: Library.lend contains if (member.loanCount() >= 2) throw ....
Show solution B3
B3. For example: "The number two now appears in Library and, presumably, in Member. Could Member.canBorrow() own the rule, so Library asks instead of counting?" It is specific, names the class, and suggests a change.
Level C: Challenge
C1. Critique this rationale: "My design is clean and follows OOP principles. Everything is in classes. It is easy to extend." What is missing, and what would you ask the author?
Show solution C1
C1. It names no problem, no classes, no decisions, no rejected alternatives, no risks. "Clean" and "easy to extend" are claims without evidence. Ask: which rule lives where, what variation did you expect, what did you reject, and how would I add a new fee rule?
C2. You disagree with a review comment and, after discussion, the reviewer still disagrees. Describe what you write in the rationale and why.
Show solution C2
C2. State the comment and your decision in the Risks or Decisions part ("Reviewer suggested X; kept Y because Z; revisit if W"). The disagreement is then visible and the reasoning can be checked later. It is not a defeat for either side.
Mini Challenge
Take the design you made in the Mini Challenge of lesson 1 (or any small design of your own) and write a half-page rationale with the five headings. Add a three-line walk-through of one normal and one failure scenario. Then swap with another learner, or read it aloud to yourself in two minutes, and write down one comment you would make on it.
Check your work: you have at least two decisions with a rejected alternative and a cost each, and one honest risk.
Summary & Next Lesson
Key takeaways
- A rationale has five parts: problem, main classes, decisions and trade-offs, risks, next steps.
- A decision names the choice, the rejected alternative, the reason, and the cost.
- Walk through one normal and one failure scenario with the diagram.
- State weaknesses yourself; it builds trust and informs the next reader.
- Treat review comments as comments on the design: listen, discuss, decide, and write the outcome down.
Next lesson
Next is "Demo: modeling the parking garage from requirements". You will apply the whole module to a new domain, from the text to a working design, including a planned mistake that grows a god class, and you will write a short rationale at the end. It prepares the module's lab.
Self-check
- What four parts make a design decision?
- Why name the alternative you rejected?
- What is a scenario walk-through for?
- How do you respond when a reviewer finds a real flaw?
- What should a good review comment contain?
Show answers
- Choice, rejected alternative, reason, and cost.
- It shows the choice was deliberate, lets the reviewer check your reasoning, and records the cost.
- To follow the objects through a case and reveal unclear responsibilities.
- Acknowledge it, decide whether to change the design or record it as a risk, and write down the outcome.
- A specific location, the concern, and a suggestion to try.
References
- Wikipedia, Class-responsibility-collaboration card. Supports the idea of reasoning aloud about what each class is responsible for and which classes it works with.
- Wikipedia, Single-responsibility principle. Supports separating things that change for different reasons, the basis for the policy-class decision in the examples.
- Not verified against a primary source: the five-part rationale template and the "choice, alternative, reason, cost" form (taken from this module's course notes and common design-review practice), and the remark that architecture decision records record context, decision, and consequences, which we did not check against a primary page.
Practice
Apply this lesson with the module's lab, exercises and quiz.
Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.