Much of our work is on applications that are old or were built by someone else. This lesson covers how we make such applications stable and pleasant to work on again.
Important
Work on this lesson in
buildermode.
Learning goals
- You can explain how legacy applications become complex, and why keeping software simple is hard.
- You can explain our approach to adopting a legacy app: end-to-end tests for the happy paths first, tests for everything you touch, improving whatever you work on, frictionless setup and deployment, failure notifications, and regular time set aside for stability.
- You can explain why end-to-end tests, unlike unit tests, survive a refactoring — and why that makes them the first tests to add.
- You can refactor legacy code safely under a green test suite before adding new requirements, e.g. in a kata like Gilded Rose.
Resources
Read what's new to you, skim what's familiar, skip what you already master. Stop when you can meet the learning goals.
Your agent can also generate an overview, a tutorial or an explanation for anything here, tailored to what you already know. Just ask.
- ▶️ Why Can't We Make Simple Software? Show archive.org snapshot — Peter van Hardenberg on how software becomes complex
- ▶️ All the Little Things Show archive.org snapshot — Sandi Metz refactors the Gilded Rose kata live (RailsConf 2014); watch after your own attempt
- 📄 Gilded Rose kata Show archive.org snapshot — our Ruby version with a test suite; the original description Show archive.org snapshot
- 📘 Working Effectively with Legacy Code (Michael Feathers) — the classic on getting untested code under test; check our library
Discuss with your mentor
Talk to your mentor about how we're approaching applications that are either old or abandoned by a different team earlier:
- Add E2E tests for the happy path. Other than unit tests, E2E tests will not break when we refactor later.
- Always add tests on whatever we work on.
- When you work on something, improve that part of the code.
- Make sure setup for a new developer is as frictionless as possible (ideally it's
bin/setup). - Make sure deployment is as frictionless as possible.
- Setup failure notifications.
- Set aside some time every month to deal with the most frequent failure types until you reach an acceptable level of stability.
Exercises
Refactoring kata
Do the Gilded Rose Kata Show archive.org snapshot in Ruby.
The linked repository comes with a test suite for the existing requirements Show archive.org snapshot . Make sure you see a green test suite before you begin to move code around.
It is recommended to refactor code before you add the new requirements (conjured items).