This Hacker News discussion revolves around a book about working with legacy code, eliciting a wide range of opinions and experiences from developers. The core themes emerging are the definition and approach to legacy code, the role and challenges of testing, the nature of refactoring, and the practicalities of navigating organizational resistance.
Defining Legacy Code
A central point of contention is what constitutes "legacy code." While the book's premise is that "legacy code is code that is untested," some participants offer broader definitions.
- "I think a more accepted definition would be that it is not well understood, uses old tooling/languages/runtimes and is usually high stakes code (driving some business that was successful enough to last longer than the staff that coded it up)." β jbjbjbjb
Others agree with the book's definition, or at least find value in it.
- "I read through this book relatively recently and agree with the praise here for the core idea that legacy code is code that is untested." β allemagne
The idea that "All code is eventually legacy code in one way or another" is also put forth, highlighting the transient nature of "new" code.
- "All code is eventually legacy code in one way or another, whether it's the code directly, or the infrastructure level. Today's code might be the best one writes today.. looking back in 5-10 years.. one might wonder if best practice was best practice." β j45
The Role and Challenges of Testing
The most frequently discussed theme is the importance and difficulty of writing tests for legacy systems. The book's core advice is to "write tests first," but users highlight various obstacles.
-
The Necessity of Tests: Many understand the theoretical benefit, especially for new work.
- "When code is not tested, how do you know you didnβt break anything?" β strken
- "Do you trust yourself enough to not break existing code while maintaining or adding features to it? What would be the consequence of you screwing up? Where would your screw up get noticed? Is it a scary person or group of people who will chase you down to fix it?" β ZaoLahma
- "The goal of existing and new functionality is reliability. What you touch will be on you. So writing a test for your own things, and testing what you are using of the legacy code as you go is a good way to maintain your own coverage in case someone else breaks something in the legacy code, or maybe an update to a library or something goes sideways." β j45
-
Practical Difficulties: Users point out that writing tests can be a significant undertaking, sometimes requiring refactoring just to make the code testable.
- "I've made huge successful refactors using nothing but carefulness and manual testing, maybe just a very little bit of unit testing :)" β shahindohan
- "I was glad the author briefly seemed to acknowledge that but still... the pain..." β pkdpic (referring to the difficulty of writing tests for a ginormous legacy codebase)
- "Writing tests yourself? It would require you to put the test framework back in order first, they don't have the budget for that. Something as simple as reformatting the function you are working with is already a luxury." β GuB-42
-
Testing Older/Obscure Languages: The challenge is amplified when dealing with languages not commonly supported by modern testing tools.
- "The problem with real legacy code is that sometimes it's not even in those languages. It's VB.NET, COBOL, AS400, BASIC, FORTRAN...and these may not have a chance to "wrap around your class", or "think about all the ORM code that you use". None! I use none of that!. And I can't even call any tests because I can't extend a non existant class, there's no objects in here!" β Lovesong
-
"Characterization Tests" and Behavior Testing: Some users emphasize testing the behavior of the code rather than its internal structure, which aligns with more flexible testing strategies.
- "You don't want to test code. Code is not what the user care about. You want to test behavior. And for this you don't need to extend classes. You should not have to rewrite any code from your application. Like you say: write tests at the seam. Automate user inputs and checking outputs." β arkh
- "The test suite not only let me validate the implementation, but the exercise of developing the test suite also helped me understand exactly what I should be implementing in the first place." β neilv
-
The "Test Pyramid" Misconception: One user argues that the traditional view of unit tests (close-coupled class-method tests) is outdated and that broader, behavior-centric tests can also be considered effective "unit" tests.
- "The idea that unit tests are only close-coupled class-method tests, or that testing 2 collaborating classes from the same app at once counts as an "integration test" is a latter-day misconception. A dumbing down." β SideburnsOfDoom
Refactoring and Code Transformation
The book's strategies for refactoring and rewriting code are met with mixed reactions. Some find the concepts obvious, while others see value in formalizing these approaches.
-
Obvious vs. Formalized Strategies:
- "I would squint at the introduction to a new term, try to parse its definition, look at the code example, and when it clicked I would think "well that just seems like what you would naturally choose to do in that situation, no?" Then the rest of the chapter describing this pattern became redundant." β allemagne
- "I think of the second half much more as reference. I can give it to a junior engineer or early mid-level and say "here is an example." It gives nomenclature and examples." β ebiester
- "Not everything is obvious to everyone, and it's been 20 years. Regardless of whether people have read the book, the knowledge of these things as grown since then." β michaelfeathers (author of the book)
-
Incremental Refactoring and Feature-Driven Refactoring: Many advocate for refactoring in small steps, often tied to feature development.
- "The approach usually works: refactor in small steps and tie it to a feature so itβs testable and adds value." β zabil
- "Most of my features are implemented as double figures of tiny refactoring commits to prepare the code so that the feature can be implemented in a straightforward way." β tome
- "My feeling about it is that there is not a tension between refactoring and feature work but rather that a specific bit of feature work is best done with a refactoring." β PaulHoule
-
Refactoring vs. Rewriting: The distinction and potential for misusing the term "refactoring" is noted.
- "Nowadays people throw the term "refactoring" around quite loosely, usually meaning "rewrite" when that was not at all the original meaning of the term!" β _mu
-
Alternative Strategies: Strangler Fig and Parallel Runs: Users suggest alternative or complementary strategies for modernizing systems.
- "The only way guaranteed to work is to run the old system concurrently with the new system with live inputs and compare results for a trial period and fixing discrepancies as they arise. Only when there is 100% behavioral/data fidelity with the old system can a switchover to the new system occur." β avgcodor (describing a parallel run strategy)
- "Iβve seen Martin Fowler call something like what youβre describing the Strangler Fig pattern" β grahamplace
- "one complementary general technique that the article didn't get into is that sometimes you can run two implementations in parallel, and check them against each other." β neilv
Navigating Organizational and Management Challenges
A significant portion of the discussion highlights the non-technical hurdles encountered when dealing with legacy code.
-
Management Perception of Refactoring: Executives and management often view refactoring as non-value-adding work, preferring visible feature delivery.
- "now you have to be careful how and when you use the term "refactor" because the people who ought to be supportive hear "wasting time"." β commandlinefan
- "If the choice is thought to be between: delivering value directly to the customer to justify a company's existence, or adding tests to things that already work (shore up) in an effort to make more correct changes in the future. Will anyone be surprised how often it's the former that management will go for?" β drzaiusx11
- "When people ask permission to do make what I thought was the correct change. I don't think I have ever asked permission to do make what I thought was the correct change." β dotancohen (implying the work is done pragmatically rather than by seeking approval)
-
The Political Nature of Legacy Code: Some argue that the biggest challenge isn't technical, but political, requiring constant advocacy and "selling" the value of maintenance.
- "However, the big problem with legacy code is always political. And the only book I've seen ever try to address that is "Kill It with Fire"." β bsder
- "You need to be constantly selling what is going on in front of the important eyeballs." β bsder
-
Lack of Buy-in for Testing: The argument that testing is necessary is often not compelling enough for management if the system isn't currently failing visibly.
- "So if you tell your boss that you are implementing Unit tests in a 40 years old codebase, the first question he is gonna hit you with is "Why?", and the article doesn't give any compelling argument to answer this." β Lovesong
Technical Issues and Ergonomics
Minor but recurring themes include technical issues with how the article was presented, and the inherent complexity of the domain.
-
Website Rendering Issues: Several users reported problems viewing the article on mobile devices or with their browser settings, particularly with dark mode and legibility of pull quotes.
- "The pull quotes are in black on a black background for me on Brave, made it a bit of a confusing read I have to say!" β pmg101
- "All the blockquotes are coming in as black on black for me in Safari, Firefox, and Chrome. This appears to be due to a css file called..." β egypturnash
- "the website doesnt render properly on mobile. the first aid website is unreadable on mobile darkmode" β brainzap
-
LLMs and AI in Legacy Code: The potential for LLMs to assist in understanding and refactoring legacy code is mentioned as a promising development.
- "Since you'll be doing a good job of mapping it out below is something elsee. The nice thing is LLMs can help a lot with writing tests." β j45
- "AI can even explain what most code is doing no matter how convoluted it is. From there, things like test driven development, or test driven legacy code stabilization is much more doable and beneficial not just for the legacy code, but keeping the AI behaving if it's helping with coding." β j45
-
The Depressing Accuracy: There's a sentiment that the discussion is depressing because it accurately reflects the difficult reality of working with legacy systems, a reality that often goes unaddressed.
- "Kind of depressing to read because it's so accurate, yet so likely to be ignored." β commandlinefan