The only constant in software is change. So I guess as developers we should work on getting really good at changing it. Problem is, changing software without modifying existing behaviour is really hard. So what can we do to make it easier?
Welcome to the first episode of Book Club! A serious of articles where I share what I learn or any insights I gain from the books I read. If you want to join me, post a comment or a link to your book club article in the comments below for others to find and join in on the discussion!
The book I’m reading is Working Effectively With Legacy Code by Michael Feathers. I’m going to share what I took away from reading the preface and chapter 1.
By far the biggest thing that resonated with me in the preface is Michael Feathers’ definition for legacy code. I never got around to completing the book but I read the preface over a year ago and honestly it changed the way I think about code.
He says that legacy code is simply code without tests. Here’s a direct quote from the book explaining his stance:
Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.
The first time I read that I was in the middle of transition between projects at work as well as picking up a new freelance project. So my brain was a little taxed and I remember the freelance gig was something I would pick up and what I had worked on the week before would feel like someone else wrote it. And as clean as I tried to keep things, I had started to not bother writing certain tests.
That untested code ended up being really hard for me to change. I couldn’t remember writing so it literally felt like working with legacy code to me and I had only written it a week ago. The definition really hit home while I was going through all that. And so I’ve viewed untested code as legacy code ever since.
There are more interesting things in the preface to talk about, but that was the main highlight for me. If there was something in the preface you thought was worth discussing share your thoughts in the comments, I’d love to hear from you!
Chapter 1 to me was really about dialing in on the core issue when changing software. It gets broken up into different categories of change, and different reasons as to why we change software in the first place.
Changes can be to improve the design of existing code, improve performance, fix a bug or add a new feature. When we’re refactoring or optimizing code we don’t want to add new behaviour, and existing behaviour shouldn’t change. When we fix bugs or add new features, we’re adding new behaviour or in the case of a bug fix modifying existing behaviour. When we fix bugs though, it’s a very small amount of behaviour we want changed. Most existing behaviour needs to remain the same, otherwise we’re just replacing a bug for new bugs.
What each change has in common is that we want to have the ability to add or modify code while preserving existing behaviour. If you read the preface it’s obvious he’s trying to hint that we need tests in order to do this. But I liked that he didn’t mention tests. The chapter gets you to really understand the problem and to think about it before giving you any answers.
One thing he mentioned is developers in large untested code basis tend to make additive changes whenever they can. So if they can add a new feature without having to break apart an existing method or class they will. What’s another
if else? What’s 10 more lines of code in this 300 line method? This class already has 50 methods, what’s one more? Reminds of the broken window theory actually 😉 (I just wrote about that yesterday).
I’ve been there myself. The largest codebase I was in that had no testing was around 600k lines. And yeah there were some beefy classes in there. And although we did tend to do refactorings they always felt super sketchy and they had people on edge. It wasn’t common for a few bugs to find there way into the app after a large refactoring either.
When we did start adding tests those areas of the app got easier to change. But it took a lot of learning. Our first test suite was brittle and slow and it actually made change harder. Refactoring things caused tests to break, but the test suite took so long to run people stopped running it. It wasn’t until we figured out how to write lighter and less brittle tests that we saw the benefits.
Well that’s all my thoughts from chapter 1 and the preface. If you want to join me in reading along, feel free to post your thoughts as a comment below. Or if you have a blog, write an article and link to it — I’ll definitely give it a read. If you don’t have the book already, I’m sure there’s lots of places you can find it but I’ll get a small kick back if you use my affiliate link → https://amzn.to/30qEQBD
If you decide to use it, thank you! Either way thanks for stopping by my little corner of the internet and reading what I have to say!