Saturday, November 04, 2017

Refactoring Legacy Systems

In his book Working Effectively with Legacy Code (Robert C. Martin Series) Robert C. Martin defined legacy systems as systems with no unit testing code.

I have many experiences working with and refactoring legacy systems. Usually, the moment the word "refactoring" pops up in our head, is when the system is too messy and not just without unit testing:

  • The whole system is monolithic. It only can be divided into modules conceptually, but not physically. That is you can never successfully compile part of it separately. 
  • Modules boundaries are blur. No clear responsibility is defined and followed.
  • Dependencies are complex. Singletons are defined and referenced everywhere.  No only they are depended, themselves are dependent on our singletons.
  • ...
In my experience, to successfully refactor a legacy system, I usually go though the following steps:

Refactor building scripts to allow build modules separately. I usually refactor module by module: that is by extracting a cohesive collection of responsibilities into a sub module once at a time. The may depend on other refactored modules, but they should never depend on the monolithic chunk they are originally extracted from. Building modules separately is a good sign of dependency decoupling.

Setup testing environment. The most significant obstacle in refactoring is not that we don't know what's the right thing to do, but that we are afraid that bugs may be introduced. Martin suggest that characterization test code that define existing behavior should be written first. After that we can be more confident when modifying code.

Define and refactor out modules one at a time.  I define modules by their responsibilities. Cohesive responsibilities can be put into one module. Then the real job of code modification begins. Both Robert C. Martin's book and  Martin Fowler and Kent Beck's book gives lots of techniques to show you how to do this.

Write demo programs if unit testing is hard. To be honest, some modules are very hard to unit test, such as 3d rendering related modules. But we can always write some demo programs that uses the module we have just refactored to show that it's self functions is complete and correct.

Some more advice are:
  • Choose a good IDE differs a lot. To be more specific, I strongly recommend Intellij IDEA which I think is a must have tool for me when refactoring.
  •  Decoupling dependency is the most important job. Even if it may introduce some ugly code during the process, you should finish decoupling first. After that, more refactoring is very easy, and that's when you can fix these ugly code introduced earlier.
  • Read Robert C. Martin's book first before you do any refactoring job. It's very practical.

0 评论: