I consider myself a journeyman software engineer. I am dedicated in my work to honing and practicing a fine craftsmanship. Having worked in software since 2005 (working in IT and dabbling since 2000), I am fortunate to have worked exclusively on agile teams – I like to say that I’m “growing up agile.”
I consider myself a journeyman software engineer. I am dedicated in my work to honing and practicing a fine craftsmanship. Having worked in software since 2005 (working in IT and dabbling since 2000), I am fortunate to have worked exclusively on agile teams – I like to say that I’m “growing up agile.”A Concept Falls in the Woods...

If a concept in your software is not actually represented in your code, does it really exist?
As a simplistic example, if your customer or user thinks of your application in terms of "notes", but there is no code that describes anything called a "note", that concept is not represented in your code. One significant thing an agile development team can do to make a code base more agile (supple) is to ensure that there is a high degree of correlation between how we describe and think of our software, and how it is implemented.
This is another way of looking at Ubiquitous Language, a fundamental concept of Domain Driven Design. Oversimplified, the nouns and verbs of your system need to be aligned with the nouns and verbs used to talk about the system. But even more essential is the alignment of concepts: words may need to be translated, but it is infinitely more complex to reconcile disparate concepts.
Why is this important? For one thing, aligning the implementation with the picture in the customers' heads reduces a lot of friction in communication while developing features. Additionally, a system that doesn't reflect the mental model that bore it will eventually prove rigid and resistant to new features to: the customer may want something that, while perfectly compatible with his idea of what the system does, is impossible to implement.
When a concept changes dramatically for the sake of a feature (e.g. a major change or addition), we expect it will be a large effort. However, if the concept doesn't change much, but the code does, it's an indication of a departure in the code from the concept.
How does this happen? Basically, the developer conceives different abstractions than the customer, and these are never resolved. This can be caused by poor communication, insufficient design or premature generalization. Most often, we are driven as engineers to provide value by 'translating' the customers needs into implementation instead of fostering and maintaining a ubiquitous language.
Then, down the road, when the customer expects to extend or enhance a concept that's poorly represented, there are no cohesive parts in the code to target. As a result, the developers find themselves doing "shotgun surgery" all over the application to try to get the application to behave as the customer expected.
The value we provide between concept and delivery is not a one-way translation: it's a dialog. Moreover, the apparent simplicity of this idiom should not cause us to pass it over for more complex and seemingly sophisticated solutions.
You can’t spend your way out of technical debt
This also holds true for technical debt in Agile Software Development.
For example, let's think of an Agile XP team. They have this old component - let's say it's a charting component. Tied to this charting component is a significant amout of technical debt. Adding new features is expensive, and there are some bugs. After some exploration, the team has decided they must code a replacement - in parallel and without the debt, this time.
Once they begin working on the replacement, they hit an interesting snag: the old charting tool did a lot of stuff. Bar graphs, pie charts, smiley faces. They use it all over the application for many, many things. It's stated as a requirement that the replacement must - from the start - look, feel and behave like the the old one... just without the bugs (and debt, presumably). Now it looks like the replacement is going to be incredibly costly - perhaps prohibitively so. This isn't a solid way out of technical debt.
This is where it gets tough: the behavior change. The same old requirements/delivery patterns that got you into debt won't get you out of it. It's the opportunity cost of paying off technical debt: you can't buy functionality with the velocity you use to pay off debt. You have to realize that those things we 'got for free' in the past weren't really free, after all. There's no such thing as a free feature.
One thing you could do instead is 'downshift' to incremental development: you get the highest-priority, core-value functionality ready to ship, then you iterate. This is agile 101. Each iteration gives you an opportunity to re-evaluate what you want this thing to do. Perhaps you don't want the same old stuff as before. Maybe you get some innovation out of your technical debt pay-down.
The behavior change comes in forgetting what you already had, and building it right this time by managing the process correctly. You wouldn't design it all up-front, then deliver a monolith of a feature in a green-field situation, don't do it here, either.


