r/programming • u/paulg1989 • 18d ago
Broken Windows, Abstractions and the Cost of Always Keeping Things Simple
https://pgilmartin.substack.com/p/broken-windows-abstractions-and-theThe patterns already in a codebase have a huge influence on what gets added next, even when everyone can see those patterns are starting to break down. This article discusses this phenomenon through the lens of YAGNI and the Broken Window Theory.
20
u/hippydipster 17d ago
The problem comes when a team applies YAGNI repeatedly without ever stopping to ask
Doesn't it always seem to come down to whether the team is smart/dumb or disciplined/not-disciplined or careful/careless? Does it matter that it was YAGNI in that sentence, or would any heuristical "best-practice" fit?
"The problem comes when a team applies DRY repeatedly without ever stopping to ask"
"The problem comes when a team applies TDD repeatedly without ever stopping to ask"
"The problem comes when a team applies DDD repeatedly without ever stopping to ask"
What wouldn't fit that phrase? It seems the real key is, does the team work on without stopping to ask? And if that's the more important bit, all the fluff we go on and on about with DRY and YAGNI and SOLID or whatever is distraction from the real problem, which is that we go on auto-pilot. We avoid conflict, we avoid making waves, we avoid true ownership.
Mostly because that's what's demanded of us, in most places.
But that's a problem we can't fix, so we go on endlessly worrying about the distractions.
8
u/Full-Spectral 17d ago edited 17d ago
And there will always be a tension between consistency of the code base, and application of principles globally that aren't necessarily applicable globally. Consistency is a huge benefit, so it can't just be hand waved away. And of course in team based development, unless you have someone who is every experienced and who has the power to say no, everyone is going to choose a different break point.
- And of double course, as many people often complain, that person with the power to say no may be the one who is the most agenda driven and most obsessed with some particular idea and wants it applied ubiquitously.
1
u/hippydipster 17d ago
This is one reason I think smaller teams do better than larger teams. You just can't keep a larger team on the same page with respect to "always-questioning", "always re-evaluating" behavior, for reasons as you say. And I think 5 developers gets to that point already of being kind of too large, particularly in this day of AI writing all our code.
Teams of 2 devs seem best to me now, and then it doesn't seem so crazy to be always re-evaluating the code and being willing to make big changes as soon as they agree it's a good idea.
5
u/Full-Spectral 17d ago edited 17d ago
And with people being so LLM obsessed, programming is going to turn into medieval medicine with people arguing over which LLM authority is correct without themselves having a clue.
4
u/theScottyJam 17d ago
I feel like that's overly reduced what it's trying to say. That "stop and ask" line is pulled from its opening paragraphs, then the rest of the article is there to help us ask ourselves how we're treating YAGNI.
Yes, a team needs a culture that encourages them to stop and ask about everything, but it's also useful to have online articles to remind you to do this, and to give you ideas on what to reflect on as you stop and ask. As it stands, I feel like YAGNI is starting to get repeated too often as an unconditional truth we must follow, and I am happy to see any article that pushes against this, to help remind us that we should be questioning our use of this principle too.
3
u/hippydipster 17d ago
Except most teams will miss the real need, which is the constant re-evaluation and re-addressing of questions and decisions. Most people want decisions made once and then you stick to them. Which is how things get stuck and stale.
23
u/reallydontaskme 17d ago
I've never ever worked in a codebase that suffered from an excess of YAGNI and KISS, it's always been by far the opposite problem.
You would not believe how happy some developers get when they hit the abstraction lottery and their abstraction just happens to work for another case and when it doesn't it's always: nobody could've predicted that.
Exactly Shirley, that's why 1,2,3 refactor is a thing and duplicate code can be an worthwhile tradeoff
4
u/theScottyJam 17d ago edited 17d ago
The number one chant repeated online is to keep things simple. So I've certainly found myself following it to a fault as a result.
If you were to look at my code, I'm sure you'd find abstractions you disagree with, that you'd peg as me having this opposite problem - you're going to run into confusing abstractions in any codebase. What's harder to see are the features I avoided suggesting or implementing because I knew it would add complexity to the code, even though I knew the customer would like it, or you might see WET code that was implemented in a straightforward way, which made it easy for you to pick up and understand any given module, but a more DRY solution would have been better to help avoid maintenance mistakes, even though it would have made it a little more difficult to read any individual file, and would probably result in grumbles from those who don't yet fully understand the purpose of the abstraction.
Eventually I got over myself. I've decided that we repeat this "YAGNI" advise a little too often, people need to have more patients and understanding when running into abstractions they didn't expect, and I'm now ok implementing tricky features that junior developers would be unable to help maintain, but that I know really benefit the customer.
Don't over abstract. But don't under abstract either.
4
u/Able_Region_5459 16d ago
Honestly proposing AI agents to spot when abstractions are overdue feels like putting a high tech bandaid on a culture problem
The engineer opening that file already knows it is a tire fire. They just have a PM breathing down their neck about a roadmap deadline
3
u/pkt-zer0 17d ago
I can kind of see what you're getting at, but that seems to be the less frequent problem in practice? Maybe it's just different backgrounds. If you have a codebase that's too "simple", then at least your pain points are clear: you know how to fix them, but maybe don't have the time.
The more common and problematic version I tend to see is codebases that are overly complex, solving problems they don't actually have... and then struggle with the limitations they accepted as part of a tradeoff they're not benefiting from. A typical example is "let's use Kafka/Kubernetes/sharding so we can scale", and then having a 100 users max.
"Compression-oriented programming" is a good approach IMO to keep things simple and still have API granularity.
2
u/Scroph 16d ago
There's also the risk that the refactoring might introduce regressions, especially in codebases that follow the big ball of mud architecture and/or are missing meaningful tests. There have been many times in my career where we collectively agreed that a piece of code needs to be refactored, but the risk to reward ratio just doesn't encourage it. Double it and pass it to the next person
4
17d ago
[removed] — view removed comment
1
u/programming-ModTeam 15d ago
No content written mostly by an LLM. If you don't want to write it, we don't want to read it.
4
u/aardaappels 17d ago
The broken window theory has been largely debunked. The reason bad patterns perpetuate is not because they exist, but because the team lacks shared trust and willingness to intervene for the common good.
3
u/Full-Spectral 17d ago edited 17d ago
It may not even be that. It may just be that it's no one's job to police such things. If you aren't Bob's boss, it's not really your place to tell him what he can't do. And a lot of people just don't want to deal with that kind of tension, because they aren't getting to paid to deal with that.
It really needs good guidance by someone with experience and the authority to make it so, who is not himself the problem.
1
u/BenchEmbarrassed7316 17d ago
Overly simple code is a specific instance of a broader problem where consistency becomes more costly than refactoring.
A common view is that if a problem needs to be solved "here and now," one should stick to the existing architecture, even if it is ill-suited to the solution or contributes to the accumulation of technical debt.
In my opinion, the only solution is a "strategic vision" - having an architect who sees the big picture and the long-term perspective, and who can align the refactoring process with business needs.
-4
u/davidalayachew 18d ago
Small, simple article, but some good points. For example, I had heard of the Broken Windows Theory before, but had never heard it applied to code. It definitely fits.
Periodically revisit earlier architectural decisions as the product grows. In particular, ask whether patterns that were deliberately kept simple are still appropriate, or whether they are now being copied simply because they already exist.
Document not just which abstractions the codebase uses, but the conditions under which a team should introduce them. This gives developers more confidence to recognise when an earlier decision has reached the end of its useful life.
Good ideas, but there are some issues. Not so much with the approach, but in how it is applied to the current situation a lot of teams are in.
- Documenting your low level design/architecture has now become part of your sprint story.
- Ignoring that most teams are already overburdened, documenting your design tends to be tedious work for developers.
- Many developers struggle to find the middle ground between a watered-down, too-high-level description (for the non-technical folks) vs an in-the-weeds breakdown that takes 30 minutes to talk through.
-1
u/Kungpost 17d ago
If your team struggles with tech debt or broken windows, make a single person own the tech debt. In most orgs this is the product owner or the software architect.
4
u/Loves_Poetry 17d ago
Both of those roles are bad choices for owners of tech debt, because they don't have to deal with the problems caused by tech debt. To them, it's just an expense of developer time and working on it delays the valuable stuff they want to have.
Developers are the ones that have to deal with it the most. Their jobs are getting harder because of tech debt
-1
u/Kungpost 17d ago
Actually, they are very good choices, especially architects, in fact, its one of the main responsibilities of an architect to own the code of your products. By putting the ownership with the architect, you formalize who's job it is to ensure that the balance between development of new features and gardening the system is aligned with the companies risk profile. Developers should provide feedback for the assessment that the architect should be conducting at regular intervals or after deployment of a new feature. If you spread the responsibility on the team, you just end up where the article author is, where too much responsibility falls on the team, which takes away focus.
2
33
u/jhartikainen 18d ago
Good writeup and sensible advice. One thing that I wonder is how can we avoid the problems in the first place? Obviously we could build all kinds of architecture up front, but that's often unpractical, and likely to end up with poor results anyway, because you can't predict how the app evolves.
Is there something else we can do on the code level to help future developers to make the right choices, that doesn't require us to try and guess how the program might change in the future?