Balancing Technical Improvements versus New Business Features

At the last Agile Austin lunch we were talking a little bit about the infrastructure improvements we’d all like to be making, if only there was time.  We talked about improving our continuous integration builds, retrofitting legacy code with more automated tests, and getting rid of VSS.   One of my friends commented that there were so many things he wanted to improve, but there wasn’t enough time.  I feel the same. 


We want to improve our code and architecture for better reliability and improved efficiency.  It’s not that simple though, because we really need to be creating new business features.  The marketplace is competitive and we’ve got to keep ahead or at least abreast of our competition.  Many of our clients are very large corporations that inevitably have unique requirements, and they need them now!  All the same though, my team is going to have to spend some time dealing with configuration management and access to a shared database or we’re going to create a support monster.  It doesn’t create any apparent business value, but we’re jeopardizing our ability to continue making changes to the code if we don’t get it under control.  The point being, we’ve got some technical debt that needs to be paid down because it decreases our efficiency while increasing the risk of any modification to the code – and the code is always changing.


So we’ve got a common dilemma.  How do we make improvements in the existing code to make us more efficient and reliable while delivering new stuff?  Some times you really have to stop and clean things up first.  How exactly do you communicate this to senior management?  How in the world do you convince management that it’s a necessary task?  How do you quantify the risk of not doing some sort of infrastructure improvement so management can make an informed decision versus new functionality? 


In a prior life as an enterprise architect I failed to convince management to create a proposed naming repository for vendors across our manufacturing, inventory, and supply chain systems.  Without that structural improvement the security model continued to be haphazard and wrongly allowed access to very sensitive data to the wrong folks.  The problem was pretty obvious to me and my peers, but we didn’t manage to communicate the impact of their decision to forego the new naming repository.


Life’s a lot easier when there is a good trust relationship between the development team and the program management.  If that trust isn’t there you might be forced to make the situation worse by ignoring problems or do the right things under the cover of darkness (leading to people burnout).  It seems to pretty natural for project/program managers to mistrust software developers, maybe because they’ve known developers to waste time on unnecessary “goldplating.”  My experience has been that most project managers really don’t have a very good understanding of the technical situation, and I’ve found this to be every bit as true for project managers that are ex-developers.  We’ve got to be feeding them the right information in a way that they can comprehend and they’ve got to be able to have some sort of faith in what we’re saying.  You really need to guard your own credibility by being honest and at least somewhat accurate with management.  Spending months on a failed attempt to rearchitect some subsystem is going to result in a shorter leash.  You might also inherit the mistrust of your management for your predecessors.  That’s a bit unfair, but it’s happened so many times to me that I almost expect it.


Sometimes it’s obvious that you’ve got to clean something up or that doing a refactoring first will make the new functionality easier.  If the situation is really clear, I say you just do it.  You really shouldn’t need to ask permission from a project manager in these cases.  It’s simply a matter of you coming up with the best mechanical path to your end goal.  Anything that is big enough to affect velocity probably needs to be justified to a project manager and tracked as a user story.  That doesn’t have to stop the idea in its tracks, but it makes it harder to get it done.


Other times you just have to bide your time and look for opportunities to make the refactoring work as you’re building new functionality in the same area.  You take an attitude that anytime you make changes in an area of code that you try to leave it in a better state when you’re finished.  Kind of a more active version of the Hippocratic Oath for code.  You make incremental changes to break coupling, increase cohesion, speed up the build time, and increase the unit test coverage whenever the opportunity is presented.  We spend a lot of time being frustrated because we have many more ideas of how to improve things than we really have time to accomplish.  I say that it’s still important to think and talk about the improvements that you’d like to do.  You’ll never make any kind of improvement if you aren’t creating a vision of some kind, and you never know when an opportunity will present itself.


Of course the real answer is not to allow technical debt to build up in the first place.  You simply cannot cut corners in design, coding, or build management (damnit!) and sustain a rapid pace – not even in the short term.  Slacking off on good development practices will make you slower over time.  Another way to say this in MBA language for the suits is “Opportunity Cost.”  When you write badly factored code or skimp on test or build automation you’re making future endeavors more difficult and costly.  Agile development includes the practice of Refactoring.  I’ve often seen an apt analogy comparing refactoring work to washing the dishes in your kitchen (I think it originates with Ron Jeffries, but don’t quote me on that).  It gets a lot more difficult to cook in the kitchen if you didn’t wash the dishes.  Washing the dishes is a lot easier if you do it right after using them. 


