I’d bookmarked this video to watch when I got back from break, as it seems some more of my work is running into “this is legacy code” issues:
I’m pretty sure I found this by looking for talks on refactoring legacy code on YouTube or in some way, and behold! Also, this reminds me that the Tech Talk Watch Club site has run out of content, and hey, since I’ve started watching talks every so often maybe I could fix that. Idea.
Nayan Hajratwala talked about refactoring legacy code, with the framing of the four rules of simple design. I forgot that this would mean he’d be talking about the four rules that are the same ones Corey Haines discusses in a great book on this and the Turing-Incomplete podcast talked to him about it in 2014, if you want to listen (TIME, what is TIME).
- Passes the tests
- Reveals intention
- No duplication
- Fewest elements
Nayan starts with the simple rules applied to legacy code with the fourth rule, which is basically “stuff, have less of it” — a good 10 minutes of the talk is Nayan running Eclipse’s “find unused stuff” plugins and deleting — it takes multiple rounds because once you delete something, you find something else that was referring to it, that can now be deleted, and so on! This was about 10 minutes, but by that I don’t mean to imply it was boring, Nayan has screencaptures sped up in the background while he talks, so you can see what’s happening but it by no means feels slow or tedious.
After deleting and deleting some more (and then, maybe again for good measure) Nayan renames things so they better reflect what they do. It’s clear now why this is where he started when talking about applying the “rules” to legacy code — first, make it more understandable. Make it more understandable by first getting rid of things that don’t matter, and then make the stuff that’s left make more sense: rename things, extract methods into smaller ones, etc.
The next rule Nayan discusses is “Passes all the Tests” which led to a term new-to-me, a “characterization test” — writing a test that basically calls the method and asserts that it does whatever it does. This is essentially the technique I was searching for a refresher on: how do I write a test for legacy code?
I also like putting this kind of test into its own conceptual category. As Nayan says, if you’re writing a characterization test for new code (versus legacy) it probably means you haven’t designed your current app very well.
Nayan works on this test, letting it fail/find what doesn’t exist and mocking things out until it describes current behavior, and uses code coverage tooling to show “yes, the paths of this code have been tested”. At this point, it’s “safe” to refactor.
Or to put another way, from the perspective of this talk, the pre-work to get to this point is what was necessary in order to touch that line of code and confirm you haven’t broken current behavior. As Nayan says, the first rule of legacy code is “don’t break it”.
Nayan then talks about the third rule, DRY (don’t repeat yourself), which is applied while building out this test coverage and thereafter (tests should be understandable too) — he says go for full test coverage, which I don’t totally agree with, but maybe I should for legacy codebases and the purposes of refactoring them.
Overall, enjoyed the talk! Of course, would’ve enjoyed it in Go, rather than Java tooling, but those are details and I’m sure I can find similar tooling in Go. Plus, I like watching talks from different languages!