Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

There are some grievances in codebases that do not come with a huge expense. For example, duplicated code. For another example, overly verbose code. I've seen a lot of new codebases and these are minor nuisances and are pretty easy (i.e., take little time) to cope with. I don't classify these as technical debt because if they cost anything it's always so little.

What costs the most is architecturally unsound code. It's actually not really the code per se, it's the abstractions and how they fit together--very specifically, to what extent the abstractions cohere, to what extent they are coupled, and how narrow are the interfaces. Give me a code base that nails these qualities (narrow interfaces, minimal dependencies) and all else (duplicate code, inelegant code) is in comparison NOTHING to deal with.

So the cost of code is almost entirely related to its _architectural soundness_ (to what degree it's coupled, its interfaces are too wide, etc.)

The biggest and prevelant fallacy of our industry is this notion of technical debt. Because the notion implies that it's somehow necessary. It's not necessary.

The ability to build and evolve architecturally sound code is a function of skillset. If the skillset is there, there is no necessary extra cost. In fact, for people that have this skillset it costs MORE to depart from instincts and couple code, create wide interfaces, etc.

When a developer says 'It will take too long to do the right thing,' (i.e., build architecturally sound code) he/she is saying, 'I don't have the skillset.'

I know all the objections here (it takes time to understand your use cases, etc.), but the objections nearly always miss the fact that architectural soundness and things like code scope/flexibility are ORTHOGONAL properties. You can have very specific code that does very specific minimal-viable product type things ... but this has nothing to do with whether the code is architectural sound or not.

As long as we continue to think of techincal debt as something that's somehow necessary and something to be negotiated we will always be missing the point. The point is that we need to produce workers with the right skillset. There are so few people that have it--which is entirely a failure in our academies, educators, training systems... To keep talking about technical debt and not about how to acquire the architectural skillset is to keep chasing our tails.



> When a developer says 'It will take too long to do the right thing,' (i.e., build architecturally sound code) he/she is saying, 'I don't have the skillset.'

I'll be charitable and say this may be the case part of the time. But as a general argument it is bollocks. In the vast majority of production systems that survive for any amount of time there will be requirements changes, and sooner or later an engineer will face a choice of shoehorning an attribute in somewhere it doesn't fit naturally, versus refactoring to more appropriately model the new business universe. Saying that this won't happen if your skills are sufficient is a no-true-scotsman argument—it's all tradeoffs, and no matter how good you are at anticipating change, sooner or later even the best architect will be blindsided by some out-of-the-blue business requirement.


This is the fallacy I was referring to--architectural soundness has nothing to do with anticipating change.

The "choice" your engineer faces to shoehorn a feature in [1] versus implement it in a way that optimizes for soundness (decoupled code w/ narrow interfaces) is not a choice if the skill set is there--i.e., if he/she has trained and practiced the right skill set.

[1] (By 'shoehorn' I assume you mean implement it in a way that leaves the code base in an unsound state.)


You can't just reaffirm that without evidence and an argument. It is self-evident to me (and I presume every other software engineer here) that different architectures lend themselves to different types of change. If you want to make that claim than you probably should write a dissertation about it because it's quite a controversial claim. But simply stated as if it were unassailable fact is pushing you right into crackpot territory.


> It is self-evident to me that different architectures lend themselves to different types of change.

This is such a vague statement, I have no idea what you mean or how it relates to our discussion.

My argument is this:

(1) The most costly issue with a code base has to do with its architectural properties. How architecturally sound it is [1]. Most other issues that we tend to categorize as technical debt (like code duplication or verbose code, for examples) pose such tiny cost in comparison to the cost of poorly architected code [2].

(2) Architectural soundness is an objective property of code independent of the code's generality, flexibility, etc. Again, it's the degree to which its components and its interfaces narrow.

(3) There exists a skill set that understands, recognizes and produces architecturally sound code. [3]

(4) Given an architecturally sound code base and a set of features, a skilled person can implement the features without violating the architectural soundness of the code base AND do so without having to pay for it in time-to-delivery. [4]

I think I'm being fairly clear in my assertions here. They are based on my long experience. To disagree is to pose a different theory. Do you care to elaborate on what you mean by 'crackpot territory'?

---

[1] More specifically, the degree to which its components (modules, classes, functions) are coupled and their interfaces not as narrow as they could be. This is an objective property of a code that has clearly delineated components (i.e., you can quantify dependencies, interface sizes, module sizes.)

[2] Yes, this is a claim based on my 20 years of experience working in myriad code bases. How to distill and prove this, formalize the argument, etc is probably work to be done.

[3] This skill set doesn't come cheap and requires proper training, and currently our industry/academies aren't producing it.

[4] Again, this claim based on my experience and yes there is probably some good research opportunity here to formalize it.


> Architectural soundness is an objective property of code independent of the code's generality, flexibility, etc. Again, it's the degree to which its components and its interfaces narrow.

I like this definition, and I agree you could quantify this into a useful measure. However the optimal architecture according to this measure is a function of the problem domain. You split the modules and define the interfaces to maximize the encapsulation and minimize the interfaces.

So what happens when the business rules introduces a new cross-cutting concept? The basis of the architecture soundness is now in question. Do you define a new module and add n new interfaces? Or do you split the concern into the existing modules, fattening them in the process, and widening existing interfaces as well?


> However the optimal architecture according to this measure is a function of the problem domain.

I agree with this. But domains typically evolve incrementally -- and using the skillsets I mention you can evolve your code accordingly. [1]

There is then the question of these cross-cutting, earth-shattering domain changes you mention. I'm not convinced my argument doesn't have a play here but regardless if these kinds of major domain changes are happening frequently enough to matter in this discussion then I think there's a different business-level problem going on.

It's hard to talk abstractly about this for so long--until of course someone gets to building out these ideas more formally. Getting into concrete cases would be more fruitful.

---

[1] That you can without cost tradeoff is my argument. Today these skills are so rare so you don't find orgs/codebases that do this properly--and therefore we have this fallacy that because it's prevalent that it's somehow necessary. We don't realize it's really a skills problem.


> I don't classify these as technical debt because

Apologies if this is too meta, but that is the most interesting part of your comment for me. It conceals a massive assumption which all devs make, resulting in very different conclusions.

What IS technical debt?

My own preference for the answer is Uncle Bob's description, which is this: technical debt is any production code that does not have (good) tests.

But regardless, any attempts to address technical debt must necessarily begin with a common understanding of what technical debt actually is.

I've rarely seen teams agree that understanding and I think that contributes to their problems.


> What IS technical debt?

Any feature of the code or tech stack that increases maintenance/operations cost compared to alternatives.

> My own preference for the answer is Uncle Bob's description, which is this: technical debt is any production code that does not have (good) tests.

That's certainly an example of technical debt.


> > My own preference for the answer is Uncle Bob's description, which is this: technical debt is any production code that does not have (good) tests.

> That's certainly an example of technical debt.

Agreed, it is not the only example, but perhaps it is a good one, as that is a particularly important form of debt that makes the code harder to safely change. I.e. it is a form of technical debt that makes it more expensive to pay off other kinds of technical debt.

Curiously, Michael Feathers has a similar definition of legacy code [1]:

> To me, legacy code is simply code without tests.

[1] http://www.amazon.com/dp/0131177052


I think "code without tests" is a fine example of technical debt or legacy code, but using it as the definition of either disregards the importance of everything other than tests that goes into making systems maintainable.

Tests are necessary but not sufficient. (Particularly, tests embody




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: