Your increasing thrash betting that AI will fix it for you. The only thing your getting in return is not having to think that hard.
It doesnt cost that much time or effort to think hard, so you will be outcompeted by people levergaing AI as much as you, but thinking enough to not have it be thrashing around
> This is the number one thing I optimize for now: the ability to quickly and safely change significant parts of the code and product.
This was always a good thing. Its value has nothing to do with the advent of AI coding.
> The opportunity cost of not being able to safely restructure has gone up substantially.
This bit is contradictory with everything else you said. Prior to AI coding it would take a lot longer to perform restructures. If anything, the thing you're now optimising for has gone down in value. It's still valuable, but perhaps a little less.
I'm not talking about time. I'm talking about safety. The amount of times I've seen "I refactored it, but I'm not confident enough to take it to prod" is significant. Being able to go faster but still not ship it is the huge opportunity cost.
Time, safety and cost are one and the same. Not safe enough? Spend more time increasing confidence. Taking too long? Cheap out now and pay the price later due to added risk.
All of that is orthogonal to AI. All AI did was accelerate the typing code part - which was never the bottleneck or a very significant cost to begin with.
In the broader corporate world, that's not "opportunity cost". All changes are considered "risk".
All deployments must be approved by an advisory board. All work must originate from a clear business need. Analysis of those needs is not concerned with implementation, least of which whether "AI" is used.
What matters far more is that a contract requires work to be done by a deadline. Those deadlines are driven by policy. There will be no adjustment to policy unless tangible benefits are shown from more frequent deployments of code.
I gotta tell you that's extremely unlikely if you're already shipping every other week at the end of the sprint. Most of that sprint is spent in meetings, not writing code. Nobody is doing big refactors because it wasn't built so fast to require them. There's some technical debt, but nothing so severe. Those meetings are preventing risk, not wasting time. The bottleneck is a feature, not a bug.
If you think the future of dev work is to be a bureaucrat, you're right! It looks like the rest of the world outside of SV is ahead of the curve and living in the future.
I mean "We can't build X because our code structure makes that difficult" has an opportunity cost of the value of X.
I don't think the future of dev work is being a bureaucrat. I've done more rigorous engineering the last two years than I did previously. I'm more confident in the things I shop and they were built in a fraction of the time. It's a bright future for software engineering.
(In general, I think we don't do enough to emphasize best practices in the era of AI, but...)
What Kent completely ignores here, as far a I can tell, is that there is significant value in finding out sooner what the needed features are. Building speculative structure can be a forcing function to establish requirements, because at least you start exposing failure modes. It might be more expensive than waiting, so hopefully you don't do it for most of your requirements, but sometimes it's your best option.
Building the wrong thing is now a much less expensive option, and that means the calculation around YAGNI is different. But it's still a calculation, and for now, each team needs to figure out how it has changed for them.
I personally think it all comes to exploring and implementing solutions for problems. There is always a cost associated with solving the wrong problem. Or implementing a bad solution for something that was not even necessary.
Sometimes software developement can devolve to, just becoming a trial-error approach instead of thinking about a set of strategies/problems to explore.
There is a good case that exploring problems further in specific direction than needed can help long term. But implementing solutions aimlessly is never a good idea.
I think this is what Kent Beck really means, critizing implementing something just in case because you might need it in the future.
Seeing running software as an asset is the right approach.
But the costs of executing and even re-doing things went significantly down.
The costs that didn't went down are the ones of breaking the chain of trust to a predictable outcome. A specific version of some running software accumulated trust. If you rewrite it from scratch that capital is reset on release.
Kent Beck compares unwritten code with a financial option to buy something at a given price.
But that's just an analogy, and it can be taken too far. If you haven't written any code, do you have infinite options? You haven't spent any time yet, but still, that doesn't seem quite right. It might be used to justify staying in the planning stage and putting off writing code indefinitely, to avoid committing to anything.
Why might the analogy work anyway?
Maybe the cost is reading the code? Code that hasn't been written doesn't need to be read. And if you're using a coding agent, it doesn't clutter up the context with irrelevant detail.
Also, code that hasn't been written yet doesn't need testing. Tests you haven't written yet don't take any time to run.
These are good reasons to try to keep a project as small as possible. By putting off features, you delay codebase growth as long as you can.
This suggests that you can avoid a lot of costs by running someone else's code. If you can use a standard API then you don't need to understand the implementation in detail or run its tests. But there are risks to adding dependencies.
> Even a correct guess leaves you worse off than not committing.
Similarly, this is also confusing. If I scaffold a highly-likely feature and everything lines up, I ship the feature faster. My team isn't guaranteed to grow or even maintain our headcount, so scrambling to account for YAGNI close to the deadline feels worse than congratulating ourselves on our restraint.
Honestly think a lot of this article is ai babble - check how it ends on several classic ai negative triples such as "you’ll pay both bills on it just the same — plus you’ll comprehend it less, because you didn’t write it." ... etc.
My general principal is the cost of deleting code should be as low as possible and that includes the entire application as long as the data is around and easy to repurpose then the program itself should be as deletable as possible
"When you build structure before the feature arrives, you’re committing on a guess."
I would argue that you are guessing either way. It could be probable that your feature will arrive, but not certain. It's a probability. If you don't build structure now, there's a cost for refactoring. If you build prematurely and the feature never arrives, you wasted effort.
What's the cost, probability and trade off between those possibilities? Obviously it depends. The whole YAGNI idea is a massive generalisation by design. Ultimately it depends on the circumstance.
Either way, it's often full of guessing and hand waving. It's the same problem as giving reliable work estimates. Certain software developers don't cope well with an uncertain world and look for black-and-white rules for everything.
I can't tell if my brain is decaying or if this is just drivel. It's happening more and more, not just this article. Maybe I'm just burnt out and my brain rejects any attempts at comprehending software articles.
I think it's the latter. I find the introduction (written by Kent Beck) easier to understand than the rest of the article (which he says is AI-written: "genie-generated description of YAGNI").
In particular writing like this is just annoying:
> Perfect foresight doesn’t save you, because the discounting doesn’t care whether you were correct. It cares that you sequenced the cost ahead of the return. The gap between the two is the loss, and you opened the gap on purpose.
I fed it into Pangram and it came back as "70% AI generated".
I do feel it's better than some of the pure slop out there, but it still feels pretty sloppy. And I know that this author can write, so if this really was partially done with AI, it's disappointing.
Nothing I have read by Kent Beck has ever suggested that he would be useful in a chip company, where lots of people toil for a long period of time in order to produce something that no customer can possibly see until it's finished, and that must be sold in quantities of millions in order to make money.
> Well he makes software and writes about software development doesn’t he? Hardware has some hard limitations.
Right.
> The reason software was even invented at all was precisely to escape those limitations.
But the methods which are useful for hardware are also often useful for software. Most of the useful parts of agile were already practiced well before that was a name for anything. And the demonization of the straw-man version of waterfall in order to sell more agile consulting has led to some serious misconceptions of what waterfall really is and what it is really capable of and useful for.
The initial impetus for what became known as TDD was software maintenance, and it makes sense there.
But most TDD practitioners are nowhere near as good at real testing as the waterfall test practitioners who understand that a single missed testcase could delay a $10 million project by six months.
And this is why, even in the realm of software you still see serious efforts for aviation and nuclear power plants, and other things with real-world consequences, using more traditional methods.
> no customer can possibly see until it's finished
I'm sure lots of chip companies don't share their work in progress, but it's not impossible. Sharing simulations and prototypes and engineering samples can and does happen. You've typically got to be a big customer, of course.
But yes, insights for an industry with relatively small costs for change don't apply easily to an industry with large costs for change, and often vice versa.
> You've typically got to be a big customer, of course.
Yes, if you're a big enough customer, you might essentially be part of the design team.
> Sharing simulations and prototypes and engineering samples can and does happen.
Simulations aren't the thing. They don't go fast enough to solve anybody's problem. To your point, if a customer is part of the design team, then yes, they can, at that point, help to debug, or possibly even get started on their own dependent designs. (Part of the shift-left I talked about in another comment.)
I'm not sure what you mean by "prototypes" but "engineering samples" are essentially the finished product, done after all the work I described.
Yes, they may have bugs (or they might just not have passed validation and ESD testing yet), but that doesn't alter the fact that a waterfall effort happened before they were delivered.
> But yes, insights for an industry with relatively small costs for change don't apply easily to an industry with large costs for change, and often vice versa.
The problem with indiscriminate use of agile is that, while, yes, the software industry has relatively small costs for change, it has traditionally had huge costs for the initial delivery, and many agile proponents don't properly segregate those two cases.
If LLMs live up to their apparent promise, then, of course, the equations around the huge costs for the initial delivery could change dramatically.
Of course, the same LLM promise means that the strict definition of TDD (tests written first) is also irrelevant, and perhaps even counterproductive.
(Some) chip companies have jumped on the agile bandwagon for (some) tasks.
It's always interesting to read about some chip company or another making some agile move, when the reality is that they were already doing about as many agile things as possible before agile was a thing. (For example, a management commitment to "shift left" when they have always been about significant up-front testing and feedback.)
In many, if not most, cases, the testing software is so huge that at least some of it needs to be tested itself. That can certainly benefit from agile.
But the overall process more resembles traditional waterfall. You have several definite final endpoints, and although you can make subsequent changes, those are expensive. Also, you have a silicon budget, and a pin budget, and a heat and power budget. At the end of the day, you are producing something physical with real-world physical constraints that (a) cost real money, and (b) can't be altered by just telling your customer to add more RAM or a bigger processor.
Also, in general, although designers will write their own little unit tests for a few things, it is best practice to insure that the real tests are performed by internal organizations that are different than the organization the designer is in.
I think that subconsciously, he truism that it is easier to work with and reason about a system that is already working, and to keep it working, than to get it working at all to begin with, drives a lot of the methodology.
The designer might focus on tests to insure that things work well enough to see some results, so things can be hooked up and system tests performed earlier. In one sense, this is a shift left -- the validation people and the people writing software for the chip can get started sooner than they would have otherwise, even if it's a bit frustrating because not everything works off the bat.
But the real torture tests are typically written by the dedicated verification and validation teams. Those are really different skills than design.
All tech debt I have ever seen in my 15 years of professional software development has been someone building too many abstractions or generalizations trying to future proof stuff.
That's interesting, because it's not my experience. A lot of the technical debt I see is that someone half-assed something thinking it would be easy to improve later, but the layer violations and inadequate tests make doing so a massive project.
Nothing is all black or white of course, but I have personally observed situations where software engineers started with YAGNI and then said "that will require too much restructuring, we went into another direction, so, no, we cannot do it anymore". The worst part is that software engineers are not even in a good position to understand when YAGNI fails: when they don't plan for a useful feature, the solution is often for the users to just shrug it off and use a suboptimal solution rather than fighting and dying on a hill that they cannot win (at the end, the software developers can just say "nope, it's technically impossible" even if it was possible, they have a huge advantage). I also saw users just assuming there were good reasons why the feature did not exist ("well, I guess if they did not did it, it's technically impossible") and just don't even say it. And as the developers are not the users, they never notice anything.
100% with the way of illustrating: YAGNI is "we are consultants in a field we don't understand": sometimes, users are asking for too much, sometimes, they are asking for something reasoning, and the developers have no experience to distinguish between the two.
YAGNI is simply a tacit recognition that you can't predict the future with any reasonable level of certainty. The reason it is controversial is that some devs truly believe that they can predict the future with all the self assurance of a grandma sitting in front of a one armed bandit in vegas. So, they will:
* Create generalized functions where a specific one would have done.
* Create abstractions for something that will never be needed in the end.
* Create abstractions for something that will be needed but not in the form they initially expected.
It is not about avoiding refactoring. That misses the point entirely. Refactoring cleans up code mess that exists NOW - creating abstractions for somehting that exists NOW.
This is the key insight. Design patterns were developed by a set of consultants. Promoted by other consultants. Consultants have perverse incentives, like bankers.
Realizing this made me critical of the design pattern kool aid. I've come to terms that these are going to be around longer than I'm going to be employed writing code. i keep the criticism to myself and avoid them when i dont see fit. Works ok.
As Hoare said:
There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.
The first method is far more difficult.
The cost of shoring up behavior with tests ahead of a restructure has gone down because of AI.
The cost of implementing a zero downtime migration has gone down because of AI.
A big part of the rust hype has been the low cost of restructuring within an application, even before AI. And now even more so.
The opportunity cost of not being able to safely restructure has gone up substantially.
This is the number one thing I optimize for now: the ability to quickly and safely change significant parts of the code and product.
It doesnt cost that much time or effort to think hard, so you will be outcompeted by people levergaing AI as much as you, but thinking enough to not have it be thrashing around
This was always a good thing. Its value has nothing to do with the advent of AI coding.
> The opportunity cost of not being able to safely restructure has gone up substantially.
This bit is contradictory with everything else you said. Prior to AI coding it would take a lot longer to perform restructures. If anything, the thing you're now optimising for has gone down in value. It's still valuable, but perhaps a little less.
All of that is orthogonal to AI. All AI did was accelerate the typing code part - which was never the bottleneck or a very significant cost to begin with.
All deployments must be approved by an advisory board. All work must originate from a clear business need. Analysis of those needs is not concerned with implementation, least of which whether "AI" is used.
What matters far more is that a contract requires work to be done by a deadline. Those deadlines are driven by policy. There will be no adjustment to policy unless tangible benefits are shown from more frequent deployments of code.
I gotta tell you that's extremely unlikely if you're already shipping every other week at the end of the sprint. Most of that sprint is spent in meetings, not writing code. Nobody is doing big refactors because it wasn't built so fast to require them. There's some technical debt, but nothing so severe. Those meetings are preventing risk, not wasting time. The bottleneck is a feature, not a bug.
If you think the future of dev work is to be a bureaucrat, you're right! It looks like the rest of the world outside of SV is ahead of the curve and living in the future.
I mean "We can't build X because our code structure makes that difficult" has an opportunity cost of the value of X.
I don't think the future of dev work is being a bureaucrat. I've done more rigorous engineering the last two years than I did previously. I'm more confident in the things I shop and they were built in a fraction of the time. It's a bright future for software engineering.
What Kent completely ignores here, as far a I can tell, is that there is significant value in finding out sooner what the needed features are. Building speculative structure can be a forcing function to establish requirements, because at least you start exposing failure modes. It might be more expensive than waiting, so hopefully you don't do it for most of your requirements, but sometimes it's your best option.
Building the wrong thing is now a much less expensive option, and that means the calculation around YAGNI is different. But it's still a calculation, and for now, each team needs to figure out how it has changed for them.
Sure, if you're doing it as a spike but if you're not throwing the code away then it functions as a forcing function for creating slop.
Sometimes software developement can devolve to, just becoming a trial-error approach instead of thinking about a set of strategies/problems to explore.
There is a good case that exploring problems further in specific direction than needed can help long term. But implementing solutions aimlessly is never a good idea.
I think this is what Kent Beck really means, critizing implementing something just in case because you might need it in the future.
But the costs of executing and even re-doing things went significantly down.
The costs that didn't went down are the ones of breaking the chain of trust to a predictable outcome. A specific version of some running software accumulated trust. If you rewrite it from scratch that capital is reset on release.
But that's just an analogy, and it can be taken too far. If you haven't written any code, do you have infinite options? You haven't spent any time yet, but still, that doesn't seem quite right. It might be used to justify staying in the planning stage and putting off writing code indefinitely, to avoid committing to anything.
Why might the analogy work anyway?
Maybe the cost is reading the code? Code that hasn't been written doesn't need to be read. And if you're using a coding agent, it doesn't clutter up the context with irrelevant detail.
Also, code that hasn't been written yet doesn't need testing. Tests you haven't written yet don't take any time to run.
These are good reasons to try to keep a project as small as possible. By putting off features, you delay codebase growth as long as you can.
This suggests that you can avoid a lot of costs by running someone else's code. If you can use a standard API then you don't need to understand the implementation in detail or run its tests. But there are risks to adding dependencies.
I disagree with this. The argument _only works_ if prediction is hard.
Similarly, this is also confusing. If I scaffold a highly-likely feature and everything lines up, I ship the feature faster. My team isn't guaranteed to grow or even maintain our headcount, so scrambling to account for YAGNI close to the deadline feels worse than congratulating ourselves on our restraint.
I would argue that you are guessing either way. It could be probable that your feature will arrive, but not certain. It's a probability. If you don't build structure now, there's a cost for refactoring. If you build prematurely and the feature never arrives, you wasted effort.
What's the cost, probability and trade off between those possibilities? Obviously it depends. The whole YAGNI idea is a massive generalisation by design. Ultimately it depends on the circumstance.
Either way, it's often full of guessing and hand waving. It's the same problem as giving reliable work estimates. Certain software developers don't cope well with an uncertain world and look for black-and-white rules for everything.
In particular writing like this is just annoying:
> Perfect foresight doesn’t save you, because the discounting doesn’t care whether you were correct. It cares that you sequenced the cost ahead of the return. The gap between the two is the loss, and you opened the gap on purpose.
I do feel it's better than some of the pure slop out there, but it still feels pretty sloppy. And I know that this author can write, so if this really was partially done with AI, it's disappointing.
Hardware has some hard limitations. The reason software was even invented at all was precisely to escape those limitations.
Right.
> The reason software was even invented at all was precisely to escape those limitations.
But the methods which are useful for hardware are also often useful for software. Most of the useful parts of agile were already practiced well before that was a name for anything. And the demonization of the straw-man version of waterfall in order to sell more agile consulting has led to some serious misconceptions of what waterfall really is and what it is really capable of and useful for.
The initial impetus for what became known as TDD was software maintenance, and it makes sense there.
But most TDD practitioners are nowhere near as good at real testing as the waterfall test practitioners who understand that a single missed testcase could delay a $10 million project by six months.
And this is why, even in the realm of software you still see serious efforts for aviation and nuclear power plants, and other things with real-world consequences, using more traditional methods.
I'm sure lots of chip companies don't share their work in progress, but it's not impossible. Sharing simulations and prototypes and engineering samples can and does happen. You've typically got to be a big customer, of course.
But yes, insights for an industry with relatively small costs for change don't apply easily to an industry with large costs for change, and often vice versa.
Yes, if you're a big enough customer, you might essentially be part of the design team.
> Sharing simulations and prototypes and engineering samples can and does happen.
Simulations aren't the thing. They don't go fast enough to solve anybody's problem. To your point, if a customer is part of the design team, then yes, they can, at that point, help to debug, or possibly even get started on their own dependent designs. (Part of the shift-left I talked about in another comment.)
I'm not sure what you mean by "prototypes" but "engineering samples" are essentially the finished product, done after all the work I described.
Yes, they may have bugs (or they might just not have passed validation and ESD testing yet), but that doesn't alter the fact that a waterfall effort happened before they were delivered.
> But yes, insights for an industry with relatively small costs for change don't apply easily to an industry with large costs for change, and often vice versa.
The problem with indiscriminate use of agile is that, while, yes, the software industry has relatively small costs for change, it has traditionally had huge costs for the initial delivery, and many agile proponents don't properly segregate those two cases.
If LLMs live up to their apparent promise, then, of course, the equations around the huge costs for the initial delivery could change dramatically.
Of course, the same LLM promise means that the strict definition of TDD (tests written first) is also irrelevant, and perhaps even counterproductive.
It's always interesting to read about some chip company or another making some agile move, when the reality is that they were already doing about as many agile things as possible before agile was a thing. (For example, a management commitment to "shift left" when they have always been about significant up-front testing and feedback.)
In many, if not most, cases, the testing software is so huge that at least some of it needs to be tested itself. That can certainly benefit from agile.
But the overall process more resembles traditional waterfall. You have several definite final endpoints, and although you can make subsequent changes, those are expensive. Also, you have a silicon budget, and a pin budget, and a heat and power budget. At the end of the day, you are producing something physical with real-world physical constraints that (a) cost real money, and (b) can't be altered by just telling your customer to add more RAM or a bigger processor.
Also, in general, although designers will write their own little unit tests for a few things, it is best practice to insure that the real tests are performed by internal organizations that are different than the organization the designer is in.
I think that subconsciously, he truism that it is easier to work with and reason about a system that is already working, and to keep it working, than to get it working at all to begin with, drives a lot of the methodology.
The designer might focus on tests to insure that things work well enough to see some results, so things can be hooked up and system tests performed earlier. In one sense, this is a shift left -- the validation people and the people writing software for the chip can get started sooner than they would have otherwise, even if it's a bit frustrating because not everything works off the bat.
But the real torture tests are typically written by the dedicated verification and validation teams. Those are really different skills than design.
I think a huge amount of technical debt goes straight to YAGNI - devs pretending they are not going to need something that, yeah, they need.
YAGNI and related tenets were all excuses for “we are consultants in a field we don’t understand”.
Usually tech debt is debt—-ie something you take on to ship faster now at the expense of paying it in the long run.
Nothing is all black or white of course, but I have personally observed situations where software engineers started with YAGNI and then said "that will require too much restructuring, we went into another direction, so, no, we cannot do it anymore". The worst part is that software engineers are not even in a good position to understand when YAGNI fails: when they don't plan for a useful feature, the solution is often for the users to just shrug it off and use a suboptimal solution rather than fighting and dying on a hill that they cannot win (at the end, the software developers can just say "nope, it's technically impossible" even if it was possible, they have a huge advantage). I also saw users just assuming there were good reasons why the feature did not exist ("well, I guess if they did not did it, it's technically impossible") and just don't even say it. And as the developers are not the users, they never notice anything.
100% with the way of illustrating: YAGNI is "we are consultants in a field we don't understand": sometimes, users are asking for too much, sometimes, they are asking for something reasoning, and the developers have no experience to distinguish between the two.
* Create generalized functions where a specific one would have done.
* Create abstractions for something that will never be needed in the end.
* Create abstractions for something that will be needed but not in the form they initially expected.
It is not about avoiding refactoring. That misses the point entirely. Refactoring cleans up code mess that exists NOW - creating abstractions for somehting that exists NOW.
This is the key insight. Design patterns were developed by a set of consultants. Promoted by other consultants. Consultants have perverse incentives, like bankers.
Realizing this made me critical of the design pattern kool aid. I've come to terms that these are going to be around longer than I'm going to be employed writing code. i keep the criticism to myself and avoid them when i dont see fit. Works ok.
As Hoare said:
https://news.ycombinator.com/newsguidelines.html