|A||Acceptance Criteria/Test, Automation, A/B Testing, Adaptive Planning, Appreciative inquiry|
|B||Backlog, Business Value, Burndown, Big Visible Charts, Behavior Driven Development, Bugs, Build Monkey, Big Design Up Front (BDUF)|
|C||Continuous Integration, Continuous Deployment, Continuous Improvement, Celebration, Capacity Planning, Code Smells, Customer Development, Customer Collaboration, Code Coverage, Cyclomatic Complexity, Cycle Time, Collective Ownership, Cross functional Team, C3 (Complexity, Coverage and Churn), Critical Chain|
|D||Definition of Done (DoD)/Doneness Criteria, Done Done, Daily Scrum, Deliverables, Dojos, Drum Buffer Rope|
|E||Epic, Evolutionary Design, Energized Work, Exploratory Testing|
|F||Flow, Fail-Fast, Feature Teams, Five Whys|
|G||Grooming (Backlog) Meeting, Gemba|
|I||Impediment, Iteration, Inspect and Adapt, Informative Workspace, Information radiator, Immunization test, IKIWISI (I’ll Know It When I See It)|
|K||Kanban, Kaizen, Knowledge Workers|
|L||Last responsible moment, Lead time, Lean Thinking|
|M||Minimum Viable Product (MVP), Minimum Marketable Features, Mock Objects, Mistake Proofing, MOSCOW Priority, Mindfulness, Muda|
|N||Non-functional Requirements, Non-value add|
|O||Onsite customer, Opportunity Backlog, Organizational Transformation, Osmotic Communication|
|P||Pivot, Product Discovery, Product Owner, Pair Programming, Planning Game, Potentially shippable product, Pull-based-planning, Predictability Paradox|
|Q||Quality First, Queuing theory|
|R||Refactoring, Retrospective, Reviews, Release Roadmap, Risk log, Root cause analysis|
|S||Simplicity, Sprint, Story Points, Standup Meeting, Scrum Master, Sprint Backlog, Self-Organized Teams, Story Map, Sashimi, Sustainable pace, Set-based development, Service time, Spike, Stakeholder, Stop-the-line, Sprint Termination, Single Click Deploy, Systems Thinking, Single Minute Setup, Safe Fail Experimentation|
|T||Technical Debt, Test Driven Development, Ten minute build, Theme, Tracer bullet, Task Board, Theory of Constraints, Throughput, Timeboxing, Testing Pyramid, Three-Sixty Review|
|U||User Story, Unit Tests, Ubiquitous Language, User Centered Design|
|V||Velocity, Value Stream Mapping, Vision Statement, Vanity metrics, Voice of the Customer, Visual controls|
|W||Work in Progress (WIP), Whole Team, Working Software, War Room, Waste Elimination|
|Y||YAGNI (You Aren’t Gonna Need It)|
|Z||Zero Downtime Deployment, Zen Mind|
I had a few interesting take-aways from this discussion:
- A debt always has a notation that you need to pay it eventually (unless you default.) This is not true in case of a technical debt. There might be parts of your code which is a complete mess, but you don’t touch it and its fine to live with that debt. Or you might just decide to throw away that code since it served its purpose. You might never need to pay off that technical debt.
- Deep down in our psychology, the term “debt” trigger a negative thought. We strive hard to avoid a debt. However if you project the same thing as a lease, it seems to have a more positive feel. In the business world, taking on a lease, in many cases, can give you a good business advantage. In fact some might even consider it to be stupid not to lease out stuff.
- The important thing to consider is: what is the “Cost of Service” for a lease/debt? If the cost is significantly high, you are better off not taking it on. But if the cost is really low, it makes all economical sense to embrace it. We’ve learned that long-term, heavy interest leases/loans are a bad idea for that very reason. But a short-term, low interest loan can provide extra working capital to expand business.
IMHO it can really help teams to think of technical debt really in terms of the “cost of service” of a lease.
Beware not to make technical debt a dumping ground for tasks that the team wants to defer without a conscious, thoughtful reason. I’ve seen in many organizations, technical debt becomes an easy excuse for the team to skip things that are very important but for their short-sighted hasty decisions.
- C3: Coverage, Complexity & Churn – Instead of looking at each of these parameters in isolation, we generate C3 graph using a TreeMap and use the cumulative graph to see red spots in the product. Esp. helpful to quickly raise awareness.
- Slack: Every team members gets a 10-20% time every iteration to invest on things that hurt them.
- Scratch your Personal Itch day: Every iteration each team members gets 1 day to fix unplanned issues on the project
- Visitor from Hell: Every month have one person from other team visit you and give you feedback on various aspect of the team. Its up to the team to address these issues or not. But certainly can be used to pitch to the management for additional time to work on these issue.
- Code Walk Throughs: Every time a team member (or pair) implements something important, they give a code walk through or a demo to the rest of the team. This usually ensures team members don’t have crappy things when they give a demo.
Check out the project rescue report, if you would like to see some examples of how we’ve used C3.
Technical Debt is any technical issues slowing down the project due to hasty (short-sighted) decisions made at an earlier point.
All of us make bad decisions, but not fixing them and just differing them really leads to bigger problems as these issues have a snowball effect.
Technical debt can be introduced at various levels:
- Code smells is the most obvious one,
- But things like lack of (or poor) automation,
- poor choice of tools,
- fragility in the development environment
- and so on
can also contribute to technical debt.
Writing ToDos in your code as a reminder that some needs to be fixed is almost considered as a holy grail (universal best practice) to manage technical debt. No one seems to talk about issues using ToDos.
While I’m not against ToDos, I think, in some cases developers build a tendency that:
I’ve put a ToDo, I’ve done my job and now I can move on.
I’ve a problem with this behavior. In some cases there might be tangential work that is worth marking as a ToDo, but in lot of cases what should be fixed now, gets pushed off for later. Slowly the code quality keeps dropping and technical debt sets in.
Building on this thought process, ToDos can encourage wrong behavior of not fixing stuff at the source and pushing them in the future. It’s kind of the broken window syndrome:
There are so many ToDos in this code, one more won’t make a big difference.
Even if someone wants to fix some, looking at the sheer numbers, the person can get intimidated.
Some teams have so many ToDos in their code, that the team develops immunity towards them by now (it losses its value).
So please think before adding your next ToDo.
Recently I spent 2 Weeks helping a project clear its Technical Debt. Here are some results:
|Project Size||Production Code
|Obvious Dead Code||Following public methods:
Total: 7 methods in 4 classes
|Following public methods:
Total: 1 method in 1 class
Note: This method is required by the tests.
|Version Control Usage||
Note: Since we are heavily refactoring, lots of files are touched for each commit. But the frequency of commit is fairly high to ensure we are not taking big leaps.
|Coding Convention Violation||976||0|
Something interesting to watch out is how the production code becomes more crisp (fewer packages, classes and LOC) and how the amount of test code becomes greater than the production code.
During the recent Agile Coach Camp, during one of the discussions, Chet Hendrickson talked about using Pollution as a metaphor to better explain Technical Debt. Following is my interpretation of what he proposed.
Technical Debt is a wonderful metaphor developed by Ward Cunningham to help us think about the problem where the architecture of a large software system is designed and developed too hastily. In this metaphor, doing things the quick and dirty way sets us up with a technical debt, which is similar to a financial debt. Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice. We can choose to continue paying the interest, or we can pay down the principal by refactoring the quick and dirty design into the better design. Although it costs to pay down the principal, we gain by reduced interest payments in the future. The all too common problem is that development organizations let their debt get out of control and spend most of their future development effort paying crippling interest payments.
Another way of looking at this situation is that if your code base has a lot of code smells or bad design decisions that make it difficult to add new features at the same rate as you are used to, then you know there is something getting in your way and bringing down your efficiency. In this state you realize that you have borrowed way too much time from the system by cutting corners. You have not paid back the system by investing regularly in cleaning up the code base.
Even thought this metaphor is really powerful in conveying the messaging that if you continue to hack code, after a while the code and its design will get in your way and stop you from making any real progress due to the heavy interest rates you’ll end up paying.
As Martin points out
The tricky thing about technical debt, of course, is that unlike money it’s impossible to measure effectively. The interest payments hurt a team’s productivity, but since we Cannot Measure Productivity, we can’t really see the true effect of our technical debt.
Also what I have noticed on lots of teams is rarely a developer intensionally introduces technical debt. Today’s quick fix turns out to be a bad hack and that leads to adding to the technical debt. Also like financial debt, technical debt builds up slowly without the team members realizing it. Since you cannot directly measure Technical Debt, the only time you realize you have technical debt is when its too late.
If you really think about it, Technical Debt is a lot like Pollution. Like pollutants in the environment, quick fixes and hacks, degrades the system in which they live. They constantly bring down developer’s ability to build new features (harm people living in the affected area). Pollutants gradually affect people and as time passes by, makes it exponentially harder and costly to fix it.
What is interesting about the pollution metaphor is that few years back who realized CO2 leads to pollution and global warming. But today its all over the place. People driving 2 stroke vehicles never realized that they were polluting the environment. Similarly, few years back who realized Switch Statements are considered harmful? Now with so much emphasis on Code Smells, we can think about these things and avoid some of them.
Also like Pollution, one person introduces a hack into the system and all it’s neighbors (team members and customers) suffer from it. Note that you don’t suffer as soon as you introduce it, its only after delta T that you start feeling the pain.
The biggest problem I find in dealing with Technical Debt is that one man’s elegant solution might look like another man’s hack. Terms like “clean”, “simple” are very relative. To make matters worse, today’s elegant solution might look like a hack tomorrow to the same person. We constantly keep learning better and simpler ways to do things. Tools and languages are constantly improving and getting powerful. What bothers me the most is that people talk about Simplicity as if it were one thing. Unfortunately, simplicity is not as Black and White as I would have liked it.