Sunday, May 26, 2013

Agile Development with debt ridden code

Is your code base as messy as this kitchen?

If it is, I am sure it will be slowing you down. Working on technical debt ridden code is very hard to do in an agile way.

This is because the debt: 

  • Limits our ability to easily cut scope to meet our deadlines. (Caused by Coupling)
  • Makes it hard to split the work into small user stories. (Caused by Coupling)
  • Makes it hard to predict when we will be done. (Caused by lack of tests, coupling, defects, unexpected side effects)
  • Limits our ability to work fast, while maintaining high quality (Caused by all types of debt, especially debt with the tests)

Technical Debt that impacts our ability to delivery consistently:

  • Tight coupling
  • Design that limits extensibility
  • Inconsistent design
  • Inconsistent coding style
  • Existing defects, especially hidden/unknown defects.
  • Lack of automated tests
  • Unpredictable/ inconsistent test results 
  • Slow tests 

Recommendation One: Focus on Fast, Reliable Automated Test Results

The aims are to improving the quality & scope of our test suite, along with obtaining faster feedback. Fast, reliable feedback allows the team to work towards their sprint goals in small controlled steps and this improves reliability of delivery. 

Here are my specific tips to achieve these aims:

  • Run the test suite more often. Once a day is rarely fast enough, aim for at least three test suite runs during working hours, more is even better.
  • Increase granularity of reporting; ensure that all tests report their results separately. Watch out for 1 test failing that stops several other tests from running; this results in secondary defects being hidden until the defect causing the first test to fail is resolved.
  • Split up the test suite into separate tests or test groups; run them in parallel on separate environments. You may need to acquire more environments. This does a couple of things; it removes dependencies within the test suite which will likely identify some hidden defects. Secondly it will greatly reduce the overall duration of the test suite resulting in faster feedback.
  • Get faster hardware to run the tests on, resulting in faster feedback.
  • Add more environments, with at least one environment per team; giving flexibility of when/who runs the tests, resulting in faster feedback.
  • Set standards of how tests and test suites are structured. Ensure all new tests are developed to the standard and any exist tests that are ‘touched’ are updated to the new standard. Over time this will improve the quality of the entire test suite.
  • Improve the reliability of the test suite by identifying and removing intermittent tests. Refer to Martin Fowlers excellent article on Non Determinism in Tests for specific approaches to removing intermittent failures.  Also run the test suite on isolated hardware to remove outside influences. 
  • If your tests are running over night, identify regular IT maintenance work that could be impacting on your test results. For example database backups that greatly reduce the speed of the database.
  • Enforce that all new development work has automated tests that cover that work. This is not just for new features/components. Any work on existing code must have tests added, if there are no tests for that area of the code, they may have a substantial piece of work to do. However it does not take long for the extra effort to start paying dividends.

Recommendation Two: Incrementally attack the debt

Fast, reliable feedback allows the team to engage in effective refactoring.  This in time allows them to reduce coupling with their code and also reduce other types of technical debt, which further increases their reliability of delivery. 

With our Fast, Reliable Test Suite in place it is now time to start attacking the debt:
  • Revise the existing Coding standards with a focus on decoupling and consistency. Ensure all new code is developed to the standard and any exist code that is ‘touched’ is updated to the new standard.
  • With each new piece of work that the team is about to start, get them to think about technical debt that is related to this work. Investigate the debt, make it visible, do a cost benefit analysis for the reduction of that debt and involve the Product Owner.

Do you have any other tips for working in these difficult situations?

Photo Credit: independentman    


  1. Start with The Mikado Method ( This will help you get your tangled legacy code under control. Use the techniques in Michael Feathers' Working Effectively With Legacy code to find or create testable seams.

  2. George I have not heard of the Mikado method, sounds like it is time for me to do some research :)

    I am a big fan of the techniques in Working Effectively With Legacy Code and have used it repeatedly to help others start to add tests were there are none. A great tip.

    Thank you for the input.

  3. Thanks for the article Andrew.

    If working in a team, it is worthwhile spending some time encouraging the developers towards a consistent, shared approach to solving problems.

    A good understanding of Design Patterns, SOLID OOD Design Principles, Clean Code etc. can give the developers a common language and understanding of what constitutes good code.

    My preference would be to raise the skills in these areas and have minimal coding standards.

  4. Sean,

    It's my pleasure.

    For sure, increasing your developers capabilities around delivering clean code is really important. I guess I take all of that stuff for granted these days. Yet calling it out and putting effort into improving their skills is crucial.

    For me coding standards should be small enough that they are easy to read and refer to. Any 'tome' of standards will not be read/use so keep it small.