Skip to content

Cheatsheet

When… Do… Because…
A small kludge would finish the task faster Don’t add it; spend the extra time Complexity is incremental; working code isn’t enough.
You’re tempted to split a class or method for size Check whether the result would be shallow or conjoined Length alone is rarely a reason; every interface adds cost.
Two modules both know the same format or protocol Merge them, or extract the knowledge behind a simple interface That’s information leakage.
Your modules follow the order of operations Restructure by knowledge Temporal decomposition leaks shared knowledge.
Almost every caller needs a feature Make it the default Make the common case simple (Java buffering vs. Unix I/O).
A lower-level class has a method per UI action Replace them with a few general operations Special-purpose methods are shallow and leak UI concepts.
A class’s methods mostly forward to another class Expose the lower class, redistribute, or merge Pass-through methods add interface without function.
A value is passed through methods that don’t use it Put it in a context object Pass-through variables burden every method on the path.
You’d add a parameter because you can’t decide a policy Compute the value, or give a good default Configuration parameters push complexity up.
You’d throw an exception you don’t know how to handle Define the error away, mask it, or aggregate it The caller probably won’t know what to do either.
An error is rare and unrecoverable Crash with a clear message Handling it adds complexity for little benefit.
Code checks a “doesn’t exist” flag everywhere Represent absence as empty The normal path then covers the special case.
You have your first design Sketch a radically different second one Nobody gets large designs right on the first try.
A comment is hard to write or must be long Rethink the design A hard-to-describe abstraction is a bad one.
You’re fixing a bug in old code Leave the design as if planned for this change The smallest change makes the design worse each time.
You have a “better” convention Keep the old one unless you have new information and will convert everything Consistency beats a marginally better approach.
Code is slow Measure first; seek a fundamental fix; else redesign around the critical path Intuition about performance is unreliable.
Criterion Prefer
Interface vs. implementation A simple interface over a simple implementation
Ease of use The design that makes higher-level code simplest
Generality Somewhat general-purpose: general interface, current functionality
Layers Each layer a different abstraction from its neighbors
Performance Naturally efficient, if just as simple; extra complexity only if hidden or proven necessary
  • Can the operation be redefined so the case is normal? → Define it out of existence.
  • Can a low-level module (used by many callers) recover? → Mask it there.
  • Do many errors end in the same response (such as an error reply per request)? → Aggregate in one handler near the top of the request loop.
  • Is it rare, unrecoverable, and likely a bug (out of memory, inconsistent data)? → Crash with diagnostics.
  • Does the caller need to know to stay robust? → Expose it and document it.
  • Design investment: about 10–20% of development time. Tactical work ends up at least 10–20% slower.
  • Comment cost: comments add about 10% to development time at most (Ch 12), or about 5% if half the lines are comments (Ch 15).
  • Design it twice: an hour or two for a class.
  • Names: two or three words at most; longer names the farther uses are from the declaration.
  • Comments: every class, class variable, and method gets one.
  • Performance (2018): datacenter round trip 10–50 µs; wide-area 10–100 ms; disk 5–10 ms; flash 10–100 µs; DRAM cache miss a few hundred instruction times. Hash tables can easily be 5–10x faster than ordered maps. Ignoring performance can make a system 5–10x slower than necessary.

Shallow Module · Information Leakage · Temporal Decomposition · Overexposure · Pass-Through Method · Repetition · Special-General Mixture · Conjoined Methods · Comment Repeats Code · Implementation Documentation Contaminates Interface · Vague Name · Hard to Pick Name · Hard to Describe · Nonobvious Code. Full table with symptoms in ch21.

  • Planning to clean up kludges later → tactical slide; by then the cleanup takes months that the schedule can’t allow.
  • getCount(), result, status, x/y → vague names.
  • Pair<Integer, Boolean> in a return type → nonobvious code.
  • getParams() returns a Map → exposed internal representation.
  • A reviewer says the code isn’t obvious → “If someone reading your code says it’s not obvious, then it’s not obvious.” Fix the code or comment.