Avoiding Technical Debt: How to Accumulate Technical Savings

sisyphusThe metaphor of Technical Debt has been widely accepted as part of the current reality of software development. Programmers agree that they frequently need to make sacrifices in order to meet deadlines, and the consequences of these sacrifices are modules that should be redesigned in the future.  In order to “pay” the technical debt, Refactoring became a routine in the development process, and Test-Driven Development helps assure that these constant refactorings do not break working code.

I don’t feel comfortable with this reality. I think that software developers should not incur technical debt so easily. And I think software developers are wasting too many efforts with constant refactorings, what has been called “Refactor Distractor”. In my opinion, the right way to fight technical debt is to accumulate Technical Savings.

Technical Savings: Well-designed code, planned to satisfy future needs. Technical Savings are a form of wealth that makes a module more maintainable, extensible or reusable.

Now the question is: How do we accumulate Technical Savings?

We can save money when we earn more than we spend. If our earnings are the result of our work, then if we are saving money we could say that we are actually working more than we need. But we all understand the importance of having savings in our bank account, because we know that we may have more needs in the future.

Exactly in the same way, Technical Savings are the result of some extra work. We must invest in the design of our modules so that they are indeed more maintainable, extensible and reusable. But we must believe that this investment will pay itself in the future. If done right, the efforts invested in accumulating Technical Savings should be smaller than the efforts required in the alternative of incurring technical debt and then paying this debt through successive refactorings.

Technical Savings and Adaptable Design Up Front

In some of my previous posts, I’ve described my approach of Adaptable Design Up Front (ADUF). The key idea is that software systems must evolve, and that this evolution must be supported through well planned, adaptable designs.

In other words, there will always be changes, either in the form of new features or modifications in the original requirements. One option is to implement these successive changes as they happen, what inevitably will cause technical debt and the need for refactoring. Another option is to be aware that these changes will happen, and to plan our systems to accommodate these changes as easily as possible. A design that is planned to accommodate change is an adaptable design.

In one of my posts I explain how adaptable designs can be implemented through frameworks and platforms. In this same post I talk about the importance of decoupling through Design Patterns and about the need of Domain Modeling.

In another post I explain how adaptable designs should actually be an application of the Open-Closed principle. Our design will be really adaptable only if it has some parts that do not need to be changed, and if the parts that may change are easy to change.

In Summary

It is possible to avoid the trap of constant debt and refactoring. We may accumulate Technical Savings, a form of wealth that makes our modules more maintainable, extensible and reusable. One approach to acquire these Technical Savings is trough Adaptable Design Up Front.

About Hayim Makabee

Veteran software developer, enthusiastic programmer, author of a book on Object-Oriented Programming, co-founder of the International Association of Software Architects in Israel.
This entry was posted in Adaptable Design, Refactoring, Software Evolution, Software Reuse, Technical Savings and tagged , , , . Bookmark the permalink.

