Refactoring with Fire

You are a responsible agile developer, practicing TDD and keeping your code  clean through refactoring.  Your “bar” is always green, but are you  living and developing in a world of “false green”?  Is your green bar  continuous or is it only measured at points in time – when you run your  tests, for example?  At the Lean Conference in April,  Joshua Kerievsky gave an excellent presentation titled “The Limited Red  Society.” A summary of this presentation can be found on Joshua’s site and the video can be found here. Synopsis: In application development, we need to be aware of the state of  our code at all times, not just when we run our tests.  In the real  world, things may break at non-ideal times, like during the middle of a  refactoring, and we must fix them. Joshua’s session really hit home  about a month ago when I felt like I was refactoring with fire.
To set the stage, I was working solo on some custom code for a  customer.  I developed it test-driven and had solid tests.  After I  delivered the code to the customer, I saw a great spot for refactoring  and simplifying the code, so I dove in.  Then the customer came back with  a change…but I was in the middle of refactoring! The change would  only take me about 10 minutes but the refactoring session would last  another hour or two to get to the point where I wanted it.  Right then I  felt like I was refactoring with fire.  This was only a 10 minute  change, but a production emergency could go on quite a bit longer and I  would be leaving my codebase unstable. I vowed to not let that happen  again.

Fast forward to last week.  I am working on some more custom code for  a customer.  Without getting into too much detail, the application was  building relationships of work from VersionOne.  The application was  originally implemented with one level of relation – parent to child.   After some discussion, we came up with a story where the relationship  would need to be up to eight levels deep (parent to multiple children to  multiple children and so on).  My tests are solid so I was comfortable  making the change, but I knew it would impact quite a bit of the  system.  If I was to make the relationship-building recursive, it would also impact how I query and report out data.  What to do…I said “Don’t  play with fire.”

I used Parallel Change in this approach to make sure the codebase was  available in the event of an emergency. In the software development process, Parallel change is creating  and working on new functionality without connecting into the main  process flow.  We have all used parallel change before.  I wasn’t using  it often enough.

Here is what I did …  nothing groundbreaking mind you, but by  employing this approach, I was able to deliver my code continually while  the large change was worked out.

  • Create new tests for my new recursive relationship  builder (using mocks to simulate the result from the query)
  • Implement enough code to make my test for the relationship builder  to test (all older tests will be passing and remain passing as they  haven’t been modified)
  • Add more new test cases around the relationship builder
  • Add code to make these tests pass
  • Rinse and repeat for the other new areas of functionality  needed – the query for the data and the structuring of the data for  reporting in this case
  • Once I have completed the tests for the independent levels of  functionality, write the integration tests around the cumulative effect -  query, build relationship, structure data for reporting

Only after my tests pass in that last step do I cut over my app to  use this new flow.  With this approach, my code could have been put on  hold at any point and been stable for a production release.

Challenges with this approach:

As with any code, higher coupling and multiple responsibilities in  objects and methods will make Parallel Change more difficult.  Think of a  highway.  If it is a simple highway (2-way traffic, not multiple on and  off ramps) then building a parallel highway is simple – you run a new  straight stretch of road, and once it is done you cut over the entry and  exit points for the new road. Just like your code – if it is a straight  run, Parallel Change will be easy.

If the highway has multiple on-ramps, off-ramps, a railroad crossing, and a wandering herd of yaks in the middle – then building your parallel  road to that is going to be very difficult.  With that scenario, you’re  obviously better off simplifying the highway before you try and create  the new stretch of road.

Interested in learning more?  Check out Kent Beck’s presentation on Responsive Design or Joshua Kerievsky’s presentation  The Limited Red Society.

This entry was posted in Agile Development, Test Driven Development. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>