I have found it’s best to not take tech debt complaints very seriously and instead look at actual success metrics. For example if every change to a bit of code introduces new bugs then that might be a reason to tidy it up.
I have found it’s best to not take tech debt complaints very seriously and instead look at actual success metrics. For example if every change to a bit of code introduces new bugs then that might be a reason to tidy it up.
Complaining about technical debt complaints is an easy way to potentially bias oneself against recognizing real issues before it is too late and everything is on fire all the time. Be wary of any such blanket assumptions in engineering.
Would you agree that we should think about specific issues that are slowing us down, and fix them one by one, starting from the worst ones?
(worst in sense of biggest slowdown/pain levels)
Blanket painting of a class of complaints doesn't help them or you accomplish business objectives better long term.
Most complaints about tech debt are not worth actioning, but that doesn't mean you shouldn't listen to all of them and try to filter the signal from the noise.
I'm lead engineer on my startup's project, not the CTO but reporting directly to him. Team of about 30.
There are of course many legitimate things that can be described as tech debt, files that got too large and convoluted over many patches by many people, that sort of thing. But I find I have to watch out for the concept of "tech debt" because a few engineers will abuse it if given the chance.
For instance they will insist that code that was just written fresh by a colleague is "tech debt" because they would personally have written it differently, when there are no meaningful differences between the two approaches.
They can claim that a design they don't understand the reasons for immediately (regardless of whether it's documented) is tech debt.
They can claim any feature they don't personally want to do or which is perceived as hard work will create tech debt. And so on.
I wrote the initial code and I'm close enough to the codebase still to be able to fairly thoroughly examine claims of tech debt. I'd say most such claims are actually not a big deal and do not justify any non-trivial investments of time to resolve.
Moreover the sort of engineers who pay down more than their fair share of legitimate tech debt are invariably the ones who complain about it the least.
I'll upvote it as well, as it is possibly the thing with the least amount of intelligence that I've read so far in my life.
I've been on the other side of this. I was developing the frontend part to a series of http endpoints and my colleague was working on the http endpoints. He was creating some terrible code but I had no power at the time. When he was done, the code was functional, had various bug and a new feature was needed. I spent a week studying the code and managed to add a feature, which however was buggy due to how the code was written originally. I fixed all the bugs, and ended up totalling 4 weeks of work. This colleague was let go after this due to a series of circumstances, so I became the owner of the code. Then a new feature needed to be added but to do that i'd need to change various things in such code. Two weeks in, I still wasn't done. At some point I asked to be able to rewrite the code. I did, it took 2 weeks and was able to add the feature easily. I'm no genius but code that cripples you down from the get-go is tech debt. Tech debt is failure in software design, which ends up in unmaintainable code. I'd listen to anyone pointing at tech debt in my code, it means my code sucks, I made a big professional mistake and I need to correct it.
There is also voluntarily added tech debt, that's the one added by taking shortcuts. As long as you don't build new features on top of it, you are good.
> For instance they will insist that code that was just written fresh by a colleague is "tech debt" because they would personally have written it differently, when there are no meaningful differences between the two approaches.
> They can claim that a design they don't understand the reasons for immediately (regardless of whether it's documented) is tech debt.
> They can claim any feature they don't personally want to do or which is perceived as hard work will create tech debt. And so on.
Yeah, those things are not technical debt. But that doesn't mean that technical debt is a real issue. Technical debt isn't about whether you like or understand a particular approach, it's about whether the codebase as a whole is still maintainable, whether the bugs make sense and are fixable, whether new features can be added without stabilising the whole code base.It's never the new feature that's the problem. If the new feature can't be added in a good way, it's the old codebase that has unhandled technical debt.
Edit: Is saying "bad design" or "ineffective design" going to lead to some fearful confrontation?
Is it obvious to you that it's not just me?
Where would you substitute "bad design" or "ineffective design" into the comment?
Perhaps this will help: http://wiki.c2.com/?TechnicalDebt
> Perhaps this will help: http://wiki.c2.com/?TechnicalDebt
Seriously, it won't. That's the point. People overload these words. It's a cute ideal definition though.
Over and out.
P.S. Yeah, go ahead and downvote me, troll.
Edit: I apologize for beating a dead horse.
It's not about that either ... it's about things that were put off, generally for valid reasons at the time.
> It's never the new feature that's the problem.
What do you mean by "problem"? Many new features are inherently problematic.
> If the new feature can't be added in a good way, it's the old codebase that has unhandled technical debt.
That would only apply to waterfall development with infinite foresight. In the real world, wise people employ the YAGNI principle.
Oh really? I recently contracted with an industrial firm where most of the programming staff copy and paste at the drop of the hat and have no idea what DRY is, and think that technical debt and refactoring are some fancy university CS theory that "practical" programmers like them have no use for. I explained to the manager at some length the development and maintenance costs of the massive technical debt of their 30 year old code base, while at the same time I tried to reduce it a bit with every submit.
I think your situation sounds a bit different, where the manager either isn't very technical or isn't technical enough. Otherwise they'd be able to see the problem for themselves.
What I'm talking about are employees who have managers who understand the value of refactoring. What I find is that the people who get stuck in and most unambiguously improve hairy bits of the code (with full support of management) are usually not the ones who complain loudly and publicly about tech debt.
Speaking as a manager for a sec here, what I'd watch out for in your case is to not be seen too much as a complainer. Rather than say "this codebase is shit why does nobody care" look at it as, "hey guys! why not come to my interesting 10 minute lightning talk on my favourite refactoring technique" and maybe don't phrase it as about tech debt if they aren't responsive to that kind of analogy.
Managers in particular probably know their codebase is shit even if they aren't very technical, but labelling things as "tech debt" is always tricky because it's entirely possible that the debt was created by colleagues or those very same managers themselves, and whilst financial debt is well defined and measurable, tech debt is just an analogy. They may not even agree that any given bit of code is a problem.
Even if so, that's not relevant; you said that people like me "invariably" don't exist.
> where the manager either isn't very technical or isn't technical enough. Otherwise they'd be able to see the problem for themselves.
No, that's entirely wrong. As I clearly stated, it's the programming staff who can't see the problem. They are the people who never complain about technical debt while also never reducing it, contrary to your statement. That's the point, and your "good for you" is point-missingly dismissive.
> Speaking as a manager for a sec here
Just don't; I've been developing software since 1965 and I don't need your lectures (which are based on a complete lack of knowledge and erroneous assumptions about the software manager at that firm and my relationship and interactions with him), I simply pointed out that your sweeping generalization about who reduces technical debt and who points it out is erroneous. That's all. Period. The end. I won't respond further.
Edit: If developers are warning the CTO that there is an issue with technical debt that should be a warning flag. Particularly if these are senior/experienced developers who understand the insane costs of re-writing production code.
This one doesn't require you to read between the lines, people usually just tell me that directly :)
Your mileage may vary - in my experience this is another one of things where it's not actually true most of the time. Note how it's a really easy to claim to make, and basically impossible to disprove ("at some unknown time in the future something bad will happen unless you let me have my cake now"). To me that's a warning sign that it might be wrong.
As a leader (or CTO or whatever) your job is to make the call. And if it turns out you were wrong and there is literally nobody who wants to touch the mess, well the buck stops with you and you have to clean it up.
I'm happy to take that bet!
The harsh truth, which is evident from the thread, very few companies/managers actually reward fixing code debt.
There's a paradox in this viewpoint. On the one hand you believe that your developers are so immature that they automatically shout "tech debt" for any code they didn't personally write ("only MY code is good"), then on the other hand you're confident that the code produced by these immature developers is actually just fine and doesn't have any technical debt.
I know you're not speaking in absolutes, so you may be right. You especially may be right about your own specific situation. However, I think a lot of people who have this viewpoint are simply kidding themselves into believing that "everything is awesome, surely there couldn't be any problems because I am the team lead".
Just remember the general form of the argument is "my team is great and talented, but I can't trust what they're telling me". It might be the case, but be careful of your own biases.
I'm not disagreeing, but there is something to be said for writing code that any idiot can understand so that future developers don't even want to rewrite it, and can maintain it.
I've landed in code bases on both ends of the spectrum, and I never asked management to rewrite the well-written ones.
There's a skill to writing readable, ideally self-documenting code. If that skill is wanting, even the most stable requirements won't save you from the mud.
Or not being allowed/kept too busy to fix it.
“rewrite” is in sense of “I don’t even want to understand it, going to just delete it, and implement anew”,
VS
“refactor” is in sense of “I had to spend quite a while trying to understand this code, and I think it can be improved, so that the next developer doesn’t have to spend this time.”
I see no excuse for leaving the reader to guess at what on Earth you were thinking. Implementing a wacky solution is sometimes a necessary evil. Incomprehensibility isn't.
I realize that as developers we often glaze over the comments (my editor even shows them as low contrast grey), but docstrings and code comments can be tremendously valuable when trying to understand why something needs to do things a particular way.
When I see WTF code, I want to know what story it was associated with so I know why the fences were erected. Sometimes they are right and I need a complex solution. Sometimes they were accomplishing something the hard way and there was an easier spot to achieve the goal.
Basically I am fixing two bugs. The old one again, and the new one.
I am not saying that writing convoluted code is good, no, but I can tell, even if based on personal experience, that barely anyone talks about "wow, this is such a straight forward code" or gets promoted for "everyone can understand your code!".
It is a weird dynamic that gets worst by having non-technical managers, and the reason why I believe team leaders should be hands-on in software development and involved with code review.
Person A, a programmer, who writes easy-to-understand code, but takes a bit more time to finish their tasks
Person B, a programmer, who writes dirty code, but takes much less time to finish their tasks
The current non-technical manager will see only one part of the picture and promote Person B. Moreover, Person A might get in trouble, and pressure to “compromise on quality.”
Within a short-term, it is understandable.
Within a long-term, this is a disaster scenario!
So should the “code quality” be part of a performance portfolio of the developer when it gets to promotion time? And how do we get there?
Programmer A writes straightforward code that's easy to change and understand.
Programmer B writes convoluted "clever" code that completely falls apart when requirements change, or even just in production because their clever solution didn't account for all of the edge cases.
Now Programmer B has to save the day consistently, and therefore is seen as the person saving the company, when the problems were all of Programmer B's construction to begin with.
Unless we're talking about a seriously silo'ed org, or Programmer B is actually "Team B"
And if you don’t take “I can’t trust you” as the highest insult a developer can give, then you are in the wrong line of work.
Then you start to find which engineers the other ones don't like to work with.
The best code is impossible to spot, because it's not even there.
Put another way, a truism I've often heard from the most senior programmers (especially in the context of critiques of LOC as a measure of productivity), is that their best work is often writing less code, or outright deleting existing code. It stands to reason that this kind of work is much more difficult to spot if all one looks at is the codebase in its current state.
I would and do advise anyone who possesses that sort of clarity to push for more responsibilities. They should be involved in all of the major problem solving discussions.
Sometimes in order to meet business needs and get things out the door you have to cut corners that you need to go back and take care of later, or you are crippling the future growth and stability of the project. I like your final point "if every change to a bit of code introduces new bugs then that might be a reason to tidy it up".
I think sometimes proper testing is the first thing to go in a time crunch, and good tests improve velocity. If you know that the entire app is being tested automatically, you can develop a lot faster and more fearlessly. Plus writing good tests inherently makes the original code better. You find and fix hidden bugs, and you refactor the code to be more testable which makes it better in other ways.
Oh, that is quite an interesting idea. If the author themselves acknowledges there is a problem—there should be a real problem.
when I first heard the term 'technical debt', I thought it was fantastic that we had a shared name. but as someone else pointed out in this thread, the normal compromises one makes because of schedule and lack of importance are really a different thing entirely than a codebase that is failing structurally.
normal compromises can be ignored, and often aren't even compositional. thats the kind of linear, easily repairable stuff I think should be called 'debt', and it isn't scary at all. you overcome it at some later date when and if it makes sense. maybe debt isn't the right word, because you aren't borrowing failure from some abstract ideal, you're just choosing to trade of time for quality, which every effort in every field has to do.
structural issues that compound exponentially, and make it increasingly difficult to make any changes at all are a different thing (call it 'crippling debt', idk). its a metastatic cancer and can easily be fatal.
Reading code is harder than writing code. So, IMO, lazy or slow engineers would rather complain that code should be rewritten than refactored. Or that different frameworks / languages should be used.
Ive entertained them a few times before realizing that it was a waste of time and often things came out worse.
IME it can be one of many things, including but not limited to: was written by someone who is no longer with the company, doesn't have (relatively comprehensive) tests, doesn't have any documentation, commit messages don't explain the codes' reason for being, is a blocker to getting more lucrative features out, nobody understands it ergo nobody dares touch it, written in a language that is hard to recruit new devs for, is working fine now but will be a problem in x months/years time, contains potential WFIO points but is business critical, is difficult to scale, and possibly more.
What i'm saying in the above is that it's possible to write something in a easy to recruit for language, that scales well, is comprehensively tested, has no nasty bugs, but could still be considered technical debt because the original developer(s) wrote useless commit messages, no documentation, and then left the company.
I've never seen this happening but it seems to be common in hipster environments.
Do not hire people that want to rewrite something just because it's not written in the popular language/framework of the year.
A lot of rewrites I have seen just traded one set of problems with a different set of problems.
Those issues are very much constrained by a very good test suite.
(Better refactor, of course)
I agree it's pretty common though. I've also seen huge test suites of only unit tests, no integration tests. As a result, you have no assurance that your refactors work because changing the inner workings fundamentally requires you to change the unit tests too, and nothing checks the top-level interface.
Not both at the same time, in my opinion.
Desk.com has a gigantic Rails codebase and a test suite that runs for... well when I left them it was 40 minutes long but it's probably longer now. But it did save us many many times.
I'm working at another company right now (can't disclose) and they also have a rather large Rails codebase and a fairly good test suite.
I think the Rails community historically has been pretty great at communicating good test/design decisions, so the modularization issue you mentioned is largely moot.
Modularization is the issue, not size. If you have a big project and it's nicely modularized you probably already have good tests for it, but don't need to refactor. If it's big and needs a huge refactor it's probably hard to test and doesn't have appropriate tests.
Often when some code reuse gets nested (re-using something that is re-using something), then having to tweak it a little at the end to get to the right state.
Basically a bunch of development is done towards a local maximum. But looking at it as tech debt can bring it up to a global maximum.
The people with this attitude seem to be the best sources of hard to understand legacy code.
While I have to agree that it takes the pain and struggle to understand some code out there, it is still worth doing, and a good indicator of the quality of the code, and the fact that it needs improvement.
Also, I believe leaving some “bad code” without understanding it, and just rewriting it, _might be_ unprofessional…
Most code complaints are this code sucks. But honestly most code looks like shit, and battle tested code that's been heavily patched to work well and cover lots of special cases especially lookS like shit.
But when there is a documented problem with a piece of code that is important and worth refactoring because it can't be mediated otherwise then of course you need to fix it.
For example recently a previous dev split the data model across persisted HTML and rows in a database. Which means it was very easy for the domain critical computations(driven by the database) to display one set of inputs to the user, but calculate with another.
There was an agile coach I heard an interview with who insisted that Tech Debt was the wrong analogy. He preferred Wear and Tear. I think the problems of kludgy or overclever code are more apparent if you think of it that way.
At the very least, the main thoroughfares of the codebase need to be clean and free of dangerous obstacles.
On my own, I would look at code I wrote 6 months ago, wonder what idiot wrote that, then figure out if it was actually bad, or I just didn't understand it.
With staff turnover and a lack of incentive for engineers to prioritize shipping (thats the manager and PM's problem), there's a heavy bias to "It's bad, rewrite it" rather than "Oh, it gets the job done, I just didn't understand it, let me research and comment the code". _Tons_ of time is wasted.
But mostly, it's decisions that seemed to make sense at the time, but now turn out to be wrong. Or simply the accumulation of fix upon fix, feature upon feature, without without doing a redesign based on changing requirements or lessons learned. If you don't work to stop it, entropy will add up and eventually turns the code into an unmaintainable mess.
I'd add "this code I wrote is technical debt because I'd rather re-write it then create a proper test harness for all its bugs and edge cases".
Instead of rewriting the code, there should be some effort to show figure out how it links and how it works together.
- speed of delivery (not so much hitting a public deadline as shipping it as fast as you thought you could internally)
- quality of final product (were there delighters that didn't get built because they were too hard)
- number of follow up bug fixes shipped shortly after the main project ships (did we ship a bunch of bugs and not realise until users found them)
- number of new users acquired from shipping the feature
> number of new users acquired from shipping the feature
1. It's one of my dreams to work at a place using prediction markets for internal estimates. Anything else feels worthless and engineers are incentivized into the "quadruple what you're currently thinking" estimate so they more often meet deadlines -- or try to "under-promise, over-deliver" except management rightly catch on to that one immediately. (As an engineer I still want to be a La Forge and work with other La Forges, even if Scotty[0] sometimes has a point; modeling managers as demanding children has some gaping model gaps.)
2. What I've seen is that many delighters aren't that hard, but they're often treated as "polish" that goes into the p3/p4 priority backlogs and maybe might resurface if a customer ever brings up a desire for that to the product management. What delighters have you seen that weren't shipped because they were too hard? Were they actually too hard, or was it just too much to get them done by some release date alongside all the other stuff so they get shoved to the backlog just the same?
3. Are you measuring bug count based on what customers report or internal bug reports? If internal, even if people aren't gaming this directly, it's still easy to get into a bad cycle where reported bugs get ignored and go unfixed which leads to fewer reported bugs. That might be mistaken for higher quality.
4. Is this one measured from surveys? Obviously not all features are directly customer visible so let's take something concrete like shipping an Observer mode for an RTS video game that shipped its big release a couple months ago. How would you measure the impact of getting new users from that one feature?
Extensibility is just as important as Bugfree software for some businesses. Actually, for most of them.
Technical debt hurts much more the extensibility of your code rather than raises the number of bugs.
In my experience it is used by senior developers having dealt with the same systems for years.
But I don't work in a fancy startup or similar. YMMV.