Free through lesson 3

Intro to Design & Refactoring

From naming, splitting up functions, and early returns, through SOLID, dependency injection, ports and adapters, characterization tests, and ADRs. Across 30 lessons you'll get to the point where you can turn "working code" into "readable, easy-to-change code." Every lesson lines up a before and after in both Python and Java, and confirms with a test that the same input still returns the same answer.

Curriculum

The 30 lessons are split into 6 chapters. We recommend working through them in order starting from Chapter 1, but feel free to skim just the parts you're curious about. * The code was actually run against Python 3.14 with pytest 9, and Java 21. Lessons that only need the standard library let you run before and after right in the browser and compare them. Try the pytest and Java tests locally.

Chapter 1 — Start with Readability (lessons 1–5)

Fix the things that snag you the moment you read the code: names, function length, comments, and nesting depth. We finish by learning to spot magic numbers and duplication as "code smells," giving you a checklist of what to fix.

Chapter 2 — Organizing Functions and Data (lessons 6–10)

Rebuild the shape of your logic and data with function extraction, removing duplication, and parameter objects. We finish by separating side effects from queries and updates, arriving at functions that are easy to test.

Chapter 3 — Principles of Object-Oriented Design (lessons 11–16)

Confirm each of the five principles — single responsibility, open/closed, Liskov substitution, interface segregation, and dependency inversion — one lesson at a time, each with a before and after. We finish by layering all five onto a single piece of code and seeing how the principles reinforce each other.

Chapter 4 — Cutting Dependencies (lessons 17–22)

Use dependency injection, ports and adapters, and layers to separate your core logic from the database, the clock, and the network. We finish with an exercise where you combine all of it to build a mini app yourself.

Chapter 5 — Letting Tests Protect You (lessons 23–27)

Learn to capture how untested code behaves right now, find seams to work through, and safely refactor in small steps. We finish with an exercise where you rebuild a legacy function while tests keep you safe.

Chapter 6 — Keeping It Up as a Team (lessons 28–30)

Turn good design from one person's effort into a team habit with a code review lens, making technical debt visible, and recording design decisions (ADRs). We close out all 30 lessons by linking an ADR back to the code it describes.

Once you finish all 30 lessons, move on to the Intro to Systems Development course, which puts design decisions into your development process, or the Intro to Agile Scrum course, which brings review and retrospectives into your team's rhythm. If you want to go deeper on writing tests, there's also the Intro to Testing Techniques course. All courses unlock with a membership.