This talk will provide helpful suggestions on how to deal with the tangled web of legacy code created over time. It will address approaches to effectively plan for refactoring to comply legacy code with a modern framework.
Tanvi starts with the story of Alice In Wonderland, going down the rabbit hole – little does Alice know what lies ahead. She’s lost and confused and doesn’t know how to survive in Wonderland.
This is how Tanvi felt when she joined Yelp. Yelp has a tradition of people pushing code on day one – and it took half a day just to get a trivial change pushed. It was a legacy code base that was difficult to work on. Tanvi had to learn how to survive in this strange Wonderland.
— Web Directions (@webdirections) June 21, 2019
How does the legacy code jungle grow? As the size of the team and code base grows, different styles come into play; and the code starts to get messier. Eventually you find duplication of logic and a tangled set of dependencies that are difficult to unpick.
So why is it a concern? If your application isn’t going to be kept, not so much. But if you need to keep growing and extending the application, it causes problems:
- architectural decisions – scalability, re-usability, ownership and tight coupling
- maintenance – code gets more complex, changes take longer, deployments take longer
- testing – code gets harder to test, particularly when “we’ll come back and write tests later”. Legacy code bases rarely have sufficient tests.
- performance – the multiple layers of tangled code slows down the app. It can help to set a time/performance budget.
So how do you fix it? There’s no one-size-fits-all solution.
- This may mean taking preventive measures – this may happen when you recognise the problem, looking ahead and realising you need to make changes to avoid future problems.
- Recognising the problem: tight coupling of unrelated code, frustrated devs, slow updates.
- Forsee the future: don’t fall for immediate gratification. Put your foot down if you have to.
- Control adding new code – avoid adding to legacy, invest in training, use code guards.
- rewrite or iterative fixes? This depends on the team and context. Do you have the opportunity to shut down the app or parts of it, to rewrite?
- smaller refactors are usually the way to go – break it up into smaller chunks, that can be more easily addressed and subsequently monitored
- broadcast information – educate everyone about the refactoring that’s going on
- monitor with metrics – invest in writing tests, monitoring and error detection (including client side with tools like Bugsnag)
- dark launch – run experiments and test with small cohorts, monitor before rolling out to 100%
- automated refactoring – Yelp built their own tool ‘Undebt’ that defined complex find/replace rules in a python tool
— Connor Deckers (@connordeckers) June 21, 2019
- the frontend changes relatively quickly, so it’s likely you’ll need to change your UI at some point
- have good reasons to migrate – FOMO/“I like X” is not a good reason
- define ways to do it – create a proper technical specification (Tanvi showed an example of a formalised tech proposal and project plan)
- identify components that can be migrated – example of changing a spinner from jQuery to React
- define strategy – are you using any common components that you can refactor in place? what infrastructure will you need? who are your supporters in the organisation and how will they get involved? what metrics and monitoring will you use?
- monitor the results
- build a case study – it may be useful to others, so share the knowledge
- run retrospectives – what might you do differently in future?
- broadcast that information in your community
Legacy is a natural phenomenon, migrations are inevitable. It takes planning, communication, patience and dedication.
Escape from the Wonderland of confusion!