Skip to content

Unit 1 — Design in the small

Weeks 1–5. Reading code you didn't write, naming what's wrong with it, and changing it without breaking it.

A bridge is finished. Software never is — we expect to modify it for as long as anyone uses it, and usually by people who weren't there when it was written. So the question that matters isn't does it work? but what will the next change cost?

This unit answers that at the smallest scale, where every caller is still in your diff. You can see everything, you can change everything, and you can fix every call site in the same pull request. That's a luxury — unit 2 takes it away — but it's the right place to learn the vocabulary, because here a mistake is cheap enough to undo.

It makes cost of change measurable first, then does something about it.

Lectures

LectureWhat it answersRead before
The cost of changeWhy does change cost anything?TBD
Measuring a changeHow big was that change — and which dimension actually hurts?TBD
Cohesion & connascenceWhat belongs together, and what kind of agreement makes change hard?Design Principles (cohesion only)
Refactoring as a disciplineHow do I change it safely?Refactoring
Polymorphism & LSPWhen is it safe to substitute one thing for another?Design Principles (SOLID)
What makes code testableWhy does code resist testing?Testability
Seams & dependency inversionHow do I get control of something I don't construct?Testability · Design Principles (SOLID)
Patterns: Adapter & CompositeWhat does polymorphism buy at a boundary you don't own?Design Patterns
Patterns: Factory & DecoratorWhat does delegation buy once it goes through an interface?Design Patterns

Slides are posted on the schedule as we go.

By the end of this unit you can

Measure a change

  • Describe a change in terms of magnitude and footprint, given a diff, and say why footprint is the expensive dimension
  • Draw a dependency graph for a slice of a system, where an edge means "these must change together"
  • Name the footprint smells — shotgun surgery, divergent change, feature envy, onion surgery — and point at an instance of each in real code

Name what you found

  • Use the three axes of coupling — strength, degree, locality — to describe how two pieces of code are related
  • Identify five kinds of connascence (name, type, value, position, algorithm) in unfamiliar code, and say how to weaken one
  • Say whether a module is cohesive, and what it would take to make it more so

Change it safely

  • State what "behaviour-preserving" actually requires, and why it's the hard word in the definition of refactoring
  • Write a characterization test, and explain why encoding a known bug in one is the correct move
  • Use delegation to fix a cohesion problem, and say what moved and why
  • Convert a switch-on-type into polymorphism, and say which coupling axis that improved
  • State LSP as a contract rule — require no more, promise no less — and name four ways a subtype can violate it
  • Explain technical debt in terms of cost of change, and why an incomplete migration can be the right call if it's recorded

Make it testable

  • Given a class and a test, determine its controllability, observability, and isolatability
  • Fix an observability failure by returning a value instead of logging it, and an isolatability failure by extracting the unit you actually want to test
  • Define a seam, and say why an interface with one implementation constructed inline isn't one
  • Reverse a dependency by introducing an interface, and say which side should own it
  • Design an interface around the need rather than the mechanism
  • Name the kinds of test double, say which testability axis each buys back, and say what a test proves once a collaborator has been replaced — and what it doesn't
  • Say when not to add a seam

Compose the moves

  • Explain a design pattern as a named combination of principles you already know, rather than as a recipe
  • Given a pattern, identify the specific conditional or duplicated check that disappears from calling code
  • Recognise a pattern used for its own sake, and name the failure mode that creates

Vocabulary

You'll be expected to use these precisely, in writing, on the midterm and in your project rationale.

cost of change · magnitude · footprint · dependency graph · shotgun surgery · divergent change · feature envy · onion surgery · coupling (strength, degree, locality) · connascence (name, type, value, position, algorithm) · cohesion · refactoring · behaviour-preserving · characterization test · technical debt · delegation · polymorphism · apparent vs. actual type · Liskov Substitution Principle · precondition · postcondition · invariant · ravioli code · controllability · observability · isolatability · seam · dependency inversion · constructor injection · test double · stub · mock · over-isolation · Single Responsibility Principle · Open/Closed Principle · Adapter · Composite · Factory · Decorator

Where this is going

By the end of week 5 you can diagnose a design, repair it safely, and test the result — all inside a codebase you own completely. Unit 2 asks what changes when you don't.

Course reader licensed under CC BY-SA 3.0.