Understand Legacy Code
understandlegacycode.com · Personal blog · on HN since 2020
Understand Legacy Code, by Nicolas Carlo, teaches techniques for working with legacy codebases, including refactoring, testing, and safe rewrites.
What HN saysHN links it for practical advice on legacy code, such as the Mikado Method and strangler rewrites, and commenters discuss testing and microservice tradeoffs it raises.
28HN people shared it
8linked it in comments
53stories submitted
964story points
8 months agolast shared
2020people per year2026
Most-shared posts
- 1Arguments to make managers care about technical debt8 people · 15 points · first shared 2020 · 1 comments on HN
- 2The key points of "Working Effectively with Legacy Code"4 people · 236 points · first shared 2020 · 73 comments on HN
- 3Use the Mikado Method to do safe changes in a complex codebase3 people · 6 points · first shared 2020 · discussion on HN
- 4Techniques to regain control of your Legacy codebase3 people · 6 points · first shared 2020 · 1 comments on HN
- 5Avoid rewriting a legacy system from scratch by strangling it2 people · 398 points · first shared 2020 · 121 comments on HN
- 6Adding tests when you don't have time to2 people · 159 points · first shared 2020 · 66 comments on HN
- 7Refactoring vs. defactoring2 people · 53 points · first shared 2021 · 43 comments on HN
- 8Work faster and safer on untested code with Overcommitting2 people · 3 points · first shared 2020 · discussion on HN
- 9The key points of Software Design X-Rays1 people · 21 points · first shared 2020 · 4 comments on HN
- 10Convince Managers to Address Tech Debt with Enclosure Diagrams1 people · 19 points · first shared 2020 · discussion on HN
- 11Write documentation you don't have to maintain: ADRs1 people · 5 points · first shared 2020 · discussion on HN
- 12Reveal the structure of long methods with an online Word Counter1 people · 5 points · first shared 2020 · 1 comments on HN
- 13What is wrong with boolean parameters? 4 ways to deal with them1 people · 4 points · first shared 2020 · discussion on HN
- 14A quick way to add tests when code has database or HTTP calls1 people · 3 points · first shared 2020 · discussion on HN
- 15Are functions that simply call another function a bad design choice?1 people · 3 points · first shared 2020 · 1 comments on HN
What HN people wrote when they linked it
PaulHoule · 2024-09-19
Software testing practices are still pretty controversial.
I spent about a week redesigning the interfaces of a security-sensitive system to make it testable and developing a test harness, the actual implementation was about a day of work. I felt it was a great use of time.
I have not found an answer for testing React components that seems like a good use of resources. I've tried numerous test libraries from Enzyme to react-testing-library and found them all to be terribly flawed (sorry, if you think "I shouldn't have to modify my code to write tests" and then tell me to "use data-testids" that's the end of the conversation. I have an hour to write a test, I don't have two weeks to diagnose how a third party library I use interacts with the Rube Goldberg machine react-testing-library uses to emulate ARIA support)
Code that is basically "functional" and doesn't interact with a large mysterious system is straightforward to test; a lot of UI code has the issue that it not only calls a mysterious large and complex system but it also gets called by a mysterious large and complex system. I'd really love to have a system that would give me a heads up that some CSS I changed has a spooky effect on a distance on part of the UI because of the complexity of selectors but that's asking a lot
https://understandlegacycode.com/blog/key-points-of-working-effectivel…
makes the strong test that tests have to be really fast because you should have hundreds or…
nerdponx · 2023-12-30
This has been an essential tool for me over the years as a working "data scientist".
Let's say you've been working on an "algorithm", which is a combination of cleverly-crafted SQL to fetch the right data, some ad-hoc data processing code in Python, getting predictions from a model, and some additional mathy stuff to translate the model prediction into something useful. You probably built it interactively in a REPL or notebook environment. You might have some ad-hoc assertions scattered across your scripts, but nothing resembling a test suite.
That's just how things go, and if you did it differently you'd probably never get your work done. But now you have a problem: you have what you believe is a mostly-working/mostly-correct implementation, which you built incrementally and interactively, but now needs to be put into production. Without any real tests, your script has immediately become "legacy code": https://understandlegacycode.com/blog/what-is-legacy-code-is-it-code-w… If things went well, you had time to extract some common utility functions and write unit tests for them, but you probably don't have more than that.
So now what do you do? You want to refactor it into testable units, so you can build out a proper test suite. But you can't refactor code without tests, lest you risk breaking something. You did extensive manual checking and validation of your outputs, but you can't keep doing that over and over.
In this case, the best option that I've found…
egypturnash · 2025-09-08
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 "https://understandlegacycode.com/_astro/ai-support.D3anziw5.css". Anyone wanna lay odds on whether that filename is a big tell that much of the text is also written by three autocompletes in a trenchcoat?
gavmor · 2025-05-05
Michael Feathers, Working Effectively with Legacy Code.
https://understandlegacycode.com/assets/legacy-code-commitstrip.png
carlmr · 2023-06-21
>identifying a logical feature and moving it to a microservice is one of the safer ways to begin a gradual rewrite of a critical system
Why not identify that same logical feature and move it into a library. How does a Microservice add value here?
Identifying, extracting and adding tests to logical features has been the sane way to rewrite software for ages. Michael feathers even wrote a book about it [1]. This ship of theseus approach works because it's incremental and allows for a complete rewrite without ever having non-functional software in between.
Adding a REST/networking/orchestration boundary to make it a Microservice just for the sake of extracting it adds a lot of complexity for no gain.
Microservice can be the right architecture, but not if all you want is to extract a library.
[1] https://understandlegacycode.com/blog/key-points-of-working-effectivel…
mikewarot · 2021-10-27
Wrong link, should be https://understandlegacycode.com/blog/refactoring-and-defactoring/
ptman · 2020-05-08
not revenue gain, but https://understandlegacycode.com/blog/5-arguments-to-make-managers-car…
The_Amp_Walrus · 2020-11-05
I'm working with some researches on about ~40k lines of Python disease modelling code and these are the things that helped us becomes more productive:
- tests (unit, smoke, acceptance) (eg. https://mattsegal.dev/alternate-test-styles.html, https://understandlegacycode.com/approval-tests/)
- continuous integration (via GitHub actions eg: https://mattsegal.dev/pytest-on-github-actions.html)
- 10x performance improvements via cProfile (https://julien.danjou.info/guide-to-python-profiling-cprofile-concrete…
- getting fast feedback on code changes by visualizing outputs with Streamlit (https://www.streamlit.io/)
- input parameter validation (eg. https://pydantic-docs.helpmanual.io/, https://mattsegal.dev/cerberus-config-validation.html)
- total automation of data processing job (eg. https://www.prefect.io/ - we don't use this but that's the kind of thing we have)