Adrian previously discussed Working Effectively with Legacy Code when he talked about how to choose a programming language for your book. It deserves revisiting though, so here it is in the library section.
Quite simply, if you have not read this book yet, read it. If you have a colleague who has yet to read it, get them a copy. If someone asks you what one book to read about software engineering, it is this one. It is not Code Complete, Second Edition, nor is it Clean Code, nor any other book that claims to teach you how to get software right the first time around (you will not). It is not Programming Rust, nor Programming Elixir, nor any other book that claims to teach you a technology that solves all of your problems (it will not).
All of your code will either be abandoned or become legacy code, so if you do not plan on failing you should learn how to work effectively with legacy code.
The central premise to the book is that legacy code is usually not enjoyed because it is insufficiently tested. And that the way to work with it is to identify few, hopefully not too invasive, changes that allow for parts of the software to be tested in isolation. Once those parts are under test, it becomes easier to make more, perhaps more significant, changes to the parts that are tested to subdivide into smaller testable units. After enough iterations of this you have a system whose behaviour is both described and stabilised by the tests and will be easier to work with.
Why bother with all of this? For the same reason we avoid rewrites whenever a new programming language comes along: the existing software encapsulates both the current behaviour of the software system, and the desired behaviour: whatever the software is supposed to do, people have adapted to whatever it actually does and so that must be a starting point for any future work.
It is all too easy to say “oh the legacy code is really buggy, we should start from scratch” but those bugs are the way the system—not just the software, but the socio-technical system in which it is embedded—works. The ones that have been fixed are hard-fought lessons about what people want from this software. It may not be well-designed—but it may be. What gets called bad design might actually be good design from a few years ago: software design is fad-led, rather than engineering-led. But it may also be the case that a clean design is hiding under the weight of various patches and hot fixes. This is exactly the situation that Working Effectively with Legacy Code will let you take control of: fixing the software towards a clean design without having to let go of the good, valuable behaviour. And of course in this age of Agile®©, we work to the principle that the primary measure of progress is working software. The legacy software already works.
So why do software engineers prefer to start from scratch? Partly it is because programming is a monetised hobby: people enjoy writing software so they will find ways to do that for income. But it is also a matter of capability. A Masters-level course in software engineering contains nothing about reading or adapting existing software; not even anything about buy-versus-build decisions. And most professional programmers are not trained software engineers. Without education or experience at reading, understanding, and modifying existing code, programmers see it as difficult, unnecessary effort. Why waste my time learning from person-centuries of experience at solving this problem, when I can type cargo new and have something that solves 5% of the problem badly in maybe a month or two?
And that is where this book comes in. It is your secret superpower. Learn how to work effectively with legacy code and you will be faster and more capable than almost all of the software writers working today, through this one weird trick: not writing most of the software you need.
Cover photo by Adrian Kosmaczewski.