It does help if you can just be omniscient and never make any mistakes 😉  Thank you for listening, I feel better now.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at
This entry was posted in Legacy Code. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Brian Deacon

    At least in my experience, the problem has always been to convince management of the value it will bring to projects that are not yet on the table. Most projects I’ve been on have this ugly period right before delivery where we are committing hideous sins against the code just to meet the deadline. Convincing management that the next version will benefit by us fixing the last version is a tough one. It’s already out the door.

  • Darrell Norton

    How do you convince management? A simple benefits analysis.

    Here’s what we plan to do: it’s going to take this long and cost this much (well for developers the cost = time * pay).

    Here are the benefits in the long run: we can do this much more in the same time (which execs can easily calculate the value of), or our quality will go up reducing help desk calls by x% (which execs can also easily calculate the value of), etc.

  • Gary Williams

    There is also the matter of code stability versus testability. The more testable the code is, the less dangerous changes are. Certain areas of code are extremely risky to change, because the ramification are difficult to test – even though it *looks* safe. OTH, technical debt *must* be paid off or the interest accumulating will kill you. So the best solution I’ve found is to have an (evolving) vision of where you are trying to get to and then make changes as you go along to get there. Not perfect, but it has worked for me.

    Also, there is a Boy Scout saying that goes “Leave a campsite in better shape than you found it”, which I think fits this exactly. Whereever your new code camps out, make sure you police the area before you check it in.

  • Shoddy Coder

    Interesting post, and I agree on the just make the change without asking for the smaller changes, and for the bigger changes I like the talking about them for a while approach and then finally just planning in time to do them in an iteration. My project manager has a great deal of trust in my judgement (and I agree about the honesty and integrity point you made…. if you are a pathelogical liar about things, it won’t ever be easy to get time for changes, they will never be deemed as important) and always allows me to build in time both during our release for change as well as immediatley following a release.

    The one point I think I would possibly make though is that “not building up technical debt” is kind of a fallisy; oh sure I believe that refactoring early and often is good practice as is writing good code; the problem with it I have is that as technology changes and as the use of technology changes and as patterns are reworked or our understanding / application of them evolves, our definition of “good code” changes. Thus the conundrum of constantly wanting to make technical improvements. I’ve been a developer for over 10 years, and for at least 5 of those ten years I’ve thought I have written “good code”, however looking back at code I wrote just 2 years ago, I would question that.

  • Brendan Tompkins

    This post really hits close to home. I have a huge laundry list of things that would be nice to do to our architecture. My probelm isn’t so much support from management, because they seem to trust what we tell them has to be done, but how much time to spend doing this.

    My trouble is that most of these things seem to be thought of as Big Up Front Re-design, and as I get into the deep re-factoring, sometimes I find myself thinking “Why am I doing this? It was working afterall” Now, of course I know why I’m refactoring, but point is, there is a point when the re-factoring is just practically taking too much time. Even when mgmnt isn’t breathing down your neck, it just seems like spinning wheels when you’re not making progress.

    I think you hit on the solution, refactoring has to be part of a daily agile process right? It’d be nice if there were some sort of agile methodology for this to guide how much time you should spend doing this kind of work.


  • Jeremy D. Miller

    I’ll have to ask her then. I actually get to meet Mary Poppendieck in a couple of weeks at a little conference here in Austin.

  • Carlton

    I have just been reading “Lean Software Development” and what you describe (balancing infrastructure with new features) rings a bell in my ears. The Lean perspective would say “See the whole picture and beware of sub optimization or local optimization.” Or it might say “What are your constraints preventing you from delivering faster?” If they are serious enough, you might have to “stop the line” in order to fix them.

    I highly recommend reading “Lean Software Development” by Mary & Tom Poppendieck. It is a great book.

  • BSchmitt

    I used the approach that you mentioned, of leaving it better than I found it. I was moving code to base classes, and then as I would encounter the needed function other places, I would remove it and point it to the correct method. I know that you would end up with alot of duplicate functionality in the begining, but it did allow me to refactor while not really taking up much time.

    The other thing that to do is learn to “sell” it to the management, speak in their terms… which is usually $$$. If we spent __x__ days refactoring…Other projects/enhancements will only take….