> I've seen some managers (engineering and product alike) say phrases like, "well, if you created a better solution in the first place, we wouldn't be in this situation" – this is just stupid, inhumane, and ultimately pointless This is such a disappointing aspect of the 'technical debt' concept and surrounding discussion. The unspoken truth is that technical debt is most often a euphemism for inexperience and lack of…
> Take an engineer who ostensibly "intended" to accrue some technical debt. Ask them to fix said debt and note that you'll find more debt accrued.
I don't see how the second statement follows from the first. Are you saying that good engineers always have enough time to implement every feature "the right way" on the first try?
> But building a system with a fixed set of value in a robust and decoupled way is not a function of immediate time available _today_ -- it's a function of skill set.
Of course it is a function of immediate time available today.
> Usually it's because there's a conflation between system "flexibility" and architectural soundness, and a misunderstanding that some code duplication has anything to do with 'tech debt'.
This sounds like it's targeted at one specific developer you used to work with (I have worked with developers like this too, it sucks)... but that has nothing to do with time/quality tradeoffs in design and development.
> The fallacy behind 'tech debt' is that it assumes as an axiom that continuously building a robust system is really just a matter of time spent -- and otherwise has little do with experience and value set.
This is like Calvinism for programmers. Yes, some programmers are better at software architecture and design than others. Yes, some programmers leave behind a mess which, if not fixed, does truly turn into "legacy code" and "tech debt".
But it's ridiculous to assert that all technical debt follows this pattern. Design is often iterative; people are not omniscient. Bad engineers fail to evaluate the tradeoffs correctly, or aren't aware of all their options, and make bad decisions. Good engineers understand the tradeoffs and know their options, and make good decisions.
Let me give an example from my actual job:
I was tasked with implementing a sort of graph lookup system. I had two options: pre-compute a large portion of the graph, leading to a nice big flat table that could be easily queried at runtime with a single join, or leave the entire thing in a normalized format and do a big multi-join lookup at runtime. I chose the second option, because this allowed me develop a system and codebase that was simple and easy to understand, offloading the complicated work to the database. Moreover, it allowed me to avoid the various operational issues and technical details around setting up and maintaining the intermediate pre-computed table. The performance requirements were such that the increase in latency and server load wasn't important for the first version of the product. The business was and remains happy with the product.
Now that it's humming along and users are starting to put more load on it, migrating to the first option is now on our engineering calendar for the year. With ~12 months of accumulated knowledge about this system and its use cases, with an increasingly stable API, and with an increasingly rigorous & thorough test suite, I feel confident that swapping out the internals (including the database layout) is a relatively low-risk operation at this point. The internals have already been subject to several incremental refactorings simplifications as the business stabilized the product requirements; these were implemented without any visible effect on users, and with minimal changes to other "internal consumers" who depended on the API.
If I had tried to implement things that way from day 1, I would have had a system that was more complicated, more difficult to maintain, more difficult to explain to other programmers, and had more operational elements that could break. But I did indeed take a loan of "tech debt" in the form of worse performance and high server load, which we will have to pay off eventually.
Perhaps if I was a better programmer, I would have had the skills to implement the first option right, on the first try. But I don't know many (any?) programmers who do have those kinds of skills, while also having the wherewithal to document the thing, write useful and nontrivial test assertions, develop tooling for OpenAPI conformance, et alia. Not to mention that the flexibility granted by simplicity actually has turned out to be very important for being able to respond to changes in product requests quickly.
It seems (so far) that I did make the right decisions in this situation. I think that makes me at least a decent software engineer.