8 Tips for Successful Refactoring

Andrei Gridnev
2 min readJan 15, 2019

--

Today my teammates and I have finished a large refactoring project. We’ve spent several weeks on it and achieved excellent results. Our codebase is now simpler, more maintainable and flexible. It has no dead code, and the test suit is now faster. Everything went well. Even better than we planned.

That inspired me to share a few recommendations on refactoring large codebases, based on how our team approached that project.

1. Refactor Towards a Well-Defined Goal

Refactoring should have a purpose. Ideally, its main driver should be the next big feature that needs to be built by the dev team.

Example: for a product with legacy frontend, partially built in Backbone, jQuery UI, and React, the goal could be “to migrate from multiple frameworks to the most recent version of React to prepare for UI redesign.”

2. Break Down Refactoring Into Stages.

Large refactoring projects often include several stages. Stage can serve as milestones to help developers track their progress towards the goal.

Example: for the product from the previous example, stages could be:
1. Migrate from jQuery UI to React.
2. Migrate from Backbone to React.
3. Update React and friends to their most recent versions.

3. Have a Detailed Plan for the Current Stage.

Having a plan is always helpful. However, it is not practical to plan refactoring stages too far into the future because of uncertainty. Break down only the current stage is often sufficient.

A plan for a stage can include several tasks that should take up to one day. Ideally, each task should represent a relatively small piece of work that can be shipped independently.

4. Move Forward in Small Steps.

Implement each task separately. Where possible, split tasks into individual subtasks. Moving forward in small steps allows to switch to emergent work such as bug-fixing or to respond to an urgent feature request at any time during refactoring.

5. Integrate Continuously.

Make sure the refactored code gets into the mainline as soon as possible to ensure your teammates who are working on new features can branch out of already refactored code. Avoid keeping long-running refactoring branches. Otherwise, the refactored and original code may significantly diverge over time and developers will have to deal with painful merge conflicts.

6. Parallelise Work.

If work is broken down into small tasks, there is a good chance that some of them can be done in parallel. That means several developers can work on refactoring and get it done sooner.

7. Pick the Right Time.

Choose less busy time to do refactoring: a few weeks after a big release, holiday season, etc. Less feature work happening during that time means that more developers can focus on refactoring and there is less risk in stepping on the toes of those who are doing feature work.

8. Time-box.

Setting a time constraint on refactoring project should help developers to focus on most important tasks and avoid tempting but not very valuable ones. It should also set expectations for the stakeholders.

--

--

Andrei Gridnev

Software engineer, manager since 2002. Engineering management, leadership, software architecture, high-performing teams, professional growth.