22 Responses to Avoiding Technical Debt: How to Accumulate Technical Savings

  1. Mark Swanson says:

    Yes and no.
    There is a lot of evidence that we are poor at predicting future requirements. Which means that implementing code to handle future features is often a waste of time. That is, after all, one of the central themes of the agile movement. Develop the most important features needed now now. An easily adaptable or configurable framework can possibly simplify future changes but they are very hard to do.
    However, the Technical Successes one can acquire early lies in development practices and designs styles, the lower level frameworks and infrastructure. As an example adopting ServiceMix, SOA and OSGI reduces the cost to do integration tasks. Creating a scalable, robust infrastructure or a common security solution reduces redundant effort and the typical newbie mistakes that arise if each app does them itself. What makes these practical is that one is not trying to solve future problems but rather creating sharable services and development practices (e.g. actually using them) that solve current persistent complicated problems.

    • Thanks for your comments, Mark. But in my view Technical Savings are not about “predicting future requirements”, they are about the essential software quality attributes of Maintainability, Extensibility and Reusability. In my opinion these are required in all software systems, and not optional.

      In contrast, Technical Debt is only possible when programmers focus on a single quality attribute: Correctnes. Then they can write “quick-and-dirty” code that satisfies all functional requirements.

  2. Tom Q says:

    If Maintainability, Extensibility and Reusability are not among the system requirements, then any extra effort expended to insure them is neither technical savings or debt, but rather, immediate cost. The desire of engineers to do good work aside, whether these attributes are optional or required is a business call, and not an engineering decision. All other things being equal, everyone wants “quality,” but quality is never free. The “-ilities,” particularly the three you mention, have to be called out in the requirements and designed into the architecture to be effectively implemented – expecting individual developers to make decisions at the component implementation level, without a great deal of coordination, is a recipe for requirements creep, and could foster a growth in technical debt as other features are slighted in efforts to increase one of the “-ilities” of more interesting sections of code. If those “ilities” were requirements, they would be built into the schedule, and would be a net neutral for technical debt (and also savings, since those attributes have already been planned into the budget).

    • Thanks for your comment, Tom. I agree that the “-ilities” must be planned and “designed into the architecture to be effectively implemented”, and that’s exactly what I propose in my approach of Adaptable Design Up Front.

      But I think we can still call them Technical Savings as a metaphor, because these “-ilities” are planned to satisfy future needs, just like financial savings.

      If Technical Debt is poor design that will require refactoring in the future, then Technical Savings is good design that will reduce our efforts in the future.

  3. Hayim,
    I think you may have misinterpreted Tom Q’s point. Adaptable Design Up Front incurs an immediate cost that is only justifiable if adaptability satisfies a business requirement.

    If no business requirement demands that level of engineering, then it should be thought of as YAGNI – You Ain’t Gonna Need It.

    • Thanks, Seb. In my experience all software systems must have some level of adaptability, with the possible exception of simple prototypes and proofs-of-concept.

      Of course there are also several possible levels of adaptability, and I agree that the YAGNI rule should be applied to avoid over-engineering. Experienced software developers should be able to find the right balance between flexibility and simplicity.

    • Ken Grubb says:

      This can be a balancing act between over-engineering and consistency. A component that is over-engineered for X, but already designed, tested, and in use for Y, and which could be implemented for X with small changes, then it makes sense to do it.

  4. Interesting post, Hayim. Its absolutely true that the design and quality of a codebase affects its ongoing capacity for adaptation and new features. But I am not sure that “technical savings” is the best metaphor for this. When we save money, we are storing up a completely fungible resource which is generally assumed to be applicable to any sort of future problem.

    The problem with software design/development is that there really isn’t a direct analog to some completely fungible resource in software development. Every decision is a commitment, and each commitment carries the software in a particular direction. So I think it can be a mistake to assume that any particular class of activities will be applicable to absolutely any future situation.

    But again, while I am nitpicking the metaphor, I agree the point you are making is valid and important. When we are developing systems, we have to keep our eyes open, and take time periodically to cultivate the design and to think about the 10,000 foot view of the system in which we are working. This helps us avoid needlessly closing design doors which do not need to be closed, or adding drag which prevents future adaptability. Great writing, keep it coming!

    • Thanks, Joel. I wanted to convey the idea that it’s possible to have the opposite of technical debt. It’s possible to write code that is easier to maintain, extend and reuse. If you agree, the metaphor itself is less important… :)

      • Tim Bond says:

        It is not just the metaphor that is weak here it is the justification for the idea. Spending time making code some component more adaptable is not guaranteed to be time well spent. Adaptability is a good thing but you can certainly take it too far. So how much is the right amount of adaptability? Experience will give us some good indicators but if you wait for an actual concrete requirement then you know you are adding value.

  5. Pingback: Technical Debt – What it is and what to do about it | Form Follows Function

  6. morgma says:

    There is more to this than making an intelligent design tradeoff. Typically, this is the software engineer’s favorite double speak for doing what was fast, simple and stupid. Yes, it’s obvious I can’t foresee the future – or can I? I bet I’ll have to log errors, authenticate users or persist data in the near future! Simple areas that ar often glossed for the sake of so called design tradeoffs. Building software isn’t like building a structure. A civil engineer may not build a bridge with materials to withstand huriccane force winds across an inland river. However, building software leverages the material of the human mind – you do not start from scratch each time. Technical savings is also found in the technical aptitutude of a team that consistently exceeds the immediate needs. These arguments that we should build to the specifications religiously are akin to excercising at the gym, lifting roughly equivalent to only what you may reasonably expect to encounter on that particular day. No, we build better if for no other reason, when the project demands quality, it will not be the first freaking time they attempt to deliver it.

  7. Pingback: 关于何时偿还技术债务的建议 | DiggerPlus-一个有范儿的测试人垂直社区.

  8. Pingback: Coping with Change in Agile Software Development | Effective Software Design

  9. Pingback: The End of Agile: Death by Over-Simplification | Effective Software Design

  10. Pingback: Slide Deck for So Long and Thanks for All the Tests | Scottish Developers

  11. Pingback: Antifragile Software Design: Abstraction and the Barbell Strategy | Effective Software Design

  12. kpadmanabhan says:

    It is interesting to think of a metaphor opposite to Tech Debt.

    Any design or architecture decision taken in the early stages of project considering the business POTENTIAL than the current need, which turned out to be helping can be a win.

    It can be
    a. an educated guess the architects took based on the previous experience or from a design or architecture pattern
    b. adapted from best practices for business domain (in TOGAF they are refferred to as Reference Models)

    Is it a savings? In scrum, it will be a win in terms of effort /time for a producing a feature or a set of feature. It is hard to think of it as savings.

    Because, YAGNI and Scrum or any agile practices as far I know cannot measure anything that is done for a future need.

  13. Pingback: Technical Debt – What it is and what to do about it | Iasa Global

  14. Great idea. A detailed process and procedures to do what you propose are described in the following:
    • O’Brien, Wayne. “Avoiding Semantic and Temporal Gaps in Developing Software Intensive Systems.” Journal of Systems and Software 81 (2008): 1997-2013.
    • O’Brien, Wayne. Breakdowns in Controls in Automated Systems. Saarbrucken, Germany: VDM Verlag, 2008.

  15. Pingback: Re-Post: The End of Agile: Death by Over-Simplification | Youry's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s