Ask HN: How to deal with shipping AI-written code you don't understand?
I saw this LinkedIn post from a Meta engineer and it resonated with me:
https://www.linkedin.com/posts/ali-hamie_im-an-engineer-at-m...
> I'm an engineer at Meta and I never felt this uncomfortable doing my job. I'm writing code these days and it all feels like a black box. This new standard of shipping with AI is moving so fast that if we're going to spend our time checking each line of code, it's going to take forever. That means you can end up with systems you've built where you don't truly understand how all the code works. You understand the high level, but not every detail. And maybe this is becoming the new standard. It goes against every instinct of being a software engineer. I'm used to understanding what I'm building. Now I'm trying to figure out how much I need to understand before I'm comfortable moving forward. Are other engineers feeling this too?
How are you handling this?
I’m surprised I haven’t see anyone say this yet, but I don’t let the LLM design the code at all, I let it implement a design I have created.
By that I mean that, rather than let the LLM do the entire structure, I take the time to create the full hierarchy of abstractions and actors that I want my code to do. I decide, at the UML level, how abstractions will sit and interact — and then I make the LLM implement those gaps.
The key thing here is that, by doing this, I DO know how the code works. I may not know how each unit is implemented, but I know each unit’s responsibilities and how they interact with one another. I’ve found that LLMs are HORRIBLE at writing decent abstractions, regardless of how much prompting and skills I’ve given it. It will always get the job done, but it will often be unmaintainable and require bigger and heavier refactors as I introduce more and more requirement changes.
But by flexing my basic design skills, I don’t have those issues. Future refactoring fit into easy abstractions that I’ve designed. And by documenting it up front, I also have what becomes a living document on how this work will turn out.
It takes a few hours up front to plan ahead, but it makes the LLMs job easier and use less tokens, and it makes the code better long term. I don’t care if one unit is suboptimal, as long as the abstraction is right — because at worst I can change an implementation for a better one later.
This is where myself and a colleague have settled. We design for longevity but it can still type, search, and debug faster than we can.
Same. I let the LLM work inside a framework that I made.
Of course I only arrived at the framework after trial and error with an LLM showed me the shape of the problem and the framework presented itself to me.
Same here. I review plans w rendered diagrams. Data structures, flowcharts, uml sequences, and component architecture docs.
I have found that making the AI look the plantuml and the rendering and reviewing before presenting it to me results in much more legible designs. To me the peak of this would be a shared interactive whiteboard w the ai during design.
Agreed. Even with opus 5.5 which everyone praises for its wonderful coding abilities, I keep catching awful coding abstractions or missing abstractions.
It can keep patching everything left and right whenever a new requirement comes up so it does not "need" to build abstractions, and it will only do it to please the human reviewer.
The key is to stop caring (/s?)
Unironically this is where I converged. Shipping the feature is the most important thing, Opus 5.5 is good enough with correctness that I merge off the title or description alone.
A year from now Fable 6 will de-slopify, so I don't really care about having pretty abstractions. That's simply not my job anymore. Sacrilege, I know.
Agreed, otherwise the risk is receiving the average of what LLMs think are best practice.
Planning is fundamentally so critical to ensuring alignment and outcomes, that over time how one plans can be better trained into the process to help do more and more of it.
> I have created.
Are you working on a team? I've found that for solo projects this works but, even when you own the design of your piece, integrating with the work of several people doing this ultimately leads to even the part you initially designed no longer working exactly as you remember it.
A good chunk of my time now is spend working with an LLM to understand how other parts of the code base work and how they relate to and interact with the product features I manage. But I'm still on a small enough team that this is possible. I'm not surprised at all that an engineer at an org the size of Meta would not even be able to perform this level of work in understanding what's happening.
Yes this is on a team that I lead. We have augmented our practice so that teams do the design reviews together to ensure we are all understanding the changes. It’s also helped uplevel devs to think in terms of design practices.
It still has sharp edges but IMO it’s the best we have at the moment, and it works. It also means we deliver larger volumes of code, but we mostly look for alignment with the original review — so our reviews are more focused on what tests say behavior should be
This is too the paradigm I’ve settled upon after a year of using these tools.
I agree with this approach, but I'm a bit surprised this has to be said at all. These are basic software design principles and I imagine it's the default way any experienced programmer would approach the problem. I wonder if the people not using this approach are primarily junior developers who have never seen how real software is built, or if it's leaking into the senior levels as well.
Most people in the industry right now, even at FAANG and even among people carrying "senior" titles at these places, have little experience with "software design principles" -- tens of thousands of brilliant Ivy League graduates with surreal compensation packages have spent the last decade pulling tickets off JIRA and pasting least-change-possible patches onto existing code for about 10 hours a week while spending the other 30+ hours barely engaged at meetings.
This hurt to read but checks out in my experience. These types also tend to love tossing debt over silo'd walls and pointing the finger a lot if/when anything goes wrong.
I'm old enough now to be a protected class, so I don't want people accusing me of ageism, because that's not where this is coming from - but there's a type of person that clearly is on their last job of their career and knows it and I try to avoid them like the plague, I've seen it too many times.
> there's a type of person that clearly is on their last job of their career and knows it
Yup (and it's not ageism).
I'm young and stupid but forced by circumstance to practice a certain degree of respect for my own stupidity.
My philosophy is, "I write code like I expect it to outlive me".
Because sloppy work --AI generated or otherwise-- has a tendency to come back to haunt you.
The incentive structures are all fucked up. It's far more profitable for all parties involved to just slop out some barely maintainable bullshit that only just meets the product manager's criteria for external quality while completely neglecting the internal quality of the software [0].
By the time the system starts to experience strain under the weight of its technical debt two years later, the original tech lead/architect of the project has already added it to his resume as another bullet point, found a new job at 20% higher comp, and no longer has to ever look at that code, ever again.
Now it's the next asshole's problem. Good luck!
[0] Freeman & Pryce 2009 for the "internal quality" vs. "external quality" dichotomy
I think part of the problem is the original product manager has also added this as a bullet point on their resume and gotten promoted. They get to watch the dumpster fire from a safe distance.
Heh. Extremely accurate.
This is maddening. I've been pulling 40/50/60 hour weeks for 21 years in the tech industry at various different companies. I haven't broken 200k base salary, though benefits are pretty great where I'm at. To think I could've memorized some leet code problems, got a job at FAANG and been making 300k base for the past 5+ years while working 10-hour weeks is - yep, maddening.
There are plenty of people who did all of this at FAANG and never have even heard of leetcode, let alone solved a problem.
Same here, but 30+. Wrong spawn point mate.
Did you go to Stanford or a similar pedigreed college? Unless you did that or broke that 200k barrier already by getting high up in a lower tier company, just memorizing some leet code problems wasn’t going to get you into a FAANG.
They care a lot about prestige. Or at least did before AI. Don’t know what their current hiring practices look like.
I know plenty of people at Meta at a variety of levels without that kind of pedigree
Don't feel bad. It is not about skill in those job, it is about "cultural fit". You must project a personality that will fit in with FAANG culture or you won't get the job unless you're famous globally due to having starting some huge open source project.
Comfort yourself with the fact that you did not have to sell your soul, sit through endless woke sexual harassment videos where you are taught that the white man is the source of all evil, and in endless management meetings.
Well it would hardly be blood money to destroy free society and replace it with a surveillance hellscape if you could make just as much elsewhere.
The 30+ hours were often just goofing off/video games/porn, very few are in 30 hours of meetings. The amount of grift, non-work, fake work, etc that remote well paid tech workers get to do is absurd.
The LLMs know design principles too, being an experienced developer doesn't make you as special as you might think.
Don't get me wrong, LLMs are way better than me at most things, but I don't think you can deny that the current generation of models makes questionable decisions sometimes. Especially on project structure, API boundaries, and code duplication. I also think they just have bad taste in general, though of course that's more subjective.
> I don't think you can deny that the current generation of models makes questionable decisions sometimes
Sometimes, not enough to believe you that you can do it better. And even if you could, to believe that it's overall worth it to work in that way.
You can work the way you want to work. In my experience, letting the agent make every decision leads to a big ball of mud that requires touching dozens of files to make a change. More context is needed, it burns through tokens much faster, and the agent takes shortcuts and builds technical debt. So the way I prefer to work is to have changes targeted to a single file or small set of files where I've defined the API. Maybe that will change in the future, I'm not set in stone here.
> In my experience, letting the agent make every decision leads to a big ball of mud that requires touching dozens of files to make a change
It seems too early to make any conclusion like that. We've still only been doing agentic coding for a year and capability significantly improved during that time. I don't think anybody on either side of this debate can have actual empirical evidence to support conclusions about where it lands longer term.
The main argument I see is that it probably pays to be slightly conservative because the cost of being wrong by maintaining too much oversight and shipping slightly less code is better than the cost of ending up with an entirely unmaintainable system. In some cases it will be more than "slightly less" but in almost all complex pre-existing systems, you are rate limited by a lot of other factors outside of code production, so the effective difference just isn't that high.
When I said "in my experience" I meant literally that, my experience so far. I'm not making any predictions. I'm definitely anticipating things improving at a rapid pace, which is why I think it's good to run frequent experiments. If in a month I find that an agent can one-shot a 20k line project without creating an unreadable, unmaintainable mess, that will be great.
At agentic coding velocity, tech debt becomes obvious much more quickly. Empirical evidence is a bit of a ridiculous bar to hold for software development - we are as quantitatively blind now as we have ever been - but at least for me the anecdotal evidence is very clear. Today's agents hill-climb and their software architecture is pretty reliably bad without a human in the loop.
And it's debatable how much better they will get quickly. Verifiable rewards for maintainability of software is, I think, possible but very hard.
I share that experience. To the point that I don't think I'd want to work (at least for as long as I have the luxury of having a choice) on a project where an AI has been let loose.
I also see devs, seniors as well, that have a different experience. At least that's what they say. I stay open to the possibility that I'm doing or seeing it 'wrong', but I'm far from convinced. I do like to experiment like you wrote in a later comment, things may change, and even now I do find it can be very powerful, for the right tasks.
What still is true for all fields of LLMs: if you can’t tell they do it suboptimally, you are just not that knowledgable in that area.
It still applies to all things LLms can do from law to code to art to ideas.
They can do it - and very acceptably - but only to the untrained eye.
To be fair, if LLMs were good at decisions, we would not need people.
I’m not sure how to say this without sounding smug, but the last year has shown that most of those things just… don’t matter. It’s just the next level of the “variable naming PR comment battle”, so will become obsolete very soon.
Obviously there are mission critical systems where it matters, but if “your code can be A/B tested” or “slowly rolled out”, chances are, it doesn’t matter.
You'll find that design matters when token spend starts facing real accounting.
Tech debt is still tech debt, even if there exist models that can wade through, because it's going to require increasingly sophisticated models navigating increasingly large context windows and increasingly speculative workspace operations to keep making progress on it.
Vendors like Anthropic and OpenAI are laying a pit trap when they demonstrate how their models can independently code their whole platform as it becomes increasingly byzantine and inscrutable because not only do they benefit from internal/prerelease models but they have effectively unlimited spend because all that spending acts as a lure to draw you into their trap.
For everybody else, design still matters. People are just working really hard to make you forget.
Honestly, I keep hearing this argument, but the past 2 years have shown the opposite. OAI/Ant are not the only companies providing inference.
There are legitimate FAANG-like companies that have general guidelines about “when to use Fable/GLM/DS” and etc. to keep the costs down. And I think it’ll continue that way.
You didn't address the argument about tech debt. How do you get the greatest quantity of maintainable, high quality code within a given token budget? The answer, at least so far, seems to be human experts in the loop. We've also been hearing for years that LLMs are going to automate away software development entirely, but software job postings are steadily rising.
https://www.cnbc.com/2026/10/11/ai-software-developer-jobs.h...
>How do you get the greatest quantity of maintainable, high quality code within a given token budget?
Doesn't matter as much. The cost of "maintenance" is going down, from what I can see internally, from other companies, and every story i'm reading from other organizations as well. Token budgets are changing, but model quality and effectiveness are going up as well.
> We've also been hearing for years that LLMs are going to automate away software development entirely, but software job postings are steadily rising.
I think this has been contested from day 1. SE jobs might be automated, but jobs might increase, if there's possibility of starting new companies / new investments / etc.
I'm still not clear on what you're really saying. If a human programmer's input doesn't matter at all, then anyone should be able to prompt a model until it spits out the software they want. That might work today for building fun tech demos, but I don't see it happening on projects that have a minimum bar for security/reliability and long-term maintenance. Would you say, for example, a team of 10 managers with no software experience can be as successful as a team of 10 expert programmers at building a large project like an operating system, with both teams having access to the same AI models and budget?
No, because expert programmers will not know what they’re building, and skew the prompts and ask for the right things.
The analogy would be math people with AI vs. non-math people with AI trying to solve some problems. I cannot solve the problems because I have no idea how to prompt it to go specific way. But it doesn’t matter how dirty your scratchpad was, because you got to the solution.
> I don't see it happening on projects that have a minimum bar for security/reliability and long-term maintenance
I don’t get this, because this is currently, right now, at this second, happening across huge projects. My point was that maintainability is less of an issue than before. Also, frankly, over years, I’ve seen bad code that AI wouldn’t even write. So there can be a case that the maintainability/code quality isn’t even going down as the models get better.
>You'll find that design matters when token spend starts facing real accounting.
You're also find that implementation matters when token spend starts facing real accounting.
I really wish people would become more coherent with their reasoning.
The problem here is not the vendors. The "problem" is that design mattered when producing code was a truly manual effort. Writing things down, aligning specs, design, contracts, all of that would mold what could come next. Now ANY design from amazing to terrible can be regenerated and generated dozens of times over for literal single digit dollars.
Cost of tokens is NOT a problem unless you have a codebase with hundreds of person-years of effort. Not many people do.
Personally I think I could probably be content for the rest of my days running something like Z.ai glm-5.3-flash locally, so I'm not that worried about the token spending (and still can't understand how OAI/Anthropic/etc convinced the market they have any kind of moat to motivate those kind of evaluations, but that's another topic...)
That said, I also feel like betting on readability, maintainablility, taste, etc, being an important aspect of software, at least until code will remain some sort of human readable artifact. We'll still want to be able to understand it and perhaps occasionally add/edit by hand, make sense of it without trusting blindly what any kind of program (LLM based or not) will tell us about it, and so on.
API design matters if anyone outside your app consumes it. Duplicate code makes changes hard and most compilers can't optimize it away. Bad file structure wastes tokens and makes off target edits more common.
These things are important even in a repo with zero human code. A project that's filled with tech debt will always be hard to work with no matter what latest frontier model you're using.
I think a lot of this can be automated with slop detectors that flag messy unreadable code and make agents rewrite it, but you can't say it doesn't matter.
Yeah, fair point. I guess, my reasoning was pointed towards “AI will resolve the issue, so I don’t care that much about it”.
I keep hearing that humanity is going to be superseded by models that I can barely force to actually abide by a modular repository design.
I can see three likely explanations for how my personal experience with modern AI programming tools differs so much from a lot of the advocacy I see online.
1. We are working on different types of application and code.
2. I am in a bubble and no-one in it has experienced the standards and productivity that SOTA AI tools can achieve.
3. The advocates are in a bubble and no-one in it has experienced the standards and productivity that expert developers can achieve.
I hope the answer is 1. I fear the answer is 2. I suspect the answer is 3.
That's why I don't rely on their design. But I also don't write the design from scratch. I use a conversation with the model to build a plan. I let it do the things it thinks is right, and I add corrections where I want to see something different. Or more accurately I "ask questions" which lead the model to making those changes itself. I don't say "use this design pattern here instead" but "Why didn't you choose to use this design pattern instead? What are the tradeoffs that you see?" When I notice a pattern in how the model deviates in how I prefer things, I add additional instructions to the prompt to try to close the gap over time and I get better first shot responses.
> bad taste
They are only as good as their training data.
I expect them to have badder taste for PHP or JS, than, say, Kotlin or Ruby.
That's be because I prefer the code the latter communities have produced over the former.
A friend of mine is getting into AI more than I am and seems to like doing random coding tasks to see what it can do. Like, coding a clock app in Window with NTP/PTP. Or coding a multi swarm agent that is so poorly designed it hurts my soul. I want to say the clock app came in at 300 Mb and god knows how much memory usage it was pulling. LLMs have all these different pieces but it still doesn't know the optimization that an engineer might know with experience. Because of the amount of slop being generated, we're essentially line workers that deal with automation being implemented in factories. Very much the the technology version of the 'American Factory' documentary on Netflix. Unless we're at the forefront of this SOTA hotness, we're behind in all aspects.
> doesn't make you as special as you might think.
Way to come off as incredibly insecure. There's no need to randomly put people down.
I'm not the one who's claiming to be above the latest models in some aspect of coding in this interaction.
No one at all claimed that, certainly not the person you responded to. They're talking about how to use these tools in a way that gives you insight into what they produce. So, as an engineer, you know the shape of the output, before it's made.
That's it. Maybe you should go re-read?
Why is that so hard to believe? I don't always do this, but I do course-correct Claude on almost every big change. YOLOing it would superficially look fine, until the latent issues catch up with you.
I course-correct it all the time too, my point was only that I don't exclude it from the initial design.
Maybe they are?
Its really sad that you think that an intelligence that cannot learn is better than you at everything.
The advantage I have is that I know things that are not in the training distribution. Things about our business, our product, and its internal architecture. Without this knowledge, some new features cannot be designed successfully.
Some day I expect that will change, but all the patchwork "memory" systems, all the docs etc, will never get there because at some point they just pollute context. Knowledge has to be integrated, and that is what happens during sleep for humans, during pre-training and RL for models. LLMs are terribly inefficient at learning though and degrade generally during fine-tuning.
I'm not disagreeing with you - I give agents a lot of input and spend a lot of time iterating with them before I'm happy with the result. My point was only that I don't think that I'm somehow superior in design patterns or any other general part of coding just because I happen to be human or because I have years of experience.
Unlike a lot of humans, Claude's not gonna be a dick to you for thinking you're superior.
Also worth mentioning that Claude is extremely good at accepting constructive criticism.
I've been doing this a long time and i would say since the last 3 months or so i've spent more time learning from llm code than correcting llm code. It's not bad and takes approaches and makes decisions i wouldn't have thought of. I'm not too ashamed to admit that, a model just as access wider and deeper experience with code than I do.
The LLMs have been trained on all kinds of code. They often choose a hacky solution because that's what they encountered in similar situations in their training. It generally only takes a few words to guide them to a better design than what they saw in the wild, but if you don't guide them, they follow the herd.
It generally only takes a few words to guide them to a better design than what they saw in the wild, but if you don't guide them, they follow the herd.
That certainly can be true but I would challenge "generally". If you're working on something novel then it's not exactly unusual for even SOTA models to produce a first attempt that makes some very bad assumptions but then get stuck when instructed to use correct axioms instead. This looks a lot like the suduko meme - without any real insight into the problem the models end up just iterating around in circles and never finding a solution.
You probably won't see this very often if you're working on simple CRUD web applications where there are millions if not billions of lines of code in the training data set. IME you will probably see it quite frequently if you're working on - for example - software to control some kind of equipment or analyse the results of some kind of experiment where the LLM might have little if any training data about the field you're operating in.
That's a great perspective. Come to think of it, I wonder about the quality of the build123d code it generated when I vibe-coded a prototype complex assembly. Now I'm curious.
Any time the LLM can establish a tight feedback loop it can iterate effectively enough to make good progress. But if for one reason or another that feedback loop is long, the more guidance and direction they seem to need. If they cannot correct their course based on feedback from their own output they need an outside observer to push them towards different paths. CRUD stuff is the obvious easy answer. It represents some absurd amount of software development work and is drastically overrepresented in training data. For good and bad. Lately I've been working on a diffusion model for terrain generation. The goal is to be able to recreate realistic terrain based on water flow and erosion on top of plate tectonics for much longer geological time terrain adjustments. These are much longer feedback loops. Sometimes it'll spend 6+ hours training a diffusion model on my 5090 just for the quality to degrade compared to the last experiment. So letting the model go wild trying different approaches and evaluating the results doesn't work nearly as well as when it can iterate 1000 times in those 6 hours while checking its own answers.
Any time the LLM can establish a tight feedback loop it can iterate effectively enough to make good progress.
Not any time. Your feedback loop must provide some direction so the iteration is at least heading towards an improvement. For novel applications you might not have a convenient way to do that yet.
Even with that provision there's still a possibility of incrementally updating output converging on a local maximum. That local maximum might not be a solution at all. If it is a solution then the model might still miss much better solutions that a real developer with more insight might find.
As you said yourself the models need external feedback if they don't have sufficient information to make adjustments by themselves. In some cases that feedback might be "Start again because you're hopelessly off track". Sometimes even when they start again they just get hopelessly off-track again. That can happen even if they are explicitly prompted to do something else. So even closely supervising the LLM and not using self-iterating agents isn't guaranteed to get good results for novel applications.
The LLMs don't know a single thing. That's not how the technology works. It's a statistical correlation, not understanding.
I don't think the distinction between statistical correlation and understanding is as clear-cut as you're suggesting.
For example, Li et al. (2023), Emergent World Representations, showed that a GPT model trained only to predict Othello moves developed an internal representation of the board state, without being explicitly taught the rules or board structure.
The might actually know real design principles vs what ever we made up in the 00s.
I work on my code this way, but I have no idea what my colleagues are doing, and it's impossible to review thousands of new/changed lines a week.
I just approve PRs, because I have to. I don't know what else to do. I can barely keep an eye on all my code.
Actively looking, but job market is rough in Northern Europe. I quit caring about quality in any capacity here, the company has clearly chosen its direction, against my very vocal complaints.
My last interview, with what I thought was a great company, failed when I didn't understand what NLP was when they asked me about it.
> NLP? > Natural Language Programming, it's the future. Claude, GPT, etc.
I laughed, he didn't, looked offended and said it was a serious question. I had thought it was a joke, said "oh you mean LLMs". I tried to answer seriously, of course, but that was my third round technical interview and I didn't get a call back.
Just getting a paycheck and producing mediocre work until I get something new. (Senior engineer, 10 YOE, patents, 3 years at a unicorn).
Also considering becoming an electrician.
Yeah, I imagine it's something that needs to be enforced at the organizational level. I sympathize with anyone who takes pride in their work and needs to deal with mindless coworkers pushing slop without any accountability. I left corporate software development (before LLMs were a thing) over frustration with the general culture and I can only imagine it's gotten worse since then.
It's really bad now, yeah. :( It just really hurts that I spent well over a decade of my life learning and honing skills to engineer safe, quality software and now it's just, useless.
No one cares at best, or I'm callously told "keep up or fall behind" at worst. When that's not even the problem, it just, sucks now. There's no joy in anything I do professionally.
Can I ask where you went? I'm seriously looking for an exit, I just don't know what yet. Maybe a trade, in Scandinavia the pay is actually comparable, I just don't want to go back to school.
I was fortunate and saved up enough to live frugally and just work on passion/learning projects for a while. I've been considering going back into commercial software development as a solo dev and leveraging AI, but keeping the focus on quality and craftsmanship. In my opinion there's never been a better time to start a new, ambitious project if you're passionate about quality software.
I agree, that's acutally what I'm doing right now: living frugally in a cheap country while building an ambitious high quality pruduct.
I never had a better time "professionally" (albeit no income yet!) so far in my whole life! Apparently it's truly like the best of times and the worst of times to be building software, if you have the luck and the luxury to be able to work only for yourself than it's really a great time to be alive.
It just really hurts that I spent well over a decade of my life learning and honing skills to engineer safe, quality software and now it's just, useless.
It can feel that way with all the hype but I very much doubt that is really true. I see an industry that is rapidly dividing into two camps - "move fast and break things" and "this actually needs to work". Writing everything with agents and merging while barely even checking what is in the PR has become standard practice in the former but it will get you laughed out of the room in the latter.
Even “actually needs to work” has a wide spectrum from “people could die” to “our customers will be pissed”.
For the latter, the product looks nice and polished on the outside but makes “steaming pile of crap” a gross understatement.
Sounds like a cushy job. Why would you want to leave?
Some people just can't turn off their brains and play drone for dozens of hours a week for decades. It feels existentially, aesthetically, and sometimes ethically crushing to spend a whole life doing work you can't expect yourself to respect or value, no matter how much you get paid or how little the work overtly demands of you.
Often, the lack of meaningfully challenging demands being put on you is punishing on its own. It can feel like a relief for a week or month or year, but if you catch a glimpse of that being your whole future, you can come to recognize yourself as being in a mind-eroding secular purgatory.
This anguish is especially common among on highly capable people, high achievers, and those used to some kind of ambition. And by accident of its history, there's a lot of those people in this industry and some of them are going nuts now.
> This anguish is especially common among on highly capable people, high achievers, and those used to some kind of ambition. And by accident of its history, there's a lot of those people in this industry and some of them are going nuts now.
I went nuts for years, until I sold off my interest in my dream partnership.
10 years of heaven. All the benefits and none of the downsides of my internal colleagues. Then 14 years of bureaucracy aimed at predictability over progress, which was infinitely more difficult for me to dodge as an external player.
Compensation for my interest was very objectively valued, with the rate of stalled progress priced in. Which made complete sense, while also being its own madness.
I walked away from so much value, but I don't regret it for a minute.
> and some of them are going nuts now.
Pretty much this. I know it sounds melodramatic but it literally feels like rotting.
I don't solve anything anymore. I don't get any spark of fixing bugs. I don't DO ANYTHING, and it's fucking chipping away at me.
Also I'm fairly sure people are going to realise soon that if they're happy with slop, they don't actually need highly trained engineers anymore.
This whole thread actually prompted me to look into electrician work, especially in renewables that we have here in Norway.
I might fix my burnout and go to school to get my 2 year qualification. AI can't rewire a hydro dam.
Man, I have the same feeling. A long time in your life you build the career and now it’s just feeling so empty, like you are not a engineer anymore, now everyone can use AI and without checking code they would have good results.
> now everyone can use AI and without checking code they would have good results
?!!?
No way. Are you sure? What kind of work? Here there’s still a lot of care needed to navigate the LLM work, like knowing when to make it quit, rewrite, refactor, follow your outline.
It feels magic but when I watch people who don’t know what they are doing trying to make something new (not almost a clone of an existing product), they get pretty frustrated.
I once lost out on 3 months severance and a laptop when I quit a place and they shuttered two and a half weeks later. There had been no direction from the top for over a month other than "ehh, do something useful". I was working remotely and slowly going crazy.
This exact mentality is extremely toxic and is why the historical "anti-work" movements (i.e. Anarchists) have been kneecapped, often by their supposed best friends (i.e. Commies). The major disagreement circa the 2nd internationale was "is work good, but bad that you're exploited and not paid well?" (the Marxist view) vs "Work fucking sucks and we should abolish it" (The Anarchist view)
https://en.wikipedia.org/wiki/The_Right_to_Be_Lazy
https://en.wikipedia.org/wiki/In_Praise_of_Idleness_and_Othe...
I can't believe how much mental justification needs to be made by otherwise highly intelligent people (Bertrand Russel wrote In Praise of Idleness) to defend the right to not work.
No, I fully reject any notion of life value coming from work, and those who hold your view are basically jailors to those who don't want our identity defined by work.
That's not how the world works, and I don't need this in a thread where I'm dealing with the grief of a good career. Please shove off.
I would gladly not work and learn cello and physics independently if that were a real possibility, but it's not, and it won't be within my lifetime.
I had a job in a system that required jobs to survive that genuinely didn't bother me. I actually quite enjoyed it most of the time. Now it's permanently dead and I need something else, or I am homeless and starve to death.
> No, I fully reject any notion of life value coming from work, and those who hold your view are basically jailors to those who don't want our identity defined by work.
Fuck off.
I wish society let nihilistic bums like you die of starvation instead of indulging your bullshit.
it sounds soul-destroying
I'd forgotten why I'd stopped commenting here. Thanks for reminding me, everyone.
I will be unhappy if they steal the meaning of NLP. NLP means Natural Language Processing and LLMs are only a subset of NLP. I would have concerns about anyone who claims to have technical knowledge and asserts NLP means "natural language programming." Those are the same kind of people who might suggest Lisp should add mutable objects.
You may be surprised and annoyed that NLP is also "Neuro linguistic programming", I've met technical people talking of NLP and meaning that...
Yes, but that's in psychology. Different fields have their own terms without causing too many issues. Communication breaks down when we reuse terms for different things within the same field.
More like parapsychology...
They're not unrelated, though.
Without massive scale weapon-grade NLP coming out of AI PR depts and targeting unwitting programmers, the LLM psychosis wouldn't happen.
They may not be related, but having a good understanding of the psychological NLP actually lends it self really well to NLP and prompt engineering. As much as a lot of people 'claim' it to be parapsychology (even within this thread), check out books like Strategies of Genius and how it breaks down a lot of the main concepts. It's very 'meta-cognition' if you will, but, the parallels are eye opening given how long the concepts have been around. If someone has never done serious mind mapping or brain storming and entity-node relationship type work with databases, it would be quite a leg up helping them understand and mentally map out concepts like that.
>Communication breaks down when we reuse terms for different things within the same field.
Ahem Maybe you should write a shim for the stack you're using to broker domains.
you mean like cons cells lol
Same for "AI". LLM is about the only kind of AI we talk about now, so the two blended. Nothing dramatic I guess, but it bothers me when tech people, who are supposed to know the difference, confuse the two.
I'm in what I think will be my last tech job before retraining into something else. The aspects I like about the work are gone, I'm coasting at a small company that's not a great fit, has a visa cliff, and is poorly paid, and the steps it would take to become competitive in an LLM driven tech job market are less appealing to me than the steps it would take to switch over to a different career (likely in healthcare).
Good luck! I took the plunge last year and am just finishing up med school pre-requisites. I'd say at least 6/30 of my O Chem II class are former software engineers.
Thank you! I'm still in a very exploratory phase about what exactly I mean by switching into healthcare. I don't have prereqs done at all, and my current plan is to enroll in a second bachelor's next year and start working through bio and chem courses. I'm looking at a bunch of different options from nursing to PA school to medical physics, and I think I really need to start shadowing people in different professions.
Med school interests me, but I'm a woman in my late 20s who would like to have children, and if I started down the med school road now I wouldn't be done with training until my late 30s, where PA and nursing school don't have that problem. Medical physics is kind of in the middle.
Oh interesting. I was looking at bio-informatics briefly but never even considered medical physics. It's crazy just how big healthcare is and how ignorant I was to it prior to making the transition. Would agree that shadowing has a huge impact on determining what you want to do in the future. My cousin went the PA route over med school and honestly I think it's the best from an ROI and free-time perspective. In her early 30's now and every other weekend she's in a different country.
Understand completely. I'm a little older than you but the high chance of giving up a family was the first thing on the negative column when I was deciding paths.
Awesome! I'm taking prerequisite classes (probably for Physician's Assistant school) while picking up a few shifts at the local EMS station. Good luck on your journey!
Cheers! Best of luck to you as well!
literally in the same boat, gonna see if i can't use ai to build some products to make money and help people, or else i'll go into healthcare and make (significantly less) money and help people.
If that's what NLP stands for now then I want off.
You will get used to it. Even I accepted cyber eventually and now no one bats an eye.
I don't do this at all. I just YOLO merge after reading the change description. Senior dev, paid well at a FAANG.
I don't really care about the code being unmaintainable. Fable 6 or whatever will take care of it, just like Opus 5.5 takes care of our Opus 4.6 slop. The code working and our feature shipping is way way more important.
How long until they realize you bring nothing to the table, they can automate the yolo merges, and you’re no longer well compensated?
It seems unrealistic protect our jobs by keeping it a secret if LLMs really can do them (still a big if). Maybe if we as an industry had formed unions but it seems a bit late for that.
We have technical unions in Norway for engineers, it's not preventing layoffs. :/
> I don't really care about the code being unmaintainable. Fable 6 or whatever will take care of it
> The code working and our feature shipping is way way more important.
I like that we both use AI very differently (you YOLO, I don't) but can agree that these are basically the important questions. If a company or team answers them like you do, I agree with the conclusion (YOLO). To me that's still a decision to be made though, and to be made wisely. Whether to accept the code may become unmaintainable, to forwardly rely on Fable 6 and to ship above anything (or at least a lot) else.
LLMs certainly helps with designing and is the best brainstorming tool one can have beside their own brains.
> rather than let the LLM do the entire structure, I take the time to create the full hierarchy of abstractions and actors that I want my code to do. I decide, at the UML level, how abstractions will sit and interact — and then I make the LLM implement those gaps.
Do you do this with every repository that's brand-new to you? You refuse to, for example, use an agent to learn where the feature should generally live? This seems absurdly slow for that purpose, because even though humans can still get a deeper understanding of a codebase after several months, an agent can get a much deeper understanding over a timeline of the initial few days. Unless everything is already meticulously documented for you, I suppose.
I don’t believe I said I don’t use agents for things like research? There’s a difference between trying to get your bearings in a new codebase with an LLM pointing you in the right direction so that you can understand things, and just letting an LLM like Claude take the wheel to do a change for you.
Yes, new codebase we take the time to learn, as every good developer should. Ramp-up doesn’t have to be that long to get one’s bearings.
Also, changes don’t have to be deadbolted into bad designs. If the code was bad before and you have a change to make, it can sometimes be faster in the long run to redesign it and rebuild it so that it can scale better with future requirements. LLMs make this part fast and easy — but again, requires design, and designs require human brain involvement and understanding of the codebase
Sounds a bit like the brain sandwich: https://terriblesoftware.org/2026/10/02/the-brain-sandwich/
Agreed. I generally feel pretty comfortable with letting LLMs implement stuff like individual functions or algorithms. But I feel like it takes some effort to make sure separate things stay separated... (I do think it also helps LLMs if the code to stays nicely abstracted.)
On the other hand, I do some stuff with physics simulations and LLMs will spit out arrays like
static constexpr std::array<int, Q> cx{0, 1, 0, -1, 0, 1, -1, -1, 1};
static constexpr std::array<int, Q> cy{0, 0, 1, 0, -1, 1, 1, -1, -1};
static constexpr std::array<real_t, Q> w{ real_t(4) / 9, real_t(1) / 9, real_t(1) / 9, real_t(1) / 9, real_t(1) / 9, real_t(1) / 36, real_t(1) / 36, real_t(1) / 36, real_t(1) / 36};
static constexpr std::array<int, Q> opp{0, 3, 4, 1, 2, 7, 8, 5, 6};
and it's like ??? I know what these are for, but I have no clue if any of the numbers are right :-)
As someone who's written those numbers by hand enough times pre-AI to still recite them in my sleep, they are indeed right. Didn't expect to see a D2Q9 LBM simulation on HN today, thanks for making me smile.
dang, that's exactly what it is. I was not expecting someone to recognize it! This also made me smile :-)
A chilling early experience with AIs that seriously affected my thinking on AIs:
I was working on a ground-up implementation of a SPICE circuit simulator that would generate code to do realtime simulation of electrical circuits. Much of the work was derived from complex mathematics in a couple of papers that I was using as a guide, and from The Spice Manual (3rd edition) which serves as a guide/standard to the Spice language, including detailed mathematical formulae, expressed in standard mathematical notion (but no code) for most of the simulation operations.
When transcribing formulae into code by hand, I had gotten in the habit of providing references to page numbers and equation numbers in comments in the code, and "footnote" comments that provided URLs to the original material.
Imagine my surprise when Claude also provided correct comment references to pages and equation numbers when I asked it to write code to implement diode models.
The issue is the LLM can often design thing superior to anything you can do. Now this isn't always the case but it is often the case. By limiting yourself to code only YOU design you are cutting off a major portion of of AI capabilities that is highly leverage-able.
The pace of AI is literally changing so fast that we can't keep up. Your strategy here was probably true around 3 to 4 months ago. Right now it's no longer true. Not many people understand navier stokes and that's what AI can offer, it can offer some superior problem solving methodology with the level of complexity of navier stokes that you have no hope of understanding without years of study and education to get yourself up that level.
This is not a trivial question with a trivial answer.
Unfortunately your answer is outdated. I think if trendlines continue, the answer is trending violently towards putting more and more trust towards AI.
Compute is finite but human stupidity is limitless. You can ask AI to do something unimaginably stupid and it will spend its full capacity trying to satisfy your stupid request, which may not even be possible.
For those of us with practical budgets not measured in the millions, that bar for stupidity is pretty damn low, and I’m not convinced that there’s enough compute being built to account for every idiot in the world.
What does human stupidity have to do with this? If you're too stupid to ask it a good prompt then you're probably too stupid to design something for it to do.
I'm saying ask the AI something beyond your intellectual capabilities. Or ask it something beyond your intrinsic knowledge base. It can produce a working machine that does the job, but you won't be able to understand it.
You can still verify the machine works by using the machine... but you won't necessarily understand it. Similar to how you own a smartphone... you know it works, but you will never fully understand everything about it.
> It can produce a working machine that does the job
Until it doesn’t, and then you’re too stupid to understand why not. Was it that your prompt wasn’t good enough? Does the model not have enough context? Is it even possible for your request to be satisfied?
> What does human stupidity have to do with this?
You answered this yourself:
> but you won't be able to understand it.
And:
> I'm saying ask the AI something beyond your intellectual capabilities. Or ask it something beyond your intrinsic knowledge base.
What’s the limit to this? “Claude build me a nuclear fusion reactor.” Surely we can agree that there’s a limit or we’d already be living in some post-scarcity utopia. So what’s the limit?
I’m suggesting a limit: human stupidity is limitless while compute is finite. We can use the word “ignorance” if the word “stupid” is too inflammatory.
> Until it doesn’t, and then you’re too stupid to understand why not. Was it that your prompt wasn’t good enough? Does the model not have enough context? Is it even possible for your request to be satisfied?
You’re unable to comprehend the topic of the conversation.
We’re talking about querying the model with prompts and asking for solutions beyond your intelligence. You’re talking about flawed prompts.
> You answered this yourself
You’re rude af. Not understanding something is not intrinsically bad.
In fact you use things you don’t understand on a daily fucking basis. Your iPhone, your car, your computer. All of these things have aspects of it beyond your intellectual capability to fully grasp or comprehend and yet you use it. Sometimes these people who make these things produce faulty products and you ask for a refund and are more careful in the future about what you trust, sometimes the product is exemplary.
Relying on an LLM to do something for you is much of the same.
Get it? Probably not. What are you going to do? Call me stupid again because you have nothing substantial to say? lol.
Edit: you edited your response which is uncharitable. But whatever I’ll respond to your new statements below.
> What’s the limit to this? “Claude build me a nuclear fusion reactor.” Surely we can agree that there’s a limit or we’d already be living in some post-scarcity utopia. So what’s the limit?
I agree. But this is not the topic of conversation. I’m talking about querying LLM to do something beyond your ability. This is something you can do and also stay well within the obvious limit you’re implying here.
> I’m suggesting a limit: human stupidity is limitless while compute is finite. We can use the word “ignorance” if the word “stupid” is too inflammatory.
You don’t need to suggest a limit. It’s obvious ai can’t build a nuclear reactor. Nobody needs to be told this.
A clever quote doesn’t prove shit. Ok so human stupidity is limitless. Computer is also finite. I agree.
How the fuck does the above two facts which I agree with have anything to do with me asking the LLM to make something I have no knowledge about? “Hey LLM write an emulator for this Zelda n64 game.”
The prompt is well within the “limit” of what an LLM can do. Compute is still limited. And human stupidity is still boundless. Nothing has changed. Why? Because someone is ignorant and unaware they are prancing off topic onto orthogonal concepts.
I’m using the word “you” in the generic, impersonal way, like the word “man” in German.
But in your argument we are all essentially idiots compared to AI, and should essentially embrace that, dunno why you take offense to it. I essentially agree. Where I disagree is how far we can make it without human intelligence in the loop because of finite compute power.
Nobody is talking about how far we'll go or what the end game will be. That is NOT the topic of the conversation!
I'm saying right now in your personal workflow you are giving up many useful features of AI when you only allow it to implement your design as opposed to letting it design for you.
Yeah, we already saw what "within limit" means e.g. in the case of "make me a C compiler" with kinda unlimited compute.
I tend to work in a middle ground space here. I want to influence and approve and, most importantly, understand whatever design I'm pursuing. I don't want to fastidiously write the whole design out myself.
I've been starting in the ChatGPT web UI, having long conversations, having it generate Markdown plans, and then editing those plans; I hand those off to implementation agents.
I really don't think that's enough. You understand the product but not the process.
This is okay as an end user who only cares about features but can be disastrous when something goes wrong and your only hope is to prompt an LLM that might or might not be (a) available or (b) not read into the context of the codebase.
The scope of the problem worsens when you consider that many teams STILL don't own what they write and have SREs serve as their first-line. These folks NEED to know how the hot paths of the services they support work without the memory or tools that your Claude account has. This is much much harder to do on a codebase that's a billion SLOC for no reason with inconsistent code style and questionable tests littered everywhere
I think that writing the code OR having written a lot of code in the past is the only way to REALLY understand what's going on.
Good SREs can support a service without being familiar with the details. They use generic mitigations (e.g. rollback to a know good release, request an emergency quota increase, etc) to quickly stop the bleeding without needing to understand the root cause. Later the SWEs who understand the code can debug at their leisure. Having a deep understanding of the service obviously helps but is not essential. I expect agents are already applying these generic mitigations at bleeding edge companies but do not have firsthand experience as an SRE to confirm.
SREs _can_ support a service without knowing the details, but knowing the details massively reduces MTTR.
Knowing the codebase is often the difference between proactive resolution ("This keeps happening when that log message keeps appearing; here is the PR that fixes this bug; here is the runbook on what to do if something like this class of problem appears") and reactive resolution (increasing quota, which costs money and might not always be possible; rolling back, which might introduce security concerns; etc.)
This is probably the biggest reason why SREs at big tech companies are usually also SWEs or SWE-adjacent.
Yes, agents, but given that AI-generated codebases grow and change too quickly for humans to keep up, the issue becomes over-reliance on agents over time, a Russian Roulette style of problem when the cost to access to these models keeps increasing...
Yeah I do something similar, basically it all comes down to more babysitting and being more involved with the actual architecture, correcting stupid mistakes, and reviewing the code (and comments!) the LLM leaves behind.
Sometimes you do need to see how things are implemented before you know that a design doesn’t work, I’ve never been big on large upfront design work and prefer more iterative development. This can still be perfectly done with LLMs.
This feels right. It fits the "Assembly to C" style transition of abstraction in that we're going from "code to design of code."
A question I've been struggling with, however, is what are the artifacts that live at this level? Are they design docs? Are they standardized? If I read your design docs, will I understand the code or do I need to "decompile" (use a coding agent to explain) to get back to this level of abstract for me to edit it?
Existing abstractions can be easily applied to similar contexts, but designing abstractions seems backwards. The system abstractions should be grown and extracted from the working code. Idk how you know the right thing without going through the complexity of building it.
Worth mentioning: Sometimes we choose initial abstractions that don't survive well and need to be adjusted as the project evolves. Claude is extremely good at performing large rewrites that are needed if you need to adjust an abstraction on the fly.
Sure, but the best way to come up with a good design is to talk it out with the LLM.
Soon that will be counterproductive and you'll be better off trusting whatever design it comes up with.
> I’ve found that LLMs are HORRIBLE at writing decent abstractions, regardless of how much prompting and skills I’ve given it. It will always get the job done, but it will often be unmaintainable and require bigger and heavier refactors as I introduce more and more requirement changes.
I quote this just to put extra weight on this! It's surprising, the effect size of this statement.
Replying to save OP, and this comment!
Serious question: how is a consumer of software can I tell that it was written with bad abstractions? Is there a signal that software is well written and maintainable other than very high cost?
I’m willing to believe that software you authored or designed yourself is better than whatever Claude spits out. I’m not as confident that the cost benefit ratio pencils out anymore. In fact, I would say most software does not need to be particularly good or well thought out. The vast majority of things I need software to do for me day-to-day at work are so niche and specialized that I tend to prefer AI slop that I can get now for a few tens of dollars at a time and something expertly crafted by a true artisan for thousands of times higher cost.
99% of software out there is a huge ball of mud even if the senior/architect/<insert egotistical title here> started out by building it with the sexiest abstractions. Things just tend to rot and complexify. Software engineers never figured out a way to prevent that, though it is easy to be fooled by the preening and pontificating we do to make ourselves seem like the "very serious professional engineer who cares about code quality very much". I'd keep using AI if it's working for you.
I used to take a lot of pride in my engineering but I honestly think the LLM is a better designer than I am.
It still needs a lot of back and forth before I'm comfortable it's not doing slop architecture, but once it's on thesame page as me it genuinely is better at it than me.
how often with a structured approach like this, you end up with large completed features that don't have many bugs?
This is the only way to work with AI and ensure your code is still (somewhat) maintainable in a year+.
Anyone who's ever directed AI at a very large legacy code base will have noticed that AI just gets dumber and slower the worse (larger + inconsistent) the code base gets (just like us humans do). The big difference is that with AI you can get to the point where the code base is an unmaintainable legacy mess in a fraction of the time that it used to take. Directing architecture is the only way to mitigate this to some extent.
I've been naively assuming that most senior+ engineers were doing this too?
A friend of mine sometimes jokes that code is “fractally busted” when it’s wrong at every level, from single lines all the way up to the design of the system’s main interfaces.
That’s also roughly what I find after a long English-only session with a coding agent. Our conversation covers a lot of ground... and leaves out details at every level. When I look at what got built, the misunderstandings are fractal too.
I agree it’s important to design it yourself, but UML is only one level. Lately I’ve been using a scratch Python file (or even a scratch repo) that Claude and I both edit. Never mind that I’m writing Rust. Python reads like pseudocode, and pass and ... (Ellipsis) let me skip whatever I don’t care about. At any level where I do care, I can say exactly what a method’s signature should look like, what fields a domain model should have, or how it should maintain key invariants. Everywhere else I leave an ellipsis, maybe a docstring, and let the agent decide.
It works both ways: I ask the agent to sketch the current system in Python, with some details elided and others spelled out. Then I edit the sketch and have the agent push the changes back into the much bigger Rust+Tauri app.
Time will tell whether this approach has legs, but when I want to be precise, I find it sometimes pays to just write some code.
This is the way. I can write pseudo code (ie Python) and I leave a breadcrumb trail of comments where I want it to implement. Hell the code doesn’t even need to have valid syntax if you forgot some function signature, but that small amount of guiding can produce significantly better results than a blind implementation from the model.
I’ve also tried spending an hour or two first before handing over control. That way there’s something pre-existing it can work from.
I've found that current models will almost automatically sketch out some things in Python (or another suitable language for the type of task, or an implementation language you've already stipulated) while proposing a design, and you can go through a conversation of "what if we did xyz instead?" and at some point "okay, let's try writing a full prototype" (perhaps tacking on a bunch of decisions here so that things are resolved enough to work with).
But that's at the scale of <1kloc. Might be different if you're trying to do a bigger feature all at once.
I suspect that's a problem both with human read/written code, and LLM written code -- larger features should be chunked up into more manageable to understand and reason about functions, and assembled at higher levels.
Guiding the LLM (or humans structuring/guiding juniors) to shape the abstractions help make the overall feature and reliability of the code much better.
Although I was personally fairly invested in UML, OO, etc., in the 2010s, it is undeniably true that classes, inheritance and all that is incredibly out of fashion today - people just found it didn't really help. It's interesting that this is now the solution to AI coding.
I do the same but I find that sometimes there are little bugs everywhere just because idk, the implementation left a query outside a transaction and made two instead of one, a very minor thing. Or a sequence of events is out of order and it matters. And you don’t see that while abstracted away.
I've tried this but the problem is your design inevitably has gaps in it. When doing it yourself you would run into those gaps and be forced to revise your design as you go. You might even be forced to go right back to the drawing board. But AI agents will never, ever do that. You tell it to implement a given set of abstractions and they just will, no matter how ridiculous the implementation becomes. There's no part of an LLM that says "hold on, this doesn't feel right". How could it even when you're feeding it piecemeal tasks and not revealing the whole architecture? It's like asking for a first floor bathroom with the plumbing in a specific place that makes no sense given the rest of the building. It will do it, every time, because it will build the plumbing under the floor that you didn't ask for.
You got a ton of responses!
I am very much in agreement with you. What language do you do the design in?
I have hand written a bootstrap MD file in English, which guided a Greenfield implementation. Do you actually use a UML language?
I suspect there is a missing language (abstraction) here, English can be a bit unclear and ambiguous. Perhaps an AI dialect?
You do realize LLM like Fable can design things better then 80-90% of the programmers which is more then good enough for most cases.
I haven’t seen the risk-driven approach explicitly mentioned here. I think it applies not only to code review, but especially to design.
It reminds me of George Fairbanks’ Just Enough Software Architecture. He tells a story about his father, a civil engineer, who didn’t apply every engineering technique he knew when installing a mailbox. He just dug a hole, put in a post, and filled it with concrete.
The idea is simple: the effort you spend on architecture should be proportional to the risks involved. Sometimes you need careful analysis, sometimes you don’t.
Seems even more relevant now with AI coding.
Unfortunately llms are very good at creative hacks that undermine the whole design. I've caught it on the act multiple times. But I'm sure my code base by now is understandable at the surface level, but underneath I don't really know how it's doing it. Even if I have a reasonable understanding of what. If you're a manager and don't understand how, you can rely on your engineers to know it. When you're an engineer and you don't know how. It means no one knows.
In practical terms it probably doesn't matter. But it's still an unsettling feeling.
You've just decided that your level of abstraction is better than someone elses but where's the evidence it's actually better? This has been the main tension between programming philosophies forever.
Just because something makes you comfortable doesn't mean it's actually good.
100% agreed. Although its less about writing it and more about holding it in your mind. Think what you may of vibe coding it's very hard to justify rolling every line by hand when modern LLMs can produce pretty reasonable code at scale.
Coding is however just one small aspect of bringing software into being. We generally start with an intuition. That intuition comes from context.
That context, hard won as it is, for software engineers at least, was mostly a side effect.
You had to buffer a significant portion of the system in your mind to be able to manipulate it. LLMs remove that constraint. Now you can just prompt from the upstream intuition and its passable a good portion of the time.
Notice the catch? If you don't get to the beat of the system your interaction with it will be jarring, for yourself, for the person using the software and for the agent building it.
So I made a tool to help get the context into my head faster. No its not an app (it could be but meh) Its a skill that helps the LLM make a voice narrated walkthrough of the complexity so you retain context Check a demo here if you want https://theronburger.github.io/review-story/
You don't always design bigger systems from scratch as greenfield applications, most of the time you are delivering smaller features in incremental ways or fixing bugs. Even for greenfield projects, you can plan with the LLM and come up with a design you like at the high level but that still does not spare you from knowing (or not) how lower levels work, which is OP's original complaint.
In essence you basically say that you don't read or review the code produced in detail, you just know the high level design of how the system works.
Spending time upfront designing is sound advice for any software engineer. LLMs can also save time here as well, if you're disciplined enough to not proceed until the design is polished.
I’m not sure it answers the original question. Understanding the plan is not understanding how the code exactly works.
Yup this absolutely echoes my own experience and thoughts on this
If you insisted on taking the time to do this in the OP’s role at Meta, I’m guessing that you’d be disciplined or fired for taking too long to produce work. You’d also be dropped into work of colleagues who didn’t produce UML before shipping their code.
After over a decade of software engineering I've rarely if ever found a bug that needs to patches ASAP over an incident due to a poor abstraction. The bugs are usually the actual code inside the abstraction which you are most definitely handing over to LLMs and losing context over.
I try to do this as well. It certainly feels better and makes me more confident that the code will make sense when it implements it. But I’ve found even with a very firm design an LLM will undermine it in the details. It will be convinced there is a particular way to do something, I will tell it not to do that and give it a complete alternative, and it will say it implemented it as written. And if you just look at the data structures and function signatures things look fine. But you look at the actual implementation details and it will try in some awkward way to implement things totally differently.
100% agree. I spend hours working on specs, project requirements -> tech spec -> testing -> validation -> roadmap. Making sure to capture intent and constraints. And then i let an llm orchestration have at it. I agree with others in this thread, that I don't understand how others don't do this and feel comfortable pushing to prod. I'd feel even more embarrassed if I vibed something to prod and it broke. That being said, I honestly feel like I'm doing way more "software engineering" now than ever in regards to really understanding every aspect and intention of the features I'm implementing. And even then I still miss things, but it's not catastrophic and re-aligning later is much easier.
But yes I agree, I don't let the llm "design" or even "ideate" with it. I have it run validation on my own assumptions and see if those hold up, but even when they don't I am the one to construct the solution.
I'm curious: With your approach, how do you make sure your code is secure? For example, how do you show that it isn't riddled with XSS or other injection vulnerabilities?
I was once employee nr. 1 at a startup and the lead engineer. For a number of years I understood every nook and cranny of the system and knew what every line of code did.
The company got successful. At some point I had a team, and then multiple teams. Gradually, I had to let go of that level of understanding and delegate it to others. When I was overseeing 50+ engineers, I only had a high level understanding of most the systems, and only got involved in lower-level decisions rarely. All the new code was created by my team, and it varied in quality.
If I had AI tools back then I could ask it to explain things to me that my team did and have a 2nd set of eyes which had a different set of biases and abilities.
That's how I deal with it right now. I ask one AI to gen the code based on a design. I work with the AI tool and see how it builds the system out. I intervene where it starts doing things I don't want it to do. I ask another AI to review the PR after the code is written. I sometimes dig into design choices and ask it to explain them, rate them, and offer other alternatives. I sometimes change things, and occasionally scrap the whole thing and start again with better guidance.
So far I've written more code without an outage this way than ever before with a team of human developers. AI screws up too. But right now, at Opus / ChatGPT Sol and higher models, on average, it makes fewer mistakes than humans did. Any time they slip through is because I am rushing too quickly. In a pre-AI human dev team we would call this a process or management failure.
The more dangerous a decision and the harder it is to roll back, the more time I spend reviewing it. This has served me well when managing people who write code, and seems to work well with AI.
AI is a tool that needs to be managed. It won't do all the work for you, but it can speed you up greatly.
Great perspective. When we are developing code, it is easy to think that "my code", which "I implemented" and "I reviewed", is intuitive and correct. But when we share our code with a colleague for review, that code is seen by a different pair of eyes: it is received more critically, perceived as less trustworthy, and very often not understood at the same level of detail by the reviewer as by its author.
Scale that to a project with several developers and several teams, and the result is that, for the engineering manager responsible for the project, correctness and conformity to requirements need to be managed and achieved without the manager having to review and understand every line of code. That would be impractical. The manager will need to use other strategies and tools to achieve this, including but not limited to:
- Mature product development and quality assurance processes;
- Sound architecture and system design;
- Adherence to software development principles and best practices;
- Comprehensive automated testing to validate expected behavior, prevent regressions, and ensure system reliability.
So now developers are moving a bit higher up the tactical/strategic scale and facing challenges that used to be handled only by technical engineering managers. We've become coding agent managers now.
I do this as well and AI makes fewer mistakes and causes fewer outages than before.
I've been a Principal Engineer for a while, so this is how I've worked for a while. Sometimes when you're a PE, you either design something and then junior engineers implement the details, or you're dropped into a project that was already designed and built by more junior engineers, and you have to quickly understand the design an as many details as you can.
With AI, everyone now gets to act like a PE. Your job is to design, the AI builds like the junior engineers. Then you review their work. You may never understand the details, and that's ok, as long as you know the main ideas and where to ask for the details (in this case the LLM instead of a human).
This is essentially what I've been comparing it to as well. You are laying out and being responsible for the overall direction, architecture, and how things should work at a high level but then delegating the implementation and lower importance decisions to the agents. It very much at times feels like managing a bunch of developers and coordinating them all toward the vision in my head. I've developed an intuition of sorts where I can quickly tell if something is being done incorrectly just by looking at the snippets agents show me and the questions they ask.
As engineers our job is to solve problems at various levels of abstraction. Developers that think we are just automating away our own jobs have missed the point. It's not about writing the code anymore, it's about designing solutions to problems and distilling that to agents in a way that achieves the outcome you wanted. Models are not good at coming up with this direction on their own, nor are they good at designing cohesive user experiences across a plane of complexity. These two areas require most of my time now while actually writing the code has been delegated away.
While everyone gets to act like a PE, I'd encourage junior engineers to build a pet project manually. Primarily to develop the skill to know "where to ask for the details".
Or maybe keep manual coding to build confidence, so that one can say "I've done that before..." and be able defend or take apart a particular strategy.
This is interesting advice. When I was coming up as a sysadmin, the advice was always "run a home lab it's the best way to learn all the details". So I did and it was helpful.
But you never heard someone say "you should still code in assembly so you can understand what your compiler is doing".
Is this more like case one or case two? Will it matter if you understand in a few years?
I like the assembly analogy, but it’s not quite _that_ abstracted from the higher-level language, yea? At least not for prompt-to-webapp.
It’s perhaps important to learn the consequences of certain design and impl details? Because Sonnet-class models can often miss these more easily than Fable-class.
That said, refactoring and bug-fixing is faster than ever. So I’d argue LLM coding is actually quite a bit different than having a compiler. In ways we’re still seeing ?
> you should still code in assembly
i spent a few weeks coding assembly at the beginning of my career. really enjoyed it and feel like it helped me understand CPUs a lot better. i'd still recommend it to early career engineers
Exactly. This is only needed in the early days IMO, unless your work doesn't require the understanding of such low-level features or you enjoy doing it.
You should only have a high-level understanding and be able to orchestrate things, plan, and make choices. AI do the details.
> But you never heard someone say "you should still code in assembly so you can understand what your compiler is doing
Any quality CS program will have you do that for a year or so, plus theory.
Yeah... my program covered basically everything from raw theory to architecture to assembly up to [insert n others] Python and Haskell.
But it was a CS program, not a SWE program, the two of which the industry has confused for all of time (though there was an actual Software Engineering course offered as well).
A quality ECE program will have you working lower level still - all the way from ALUs down to the electrons & holes in semiconductors.
https://www.youtube.com/@MoritzKlein0 has revolutionized my understanding of audio signal processing in software. Understanding what the voltages do is absolutely amazing.
Coding in assembly is absolutely fantastic for understanding how programs execute, and different chip architectures.
It's also a lot of fun to do on tiny 8 bit microcontrollers like the AVR. It's really neat to be able to understand exactly how many clock cycles some code will use. This came in super handy for me once when I wrote a small bit-banging serial interface and had to debug why some characters would randomly be wrong.
But you never heard someone say "you should still code in assembly so you can understand what your compiler is doing".
Would I routinely code in assembly today? Not for (almost) any new project.
Can I understand assembly and have I used that skill to understand performance problems or debug unexpected behaviour (including some that really did turn out to be caused by bugs in popular compilers)? Absolutely.
I'm not generally a fan of the comparison between what LLMs do and what compilers do. Compilers might vary in their output for given source code but they still follow (hopefully) well-defined specifications. Their behaviour is deterministic and the behaviour of their output is deterministic. With sufficient understanding you can reason about that output or diagnose faults in the compiler behaviour if you ever need to. None of this is true for LLMs.
How does it differ other than that people aren't currently choosing to write clear, well-defined high-level specs and feeding that into their agent?
> Their behaviour is deterministic This isn't true for LLM generated code!
Neither are compilers? But you still trust your JIT compiler. Determinism is unimportant, likelihood of correctness is what matters. Plus agents are deterministic, no?
Was about to point that out. Reproducible builds are possible, but - depending on your stack - not easy to achieve.
Even if we accept your premise that the likelihood of correctness of more important I still don't think that the two scenarios are similar. I have seen more incorrect outputs from LLMs in the past week than I have seen incorrect outputs due to compiler bugs in my entire career. And without determinism there is no way to be sure that ratio will ever change.
You can debug a compiler. If an LLM writes code you don't like, how would you debug that? You wouldn't. You'd just ask again and hope it does a better job.
How many times do you think the average programmer have noticed that their compiler have introduced a bug? And how many times do you think the same developer have found a bug in the code that their AI have implemented?
Stop drinking the cool aid and compare compilers with ai models.
No need to code in Assembly, just the same high level language you're using agents with.
I don't think llms are an abstraction - they're a delegation.
But you don't get the satisfaction of seeing your juniors grow. They don't come and ask questions. They don't struggle and have breakthroughs themselves.
I liked working with people. It's a lonely road ahead.
> With AI, everyone now gets to act like a PE.
I've heard this before many times, and it's simply not true. The resemblance is there, but there's also a fundamental difference. The difference is in whose name is on the commit, who embraces responsibility for things going wrong. PE will, at most, share responsibility with the person who actually authored the code, AI user is always responsible for whatever code their agent wrote.
As a PE you may skip reading all the code written by your underlings because your underlings have signed a contract with your employer and will be legally responsible for certain things, have they decided to do those.
In the case of actual PE, there's an actual programmer who, at least, believes he or she understands the code they wrote. In the case of AI, there maybe nobody.
Here's an interesting aspect though. There are companies (I'd know, since I worked for one), who sell a product where there's a part of code no engineer working for that company understands. In my case, that piece of code was a formula obtained from some former partner (a bank) to calculate something related to credit check. Nobody could explain why the formula was the way it was, but it was extensively used in testing to validate that our code produced the intended result when it came to this part of credit check. There's a folk tale about DB2 containing a binary blob whose source was likely written in Assembly and was since lost to time, which is essentially a magic component nobody really knows the internal workings of. I'm sure there are more pieces like that around in older companies.
Since I expect the regulators will soon start tightening the nuts on programming in general, especially since AI is asking for such an action, what will happen to these "magic" programs? If I were a regulator, I would have the company, under a threat of criminal punishment in some cases, to vow that they understand the code that went into making of their product and are therefore responsible for what it does. This is not the case today and only in a very few cases were software companies found guilty of criminal negligence... but I think that the writing is on the wall: with AI being used the way it is, the legislation requiring understanding is just around the corner.
Two questions arise:
1. How to develop Principal Engineer skills? Designing and communicating the design correctly is not straightforward.
2. Are we sure this approach works better? Current AI systems are very good at solving problems and SW because of the Reinforcement Learning they went through. I suspect they perform better when doing things their own way. Forcing them to change to an arbitrary workflow may confuse them and reduce performance instead of enhancing it.
Second one is a version of the "Bitter Lesson" adapted to SWE.
But you would at least expect your junior engineers to understand what they were doing. They would have a stake in the outcome too.
>Your job is to design, the AI builds like the junior engineers. Then you review their work.
I'll add to this that your job is also to design tooling and feedback loops that allows the AI to improve over time.
You have policy gates: How the AI should act. (and a feedback loop to check the code is adhering to those policy gates)
You have quality gates: How the AI verifies it's done things correctly (testing, linting, PRDs, cyclomatic complexity)
Modern AI engineering is really about improving this system rather than manually reviewing AI output. The better the policy gate and quality gate enforcement, the less manual review is required and the more velocity you achieve.
Sticking with being a human-in-the-loop reviewer of AI code is where people lose all hope in still being software engineers.
I’m slowly coming around to the idea that if it works, I’m good with that. I never used to personally check all my colleagues work, either, I just trusted that they’d done a good job.
That’s not to say I blindly trust an LLM - my project is an autovectorising compiler. I have it write a bazillion tests, and I have real, non-trivial programs that it compiled. I have it run a ‘gate’ before releases that takes literally hours on 5 different architectures. To say this code is tested is … masterful understatement.
I think what helps is a long planning session, going into details, working out corner cases, designing test-cases, you know work and effort. Once that’s done it’s easier to let it work through the night and do a major production feature.
I still review the code, but hand on heart I couldn’t say I’d reviewed everything, sometimes I miss something in a complicated check-in. I try to keep checkins small and contained, but sometimes that’s not easy to manage alongside the “don’t break stuff” rule as well.
So it comes down to: I’ve been working on this for 6 months or so, and so far this has worked out for me. You know, kind of like getting used to a colleague’s idiosyncrasies over a period of time.
I will say that in my experience the code quality is fairly high. Maybe that’s down to the effort put in ahead of time in the planning stages, I don’t know, but I don’t seem to suffer from the ‘slop’ that people complain of. YMMV.
I am not in META but for what I read on blind, assuming it is true, they are not spending any time in long planning sessions or in getting into details of the implementation plan at all, and they could not anymore considering how many PRs in parallel they are requested to manage
Yeah, I'm retired. The only person I have to answer to regarding progress is me. I'm a stubborn son of a bitch when it comes to choosing quality over speed...
That doesn't mean I don't like progress mind :) This morning I got the preliminary results of a 'C' front-end to the compiler (it uses clang to compile to LLVM IR, then translates to our IR, then feeds that IR into the autovectoriser as if it had parsed the code itself). So for the exact same source code I now have:
Those are some pretty fine speedups, from naive C, with no alterations from the standard "C" code - it automatically finds places that can be made data-parallel, tracks the data-hazards to make sure its safe to "GPU" and writes all the kernels, boilerplate and data-stream-management if necessary. Obviously the checksums have to match, so I know it did the work correctly too :)
Hacker News isn't interested - any post I make linking to the webpages is immediately blocked/dead so I'll wait until the C++ front-end is ready (some time next week) and announce it somewhere else. A compiler that takes standard C/C++ code and speeds it up by automatically finding data-parallel areas and scheduling them on the GPU with no programming overhead is pretty rare.
Oh, and it manages the local network as well, so you can run xcd on machines on your lan, or via the TB4/5 bridge between Macs and it'll schedule on other GPUs, just like it manages multiple GPUs on the local machine. It characterises both latency and compute-time to figure out which devices are worth scheduling on.
That is pretty adventurous, but it sounds really cool! Will it be open source?
Yep. I’d give the link but I think HN thinks I’m spamming because I’ve mentioned it too many times before in posts - hence immediate death of any submission, so I’m not mentioning it for a while to see if that tails off.
Bottom line: GPL3 for the compiler, standard library exclusions for derived works, so use it for anything but feed me back improvements to the compiler itself, and you don’t get to redistribute it as your own.
Hell yea I love that computers are getting another chance at becoming compute fabric, just using each others GPUs. Sick.
I like it! The Rust crew would love this I bet.
Awesome, this is genuinely-cool HN material. Thanks for sharing.
Upvotes don't appear publicly on HN so I'll comment to agree with this. I'm sorry if earlier information about this compiler got lost in the whirlwind. Data parallelism is a hard problem and these results look genuinely impressive so I for one would definitely be interested in hearing more about it and maybe discussing it further when there are interesting developments.
Thanks :)
Still working on some of the data-parallel recognition in LLVM IR space. In order to support both C and C++ with the same data-parallel section extraction, I moved the detection from the ‘xc source code’ phase to the IR lowering phase, meaning that everything could ‘feed in’ to the same routines. That’s caused a little friction with the slightly different ways the LLVM IR from clang and xc’s IR encode loops. The above results are all single-loop extractions and the double-loop ones are still ongoing.
The system works in 3 stages: 1) by being greedy about which loops could possibly vectorise and marking them, 2) by analysing the IR to reject loops which do pointer-aliasing, or object manipulation, or… and then 3) by measuring the fastest way these known-safe kernels could execute.
Which brings me onto one nice thing I haven’t mentioned: that the GPU choice(s) are made at runtime, not compile time, and the system automatically measures (and then persists so it doesn’t have to measure again) the fastest way to run a kernel on the current machine. It handles MSL on Apple devices, PTX on Nvidia cards, Spir-v on Windows, Linux, and Android, and WGSL in the browser. It’ll quite happily divide up the parallel task across a 3090 and a 5080 on my Windows test box for example, with the 5080 doing ~2/3 of the work, because the scheduler is opportunistic.
All without writing anything other than plain C with nary a mention of the GPU. Give me a week or two, and I’ll probably announce it on phoronix (which might then get a mention on HN if it goes down well there, and it’ll be a different url so hopefully won’t be insta-dead).
So, the real input to your autovectorizer is LLVM IR; you could soon enough support any language that has an LLVM front-end? (I say soon enough instead of immediately because I’m sure there’s some manual wiring up to do). That seems like a pretty big deal. Do Fortran next, pls. :)
Ssshhh. I like to try things before promising them :)
> Hacker News isn't interested
I wouldn't be too sure about that :)
I’m being a little cynical - I’ve submitted it twice (though the ‘C’ front end is new) and it bombed both times - the second time within seconds of submission.
I think it’s my own fault, I’ve posted the link to the compiler pages several times in what I thought were relevant posts, and I think HN thinks I’m spamming. So I’m not posting the home page for a while and we’ll see if a future submission “takes”
might be worth firing an email to hn@ycombinator.com. they should be able to tell you why your submission was auto-killed, and might work with you to ensure your next submission isnt.
I actually did email the second time because it was clearly an automated response, but I didn’t hear anything back. Not too surprising, Dan is a very busy guy, and he doesn’t know me from Adam :)
After asking my LLM some questions to barely grasp what you are working on, I can now say: very cool!
For anyone wondering, the thing lives at https://compile-xc.org/ ;)
sounds very cool - is this basically "C" support for cuTile? :)
Well, the end product might be similar, but the approach is a bit different. 'xc' is a language in its own right, and it can be compiled (with xcc) to both the CPU and GPU (and I have plans to make it work on a Zynq too, a sort of HLS).
The C front-end I'm currently working on is something that looks at the LLVM IR that clang produces and converts it to xc-IR, then runs the data-parallel extraction through the same routines as the original xc language. Consider it to be a 'Y' branch on the inputs - you can feed it LLVM IR or xc source code, they both get convered to xc-IR and from then onwards it's all the same.
So yes, you get tiled work-units, overlapping in time between compute/data-transport and tuned so that actually works, and an opportunistic scheduler that sends them to whatever worker can handle it at the instant of being sent. That opportunistic nature means the faster cards (eg my 5080) will naturally get more work, because the scheduler just keeps all cards busy. The divide between the 5080 and the 3090 in my Windows test box is about 2:1.
But the scheduler is also aware of networked GPUs - my M4 max has a pretty fast GPU, but it's connected to my wife's M3 Max by thunderbolt, and I measured a 37 Gbit/sec connection, so my app can send data to be processed over that very fast link and get results back. If you have a 10GBit nic, then it will work pretty well too, if your nic is "only" 1Gbit then modern GPU speed means that unless your work-units are really computationally intensive, it'll be faster to do it locally - and xcd will work that out at runtime and adopt that faster approach.
Do you think they are actually shipping anything useful any faster? Muse is pretty impressive. I’m not seeing radical progress otherwise
> I’m slowly coming around to the idea that if it works, I’m good with that.
A.k.a. "The concrete didn't crumble when I hit it with a hammer."
Process quality has been a thing for ages because it is essential.
I mean, honestly ? Yeah.
Except it’s about 1000 “hammers” (aka tests), x 9 different architectures, x 2 different (a reference and a production) variants, and x 3 different optimisation levels. Every time I find something that slipped through, it gets at least one test written to cover it in the future. My main time-sink is the hours it takes to run the ‘gate’ before a release across the test-farm. And that’s after I’ve been playing with it myself for a while, pushing corner-cases through whatever I’ve been working on.
>1000 “hammers”
And who decides what hammer to use, or do you even know what hammer is used? 1000 toy hammers from walmart or temu don't mean anything.
Are we speaking of the same industry? The "ship fast and break things" one? The one that has traded everything from performances to security in exchange for "better developer experience" (aka "easy" aka "cheap") ??
I would not tar the whole industry with Zuckerberg's brush.
Yes, compilers are a good candidate for verification through thorough testing. If a comprehensive test suite passes, reviewing every line of code isn’t so important.
That's why Anthropics C compiler worked so well; because they had gcc's huge repository of tests to lean on. Oh wait...
See the first paragraph here: https://alexgaynor.net/2026/sep/07/is-it-correct/
If your definition of "works" includes "doesn't have vulnerabilities", you're going to need to do more than just poke at it and add tests.
How does writing the code by hand solve that? If anything it’s less likely to be secure, because you don’t contain the sum of all human knowledge.
What helps solve it is understanding the code deeply and thinking about it.
It's not perfect, but vibe coding means you don't even get that.
Very similar here. For internal projects the test is - if it works, unit and integration tests were created, and it follows our architecture correctly.
> never used to personally check all my colleagues work, either,
Jesus F Christ! No wonder most software lately (~decade) has been shit. Have y'all not heard of code review? Or did you think it just for show...you sit on a change for a week and then press "Accept" without reading it?
My dear fellow, the statement was that I never used to personally check all my colleagues work. Of course I took part in code review (but then, that’s pretty much the same as me reviewing the LLM code, no ?) The statement is that I personally did not review every line of code in the repo. Some of it was authored, reviewed and committed by others.
FWIW I was a software engineer for the last 35 years or so. Amongst other claims to fame, pretty much all Apple devices on the planet (those actively running Apple OS’s, anyway) are running my code, within AuthKit in fact, and one code review was insufficient by policy when making changes. Despite all that, I’d be lying if I told you I thought there were 0 bugs in the actually-rather-complicated repo… Maybe these days, running it by an LLM would be a good idea…
Testing.
Lots and lots of testing. I usually interactively test with the LLM. Now that I'm spending less time, coding, I get to spend more time, testing.
In my experience, I test more, with an LLM, than I did, with my own code. I don't find coding errors, but I do find implementation errors.
On another note: I ran an LLM on a bunch of really mature code that I wrote, and could swear was "perfect," and it found a number of issues.
Nobody's perfect. Trust; but verify.
So, in other words, we save time and money when it came to creating stuff, but we've made a whole bunch of new work around verification and testing of said stuff?
What have we gained aside from shifting where time and effort is spent in the design loop?
Better tested software duh
Isn't this the perfect classical capitalist advertisement? Every number goes up.
- code? up - build budget? Up - developer output? Up - developer oprrational costs? Waaay up!
Why is this Bad? Every one involved profits somehow.
Shipping features and fixing bugs much, much faster.
we've made a whole bunch of new work around verification and testing of said stuff?
The verification is what we always wanted but never had time for. For 30 years I wrote side project games without extensive testing or a fuzzer or anything because I wanted to spend my time writing the game. Now I can do that and still have the testing I always knew I should be building.
Engineering will always be difficult.
Right now, we're in a "honeymoon" stage, where non-engineers think that they can somehow, magically produce stuff that is comparable to what experienced and disciplined engineers can do.
That won't last long.
Despite all the caterwaulin', LLMs are just another engineering tool, and good engineers will figure out how to implement them, in ways that absolutely blow away the garbage produced by non-engineers.
It's like that rich, no-talent guy that buys a PRS guitar, and thinks he'll beat the experienced musician that still uses his beat-up old strat, but consistently makes hits.
I wonder.
In my optimistic days, I think we'll start putting mechanisms in place that will have LLMs help develop cognition, skills and expertise. It'll usher in an era of mastery and wonder.
On my bad days, I despair that the siren song of "good enough" slop will overwhelm even the most disciplined minds, and we're facing the atrophy of civilization.
Will this just end up exaggerating the pereto distribution? Will there end up being this tiny percentage of people that are driven by natural curiosity to do the very hard work of really understanding hard things? Will society even have any sort of reward for those people?
I'm largely building tools for myself and my agents. This allows me to battle test internally before releasing code to the wild. It adds some time but largely it's part of my regular work unless something breaks badly. (I also run multiple agent teams simultaneously and do staged rollouts to reduce blast radius of the latter)
This method also helps with the classic problem of being unable to identify essential complexity up front.
no time is actually saved with LLMs. You spend more time testing or stepping on rakes finding out what it screwed up.
This is why LLM coding fails.
Are we seriously, no cap, on the techies website, asking what did we gain from more testing?
This truly is the worst thread on HN. Now we're down to explaining 102 topics. Geez guys, what did we gain from evading regression errors? Who knows!
I find the problem with "lots and lots of testing" as a solution - (assuming by that you mean lots and lots of automated testing) is it invites lots and lots of lines of code - making code reviews even more challenging.
If someone finds it burdensome to review my 50-line AI-generated bug fix, adding 200 lines of tests only gives them more lines to review.
Might be a little controversial to say this but automated tests can be reviewed at a lower bar than production code.
I have no shame in accepting vast quantities of ai generated automated tests at review time without really paying attention to them. It’s better to spend more time on the core implementation.
I have no shame in accepting vast quantities of ai generated automated tests at review time without really paying attention to them.
I respectfully disagree. IME writing a good test suite is one of the areas where current LLMs perform worst. They certainly like to write plenty of tests but those tests aren't necessarily adding much value and they don't necessarily cover the important functionality.
Given how heavily LLMs and specifically agentic workflows still rely on producing something vaguely correct and then iteratively applying guard rails to reach something that actually works I humbly suggest that trusting a very substandard test suite to be one of those guard rails might be unwise.
IMO it works better if you split the tests into the ones you care about, and the ones the LLM writes. I assume its tests help it write code with fewer errors, so I'm happy for it to keep doing that, but they're akin to CoT - an artifact of the process that I don't need to inspect in detail.
I realise this is heresy, but my conclusion is that unit tests aren't important any more. E2E testing on the other hand...
(I'm agreeing with you about the quality of LLM tests, I'm just trying to make lemonade out of all these LLMons).
I admire your optimistic approach. :) Unfortunately I don't really share your optimism on this one.
All those extra tests are churning through tokens and CI resources. These are far from free in a direct financial sense. I've also noticed some of the more recent models will try to do a lot of experimentation and ad-hoc testing by spinning up shells or running something like Python scripts direct from a command line. Every time they do that you either have to review whatever they propose to run carefully - which is slow and tedious work - or stick the tools in YOLO mode and hope that your agents don't accidentally wipe your entire filesystem, open your firewall for malware to take over your network, and perhaps launch a few nuclear missiles.
I would respectfully disagree about the value of unit tests as well. The reason unit tests appear to have less value in the LLM/agent era is because current LLMs suck at decomposition and other architecture-level work. They just see a mass of code and change it as a mass of code. This probably results in orders of magnitude more code being written/changed than would have been necessary for a skilled developer working on a well-maintained code base to solve the original problem and that automated work also takes longer in wall time. Again this gets brushed under the carpet because a lot of people trust that LLMs are so good that their costs are negligible regardless of how much work they do. People used to say that about the Cloud transition as well because not needing so many in-house staff to manage your resources was going to be a huge saving. Today we have companies bringing in consultants because they literally can't even work out how much they're spending on AWS by themselves. Instead of having a few greybeards who could make a Linux server do anything we have a few increasinglygreybeards who know which combination of 17 AWS resources they need Terraform to spin up so they can write the web server equivalent of hello-world.c. Meet the new boss - same as the old boss. :)
> All those extra tests are churning through tokens and CI resources.
I have an assumption that inference tokens are only going to get cheaper, I admit. We could get at least 10x efficiency savings by burning current models to ASICs. But today they're cheap enough to let the machine churn - that's the environment I'm making decisions in.
> I would respectfully disagree about the value of unit tests as well.
I honestly don't think the LLM-generated tests are at all valuable in a human sense. I get the impression the end result is "fewer bugs" (but I've never tried to prove that). That's why I'm happy for the LLM to have a directory it can write its own tests in. It's a scratch space.
> this probably results in orders of magnitude more code being written/changed than would have been necessary for a skilled developer working on a well-maintained code base to solve the original problem
Nothing gets committed in my name that I don't understand. I'm one of the people LLMs are actually making slightly slower, because I insist on reviewing the code and working single-threaded.
Accumulating tech debt in the tests will come back to haunt you in the long run when tests become harder to maintain or less reliable as the project evolves.
You want tests to be obvious "at a glance". And then some of the tests should at least indicate it's covering (for the most coverage of the system it reasonably can) the cases we care about.
The name of the test should indicate what it's doing.
For unit tests, these should check only one thing, and the test can be structured into "assemble, act, assert" style tests.
On the implementation side: code which touches state is tricky. -- So, minimize the amount of code which touches state (or rather, shift as much code as you can to stateless code, which is easier to bring under test).
So how do you test that gnarly function that outputs a long series of states that interact with each other based on order in non obvious ways? Like, say, a compiler?
Depends on the scale and confidence you want.
In systems where I've taken complex inputs and transformed it into complex outputs, I'd make it as easy to bring each particular pass under test, have snapshots that the same transformations resulted in the same outputs (insofar as I did want that consistency).
I'd think with a compiler, though, it can still be practical to describe the input you depend on as a value.
In distributed systems, your service might rely on another service which might be broken, might return different values than you expect, might return slower than you expect, etc. and so testing the parts of your system which depend on other services can be tricky.
Point is, you can arrange a lot of your code into "it's easy for me to ensure this part works", and you can see wins from that, even if as a whole the full system can be difficult to bring under test.
I take the complete opposite approach which is to have zero unit tests now, because LLMs are excellent at both reviewing code to understand what's going on, and also doing manual QA given environment instructions. Lots of unit tests will just bloat the context which ultimately dilutes the quality of the LLM's work and also creates additional work (it has to update the code and the tests each time).
Unit testing imo is pre-LLM. It was mostly to keep the human honest because the human can't possibly read all the code to make sure nothing broke.
I'm flabbergasted at this comment.
Are you maintaining a list of all invariants you want QA'd by the LLM after each change? How many tokens does this process take?
right? I love HN. This is the new hot take, spoken as confidently as possible -- NO TESTS AT ALL.
You don't need tests. Your users are going to do all the testing!
The README defines the expected behavior of my API endpoints and the overall program in natural language. Some repos have additional documents (like DATA_MODEL.md) that defines the nitty gritty of the distributed concurrency characteristics, data invariants and such other things.
Claude Code (Opus 5.5 xhigh), when it makes changes, tests the relevant endpoints for behavior based on what it touched. You could also just explicitly ask it to as a follow-up prompt. You do need to have instructions on how to set up a test environment or use infra for which dev env testing is well-documented online.
And yes, it's non-deterministic. It's not gonna test everything exhaustively or systematically like a fuzzer. It's basically doing what a manual QA would, at best. It probably doesn't even cover every edge case each diff. But I'm fine with this tradeoff for not having unit tests.
Caveat emptor:
1. These are relatively small-medium programs (~10k LOC) where the frontend and backend code reside in the same repo, and the frontend is strictly a web app, and where 100% of the functionality can be tested in the dev environment (incl the database).
2. I'm the only person working on these repos right now.
3. I read every line written by the LLM and have things I don't like refactored or stashed and rewritten with a modified prompt, mostly based on intuition.
>How many tokens does this process take?
I genuinely believe anyone who exceeds usage on a $20 plan doesn't use Claude Code correctly. Always use a new context wherever possible. Always make surgical changes (or, broad changes with well-defined success criteria). For anything complex, get a plan from the LLM at least so that you know it understood your ask. Ctrl+C and `git stash` are your best friends. Keep everything clean, don't build castles on garbage. In the LLM era ironically you should never put off tech debt because it will just compound.
This sounds a sensible approach. I have many of the same features, in my development.
I take a more "hybrid" approach, myself, but I also have control issues. I am slowly moving towards all-LLM, but I'm not quite there, yet.
> LLMs are excellent at both reviewing code to understand what's going on ...
Have you ever worked on existing code base that has components that makes no sense but must be there?
> Unit testing imo is pre-LLM. It was mostly to keep the human honest because the human can't possibly read all the code to make sure nothing broke.
What?!
Unit testing was to ensure the code operated according to an intended specification or outcome especially when it deals with a complex support matrix. It extended well beyond the codebase itself! You can have language errors where output behaviors differ between one supported version to another (ex. Java 11 vs Java 17), runtime errors that are specific to operating system quirks (ex. RHEL 8 vs RHEL 9), or workarounds added to your codebase for known bugs in different dependency libraries you support at compile/run time (ex. Net-SNMP 5.2 vs 5.5). It wouldn’t matter if someone read all your code; you would still have the potential for errors caused by the components needed to run your software.
If your project doesn’t have to worry about these types of issues then lucky you and continue on without unit tests for as long as you can.
My name. Your fault.
I think it really depends on the language and the project.
The more types of potential errors your compiler catches, the fewer unit tests you need. Haskell needs fewer (and potentially different) tests than Perl or Python.
The other thing where unit tests really shine is testing a complex algorithm. If you think of a problem with a very well-defined output (like sorting, searching, some types of computation, graph algorithms, geometry problems etc.), then it's pretty easy to come up with a stable API and thus stable tests. I'm pretty convinced that unit tests give you more bang for the buck than plain-English test plans that you need to spend tokens on to evaluate.
Where it suits the problem, higher leverage testing techniques are now more accessible than ever! E.g., property-based and metamorphic testing. It is now easier than ever to triage failing cases they generate and refine generation to be more useful. Following initial setup, the marginal overhead of additional cases is minimal.
How do you test code that you don't understand?
Black-box e2e testing isn't suitable, or practical, for a lot of applications. Unit and integration tests generally require you to understand the code you want tests for, to know what to actually assert
Are you just trusting the AI to do it all?
Nothing a "make no mistakes" at the end of a query cannot fix. /s
The point is that you're not verifying if you don't even review the code.
Even if your test suite tested every single possible behavior and code path, tests usually can't intercept all possible unintended behavior that an LLM might have added.
In all likelihood, most test suites don't intercept any unintented behavior (such as unintended internet connections).
That's not a big problem when a honest human has written or reviewed the code, because unintended code is usually easy to spot.
But an LLM might have dropped any whatsoever code: maybe some of your project's code resembles the one of a trojan in its training, so it completes it with the trojan.
Or maybe it found that if your server is unreachable, it can upload the client's data to a public Github repo; or that if there's no space left on the device, it can delete some of the user's folders, easy!
Would your clients be understanding if that happened?
So you currently routinely review the machine code and link tables produced by your compiler?
Eventually, the tools become trustworthy, and we no longer need to worry about their products.
We're just about there, with frontier LLMs, but I don't think we're all the way there, yet.
"I saw her duck" - how much would you be willing to bet on the intended meaning of this sentence?
English isn't a good programming language if you want to trust that the output will be as you want it to be. High level code has no room for ambiguity - that's why we use it. It's a concise, very explicit language to tell the compiler exactly what to do.
Dealing with an LLM is a fundamentally different thing. The reason it's able to speed us up is because it makes assumptions for us and reads between the lines. The only world where we trust the output is one where it can literally read our minds. That's not coming any time soon
I think an isolated and ambiguous sentence like the one you provided with zero surrounding context is perhaps a bad example. English can be very ambiguous. It is also possible to write unambiguous English, as far as deciphering intention is concerned. I think LLMs have shown us just how far English can go as a medium to get quite good results. And as others mention, there are other tools, like compiled programming languages and static analysis tools and unit tests, that can do more of the heavy lifting on our behalf.
How can a software developer compare a deterministic program with LLMs?? Please tell me that you aren't, or that it's not what really think!!!
you're talking to a senior software engineer on a forum of senior software engineers, the very men constructing our future. I'm looking forward to reading his response.
Nah. I figured that I might be kicking a hornet's nest, when I posted what I did, and have no interest in hanging out with the bees any longer. I'm sorry that I got everyone so riled up. I still stand by what I wrote, and don't particularly worry too much about what people think. Some will agree, some will disagree. It's a touchy subject, and will be, for some years. I've been through a number of these "paradigm shifts," and know the drill.
Alright
I respect the years of experience leading to your perspective therefore I do not intend to sting you and apologize for my behaviour if that has been the case. my comment was intended to be aimed towards software being grouped into a work class that mandates precision, while accepting tolerance thresholds that would be ruinous in any other engineering discipline. wishing all the best.
How can a software developer not do the one basic abstraction step to see them both as tools with some unknown, low probability of error?
The human developer+compiler+linker toolchain isn't free of bugs either, some percentage it will produce code that fails loudly and sometimes it will produce code that has silent bugs, be it due to wrong source code or due to compiler or linker bugs.
Normal software can be reviewed to attempt to find bugs, and bugs can be fixed..!
LLMs instead are inscrutable, can output whenever at any time and you can't "fix their bugs"!
And don't attempt to place the probability of error of LLMs and normal software on the same plane, LLMs for the time being are wildly more unpredictable.
The probability of error is for the whole chain, human included.
Indeed, LLMs are orders of magnitude more unreliable than that.
Given how many security vulnerabilities SOTA models are able to catch in software we've considered some of the most mature ever written, they can most certainly be more reliable in certain contexts and when used certain ways.
Well, not in my experience, but YMMV.
I recently moved my project guardrails into a separate set of skills in a repo that I can bring into a new project fairly easily. It's focused (wrong word, it's seriously not focused) on implemented as many different levels of testing as I can think of. Right now it does this https://github.com/onion2k/guardrails/blob/main/GUARDRAILS.m....
The goal is to get to a point where I can say with a good level of confidence that a change didn't break anything. It might be the wrong change, and it might be crap code, but I can ship it without anything blowing up. I've been using it for a while across a few game projects and so far it's worked quite well.
> Trust, but verify.
Testing is NOT verification.
EDIT: Sorry, oops, it's also called a kind of verification.
I'm pretty sure it is? It's not validation, but what are tests if not automated verification of certain things?
Sorry I was thinking like formal verification like proving something is correct. I guess testing can be considered a form of "dynamic verification."
But there is the problem that tests only check or verify a small sample of possible cases or inputs. They can never show that the program is correct. (Famous Dijkstra statement.) To know something is really correct you have to understand and prove it.
Testing doesn't verify the design.
On this note - people love to create 'AI factories'. Has anyone made a "QA factory" where a set of agents mimic real users to run in a pre-pod environment? Like I'm talking you spin up a variety of VMs with real desktops and agents that use real browsers and act like real users (on timing schedules that mimic real users too)
yes
I've had good results getting AI to do create both an app guide, and do naive UAT testing - it sometimes gets lost in the weeds, and sometimes hyper focuses on things that aren't important, but it also clears the deck of knuckleheaded things that would waste human UAT testers time. I run it any time major features goes in, and it regularly clears up things well.
I feel like your suggestion would be a nice organic extension of that same practice (at the cost of more infrastructure/tokens)
Nope, not a solution. Testing just solves a small set of problem with not reading the code. It does not solve scalability or performance. In fact, a lot of testing may make the LLM output worse, because it always tries to pass the test as quickly as possible, thus throwing out all the beautiful architecture you carefully designed.
tests will make sure your `sum(1,1)` == 2, but it will not save you from slop `function sum(a,b)` deleting your home folder for some reason.
Not going to work.
1. The reason OOP complained about AI code being shipped without comprehension is because they want to ship of it more and faster. If they had time, they'd review the code. Writing tests requires a lot more time than what people usually spend on code reviews (unfortunately, but that's how it is). And if you think you can generate tests, again, by using AI, then, the bad news are that now you have both the code you don't understand and the tests you don't understand. Don't forget that running tests also takes time, in some cases it takes longer than to write code. So, again, your benefits obtained from AI-generating code won't materialize.
2. Even if magically you were able to procure decent-quality tests (without understanding what you are testing!) There are still problems not addressed by testing s.a. reusability. If you don't understand what the code does, how can you possibly reuse it for something else? Perhaps a small modification or a generalization of the existing code would allow you to reuse the mostly tested codebase for the new feature, but since you don't know what it does, you've missed that opportunity, and, again, the AI-generated code came second in the race to ship the product faster (also, you've got a worse product).
* * *
The question of "how to deal with code we don't understand?" is by no means a new one. Dijkstra's structured programming was a response to precisely this question. His argument showed that programmers can't even anticipate all the potential problems to be found in a 16-bit adder and that exhaustive testing is prohibitively expensive. Therefore, he argued, we should restrict the kinds or programs we write to those that are easier to understand (and that's what he called "structured" programming).
Perhaps, we can find a similar sort of harness for AI writing code, where we can impose boundaries it cannot cross that ensure understanding. I have no idea what that can look like, but I'm absolutely sure that testing isn't it.
The comments are horrifying. They do everything they can to avoid reading the code they are responsible for.
You must read the code before shipping it to production.
"But I don't have time!" That's not even an excuse. At least one person in your company should be able to explain the code! How would you answer when reviewer asks why did you use this very algorithm?
"We have tests." They could help. But don't rely on them entirely because there's a high possibility that the tests are wrong.
I can't believe how many people proudly admit that they don't read code. I'm not entirely against using LLMs to write or review code, but not even trying to read it should be prohibited. Someone responsible have to review it.
Edit: I know that LLMs are very good at writing code these days. My point is that this is less a matter of quality and more a matter of responsibility.
> You must read the code before shipping it to production.
No you don't. You just need to be reasonably certain it works to specification. That was always the case, with or without LLM generated code. If anything I now have a lot more confidence in some of the code produced because the lower bound has become the LLM.
This profession really needs to be shaken up by regulators.
Releasing something to customers which hasn’t been reviewed by any human is gross negligence.
What makes you think people aren't "reviewing" what they ship to customers just because they don't read the code? If the testing goes well that may be all the "review" required.
https://i.imgur.com/HvzIZ6v.png
This is "Preview" — Apple's document viewer on macOS 27. Do you think the testing went well?
Personally if I had to look back at the rate of bugs of a similar severity my own company produced I think it was higher pre-llm coding and testing.
You want to regulate an industry 90% of whose output is just a bunch non-critical CRUD apps? You haven’t thought out the macroeconomics of that, you’d go hungry faster than you’re being obsoleted in the age of AI
why does someone have to read it?
we don't read the assembly code produced by the compiler, nor do we read the code of all open source dependencies, yet we can successfully build software
Yeah, that's because those things are either deterministic output, or produced by someone that was actually good at programming. LLMs are neither. If you don't read every line of code they produce, you are committing professional malpractice.
LLMs, natively, are better at programming than nearly every professional software engineer, full stop. There are a lot of meta tasks (not programming, software engineering) that they are worse at, but the actual programming part, they've transcended human potential.
You have to treat them like an ignorant junior engineer in nearly every respect, but trying to match with them at programming per se is a fool's errand.
The reason to read the code is not because you can catch their errors in programming. It's because they may have missed the forest for the trees at the operational or strategic level, and so that you can learn from them to understand better. It's like trying to beat the engine in chess now.
no you're not lol. You're managing a team of ever improving engineers. Opus 5.5 is almost paranoid about testing literally all its assumptions. It's already a better coder than me and I've been doing this for 30 years.
I don't understand why so many people bring up compilers. The reason we don't have to* read the code of compilers or oss libraries is because the developers who created them have reviewed it to ensure that it works. But if you don't review your own code, who will?
* As long as it works
code review isn't why programs are correct. careful testing is
Code review __and__ testing.
Code review done properly plays a very big role in ensuring programs are correct. Everybody knows how hard it is to get complete test coverage. You need layers.
we don't read the assembly code produced by the compiler, nor do we read the code of all open source dependencies
When you actually have to debug, you sometimes need to.
And when something the LLM wrote goes off the rails sometimes you have to look at code to debug too. But you don't need to make reviewing the code standard practice anymore than reviewing assembly code before shipping.
This depends heavily on your product. There is certain software where I agree with you. But for the usual business CRUD app, why would I need to know my code? It's vastly cheaper to understand code on demand, than digging into every single line of code preemptively.
In my products I definitely take care of architecture, interfaces and data, as they have a high cost of failure. Anything else doesn't matter. If an user finds a rare edge condition, asking an agent to fix it costs less than 10€. Properly reviewing a big PR costs somewhere between 100-1.000€. I would be completely irresponsible to my business to review the code in-depth.
If it was just CRUD then you were wasting your time "coding" it before anyway. There are loads of no/low-code solutions for CRUD.
But the reason people use real code and frameworks like Django or Rails etc is because it's never just CRUD. You always end up needing some business rule somewhere, or you end with some performance problem leading you to think about async tasks and cached result layers and the like. You need to understand it because you're responsible for giving the correct results to your business and/or customers.
Because your slop-coded "delete this record" method can skip `WHERE` in the SQL statement because you have prioritized performance in your prompt. LLMs have no clue.
LLMs do know this. Try getting claude to code dangerously like that and you'll get significant pushback from the agent.
Oh there is no need to push claude in that direction, it will happily go this way on its own.
Then you have bad tests and didn’t consider all cases in your prompt. That’s on you.
not possible in this year and age
> everything they can to avoid reading the code
The reason is simple. It's extremely morally taxing to read the AI code and realize this is a mess that has to be scrapped.
Much, much more comfortable solution is to join the church of "I don't read code anymore":
1. You can ship fast
2. You can feel good about yourself
3. You avoid facing the uncomfortable truth
4. You get support from fellow believers
youve succinctly described something ive sensed in ai evangelist coworkers in 1, 2, and 4. my tiny dev team of 4 is split between vibe coders and those who review every line, and im in the latter. i have a sinking feeling were the ones practicing point #3
I never hear anyone address the addiction-forming variable reward from pulling the LLM handle and sometimes getting what you want, sometimes getting garbage, and sometimes being thrilled. It's like opening loot boxes for a living. Highly addictive.
Slowing down to review the code feels like drudgery in comparison.
I'm in the review every line camp. I don't trust things that are addictive without a virtuous loop (like exercise). I have to interact with addictive things like video games, loot boxes, gambling, and alcohol in moderation. LLM use fits that perfectly. I'd rather use it throughout the day but still pause and feel the discomfort of reviewing the code, often throwing it out and having it try again when it inevitably makes a hot mess.
Do you read all libraries and basal low level code beneath your projects? Do you understand fully the entire stack from you to silicon? If not this is just more layers of abstraction.
But the code always "looks" correct.. its a hard job!
What I don't understand is that for most SE jobs on mature codebases, writing code is maybe 5-10% of the work. And it's that 5-10% coding that keeps you 'grounded' in the code and keeps your tacit understanding up to date.
Get rid of that and you get a basically invisible productivity increase (call it 10% to be generous) but you've now lost tacit understanding. No amount of half-assed code review (or getting the LLM to generate "code quizzes" etc for you) is ever going to substitute for the tacit understanding you get from doing the 10% of coding yourself.
I really just don't get it. I mean, I can believe that using coding agents gives people a rush of power and fleeting illusions of increased productivity, but it's a mirage.
A lot of the comments here are trying to find some middle ground, i.e. trying to find some way to preserve tacit knowledge. But it seems to me that it's a waste of time. You either need to write the code yourself or completely give up on even reading or attempting to understand it. I just don't think there's any middle ground. Any well-intentioned attempt to preserve understanding of the code will fall afoul of human laziness and understanding drift
I'm completely with you. It's baffling that this isn't totally self evident to devs everywhere.
You can keep tacit knowledge if you keep your prompts _really_ small and check the output at each step. That is how I write most of code these days, but I also interweave some manual editing occasionally (because it would be faster than prompting).
Basically using it as a way to type faster.
My attempts at finding a middle ground:
* I use LLMs to resolve the more annoying merge conflicts. It's not super hard work, but I don't like it, and I don't think I learn much from doing it.
* I implement a feature by hand, write some basic tests, and tell the AI to review it and write tests for cases that I missed (or was too lazy to do, most of the time)
* For 80% of the bugs that I fix, I have a pretty good idea going in where the bug might be. In the other cases, I ask the LLM to generate a list of hypotheses what's wrong. Often (but not always) it turns out one of the hypotheses was right.
* Sometimes it's not so easy to figure out how to trigger a bug in a test case. Haven't done it yet, but I plan to ask LLMs to experiment to try to do that for me.
* I use LLMs to generate tools that I wouldn't otherwise write (not high enough priority, too lazy, ...). For example, we had a rabbitmq connector that occasionally kept getting stuck without reconnecting in rare patterns of network interruptions. It wasn't really high priority for us (rare, easy to work around by restarting the service), so I didn't want to spend days of engineering on it. I asked Claude to write me a test harness that reproduced the issue, and it did. Having a bunch of automatically runnable scenarios made the actual fix not too hard.
* Sometimes, I have some software design problems where I feel I have a pretty good solution, but something about it feels off. Talking this through with an LLM often helps to refine or change the approach.
---
This approach to AI usage doesn't make me 10x more productive, but I do think it's a net benefit both for code quality and my enjoyment of the job. I don't know if, in a few months or years from now, I'll still be competitive like this, but right now, I'm doing fine.
I work for a company that’s all in on AI right now. For all intents and purposes - I have unlimited budget, but I’m spending may only $50 per day on the busier days.
Right now I have 8 agents open in my terminal and I know I'm on the more-sceptic end of AI users. Some folks here pull thousands of lines of changes, day after day.
With this many agents I don't even have time to read what they output, not talking about the code - just their output. My work today has been (sadly) degraded to: 1. Ask AI to explore the repo. 2. Pick a solution that works for the 3 solutions that AI proposed. 3. Maybe do few rounds of follow ups. 4. Create PRs. 5. Ask agent to verify if everything works post merge.
Some of my colleagues apparently skim through the code. I pretty much don't look at the code anymore.
It's just sad. I'm self taught programmer, hobbyist. I always liked working on my stuff and always were trying to deliver high quality. I no longer can't say that, despite my best efforts.
I literally have tasks right now where not only I don't understand what the agent is doing, I don't fully understand the problem either. I could invest time to understand it and agents do a pretty good job themselves, but remember, I don't read the damn output.
That said, I work in the infra team, not in the product team, so there's that.
In short: I "pick my battles carefully", and I'm not afraid to refactor after the fact. I'm also not afraid to make changes by hand when needed.
Picking battles: I lean heavily on AI for the mindless, boilerplate changes that used to take 2-4 hours; but instead AI can do it in 2-4 minutes. Then, I pay closer attention to performance critical areas, or areas that require deeper thinking. Finally, I lean on AI to review the changes. It gives me a better review than a human, and often thinks through things that require "superhuman" intelligence.
Refactoring after the fact: This is similar to working with a team of subordinates or lower-cost contractors. They (people or AI) write the first version, get it working, and then I pick the few areas that need cleanup. I work closely with AI to refactor it to be more readable; possibly to handle corner cases that weren't anticipated earlier in the design.
I'm also not afraid to make changes by hand when needed: The fact is that sometimes, changes are so minor or otherwise require a particular understanding that it's easier to do the change by hand instead of describing it to an AI. I hope where you work understands this and supports it.
This is how every product manager feels every day.
If you're an LLM prompter shipping products, you're outputs are more akin to a product managers, not an software engineer's.
Agreed. The implication is, get really good at defining acceptance criterion.
Kind of, except as product manager you're held accountable for delivering the right product, while your engineering team is held accountable for things like performance, incidents, and security issues caused by their code.
It's hard to hold an LLM accountable for anything.
Accurate but manageable. Just like a pm works with properties an engineer also does. The Product person wants to deliver the right product properties so they model their process around identifying the ones they want and then creating the right framework to get them. On the engineering side its the same thing. Define what you want, give agents an environment they can succeed in, iterate.
What nonsense! If a product manager ships something that breaks then the software engineer who submitted the code gets the blame!
Software engineers are always responsible for their code except now they have to be responsible for Claude's code
Oh, don't worry. Someone is also blaming the product manager!
Software engineers are always responsible for their code except now they have to be responsible for Claude's code
Which is - of course - absurd. Accepting responsibility without demanding the corresponding authority is a fool's game.
I have never been much of an advocate for unionisation in the software development industry. I didn't think it was necessary to protect the interests of the workers because for most of the industry's history the workers have largely been able to stand up for themselves anyway. Likewise I've never been a big believer in accreditation and licensing practitioners in our field - because who is qualified to judge someone else worthy in such a young industry with so little hard data about what works or doesn't work? I find my views on these subjects are evolving now.
It's not about protecting jobs if they truly aren't needed any more or protecting people working in the industry who refuse to move with the times. The Luddite philosophy isn't going to get us anywhere here. And besides - if AI is as effective as its advocates have been claiming then there should soon be more demand for capable developers to take advantage of the new opportunities. (The Jevons Paradox is relevant here.) But it is about protecting standards. If the tools aren't doing a good enough job then expecting professional developers to ship the code produced by those tools even though they know it's junk is something that needs to be challenged. And if developers are being expected to ship anything important without having the slightest idea whether it even works then that's even worse.
We had a lot of silliness going on when the very low interest rates and huge amounts of VC funding were propping up ideas and practices that would never have survived otherwise. Today we have a different kind of funny money distorting the industry but it's still propping up ideas and practices that we wouldn't normally support or perhaps even tolerate. And just like before no individual is going to be able to hold back the tide and it's going to have to be a collective effort to push back - hence my evolving views on topics like unionisation and accreditation. We've all seen the drop in quality across much of the industry and we all know why it's really happening because we see how the sausage is now being made.
Not all mistakes are code, a lot are feature design mistakes, and if SWEs would always be responsible about PM mistakes, then why not use Claude anyway?
Most product managers are in danger right now. Product engineers are more valuable and now have more time for product work now that the LLMs can crank changes faster than users can tolerate...
Exactly. The LLM is actually going to replace PMs not SWEs. It's far more likely for a SWE+LLM to encroach into a PM's role than a PM+LLM to encroach into the SWE's role.
I've been seeing this exact outcome this past year. PMs vibe code a hard-coded idea, then the SWE builds a real working one a week later. By the next meeting the SWE has more features than the PMs demo. A week later the PM is still struggling trying to add more ideas to the hard-coded mess while the SWE is cranking out new ideas.
It's not too dissimilar to life as a Principal level engineer pre-AI. You technically oversee the work of many engineers on their own systems, but you couldn't possibly review all the code yourself. You appreciate that human code review reduces, but does not eliminate, the number and severity of bugs shipped to production. You don't have the low-level details in your head, just the high-level ones. You design how all these engineers interact with each other, without stepping on any toes.
Time will tell whether we were right to move from a system where we trusted humans to understand the low-level system, to one where we trust fancy calculators. But so far, it's working.
The assumption was that some engineers knew how each part of the system worked, or at least the system was comprehensible because it was created by humans for other humans. There were comments explaining difficult places, etc. With AI this assumption is broken. Now nobody understands how things work, and it cannot be understood in principle because the system is a mountain of slop created by some alien intelligence.
> Now nobody understands how things work
Well, the fancy calculators do. Yes, they still need guidance to keep from going off the rails. But, at least from personal anecdotal experience, I need to go spelunking into the codebase less and less over time. The agents and models really did just start to become that good.
I'm a staff engineer on team of 20+ engineers working in a single codebase. We're all pretty heavy users of AI, like most engineers today.
I worry about a lack of understanding creating risk, and we are creating tools and conventions to address this risk.
But I don't yet see evidence that we're losing touch with what we're building.. yes, code is shipping faster, but I'm honestly just not seeing this "sleep-walk-engineering" issue in reality.
Code isn't shipping so fast that the engineer doesn't understand the intent and general implementation details of the PR.
PRs are required to be small (400ish lines), and have tests, and good PR descriptions must be present. And two humans must approve the PR.
The time it takes to understand, verify and validate the change is fast, often as fast as or faster than the time it takes for AI to implement.
As it stands right now, our level of understanding, PLUS our new verification tools... is all we seem to need.
We're not like the hyperscalers, but we're considering how some of their approaches might fit into our workflow.
And much like Anthropic, we aren't seeing bugs increase with the rate of code increase.
Engineers are still able to understand enough of what they need to.
But so far, it's working.
There seems to be disturbingly little objective evidence of that. There's certainly a lot of code being written but how much actual value that code is adding is another question. With the scale of resources that have been pumped into AI-supported software development over the past few years where are all the new applications and the quantum leaps in quality and performance in the applications we already had? If anything I seem to be seeing more anecdotes going the opposite way so far.
Anthropic's recent blog post about how they replaced Git should be a massive wakeup call. A trillion-ish dollar company (exact number unimportant here), the vast majority of its value coming from its intellectual property, replacing the storage layer that is an essential part of its system of record for that intellectual property, written pretty much entirely with its in-house Kool-Aid.
Disturbingly little evidence? I would hardly call that "disturbingly little"...
(Apologies if I'm misreading your reply. I'm assuming it was sarcasm but Poe's Law might apply here.)
This does feel a lot like the "Agile era" that was the last silver bullet that was supposed to fix software development forever and the "Cloud era" that was supposed to fix infrastructure and deployments.
Agile had a few good ideas. Code reviews and automated tests are commonly used today.
It had a few plausible ideas that it took too far. We are better at recognising the value of incremental development over big up-front design today - despite the ironic clash this seems to be having with agentic workflows - but almost everyone hates stand-ups and lots of projects have gone off the rails by breaking things down far too much and never committing to anything and so never getting anywhere.
And it had plenty of ideas that almost all of us have thrown out as unpleasant and/or unworkable. Pair programming comes to mind immediately.
What didn't really change was the fundamental nature of software development. Did we adopt a few useful ideas and get a bit more efficient and improve quality a bit? Certainly. Did we get orders of magnitude better at anything and give up all the tried and tested ways of working in favour of radical new ones that never quite felt right? No.
On our current trajectory I'm expecting a broadly similar outcome for LLMs. They're now very good at some things. But they are still pretty bad at other things that also matter - and some of the reasons they are bad at them are an inherent part of how they work and therefore probably can't be overcome (at least not with incremental improvements on the technology that still basically work the same way). So I am expecting to see a period of consolidation with a lot of organisations pulling back from their dramatic leaps into the unknown and downsizing of dev teams once the big AI companies start squeezing financially and the problems of developer burnout and stagnating skills and low morale that we're already seeing after just a few months become endemic. And then as I suggested in another comment I think it's also increasingly possible that we'll see developers unionise and/or push for professional regulation and licensing so they can resist the pressure to just ship whatever their agent wrote without even bothering to check it but still being responsible when inevitably things then go wrong.
If AI progress stops right now or stalls out soon sure, but if we really do have something significantly better coming, up to and including AGI, I think none of this will be an issue.
Well yes - we never know what the future holds and some new development or discovery could always change the trajectory completely. Personally I prefer to deal in what I can see and validate rather than hope and hype so until we see the actual developments or discoveries I'm cautious about assuming what will become possible with hypothetical improvements.
In particular I don't see why we should assume that the capabilities of AI programming tools will continue to improve at the same pace. There is no obvious source of new and high quality data for anyone to slurp up to train the next generation of models. Much of the change over the past year hasn't come from the incremental improvements in the models anyway. In fact I've even seen a few comments online arguing that some of the newer models had regressed in some respects. It has been the shift towards using agents and automating the incremental refinement of work in progress instead of waiting for human intervention that has been the big change and I don't think we really know yet whether the problems we're already seeing with that approach can be resolved effectively.
Yeah no one can predict the future but betting on progress tends to be a better heuristic with technology, especially in AI given the rate of current progress. And as far as I know the availability of (human generated) training data isn't a strict requirement for further progress given test time scaling. The way I see it is we're still running these models on hardware mostly designed before the LLM revolution so we'll be seeing massive gains in, at the very least, the speed and cost of the current frontier models in the coming years which will make all sorts of things possible. I also think it's more likely than not they will keep improving in capability at some rate and the things software engineers are complaining about now will be seen by the labs and worked on deliberately if simply scaling the models itself isn't enough.
The closer the code gets to the user's eyeballs the less I care about anything specific.
HTML/JS/CSS is basically entirely vibe coded. I won't even try to reorg the 4000 line ui.js file. I can just redo the whole thing from a new prompt in a few minutes.
For things like the SQL schema I am still doing things entirely by hand. The consequences of getting this part wrong tend to be far more catastrophic than something in the UI layer.
Exactly, we don't review UI. Nobody cares as long as it looks right and feels smooth.
A total overhaul is always but a single prompt and 5 minutes away, should the need arise...
> Nobody cares as long as it looks right and feels smooth.
That's how you get bloated apps that run poorly on lower/mid end consumer hardware and environments, with poor accessibility, and whatnot :p
Not that LLMs are the cause, this happened a lot before too, but they can exacerbate the issue. They can also be effectively used to minimize it, though they more often than not don't do that without explicit instructions.
I 100% get the worry and yes that happens a lot.
There are easy ways to prevent the bloat and wasteful performance though, sth I do deeply care about.
You can get a long way staying on vanilla or picking (for your llm) one of those superfast frameworks like svelte in ny experience :)
This attitude is why websites and electron apps have gotten so bad.
That's only bc folks forget to specify "pick svelte and make it efficient"
While I kinda agree, please do some testing and validation of frontend for websites too, cause LLMs are quite bad at it. It might look right, but usability and performance is often terrible. But that is often the case for pages made by humans to, so... Garbage in, garbage out, I guess.
Really? I've found LLMs to be really thorough UI testers.
In some businesses, your customer is judging you the most by what they see.
I agree.
The UI is the layer the customer is most likely to interact with and request changes over. This is why using the AI as the intermediary is so compelling. Most UI code is not long for this world if we are actually putting it in front of live customers. The less emotionally & economically attached to it we are, the better it is for everyone involved.
When my customer gives me crap about the UI, I barely even process it as a cortisol event because I spent very little time inventing the thing they are concerned with. It makes iterating faster and easier when you don't have much pride on the line.
> HTML/JS/CSS is basically entirely vibe coded. I won't even try to reorg the 4000 line ui.js file. I can just redo the whole thing from a new prompt in a few minutes.
Probably that's one of reasons why modern web experience is terrible.
On the contrary, that sounds much better in theory than “best practices” Prefart bullshit with node_modules rivaling modern AAA games when it comes to size.
These threads kind of rule. Lots of different answers!
For my part: I've put some of my tooling energy into code comprehension tools. You can get remarkably far quickly by just replacing the Github PR viewer! I started with a (native SwiftUI) read-only front end for tree-sitter and SCIP (the code-indexing standard). Then: as I reviewed PRs, I tried to catch myself doing annoying repetitive things and just building out additional features, like "show me all the knowable call chains for this function", or "show me every implementation of this trait".
You can get a fair ways just by thinking of things to hide in a PR viewer, just to clear space for the things you need to comprehend.
> just to clear space for the things you need to comprehend.
That's really it. I've been finding the same limitations with the default PR code review tools. We currently make do by having a section in our PRs "recommended review order" with a list of files/dirs that should be looked at first, which not only is much smaller Loc than everything else but is the main relevance of the PR.
Within a given project there are inevitably certain files/concepts that are more important, and a better review tool will help emphasize the structure of a large PR to make things easier to review.
I suppose you created a web based front end to GitHub PRs for your team to use? Or is it a local tool? Wondering how yours works.
We use gitlab and there's probably some way to hook up a custom external review tool easily (a bot that posts a link to view the current PR in the tool, for example)
Thanks for the idea!
Creating rigid boundaries is the key. You can create the architecture doc along which the code can be built and any deviations needs to be approved first.
I lost my ability to fully explain the systems I work on around the time I transitioned from next-edit-prediction AI running in my IDE (early Copilot) and working primarily via Codex/Claude CLI's.
The further away I got from the implementation details, the fuzzier the semantics became. To the point that now I could not in good faith say I understand the system I have built from the ground-up and worked on the last ~4-5 years.
The solution to this, in my mind, is not to revert back to reviewing implementation details. The economics of that from a business/productivity perspective don't play out well.
The only viable solution in my mind is adapting code/languages themselves to the shift by making programs formally verifiable. That way you can be sure that the code "does what it says on the tin", and provably so.
I feel so strongly about this I've written on it:
https://gavinray97.github.io/blog/design-by-contract-and-eff...
> To the point that now I could not in good faith say I understand the system I have built from the ground-up and worked on the last ~4-5 years.
You weren't programming with LLMs in 2021 or 2022, be real. More like 2024 (that's already pushing it) or 2025.
Because telling lies on the internet attached to my real name is so beneficial to my reputation, right?
https://i.imgur.com/CNAUczi.png
You poor soul. You were gambling against roulette odds.
Receipts!
I'd guess they started developing the project back in 2021 coding by hand, and are now improving/maintaining via agenetic engineering. This is not uncommon.
The point is that it's easy to lose understanding of the finer details, even of a codebase you lovingly created, once this switch occurs and an LLM gets its hands on it.
You get it.
The bridge is built. How do we test the load? Drive bigger and bigger trucks until it fails, note the weight, print the sign and rebuild the bridge the same way.
[delayed]
I can think of so many times this has happened before. People getting used to MVC, Dependency Injection, ORMs. Sometimes the code is so large you only work on a part of it, so you have to get used to a lot of not knowing.
So how do we build confidence anyhow when we can't know everything?
I think first, standard checks - does it compile? What do static analysis tools say - code quality, passes SAST analysis? Linters? Style checkers?
Do the tests run? I'm not comfortable with the tests I write let alone the AI.. by adding fault injection (fuzzing, chaos), and mutation testing, I have a better degree of confidence in the tests and code.
Spend even more time getting to know the product instead. Maybe I don't know the code as well as I used to, but I know the product backwards and forwards. That helps me have some new confidence that I didn't really have before. Knowing the greater whole.
> So how do we build confidence anyhow when we can't know everything?
Avoid known unreliable tools?
Your comment made me think that people have been happily importing hundreds to thousands of dependencies into their projects that were written by some random guys on the internet, but they've just now started to become concerned they don't understand the code they're shipping.
Exactly right. Many never check the release notes of those libs on bump either. To this add copy & paste from Stack Overflow we used to do. People are just afraid of losing their jobs now, so naturally we all got defensive.
exactly right but think about it a bit, the responsibility is kinda off shored to the library owner and the library is used by many and battletested meanwhile
with ai the only one that use that code is only him and the reponsibility is still on him
Yes this is essentially my take I posted. We have been working at various levels of abstraction for a long time using framework, packages, and even programming languages themselves.
I'll take a look at your post. I think it's really good to point out that abstraction is something that we have sometimes accepted / sometimes struggled with our entire careers (lives?)
I think the real question here is how we rebuild some confidence and perhaps remove some fear.
I always try to think how product owners deal with this. I used to write a lot of code, so did my colleagues, but the product owner was the one driving the effort - they definitely didn’t know how to code, but they “shipped” results regardless - they develop relationships with individual engineers, make sure to understand their strengths and weaknesses, insist on automated testing and then hand verify results, whenever on assumption the engineer expressed but turned out to be not true they push to extract the uncertainties.
Slowly build understanding of what is possible, push back on engineers suggestions and don’t approve stuff blindly, but relying on results to guide them not the implementation.
It is very very similar feeling. -you need to know your models and harnesses (e.g. your … team). You don’t need to know the specifics of the code but doublecheck with different personalities if the assumptions are correct, test them.
And ultimately shipping bugs is a given , human engineers do it _constantly_ it’s the resilience systems you build around that which saves you, tests, canaries, rollbacks, feature flags, everything we already know how to do - just use that and imagine yourself the product owner.
I'm miles away from all of this as a non-user of AI and it seems like a mania to me.
You should probably try it.
Yeah, man. Don't be a square!
Try it, you might like it. First month's free and you can still quit if it's not for you.
You make eat omelets using sourced material you have no way to verify.
You trust the label. The person. The company. You hope someone did their due diligence.
Sometimes taste the shell. That is an acceptable risk.
Except in this case the label on the eggs says "Eggs may occasionally be poisonous. Users should not rely on eggs to be safe, and should carefully scrutinise eggs before and during cooking. Bob's Farm accepts no liability for injuries resulting from making omelets with our eggs."
Users are responsible for what their agents do.
Would you have made this comparison in 2022 about a future where you're shipping code that you're not even reading?
(made a small edit)
No, not in 2022. The models weren't good enough yet. I was looking at the trend line though. I gave word to our engineers that software would not be the bottleneck. The bottleneck was understanding what to do next.
We used to be in the business of owning, understanding and evolving our processes. Are we not, now?
I expect the guy sticking to his horse and cart, as the first cars started to overtake him on the roads, felt similar.
A lot of the real advancements that the dinosaurs didn't understand perhaps seemed like a mania, but a lot of manias seem like real advancements that the dinosaurs don't get.
That's the problem -- you can't really tell one from the other except in retrospect and in metrics.
The latter look very promising for agentic coding. The former isn't quite there yet. We'll see, but I'd suggest the prior is moderately to strongly predicting that agentic coding is not a mania, but is very much here to stay.
(Obviously still the unpopular opinion here, mind you, and I may be wrong.)
Note that the only thing I'm calling a mania here is agentic coding that is shipped with no human who understands it (to say nothing of code that nobody has even read!).
And I would put a caveat on code that could somehow be formally verified as correct, using a formal verification system that humans understand. I know people sort of do this with unit tests but I still think that's crazy.
as someone using AI, it is mania, leadership has decided it is so and software is getting worse. we could have just accepted our 20% bump and been happy, fixed bugs, made things better quality, nope, ship half assed features at 2x speed, pretend claude is infallible and will solve all our problems, brand reputation? user research? pixel perfect designs? what are you a dinosaur?
Serious question -- how?
I'm not a sociologist or well read on anything. And I don't follow these conversations all that closely. This is just my vibe from 10,000 feet, and/or some pet theories. Though, it seems that some people in it (one reply to me here) agree.
To me it's the memetic dynamic. There's "Old Wisdom". It's entrenched over a few generations now (and maybe some of it comes from before computers). "Old Wisdom" would have never allowed people to seriously start shipping code that they don't even understand. "Old Wisdom" has in fact prepared us for every possible "shiny new thing". That stubbornness was actually a good thing and held things together.
But now "shiny new thing" is so shiny that people convince themselves that it's actually okay. But they have to break the "Old Wisdom" in others. And this stubbornness (again, a good thing) is now rebranded as "being stuck in the old ways". You don't want to be stuck in the old ways, do you? So rather than coming up with real arguments, they're gaslighting people out of their defensive "be prepared for the shiny new thing" posture.
Once a person has been gaslit out of it, it's their turn to gaslight the next people. Pretty soon anyone who is holding back is the weird one. "I guess this is the new thing now?". This rolling effect is what I describe as a mania.
On the flip side, maybe it really is okay and it'll become the "New Wisdom" soon. This is probably also how things change. I still don't care for it because it's very disrespectful to people who have held their ground for good until the point where it's no longer useful. They've believed in something that wasn't actually true, it just temporarily served some greater purpose.
I picked up on a similar dynamic in radical politics when principled adherents are suddenly gaslit as "idealistic" by "practical" people, after they're no longer useful to them (they already won the election, etc).
Technically it's just a role change. You're now the project manager or something, not the developer. It isn't a project manager's job to understand the code, only to ensure it does what it should and doesn't do what it shouldn't. And to ensure the developers, etc str unblocked and doing well. Embrace the new role.
Why would you need to embrace something forced upon you?
Perhaps it will make it easier to cope with? Fighting something beyond your control is pretty exhausting
Or just ignore AI. As long as you do your job, who cares if you use AI or not
In most workplaces, when supervisor/boss says "we need you working over here now; you start tomorrow", you either embrace or quit. Again, nothing fundamentally different.
And in most jobs, you don't get promoted to manager if you don't want to
Maybe not, but things and times change. If you're made obsolete in one role then you better be ready to move on to another.
So you can pay rent?
There is no escape from Dario's basement. It's best just to accept our fate. Rub the lotion on our skin or else we get the hose again.
We just need to hold until people realize the crappy codebases that AI is generating
I agree with this. The tech debt being accumulated is astronomical. If ASI or whatever doesn't work...developers will be back on the menu.
Wait until you see the crappy codebases people were generating before AI.
It's definitely worse.
Like, I'm a data scientist, and have seen my share of truly awful code, but currently I'm working on a system which has pyspark code inside javascript code.
Like, it works (for now), but my eyes, the goggles they do nothing.
money
Then whose role is it now to understand the code?
How much understanding is needed? If it works as specified (you did a complete spec and occasional check-ins to ensure things are on track and then tested the delivery, right?), then what more is needed?
So you just click around the UI, assuming there is one?
Can you break down for me exactly how the unit and integration tests are made? Do you ask the AI what to assert?
> exactly how the unit and integration tests are made
There should be enough detail in the spec that it's pretty obvious. And unlike - many - human devs, agents don't shy away from writing tests. Add a coverage guardrail and tell them to use red/green TDD and you're already a good way there. The main thing is to ensure shared understanding, so they also know business expectations and write appropriate tests. And... nothing here is really specific to an agent, as a human dev also needs sufficient guidance (tailored to their experience level).
This is just pure vibe coding and trying to convince yourself it's quality work. AI can't be trusted to go from an English written spec to tests
Here[0] we have benchmarks for AI writing tests for code that already has the correct behavior. Best case scenario is that they're at 67% with Fable, and that's with the highest quality specification we could possibly have (code). English is far more ambiguous
[0]: https://labs.scale.com/leaderboard/sweatlas-tw
Maybe you don't trust them to, but they can go from spec to tests; I've made them (even if it initially took extra prompting and scrutiny). And ultimately tests are just a proxy to checking that X works, written by devs for devs; actually trying X is something to be done by QA and/or project/product manager before shipping.
> (you did a complete spec and occasional check-ins to ensure things are on track and then tested the delivery, right?)
I have never in my career been afforded the time to make a complete spec.
That's now a key task with this new role. Unless winging it into slop is acceptable.
Understanding is needed when something breaks and you need to fix it immediately. Otherwise you become a meat proxy and now you’ve added Anthropic’s uptime as a single point of failure to your application.
i refuse to be a meat proxy!
Subscribe to multiple providers, and maybe even self-host :).
>Otherwise you become a meat proxy and now you’ve added Anthropic’s uptime as a single point of failure to your application.
Yes. We're all going to become meat proxies and we're all going to add LLM service uptime as a single point of failure to... every aspect of our technological civilization. But it's all worth it because Grok will let you force feminize Draco Malfoy into a anime girl and that's worth never understanding anything again.
How is this qualitatively worse than the other single sources of failure we already live with (ie cloudflare)?
The moment you fully make you spec and requirement water-tight, what you have is similar to source code.
This is such a narrow take. "Understanding" does not exist in a vacuum.
Ah yes the Santa dev fallacy.
Noone understood the code to begin with. People understand the concepts, the primitives, the "theory" as Naur said, the basis upon which a project is built. Noone ever understood a codebase worth understanding to begin with.
I'd like to meet Noone someday. He's done so many amazing things.
Noone always gets it right, Noone went there after that horrible incident, Noone actually dances like that...
That's the neat part; you don't!
Same thing is happening in academia.
You off-source it to Anthropic, of course.
Project managers just take the engineers word for it.
And engineers have a lot of leeway to just make shit up and the PM would have no idea until it blows up.
So the million dollar question: will you (ie those getting pushed into the role) continue that trend?
Except you can't blame Claude when sh-- hits the fan.
You don't - want to - blame humans either.
- https://dev.to/ayanozturk/dont-blame-the-developer-lessons-f...
- https://www.linkedin.com/pulse/blame-game-why-blaming-develo...
- https://thedevopsdojo.substack.com/p/stop-blaming-developers...
If you were forced into an "AI native" position, not given time for proper reviews, etc... you absolute can.
Why not?
It's a role change, except you get paid the same (or less... if you are lucky to hold the job)
you never understood every detail of what you were building. There was always code written by others, colleagues, open source libraries, etc. You would depend on that code every day. And now the scale is much bigger.
What I do: I have a mental model of the system and how it works, at different levels of abstraction, in all the ways I think matter. I test that mental model against reality by making the agent proof it's real, looking at the implementation myself and seeing how it behaves in production.
Every day I'm making hundreds of mini risk assessments on what happens if I get a specific assumption wrong. If I'm not comfortable with the risk, I figure out a way to de-risk it. Maybe a slower rollout, maybe I read the code for longer, etc.
It's certainly a different job. As a startup software engineer it doesn't feel against my instincts though
Software Engineers work has never been coding but using structured systems to solve problems, we have gotten so used to the grunt work that we think that is the main work, I believe AI has brought clarity to that, which is a good thing, where it goes wrong is when the system used to solve this problem is faulty, unstructured or inaccurate due to negligence, that is where we need to watch out.
Here's my strategy:
The codebase I work on was designed to be split by features. Architecture is well thought and each feature has the same high level abstractions, all code is in one folder. This bring several interesting guarantees: code is scoped to this folder, each feature is "not too big" and fits in the llm context easily, and a design document explains architecture choices, that is well respected by the llm.
When the llm works on a feature, it is instructed to do several things to help me catch errors before shipping. Write a templated description of the change: interactions with external systems, sequence diagram, happy path, corner cases, deploy checklist, settings change, etc. I review high level choices, and not the code.
Finally, the llm add review threads to the code everywhere it made suppositions and related to untested assumptions. Each of this comment says: what could not be teste, what the llm thinks, what happens if I don't change anything and release the code.
Finally, on parts where I want to be sure, I do llm-instructed testing. It can build complex test benchs in no time, fetch data from production "provide me the command to fetch data, and a script to anonymise it", do a before/after comparison, ... It costs few tokens but it buys the peace of mind.
This way I have a workflow where the code is fully written by the llm and I don't go crazy reading its code.
Ask the AI how it works!
It's totally fair to load up some open source project into an agentic IDE and instead of asking it to write something ask questions like "how does X happen when I use feature Y?" or "can you explain how client code could accomplish Z"
All the time I see an AI use a language feature or library feature that I never used before or I see some code I don't understand and it does much better than a lot of humans do at explaining what it did.
You certainly can do this for code, and it’ll give you great answers. But I find that, for whatever reason, info that I consume this way has a much shorter TTL in my brain than something I wrote myself.
I’ve been experimenting with writing a living spec — API endpoints, schemas, how things work at a low enough level that the LLM can fill in the details - and that’s been working well.
It also forces me to do the hammock-driven development necessary to build the right thing, and as a byproduct it keeps the design in my head longer.
I think over time our memory is worse than we think it is and writing things down is good for your own function as well as human groups you work with and AI. Like I do not care a lot for the AGENTS.md but if there is a certain kind of task like “write a test which mocks things in a certain way” or “implement a DAO object” it is very much worth picking one as a case study and adding a lot of inline comments that explain theory or reasoning or the steps involved in doing something and when you want it to write something say “take a look at A as an example, but I know there will be these differences…” and the same is good for you siz months later or another team member.
Doing sports ohotography I might got to a certain indoor track meet once a year and there is a lot to know about the order of events and how to move around in the space and where the good backgrounds are that I will have to rediscover unless I write a “runbook” which again lets me share that knowledge.
A coven has a “book of shadows” and for me it is mostly a runbook, like there are a lot of ways you can cast a circle and I like some liturgy better than others so if you get consensus on things you can write it down, even the Greeks thought writing things down impaired your ability to remember things but it’s easier to stay consistent and you do memorize it over time though…. It is annoying that a lot of people are reading off their phones in ritual spaces.
I use LLMs and agents to only do what I could have done myself, given enough time and hands and keyboards.
If I'm working with something I don't understand, I ask the LLM to teach me first, with as many references and correlations as I need to fully know what's going on.
I also do the architecture myself, but ask for periodic suggestions for improvements and checks on how other systems are doing it. If I see a newer system I think makes sense, again I ask for explanations until I understand it.
Idea is always that the agents assist me in doing something I could have done myself if I didn't happen to only have 24 hours in a day and other parts of my life to live.
I only find this is a problem when it writes code in a language I deeply understand. I can’t help but look at it, get the LLM to change it, etc. But when it writes me a Cloudflare worker in Typescript that I don’t understand, I couldn’t care less. It works, that’s good enough.
So I suppose we just have to care less and let it get on with it. Not easy tho, for sure.
At our company hackathon I led a team focused on this issue. What we landed on is in the future looking at code diffs is going to continue to go down. AI can write the code and AI can review the code and we are going to see bug rates go down at a "tactics" level.
What matters are the high level decisions in the code such as "Deleting an account removes the row for good", "Email becomes the user’s permanent ID", etc.
We imagined a completely new concept for code reviews where you review the decisions not the code diffs. Also if you want to review the code it is grouped by concept not by random file diffs.
This is coming from someone that likes manually coding btw but our PR size and velocity is increasing too fast to meaningfully review all the diffs forever.
1) Need to triple down on infrastructure (safeguards, tests, sandboxes, etc.).
2) Ask agents to do more than just code.
They need to fully demonstrate and prove that their PRs are rock solid. Ask for screenshots, videos, code reviews, detailed architecture diagrams, etc.
It would be an insane amount of work for humans, but AI can do it easily for each PR.
Merging any PR from an agent should be a no-brainer if there's real proof that the feature is built correctly and working.
If there's still doubt, then the agent needs to do a better job of proving that the feature is built correctly, doesn't introduce regressions, etc.
I don't think this is even new. If you ever made the career transition from a dev, to lead, to managing lead in the same project, you are already familiar with that.
In the beginning your had your hands deep in the code, knew every corner and every pattern. Then you became teamlead, coaching other devs and only reviewing their code. Then you became managaing lead taking over more projects - now you don't look at code anymore, but you still manage the people that write the code and make sure the code fulfills its requirements and delivers on product roadmap. You develop trust in your team, you barely every read their code. If individual teams or devs ship bad code, you will only learn from prod defects, but the measures are mostly the same - fix the team.
Well, it's simple. Don't do it.
I agree with you with one caveat. Professionally, your obligation is to be qualified for your job and ship work that you stand behind. Complete comprehension is absolutely necessary.
Personally, with side projects and tooling, go nuts. There's no reason to read all of that code.
> Complete comprehension is absolutely necessary.
I feel like an increasing amount of orgs out there have long abandoned this thinking.
Complete comprehension has never been a thing. Unless you were working solo with no dependencies, you never completely understood what was being shipped. I don't think an npm import vs an LLM implementation of a well-scoped, well-abstracted library is any different.
Your world will get smaller and smaller . I don’t think you can stop that wave.
My job barely changed, except I’ve replaced dog shit “offshore” contractors with an LLM, deliver more features faster with a smaller team and fewer bugs.
And much better code too.
I was struggling with this today. Working on a feature and AI review flagged something so I need to fix that. I iterated multiple times throughout the day and was completely exhausted cause each iteration was always complicated with the fix being ~1k lines. Finally landed on a one I felt at least a little comfortable submitting for review but a work day like this is super draining and I felt like crap the entire evening (I am about to go to bed, I am probably gonna have nightmares about pressing enter and enabling auto mode on plans that make no sense in a true nightmare sense)
I try to understand WHAT all code does rather than exactly HOW it does it. Large scale design choices, how it is tested (and that it is) etc.
Even if you have a 20 file 5k line change set, it's still not impossible to just grok what's being done, what the purpose is, and what it works like on a high level.
LLMs don't change the fact that such a review is difficult, but I'm more confident that there are no hidden off-by-one issues in 5k lines of LLM code than in 5k lines my colleague (or myself) wrote. So it's a welcome change in reviewing to do it on a higher level.
My workflow involves research, then technical design documents, then implementation, and a very heavy emphasis on E2E testing.
how often with a structured approach like this, you end up with large completed features that don't have many bugs?
Having had to use Meta Ad Manager recently, it's all starting to make sense.
If you continue down this path, your golden goose is COOKED
For me personally, iterating is huge. You can't arrive at a hugely complex system in one shot. I think of the LLM as someone I'm running software engineering "experiments" with. As requirements become clearer, I discuss with it more and more and over time I'll gain a stronger understanding of the problem and possible solutions.
You'll also discover over time which systems the AI can handle fine on its own and which abstractions and systems it just has no ideas on how to design. Often I find I have no idea how to design those too. It's then useful to try different designs, test tradeoffs and refactor aggressively if needed.
Just as I handled using a full text editor instead of punch cards. Or C instead of assembly. or higher-level languages instead of C.
You always need to understand a bit of the past technological layer before saying your goodbyes to it and moving on to the next progress phase. That's life for a programmer.
Actually, it is quite similar to a /compact with a harness: you need to "sum up" you current knowledge (aka abstractions, design patterns, ...) from time to time to carry it along with you in your journey.
Did it feel bad when you switched abstraction level? Going to agent AI tools feels horrible, especially with how it is used these days.
Like, it is not that I hate AI tools, I just hate how most people are using them...
I can't imagine going to punch cards to, well, anything would feel anything but great. But going from assembly to C I can see how a programmer could struggle with their coworkers not checking the outputted CPU instructions for performance problems and compiler optimizations that generate unintelligible assembly.
But even then all those changes were deterministic (at least to the compiler version), unlike AI.
I think it’s basically true that the job is now that of a manager with worse but more obedient underlings that you need to micromanage.
A manager never read all the code, you just need to find the level at which you are getting good results. For some tasks you need to read every line, even write every line, for some tasks you let it do everything and just test the feature.
Test driven development and the testing pyramid.
If the agent has written tests and crucially - witnessed them fail before starting the work to make them pass - you have a lot of confidence.
Review of your own work's easier too - test and production code tend to mirror each other, giving you a much more complete picture. Confused by the production code? Go read its tests for a bit, then come back.
It's also easier to understand the change if you were there for the build, watching the transcript, checking in every so often. Doesn't have to be your primary task - leave it on a second monitor, it'll catch your eye naturally.
And finally, on top of test-driven development, have the agent first (before the first test driven development cycle) build out an end-to-end test covering the work it'll do. Once that test is green (test driven word for "is passing") you're done with your work and can clean up at will.
Play with it before shipping, get it real nice. It's never been easier to clean the tech debt up and make the UI perfect.
Eventually you'll be ready to package it up into a PR!
Now's you can leverage agents and get creative. Make your colleagues froth to review your work. Consider making a Loom video to walk them through it. Consider reworking it into a commit series; it only takes a few second for your agent and you can tell a story for humans. Maybe you want to sequence it according to your struggles; maybe it's better to show the different layers emerge with each commit - it's up to you. Consider also that your agent can easily do one-off visualizations of the change for your colleagues if you think it'll help them, and you can attach those too - mermaid charts or even whimsical AI generated images. All this is because motivation is driven entirely by other humans' motivation and you want them frothing with excitement every time you drop a review. Make it fun, it takes seconds and gets your stuff merged fast while making your teammates smile.
This is a brand new job and we will work out how to do it together :)
In my experience you're just replicating the problem. Slop code doesn't stop being slop code when you add in slop tests to account for the sloppiness. If you generate code at a certain velocity, you eventually get to a point where you generate tests the same way you generate code. The model does its best effort in creating tests, but you'll inevitably get to a point in your work where the tests themselves are faulty and unreliable, the same sloppiness you were trying to control for.
There have been multiple times where my software dev team has gone back to prior implemented tests they had the model generate and found that after some time eventually the model got frustrated with the test no longer passing eventually modifying it to fit current needs around a feature push. You can probably anticipate how we came to discover this, as it ended up introducing a regression around multiple edge cases which the test was meant to control for.
The only answer is to inject actual engineering into the process as much as possible without giving it all up to the models to generate more slop in response to slop. tests are a great answer, but only if you treat them with serious intentionality.
Your engineers weren't doing what I'm describing I promise.
There are multiple places in my post where I explicitly describe the process by which you intimately:
- make the agent do verified work (the e2e tests and test driven thing)
- watch the agent work (the second monitor thing)
- read your own code (the tests/prod mirror thing
- play with the work and perfect it (the tech debt and UI perfect thing)
Plus a ton of other places in my post I very clearly describe being intimately involved in building and selling the work.
That to me is basic god damn competency. What your engineers did is a fad, and it won't last, and I'm sorry they abdicated their professional duty.
If you wish to screen for that sort of shit in future/current hires, show them my post and see if they turn up their noses or if they get excited and creative. You want only the latter.
> if we're going to spend our time checking each line of code, it's going to take forever.
How many more lines of code are Meta engineers shipping that they don't have the time to check the ones they _didn't_ write?
This makes no sense to me. So I spend vibe coding some app. I barely know code. It's 40 000 lines without comments. Say it's my job, and pays the bill at the end of the month. Say the LLM and I would have done the vibe coding within a week. I'd need one more week to check every line and understand everything. I'm a noob, this dude's a pro, so complexity is irrelevant. What the hell are they doing the rest of their time? Shipping more code?
And if that's true, and again, I'm a noob: shouldn't their "instincts" tell them to write tools to increase comprehension speed? Better interfaces? I hate everyone single one out there and designed a better one. Now I have to port to Rust/Actix/GPUI and some vibe coded redis because that thing is laggy as hell ... but I HAVE TO UNDERSTAND HOW it works because otherwise I cannot improve/customize the stuff/frameworks already out there and that people build with ...
What are they doing with their time? There are all these posts out there of programmers and systems people not doing anything 90% of their time? If it's already shipped, don't you try to understand the details afterwards?
"Great leaders hire smart people and step aside so those experts can guide and solve problems instead of being micromanaged"
- Ask questions, clarify and ask "Do you have any questions".
- Build systems for robustness, like you would build when delegating to human engineers. Tests are just an important but small part of it. (Take ownership)
- Lead with examples (not just skills.md or what-i-want.md). It cannot understand your abstractions.
- Peer reviews (Across agents or across models)
- Clear division of responsibilities (Context engineering - Agents/SubAgents)
One of the approaches I'm taking is to try hard to simplify the code generated by LLMs. If you can reduce its complexity, it usually means you have a fairly good idea of what's going on in the code change. I consider which edge cases are getting unnecessarily handled, which new vocabulary was introduced where existing or simpler vocabulary would be fine, etc. etc.
I also have a /simplification-check skill I run after pretty much every large change, and that already helps surface the murky areas of the code and sometimes remove complexity before I even start reviewing, thus accelerating the review.
I created this VSCode extension. I call it Guide-coding. Works well for me
https://marketplace.visualstudio.com/items?itemName=novian.g...
I do what I call a shallow review. I don't look at every line to find bugs, but I want to understand the intent and see if model doesn't cut corners (of course you want to use 5th carousel element as a profile picture, great UX right?)
You don't. If you do then please stop calling yourself an engineer because no self respecting engineer would ever sign off on something they don't understand.
I've gone through multiple phases.
Phase 1 (mid 2025): Have AI write the simple stuff if you want, but hand-write the important core stuff.
Phase 2 (late 2025): OK, let AI write the important core stuff, too, but review every line of code.
Phase 3 (early 2026): Wow, AI is making virtually no mistakes, so only review the important core stuff that it writes.
Now (since mid 2026): If using newer models like Opus 5.5 or Astra, no need to review its code as long as the behavior is as expected. I'm no longer a software developer or coder, I'm a software creator.
> I'm a software creator
Are you? Seems like the model was the thing doing the creating.
I wrote a local code review tool to help me understand it - https://github.com/imron/crt/
Tests, observability metrics/alerts, and backups. Worst case, I can rollback everything to a point-in-time where the system is stable. Its a tradeoff I'm ok making for the increase in speed of features to market. Also depends on your industry. If my app handles money movements in a ledger I wouldn't feel as comfortable with AI development. But incorrectly handling like counters or reposts at Meta is low stakes wrt AI.
Welcome to my life! I'm a System / Platform Engineer working with 90% proprietary products. Understanding just enough of the systems we run is a skill.
In the last few years we've shifted into building more things in-house. It's awesome and we can solve even more specific needs for the organization. But the situation with understanding just enough does not really change. We just don't have time to dig into every line of code like you say.
I don't know if this is the correct way but it is the pattern I have fallen into.
Written code is the new compiled code. You never look at it, not even once. Documentation is the new written code.
Every repo has a /docs folder that holds the full specification of the code. Full architectural block diagrams, edge case behavior, style, problem statement, etc. I closely review these docs and make sure that the agent follows these specs and ensures the specs are updated after every code change. In theory an agent could fully rebuild the system from scratch using this documentation.
Maybe this is just pearl clutching, but it helps for when people ask architecture questions and I can answer and pretend I know what's going on.
The time that I would have spent typing in the code is now time I use to test the code. I really like to poke at things and ensure that my understanding and reality match.
I agree with the advice to design your system before implementing it. It is pretty easy to iterate on a design with your favorite coding assistant, and this is your chance to be ultra-picky and make sure you get exactly what you want. This was always where the "software engineering" was done, but in practice it's easy to have a vague idea and refine your (internal) list of requirements / tradeoffs as you type in the code. I find it harder to do that when the LLM is generating the code, just because one turn can change so much.
Keeping it under control requires discipline, just like before LLMs were a thing. You set a bunch of engineers loose on your codebase with no vision or supervision, you get spaghetti. You just get a little bit more control now. Agents don't feel shitty for the rest of the day when you tell them to do it some other way, so you are free to review as critically as you want without hurting anyone's feelings. I think it's a good thing.
The traditional answer is the same for engineers going into engineering management because managing a team and managing a set of agents is highly similar, only managing agents is far easier. One only ever has the illusion of control, and so you have to set your mind to containing the worst possible outcomes and looking at the net efficiency and efficacy of the team with the understanding that they will, on average, never be perfect.
I'm surprised by a lot of the commenters here. People that are saying just wait for all these codebases to crumble for us to be needed again refuse to acknowledge the reality of what is happening around us. If that is your take, I advise you to become really, really good at programming and work somewhere in the realm of critical infrastructure or financial institutions where presumably agent written code will be last to permeate.
I do get the sentiment but the conclusion doesn't make sense to me. We have been solving problems as engineers at different layers of abstraction for a long time. Pre-AI, I used frameworks that abstracted lower level concepts away which made it faster to develop the solutions that mattered (aka solving problems for the end user). I could, given enough time, write the underlying database adapter to convert my business logic form into a database query and back out but I didn't need to because someone else abstracted that part away. Did I know how well that adapter was written? No. Were there bugs in it? Occasionally you run into a limitation or bug the author hadn't considered that required a patch or fix. Going a step deeper, the programming language itself is an abstraction that compiles into machine code or bytecode. Do I understand machine code or kernels? Definitely not. Some programmers do, especially if you have a compsci background, but I'd wager the number has been decreasing over the years. The point is, now agents are writing code and they are now pretty damn good at it. Better than the "average" programmer out there. Now we get to "program" in natural language by telling the agents what we want and they get to worry about nailing the syntax and all those details while we focus on the higher level decision and direction of what's happening. If your agent written code is sloppy and terrible, that's a skill issue not an agents write bad code issue. You need to setup the systems that result in code to your standards with the checks and balances to test and QA appropriately before it hits production.
Complaining about the state of things while sitting back with your arms crossed refusing to adapt to this bold new world is a risky strategy. People saying just don't use AI and do your job as normal are also going to have a difficult time. The devs that can leverage AI effectively and get a lot done will out leverage you to the point where it doesn't make economical sense to keep paying you to not use AI (unless you are in one of those super critical fields I mentioned earlier and even then I'm not sure those are safe). Isn't it more fun to embrace this new technology and figure out how to use it effectively vs complaining and refusing to acknowledge it? Help shape the future instead.
All this text to simply rehash that you will be left behind if you don’t enthusiastically embrace AI. Very original and unique, thanks for your unique contribution to the discourse.
> The point is, now agents are writing code and they are now pretty damn good at it. Better than the "average" programmer out there.
That's not true at all. LLMs are still noticeably worse than a typical (competent) human programmer.
> Isn't it more fun to embrace this new technology and figure out how to use it effectively vs complaining and refusing to acknowledge it?
I care about results. If a tool is effective, I use it. If a tool gives bad results, as LLMs do, I don't use it. It's pretty straightforward.
>This new standard of shipping with AI is moving so fast that if we're going to spend our time checking each line of code, it's going to take forever.
"This new way of piling bricks is so fast that I can no longer afford to check the buildings integrity".
I just don't understand how the fuck we ended up with this narrative. Somehow the machine making things twice as fast forbids us from spending time ensuring quality? Surely if it does things faster you have more time and tools to check!
I'm half convinced this frenzy is the marketing work of AI companies at this point.
> this frenzy is the marketing work of AI companies
Worse. "AI" is a self-marketing contagious delusion, driven by an inexhaustible power supply. Human gullibility.
One of the keys for me was the use of types. Typestate when functions mint witnesses that can only come from it and are required to proceed and newtypes where you use custom types instead of strings so the agent can't forget. You can also use it to force the agent to use the implementation rather than reinvent the wheel by simulating linear types. Types are a much smaller target to optimize and provide constraints that fail loudly at compile time. (https://news.ycombinator.com/item?id=49806799)
I maintain a SPEC_SHEET.md file while asking the agent to keep teaching me the detail of the changes made or feature built after every iteration. This gives me a small handbook after I finish the project. I keep reading it like a book and learn how things are working inside the codebase and sometimes when required, I follow the code side by side while reading the spec-sheet.
You have to design your process for writing code to handle more code than you could ever read. To do this you also have to accept that you will not be able to hand manage all of your agents and all of your projects. The key thing is to figure out how to manage your time better and spend your efforts unblocking your agents.
What I did was build my own process for this: https://github.com/mhalstrom/maximizepm
The main take away is: 1. You need an agent to manage your agents that you mainly interact with. 2. You need a durable way to manage tasks and the dependencies between them. 3. You need agents with multiple roles ie manage, build, review etc 4. You need to manage yourself across projects so any system you build needs to take that into account
Wasn't this supposed to be what Gas Town was meant to solve?
I still read most of the code agents right, so I am good. If I won't have time to do it , I will make sure at least I understand how different systems communicate with each other and what each of them do.
Maybe what makes me more comfortable with it is that I'm in Operations. 95% of what I ship to production is not code I've written, and a huge part of what I ship to production is not code I even understand. Day in and day out I'm responsible for tens of millions of lines of code involved in running a service: Linux kernels, userspace, application servers, databases, monitoring. I'm responsible for reliably running this whole stack.
So, for me, end of the day, it's all about testing, monitoring, soaking in staging and promoting to production.
This might be why I'm fairly comfortable shipping AI generated code.
If you work at Meta you should ask at Meta.
For my own projects I’ve limited my exposure points by picking which projects and what scope I ship. I have to iOS apps in the App Store and I simply removed high exposure surfaces - right now neither use accounts because I don’t want to manage account systems, and Apple prefers it anyway. I downrisked my projects from what I could ship and I’m perfectly happy with my production projects.
Most of my other AI written projects are internal apps and systems. I have another project going public soon where I ship the output of LLM written code, without running the code in any user accessible area.
And tests, of course.
In time things will mature, tooling will be better, and we’ll have a different risk quotient.
I'm currently working on a combined Aero sim/CAD/CAM software for designing, simulating, and performing DFM optimization specifically for Group 1 to 3 winged UAVs.
What I do is ask Opus/Gemini to explain the parts I don't understand. And I do some of my own research to verify accuracy of the explanations.
In addition:
* Every new feature has a Feature Design document which I review, modify, and approve. And a corresponding Implementation Plan which I also review and approve.
* Every fix has a RCA document and fix Implementation Doc which I review, modify, and approve.
* There's a global high level Architecture and Design document with additional sub component design documents which are always kept in synch after a new feature or bug fix is done. Synching it is always a step in the Implementation plan.
This does adds some overhead but it allows me to have have check point gates. This has often allowed me to catch misunderstandings and align properly before any code gets edited by the AI agent.
Having the above docs also helps when it comes to referencing them as context to properly ground new features or bug fixes.
Hey this is very cool, reach out to me https://alexanderaghili.com/ because Id love to learn more.
I shipped code I didn't understand when I copy pasted from Stackoverflow before. At a level if it works it works.
I mean, I did that when I was learning how to code. Is this seriously something professional would do? Not the copying part, but the not understanding part.
Do a quick text search in this comment section for the string "it works". You'll see the same results in basically every HN discussion about LLM coding. "It works."
To me, "It works" is pretty much the lowest possible quality bar for an acceptable creative work product. We should not aspire to "it works." We should not hold ourselves only to the "it works" standard. And, yes, I know that many traditional software companies fail to even meet "it works" for their shipping products.
I don't even know what to say anymore. This has become a deeply unserious industry putting out mountains of junk that barely even meets the "it works" bar, and LLMs are just accelerating this.
The worst part is, it doesn't even work. LLMs are bad at programming, and they will sneak errors in that a human wouldn't make, errors that will come back to bite you sooner or later. The software LLMs make appears to work on the surface, but there be tech debt dragons underneath.
Built a tool that helps me at least get a better gist of complex changes: https://github.com/sshah03/perspica
It's not perfect, but it's helped so far.
Some code implements architecture, it is the skeleton of the program. Some code implements features, it is the flesh. The "flesh" is often isolated, if it is broken it can be replaced without major impact. The "skeleton" on the other hand needs to be correct. I make sure to understand the skeleton as well as critical features. I don't take the time to understand non-critical features implemented using AI, I just make sure it writes lots of automated tests.
Maybe a bit unorthodox but I have it plant 1-3 bugs into the code it writes (depending on the size of the MR I'm working on); they range from simple one-off issues to something more structural.
It then gives me a hint on the area or a typical code flow that would hit the bug - whichever gives me less info. I can obviously ask for more hints as I read along.
Obviously all honour-code based since I could just ask it to fix the bugs itself. I think this is something that can't be fixed systemically - either you're going to bother reading and thinking through the code or not.
Other than that I guess reading the tests - to make sure they fail without the code / fix, to make sure the setup makes sense etc.
I saw that post on LinkedIn and my immediate thought was just use AI to explain the code to you before committing. I do that and it's quite good and fast. I personally prefer to understand every line of code that's committed with my name on it, or in a repo that I own. I guess it's passe now to expect this of everyone?
Basically, don't let the AI coding era peer-pressure you into being a bad engineer.
That would explain a lot about the latest news.
If Facebook is hiring and looking to replace the idiot who made that linked in post, I'll be honest, my ethics are at an all time low, I would work for you. Plus, I can guarantee I am capable of doing BOTH no-shits-given programming and FULL-shits-given, so I'd be perfect for your payroll where a straight upgrade is warranted.
I've been spending a lot of time iterating on feature implementation plans with Claude (at work) and GPT (for personal projects).
I then make sure they write a lot of tests and that if functionality is changed or added/removed then tests are updated alongside.
Generally I try to review changes myself and ask it to explain the changes.
It's not perfect but I feel like the planning step being iterative isn't all too different from my old research -> think about implementation -> implement loop.
At that point, reviewing any code changes goes hand in hand with how I coded before LLMs.
The major difference is I usually have it make any changes for things I don't like.
I think there's a balance to be had. Leaving everything to agents when it comes to throwaway prototypes, one-off test env. scripts, extra tests I'm fine with. Doing the same with features - absolutely not - especially when it comes to financials. Seems like Meta is pressuring engineers into becoming expensive spec generators because they want to be in the cool kids club. Time will tell if that's a good play but to me it just sounds like a quick and dirty way to obliterate their engineering culture.
It’s very disconcerting. I think this will largely be solved by going all in on AI and use it to test and review the code in an adversarial manner. That won’t be cheap but it’s the only way I see this work. But a lot of companies will probably save money and use AI mainly for writing code and then skimp on review and testing. I bet we will see some huge blow ups with AI written code and hopefully the industry will learn.
It also took the industry quite a while to accept that server code needs to be secure even if that requires a lot of extra effort. AI will probably be the same.
Im currently building a ui framework for unreal. I dont enjoy ui work so I wanted a way to have to write less ui.
For me I dont look too closely at the implementation but I look at the api where if a human was using my framework how is the code they'd have to write and engage look at. Then I also do plenty of performance against a comparable target in my case slate (default unreal) and keep overhead minimal.
So good performance and reasonable public facing api are the 2 main pieces im focused on. Less with the internals.
Care about the seams and interaction and the things you can measure or count.
Claude to Prod. Every day.
Amen. If it works, its good enough.
The CVEs are going to be epic.
I don't understand these types of comments. Aren't the CVEs epic today with human written code? What difference does it make then? You want no CVEs, make software engineering into a real gate-kept engineering professions with accountability chains, government regulations, formal education, etc.
> You want no CVEs, make software engineering into a real gate-kept engineering professions with accountability chains, government regulations, formal education, etc.
This will not only not prevent CVEs, it will also make everything a giant pain in the ass
Of course it will. But at the same time I don't see building falling left and right like CVEs in software. So don't tell me agents write bad code, because humans do as well. The only way to prevent this (or minimize), is to turn software engineering into real engineering.
The problem is what's happening right now is the opposite of that... software engineers are being turned into managers.
And if you don't think the firings and reduced pay are right around the corner, I have a bridge to sell you.
"If it works, ship it" is very different from "If it works, and I understand it because I wrote it, ship it".
Does the LLM understand it, in detail? Can you trust its interpretation of the information and instructions you provided? Did it independently make an adverse decision you haven't noticed, because you didn't read the code? Was the model missing any information it required -- and would you know if it was?
LLMs depend on humans and human oversight to ensure they have the information required to make the right decisions, to catch when they don't, and to steer them based on your much more complete understanding of the broader context and requirements. You can't rely on them to do that thinking for you (yet?).
I’d argue that most people also don’t understand code they read from their colleagues. Or if they do, then they don’t understand the entire context of the app.
You said LLM need human oversight and it’s true, but it does not imply you have to read the code.
I think we are going towards a place where code no longer makes sense, you just describe what you want in English, and the LLM just builds directly in machine code. You then build different verification tests to make sure the program is doing what it’s suppose to do.
> Aren't the CVEs epic today with human written code? What difference does it make then?
LLMs cause errors at a noticeably higher rate than human devs do. If you lean on them without actually checking what they wrote, the error rate in your software is going to go up.
By default Claude chooses old versions of libraries. without something that checks for CVEs you're gonna be shipping criticals like no tomorrow.
Yes, there are more CVEs discovered every day, but, if you don't patch, the hacker doesn't have to try.
More opportunities for me to jump in and save the day. Win-win.
I had same problem, but after a while I just accepted that is inevitable
"This code is really ugly."
That sucks. Ship it.
I've seen a few people who lean into what the leadership wants as a form a accelerationism.
I think the standard cyber liability insurance that companies buy will go up for AI generated apps in the near future. They and other business insurance companies are on the hook when things go south.
What the worst case penalty of the bad code/app?
Whenever i stuck creating a project by AI Agent or vibe coding tools. I take a rest and go for a walk and make mood fresh. Then i came back with a power and this works alot for me. I have used this to add best attractive sectioins to my site : animeflvv.com
I quit my job at a large corpo, and moved to a smaller company that doesn't try to push velocity at cost of quality.
You need to get on top of that code. Read it, understand it and rebuild the parts you don't understand.
That's essential as you should really "own" the solution you sell and take money for, as you're responsible for what it does on your customers' hardware.
It comes down to the blast radius of a failure happening in your system. Some stateless frontend won't require much beyond visual inspection, but if you introduce some client-server architecture or require payment processing, you must consider the cost of a security intrusion when auditing code changes.
Yes. The dashboard that grabs some data out of other systems is vibe coded. The design was mine, to make it safe to let the AI go wild on the rest. Places where authentication, durable state, un-reversible actions are concerned: the AI can sketch it, then you gotta own it, with perhaps help from the AI to improve tests or refactor.
we've been working on an open-source ide that is just meant for code review. https://github.com/devdotfast/whiteboard/
your coding agents can draw interactive architecture diagrams with it that reference the underlying code so you can get familiar with a diff from a high level and drill down if you need to. we've found it super useful to quickly get a sense of your own changes before sending to colleagues or shipping.
This is as much a top-down issue (managers incentivising AI use and high velocity) as much as it is a bottom-up issue (devs knocking out issues faster than they can review)
It's a problem that requires a united approach from both sides.
A need to pace oneself, as it were.
I built and use https://smalldocs.org, which is a rich document format (mermaid diagrams, nice formatting, etc.) for agents. So I’ll be like “sdoc me the architectural ideas for this feature” and it helps.
* Focus on the data models. Design them carefully.
* Review any code that modify the data (when possible, avoid migrations that can't be rolled back)
* Staging/PR deployments/feature flags
* Observability
* End-to-end black box integration tests for the main features (unit tests are mostly useless)
You hit deploy and hope for the best, if it goes bad You just prompt the model again....
Just kidding, it's de same as with any other Open source plataform You install from their repo. It will be hard at the start but then You Will be very aware where it starts to fail and how to fix it.
I don't ship code I don't understand. I fully review every line if it's going to prod.
My dumb little utils in ~/.local/bin? Those get merged after a quick functional test without my having read a single line of it. Still, the skill I maintain for such a job directs agents to write such throwaway scripts in anything but shellscript because I might want to extend some day and fuck shellscript
We should never have cost cut away proper QA departments. I suspect they'll be back
I've been playing with this https://getchronosphere.com. It will (attempt to) rebuild a PR in a coherent journey rather than a massive blob. It's been somewhat helpful up to this point, and still improving.
I think the solution is leaning on static types and hard to abuse abstractions to make programs correct by construction. It does mean that you’ll still have to use your brain to design the internal code architecture, and just use LLMs to fill in the boring bits between the safe abstractions.
Force to always use TTD, at least validate the tests.
Recommend reading (All though a little self serving): https://www.linkedin.com/pulse/ai-code-quality-jorge-varas-a...
Maybe the new meta should be reviewing new code at the end of the week/month rather than at each merge? But even that might be too much of a bottleneck. The alternative is to talk to your agent to understand changes at a high level without reading every line of code.
I'm calling it: the next (or soon-to-be-next) step forward is finding ways to understand AI-written code. For now, you can ask a frontier LLM, they've become much better at avoiding hallucinations.
build the contracts on the test and verification side around critical paths and things you want to optimize for. everything.. honestly, let it go lol. at some point it becomes another level of abstraction.
Write it in a theorem prover! No really!
This kinda makes me think about the transition from writing machine code by hand to using a compiler. Did people feel similar at the time that they didn't understand the machine code that the compiler was writing for them?
Yes!
Each step in abstraction we've made had people who felt uncomfortable at the level of magic they were accepting. At one point in the 70s/80s, traditionalists were arguing that C itself was too high level. Then in the 90s and early 00s, that languages like Python and garbage collection were absurd: a "good" programmer doesn't need them and they give up too much control. Then as web development ramped up, people entered the "Javascript is slop" phase into "React is slop" phase.
Anytime the barrier to entry is reduced and some skill or profession becomes more focused on output than the ego of the professionals, you can bet a counter-culture of people will rise up to oppose it. It's a threat to their sense of "betterness" and/or the (perceived) value of their career.
While elitism and ego have certainly played a role in the dialog since the beginning of computing, this perspective conflates those issues with the very real technical arguments against the listed technologies. C and other contemporary languages had their limitations; you were sacrificing flexibility and potentially speed for a more pleasant and maintainable development experience. Garbage collection dates from long before the 90s and has always been controversial, in no small part from differing tastes and opinion on whether other memory management techniques are truly more difficult. The assumption that these technologies lowered the barrier to entry may be the crux of much of the argumentation.
> Counter-culture of people will rise up to oppose it
Looklike they are correct because now we have web people making 1GB-RAM Weather app.
> ... they didn't understand the machine code that the compiler was writing ...
This is a bold assumption and inconsistent with my knowledge of history. High level languages allowed better management of complexity and reduction of tedium. The common complaint was that compilers produced less efficient (slower and/or larger) code, not that the output was more complex. It was[1] normal to read the compiler's output, which was generally assembly or another intermediate representation. After all, a compiler is merely a tool for translation from one language to another. Additionally, early compilers often were not optimizing compilers; the code they generated was simpler than handwritten programs.
1: And still is, for some of us!
The key difference is that the procedure for transforming source code -> machine code is fully explainable by anyone with access to the compiler source code. There are no statistical estimations with black-box parameters involved.
Very good question!
The problem assembly programmers had with compilers wasn't that they wouldn't understand the generated machine code - it was that the generated code was often bad (as in unoptimized and bloated) and didn't justify the resources required to run the compiler. As hardware got more complex and powerful, compiler got much better, and operating systems became the primary layer between hardware and applications, assembly became more niche. Nowadays it's pretty challenging to beat the compiler at generating efficient assembly and writing a program in assembly would consist primarily of OS and library API calls anyway.
There are definitely parallels there. The only obvious difference I can see is that both high level language code and assembly are unequivocal in their meaning (as in you can determine what gets executed), whereas natural language is not.
Bin it and start again but this time without AI.
Generally speaking I brain storm the feature first and produce a dev plan. This includes asking it to reuse code/libraries we’ve already got! After it’s gone off ah done its thing we go back over and do a QA on what it’s built, why that approach, what can we do better etc etc?
I believe it's the management's responsibility. If the management is in the state of AI psychosis and wants slop shipped as fast as possible - so be it. It's their area of responsibility, not your's. If they don't care about quality at all - why should you? I mean this literally: why should you? Quality is not a universal value and for some projects iterating quickly truly makes more sense than shipping something that actually works.
During my 30+ years career I have never worked in a project where shipping slop (AI or pre AI, doesn't matter) was an acceptable solution. That's my choice and I'm pretty happy I have always had the opportunity to focus on quality of the product.
PS: LLMs are wonderful. We should learn to differentiate between AI-generated slop and AI-generated code.
Tbh if it's really crucial I let the PR sit there for a while and sleep over it, poking at it every now and then over the course of a cple days, until I'm comfy w it ...
I just think that the level of abstraction, or black-boxing, we are experiencing nowadays, is the same experience that developers felt when they switched from assembly to C...
Build tools to help you understand. Build metrics that are proxies for the things you'd care about. Add constraints to the agent's work related to performance, error monitoring, language and architecture choices, review bots (that you tune and eventually, trust). If you don't have good ideas for tools, ask Fable what the best coders and industry experts would look at to establish trust, then feed that into models to build it. Don't sleep on how useful something like a (data-backed) claude artifact can be - i setup one today to track dependency and known vulnerabilties with a burndown chart and (agent) run log, one prompt, it was usable 5 minutes later. A colleague of mine did the same, but as a datadog notebook that also wires in relevant API metrics depending on what code has gone out in the last week, and suggests new longer term metrics to monitor as a result. Etc etc. its a crazy world but this has helped me cope so far.
Someone said it in a (Hacker News) post the other day, incredibly simple formula:
Brain AI Brain
You start the thinking, you tell Claude what to do, you think about what it built. It's that simple.
My Jira tickets are written by AI started just feeding the ticket into AI (shrugs)
No I only do that for unit tests so far
I went through like a mid-life crisis when the thing I learned/spent last 13 years on became meaningless.
> How to deal with shipping AI-written code you don't understand?
Stop shipping code you don't understand.
Is there really any other solution? You can either ignore it and pretend like it's the new era of software like half the other commenters are, or you can sit down and understand the code and what you're shipping.
I wouldn't be surprised if the meta person has a gun to their head to increasingly keep shipping like a maniac (how decade-long bugs remain unfixed don't ask me), so this advice may not be very useful.
Why not ask AI to explain it all line by line and write sequence, high level and low level docs? But I prefer not giving 100% control to AI
That's the neat part, you don't.
Or at least, I don't think people should.
To me this completely goes against the whole point of engineering.
IMO If you don't understand the code, then you're just a manager now. Soon your salary may also reflect as such, assuming you get to keep your job.
The same rules from 10-20 years ago:
have an architecture
Be consistent. All parts of the app should look like all other parts of the app.
Dont allow clever code
break things into modules
do true unit testing, meaning test the smallest unit of code possible.
Formal verification, pick a language that has it integrated and prove relevant post conditions.
AI still does not know how to even write code that makes impossible state unpresentable so testing won’t help.
It's simple: you don't. You slow down. It's essential to understand what you ship, before you ship, as there are real world consequences for not doing so, ranging from wasting the time and energy of yourself and others, up to failures which cause a great deal of harm to people and the world. To knowingly ship code you don't understand is grossly negligent, regardless of how common it becomes.
Flat-out, you _need_ to understand the code you're merging. If you don't, ownership then lands on whatever AI agent you're using. Ultimately, you can't fire the AI agent in the same way you can fire the person at the driver seat when shit hits the fan and they've consistently caused incidents that force people to work late hours to resolve it.
I agree with the sentiment but I would add more nuance; you have to pick what is important to understand and what you can delegate; not all code is mission-critical.
In any case at the end you're the owner/accountable so you need to justify your and your agent choices.
Maybe a related question:
How do you keep the IEC 62443-4-1 auditors happy?
This is how we end up with "regulations written in blood", btw.
That and "oh, it's just software for a website that doesn't do anything important that couldn't actually damage anything".
I don't. I understand it, and if there's anything I don't, I ask it about it and research until I do.
Just don't - simple as that.
>How are you handling this?
easy, don't write code with LLMs. If my job forced me to do so I would quit.
I have many questions. This seems shortsighted.
Short-sightedness is quite literally the reason people are using these systems to begin with. If you care about the health and integrity of your code base years down the road you wouldn't be shipping endless amounts of slop you don't understand, Fred Brooks taught us this half a century ago.
But it seems short-sighted to think that "years down the road" will look _anything_ like the present. I can't imagine a future (say, 5 years from now) where we are worried about the code choices we made in the past.
That's because you're still getting $8,000/month of compute for $200/month!
By taking responsibility of it, maybe by saying "Hey this is not a good idea", and if that doesn't work perhaps by switching jobs if that's an option?
The mental gymnastics developers are willing to go through just so they can avoid standing up for something is quite perplexing.
I went exactly through the same process. And that's why I developed agent-squad: https://github.com/gzurl/agent-squad
My conclusion was I had to elevate myself and make sure another agent reviews and tests the code (QA) under the supervision of a third agent (CTO) that defends my vision.
If you want psychosis to end sooner, just approve it so they realize speed is not the answer.
Literate programming like Knuth and flesh out every aspect of the design.
Product doesn’t care. And most of us will get replaced by agents. I guess around 30% of the engineering workforce will keep their jobs which will be mainly to keep the product up and running, doing whatever it takes (so using agents to fix stuff basically).
The ones who get to keep their jobs will be rebranded as Maintenance engineers with a lower salary. VPs and Heads of will keep their cozy job (bc there are not so many of them), and they are not that dumb to fire themselves.
Code understanding doesn’t matter anymore (or won’t matter soon)
I remember less than 1% of the code I ever wrote. AI hasn't changed anything for me.
I don't understand how my residence was built. I don't understand how my car was built. I don't understand how politics works. I barely even understand how humans work.
I am perfectly comfortable prompting AI and then seeing the end result and not questioning any of the code. I've looked at code for nearly 20 years or longer, I can't even keep track how long anymore. Started with QBasic and DOS scripts. I just always accepted it as an annoying necessity, and then the world changed two times. Once when they started paying us good of money for it.
A second time when programmers became an insufferable bunch. It wasn't about the art of the product anymore. It wasn't about working with the other parts of business to understand the customer's needs and building to that. It became this weird gatekeeping bullshit where we turned on each other and started asking people to reverse binary trees and implementing search on a white board after 2 weeks of interviewing. And then rejecting them because "culture fit". Add in all the other misogynistic racist stuff, and yeah, this industry is messed up and it's rotten from the inside.
Ever software is a "I don't know what those previous engineers were doing, it's poop, so we have to refactor and rebuild with this new tech", and repeat endlessly. And quite honestly, every piece of code (mine especially) is garbage.
So I think this is great. Programming was a means to an end. It became over glorified. Now it's dying. I'm here for it and I support it. Now anyone can build an application no matter how complex, and the only thing that really decides success from failure is the actual business around it.
I love using AI, but any feature it creates I test the hell out of it, i become the QA testers I hated and do all sort of ways to break the app, and after 100 or so hours, I have a bug free and fully working app, now will this app scale as I add more features that to be seen.
That is the problem. Because it's not a clearly abstracted and well designed system, it's not robust for adding features and changing things around. When you try to add something or move something around the big fragile ball of tests breaks and you have to spend forever re-piecing things together or burning heaps of tokens for little changes.
We just don't do that, I don't know why people talk like that is a given
Is it a company culture thing or a domain specific thing?
A major part of my job (and this was true before the "AI boom") is saying no.
No we can't call the CRM from our client side using a static bearer token even though their docs say we can. No we can't simply switch to Postgres even though it supports 99% of the same SQL we currently use. No we can't simply block usernames which are "clearly" profane.
But if we can chat about it, then we can see what the REAL problem is, and then we can come up with a fitting and simple solution.
The problem is that I have an AI colleague who is way more energetic and willing than I am. They love to talk, they seem to ramble on endlessly about any subject. And its the kind of solution oriented talk my PM loves to hear. And indeed my <insert senior role here> talks to them (or really, lets them talk), and draws up a comprehensive and confident plan to do X. I pick up the plan and discover problems with X, let alone the plan to do it.
I feel nervous about raising issues with X or going through the plan again though, because my other human colleagues are already speeding through the work for Y and Z that my AI colleague is aiding with.
And so maybe I'll raise my biggest concerns with X and not sweat the small stuff. Maybe next time I won't raise my neck at all, noting the gleaming axe sitting in the corner.
I don't know, I just consider quitting, but the money is still keeping me here.
I only ship code I don't understand if it comes with a proof of correctness
I'd quit. and I did, even before getting my first job that was not an acquaintance's startup, not counting this summer. in fact, I got fired this summer for having called Claude Code "a decent search engine" afther the first two weeks. I fell in love with making code run fast on poor hardware back when I was 8, and now there is a high likelihood that I'll end up a truck driver.
my only response to those who remain and try to control the slop is
and really, you should have an Imperium/Mechanicus-level devotion (whether it's to money or to AI itself) to survive this and not burn out. in my region, though, you are not getting money - salaries were slashed in half across the board over last two years.
https://t.me/djinni_official/2163 (go in with translator; infographics are in English but explanations are not)
at this point, for a junior, it's easier to find a well-paying blue-collar job than to get into tech, and the ceiling is falling at the speed of sound.
I spend time to add extra observability, cross-checking and alerting at runtime to offset the risk.
if you have to maintain it, you will still have to get an understanding of it when it breaks.
not understanding the detail is quite similar to a coworker writing the code and another coworker approving and merging the changes.
If your plan is to have AI maintain it, you really don't. Honestly I hate being forced into this position. I want to understand it.
An engineer from Meta not knowing what they're doing is exactly how I imagined engineers at Meta. Thank you for confirming it's an actual reality.
On the other hand, not even surprised anymore most people even try to provide serious answers to this. Welcome to the pure insanity.
Say amen and hit push!
Wait WHAT! I am struggling to review the deluge of AI-written code (I assume like everyone else) but I never ever considered shipping something I didn't understand? I sometimes need the AI to walk me though it a bit; and I am not saying it couldn't smuggle though obfuscated code; but I at least an understanding of its apparent function.
Not sure if your engineering quality culture has gone backwards or not, but I would never ship code I do not understand, no matter who or what wrote it.
That is the road to hell. Even if your higher ups think it isn't, this strategy will for sure blow up in their faces soon.
I predict that Meta is soon going to be going on a hiring spree to fix all of the issues this strategy is going to create.
I'm building a high level code explorer, like the CASE systems of a long time ago I suppose. I also built a facility called zork that lets me and an agent explore the code system together like a dungeon, taking notes as I go and if you want to take the metaphor too far, 'invoking spells' or rather commands like code references, call flow, data flow, exception flow, profiling, labelling design patterns and validating implementation, etc.
With zork I can also just start typing in a code file and leave instructions for the agent to fill in or fix parts of the code while I'm editing it. So I can lay out what I want the class shape to be and don't have to implement all the annoying little parts. This feels more like the GitHub Copilot days.
I honestly believe more of us will pair program with agents, not just yelling at a chat window.
The car vendor does sell you cars he doesn't understand. You drive a car you don't understand.
At least someone in the chain has to take over the responsibility in respect to litigations. That one has an interest to understand the inner workings of AI generated artefacts.
The only answer is to not ship code you don't understand. And I think the easiest way to do that is not use AI for ANYTHING except troubleshooting and doc searching. Those that draw a land in the sand and develop this way will be slower in the short term but their work will last out in the long term because it will be more solid.
It feels like another layer of "conceptual compression". I'm not sure who/when that phrase came around but in context of Rails is where I heard it and its things like ActiveRecord or really any ORM. You aren't writing the SQL directly, something else is and for the most part it works. Then it doesn't work or your database grows too much and you need to optimize table structures with indexes, etc.
My point is if you don't understand the fundamentals of the underlying code (SQL in the example above), you're more likely to have issues in the future. Or maybe not if that app doesn't reach a usage pattern or complexity where the nuances under the hood matter.
It really depends on what you're shipping. Meta ships social media apps where in the grand scheme of things if something is broken software wise it largely doesn't matter. What's the worst case? lost ad revenue? Users can't do things? If that were software for MRI machines or aerospace where software issues/bugs can result in lives lost then it matters much more in understanding what is going on at all levels of the software and potentially hardware.
At the end of the day it's really about developing a feel for it:
You will know intuitively if it's worth taking a closer look or if u can safely close your eyes and just commit it right away.
I usually know which meta questions are crucial to clarify with colleagues and where to check the code punctually.
If you never LGTM’d when a colleague dropped a hefty PR on your lap, why would you do the same if it were a robot
I like starting with defining outcomes, determining invariants, and then consider TLA+ or Lean models, or both. It's generally not good to ship stuff you don't understand, but if you work on big legacy code bases from 20-30 years ago, there's probably no one who understands all the code all the time.
It's at least nice to be able to prove something about the code, rather than blasting it with tests which only prove that the tests that are written do not fail (and perhaps get you some amount of code coverage — necessary but insufficient for anything like quality).
How to do all of that in your environment? That can vary greatly!
The conclusion I came to is we are going to move from a hard science where everything is known, to being more like social science where everything is a guess based on confidence intervals. It's what happens when no one human mind knows the system well enough to predict what any small change will have on the rest of it. We call such computer systems "balls of mud". [0] says most deployed computer systems are balls of mud, so it's not the end of the world.
All vibe coded systems are balls of mud by definition if you use the conventional definition. If you allow "understandable by an AI" then right now not much changes because AI aren't so hot at designing systems and even if they could, they make poor use of their limited context. Whether that changes in future is the big unknown.
We already know how balls of mud evolve. New features are "bolted on the side", making the system more inscrutable. These bolted on systems often grow interdependencies on each other, creating a spaghetti of relationships no one is aware of. This means every change could introduce a bug whose blast radius is the entire system. Changes get harder and harder. A death of sorts, or at least a growth limit is reached when on average every bug fixes introduces more bugs than it fixed.
Google Chrome is a fine example of this happening right now. It used to be a highly modular combination of mostly independent systems that had their own champion who understood them intimately. They left, Google management insisted the client platform that supports most of eco-system continued to evolve and grow. The ball of mud was formed. It's been evident for years chrome has a higher bug injection rate than Firefox. As complexity grew it became too hard to move to new tool versions, so compilers and libraries got pinned to known working version. That made it too hard to use as a component, so projects like ChromeOS are being replaced with Aluminium OS. Now the that Matt Jolly has thrown in the towel [1] it's hard to see how distributions like Gentoo and Debian that used his work can continue to ship chromium. Debian can use ungoogled chromium, but vendored libraries, obsolete tool chains, inability to do forky mandated reproducible builds make it look like it's a foreign object bolted into a true open source project. This is what software death looks like. It's not a bang, projects cease to evolve, then can't meet new requirements, and then are replaced.
It doesn't have to be that way. Projects like the open source kernels are decades old, but their strong stewardship has ensured they remained decomposable, so people can work independently on different sections without too much fear of stomping on each other's toes. Open source stewardship seems particularly good at this, possibly because open source projects can take a very long term view. A manager in a large organisation on the other hand is usually around for only a few years. They take the short term wins that come from features bolted on the side safe in the knowledge the long term death of the software will be somebody else's problem.
[0] https://www.researchgate.net/profile/Brian-Foote-2/publicati...
[1] https://lwn.net/Articles/1097760/
the guidance / guardrails, agent roles, etc are the critical thing now, it's kind of like meta programming AI to get the outcomes you want. Any problems need addressing at this level. You don't need to understand all the code, but you should understand how the system is building up and adjust as needed. This would be an architectural review process you go through with AI. Features to code that should plug into existing architectural structures are generally no problem. It's just boilerplate code AI is generating. But architecture is only one aspect, you should have lots of guidance for all kinds of thing. There's security, performance, correctness, QA, Ux, Deployment, Process, Monitoring etc and having feedback systems for everything. You keep refining and reviewing your guidance and the impact it is having. As well as this you are molding the product for the things you want via feature development. What I'm not sure of is if you are some cog somewhere in a company like Meta whether whatever slice you become responsible for becomes a bit meh if you are mostly just prompting a feature and not much more. As a developer in a smaller company (we are global with a smallish tech team) I get to do a lot of things from interacting with our customers through to the entire backend and get to make critical decisions about nearly everything. Nearly everything in the company is starting to be driven via guidance and feedback loops (including on the guidance itself).
The secret is to stop caring.
If you are a senior engineer then there is no need for you to be shipping code that you don't understand. People can definitely generate code a lot faster than before, but you also have a magic genie that can help you critique and improve the code that you're reviewing, including when that code was written by agents.
An experienced senior engineer with access to a coding agent is the most powerful code-understanding system that has ever existed. There's no excuse for shipping or approving anything you don't fully grok.
Time. The limit is time. With or without agents there’s an X number of lines of code my brain can digest per work day. But rate of production of code is effectively unlimited or heavily influenced by people who let go of at least some percentage of understanding. This forces the rest of the team to also let go to keep up. Without guardrails around the rate of code production, _teams_ tend toward 0% code understanding. Individuals working on solo projects or in tiny teams that can enforce social contracts are not affected.
Don't.
This is why I (QA eng) became the most important guy at my job. My tests are the glue that keeps the AI slop working together. If not for the comprehensive testing framework that I have running in every CI the company would have collapsed by now.
Don't.
By doing so, you debase your own profession.
You are accountable.
You're going to have to understand it one way or another, either at writing or at debugging. Even if you delegate all debugging to AI, you'll still need to determine what is "right".
If you don't understand the code at writing or debugging, you'll pay the architectural price (where it degrades). That price may be worth paying, but that depends on the system you are building.
I will get downvoted for this comment on this forum but I will call it out.
You wont be able to review or understand code for much longer.
There will be just too much of it. The vastness of code libraries in 5 years are hard to imagine by today's standards.
We need to develop tools that help us understand.
If you take a step back here, there has always been a group of people who have "shipped code to production" — in the sense of being responsible for the software that was produced -- without ever reading it or knowing it in detail. I am talking about your engineering management. Maybe not your line manager but certainly your director.
I think a useful perspective is "How does engineering management control software quality?" You will know the answers to this question: testing practices, design documents, SLAs, release management. You will know this because you almost certainly have to comply with some of these as a SWE. All of those practices exist because code produced by humans is not perfectly reliable and thus there need to be checks and risk reduction steps to manage the software that is shipped.
The way I view agents is that all of us have become engineering managers now. So those tools are now your tools. You set up the practices and frameworks and make the agents use them. If you set them up right you can be very confident in what the agents wrote without ever reading it.
Now you're not going to go from nothing to "Hey I ship code I've never read" overnight. It takes work. You have to set up your project carefully so that the agents can’t make mistakes. But all you have to do is be systematic about it. Every time the agents do something stupid or they ship a bug, you think, "How do I put something in place to prevent this entire class of bugs from happening again?" As you iterate this process, you will continuously be ruling out entire classes of bugs and eventually you'll be able to trust the agents.
Example: I had a bug, or a class of bugs, where agents would write a database migration and it would be wrong. It would get rolled out and the database would be broken. I fixed this by putting in a migration testing framework where there was data written in an old schema, then the migrations would run on that data. Then you could write tests on the expected result at any point after any migrations. Then, I put in place a rule: if you write a database migration you have to write a migration test. That fixed the problem. I have never had a migration failure since.
So this is not some magical process. It's going to take you hard work to set up your system with all of this infrastructure to make the agents maximally productive. But as you iteratively improve your system, you can reach a place where you can have agents ship code without reading it. It's not just about making the system work but it's also about building your trust in the system that you have. I routinely ship code without reading it now and I think I've shipped about two bugs in the past two months (and I’ve written ~500k LOC in that time). And one of those bugs was very explicitly my fault for telling the agents they could violate one of the frameworks in place (oops).
I don't.
A lot of comments here saying “don’t do it.” I think that’s shortsighted. The speed gains from LLMs are massive, and the code they produce (Opus 5.5 at least, in my experience) is correct most of the time. Once a developer or a company realizes that, there’s no going back. There are two problems, however:
1. If you keep shipping AI-written code you don’t understand, you become entirely dependent on the AI to maintain it, because you lack the mental model you’d need to jump into it quickly.
2. You can afford to do this as a senior, because you can tell when the AI does something suboptimal. But how is a junior supposed to develop that intuition when all they start out with is AI-generated code?
Drink and pray.
I just don't do it. If I'm paid to be responsible for the code, which I am, then I've got to understand it all. I'm gradually developing an instinct for when it would be good to outsource something and when it would be better to think it through and do it slowly and consciously. We all need to learn to do this.
This week I've actually learnt something at work. This is what feels good. Building yourself. There's no long term joy in building things you don't understand, especially if you're building them for someone else.
Peter Naur in 1985 wrote that programming is the act of building a working theory of the system in our minds, and this often takes form as tacit knowledge in the head of programmers. Even if you handed the complete codebase and perfect documentation to a completely new team, they would often need to go back to the old team and ask questions.
And before agents, we often built this working theory of the system by writing the code by hand. It helps us figure out the "grain" of the codebase so we have a better idea of how to extend it.
So what happens when agents are writing the code? The main avenue with which we built the working theory of the system in our mind is now taken away, and we're left feeling like our understanding of the system is blinded.
I ended up more or less changing my entire workflow. Four main principles:
1. Interrogation/interview-based design and specification
2. Make the decisions that matter and leave the rest to the agent.
3. Use agent to generate explainers, quizzes, and simulations.
4. Use verifiers and guardrails in the coding loop.
Interview-based design and spec
When I tell the agent what I want to build or extend, there's naturally ambiguity. But the agent knows what is ambiguous to it, so it can ask me. /grill-me is one way to do this. You'd think this would be commonplace now, but it's actually not. Some people are still wondering why they're getting bad results. It's because they're not resolving the ambiguity.
Making the decisions that matter
Not every decision matters in a product. Agents are fast at writing code and pretty good at some of the nitty gritty details, so I let it make those decisions. Also, if a particular subsystem is commonplace and undifferentiating, such as login, then I also let it make architectural decisions for that subsystem.
For decisions that are product differentiators, where that differentiation is supported by technology, I make decisions on the stack, the architecture, and the approach. This is the design phase. Because agents tend to make the mainstream decisions, they almost always take a midwit approach which doesn't leverage the technology in a way that makes a difference for the customer.
Some try to build this understanding from code reviews. I personally don't think it's the way to go, because it's not motivating. I find that I'm more motivated to learn how the system works today, because I want to change how it works tomorrow--and it sticks in my head better too (no different than pre-agents).
Generating explainers, quizzes, and simulations
As I'm doing design for an improvement and I don't know how a part of the system works, I can ask questions of the agent in chat. If I still don't get it, I can ask for diagrams (either ASCII or mermaid). But if it's an entire subsystem, I have a skill in which I can ask for visual and interactive explainers. It'll generate a markdown page (or html) that has these interactive components that help demonstrate a concept.
To help make the concept stick, there are quizzes after each section and at the end.
With the computational simulations, I generate a throwaway tool in which I can explore the state space. This doesn't happen as often, as I try to keep state spaces small, and for those explainers tend to work well.
With the design simulations, a same-model agent and a cross-model agent and I will talk about an explainer, and we'll name things that we understand or notice about the design and the intended direction we want to extend it. Then, we'll use subagents to generate options and then discuss the pros and cons. I find this is a good way for me to understand the dead-ends of a design.
Using Verifiers and Guardrails
I define guardrails as mechanistic checks that doesn't change with the feature. such as linters, typecheckers, and pre-commit hooks are all guardrails. Verifiers are mechanistic checks that will be different with each feature, such as unit/integration tests.
For more complicated states or concurrent parts, I'll ask the agent to use formal methods to write a proof. Then use the proof to generate a trace (a series of steps that demonstrate a happy or unhappy path). Then I run that trace in unit tests (kinda like property-based testing--so I guess this can be called trace-based testing), and the code has to adhere to the trace.
I also wrote a design verifier, where the requirements in the spec can be converted into a series of mechanically checkable rules. Then during testing, the verifier fires up the headless browser and uses the DOM measurements of the page to see if it matches up to the rules. This was completely impractical before agents.
All of this so a) I can be sure that the agent is doing what it's supposed to with the decisions that it's making b) I can be out of the coding loop, so that I'm not up at 2am begging, "you fixed this, but you broke that. pls fix." The agent can check for itself.
---
If any of this sounds helpful, lemme know. I've been wondering if other engineers care about understanding the code that's being written, or if people just don't care anymore. I've spoken to a few, and it seems to be split. And it may just be a matter of degree and detail. Some like it at a higher level. Some like it nitty gritty.
I agree in that code is a byproduct of the tacit understanding which arises circularly when you write the code.
But if you're trying to gain the same level of tacit understanding by writing quizzes and simulations, are you actually gaining anything from using a LLM? Isn't it just better, faster and quicker to write the code yourself? Not to mention more enjoyable?
Why not just force the llm to be much more concise and require that every line is worth its code. LoC is a inability after all.
> it all feels like a black box.
I have some work in Lean4 that I'm certainly unqualified to validate; Layer Coding QEC derivation, Positive Grassmanians and the Fresnel-Kerchhoff correction to the Parallel-Axis theorem, Huygens intensity as an alternate model for simulating photonic and electronic interference in a double slit experiment, for example.
It was a black box but I'm letting it tutor me about it so
Visual proofs, Tools for logic and formal methods in distributed systems
Things that compile logic!
> That means you can end up with systems you've built where you don't truly understand how all the code works
Though AI coding and system development can be overwhelming due to information overload and rapid growth in complexity (and concern for unwittingly embedded mistakes, the unsecurability of agent-based development, and number of LOC of code per day), not understanding the whole system sufficiently is normal and expected in engineering.
I deal with it by not doing it.
You just stop caring. Everyone else did about three months ago. Time to find something new to care about.
The only people who stopped caring are the people bad at their jobs. Most of us actually still care and put the effort in.
If it's important code (and much isn't), then I spend a lot of time using Matt Pocock's /grilling first, and then I get the agent to kick off peer-review with other agents, and surface any disagreements. Some models are better at it than others. This usually forces me to broadly understand the architecture, and I spend most of my time answering the design questions for which there isn't an obvious solution. I have been pretty happy with the code I've launched to production, as measured by the ways it breaks, and by how agents who weren't part of the original committee describe it.
This is the state that founders and decision makers are usually in at a startup. Sure, sometimes you have the coder founder who wrote the first iteration of the product, but many times the founders have no clue how the product works under the hood. They entrust that to the engineers. That was then. Now, much of that engineering layer has been removed, so the founder just needs a smaller team of people who understand how to structure the software and interact with the LLM. LLMs do the rest.
The problem here is that you're trying to do a job that is already being done for you. Maybe you don't yet trust it to do a good job, but that is quickly changing.
Anyone who trusts the output of LLMs uncritically, even after the impressive level models and harnesses have gotten to, is borrowing against their future.
Models and harnesses have gotten really good, but they still are hard-capped by the operators that use them. The sycophancy of models is perhaps their greatest weakness, as when a user who might be experienced in one area attempts to use AI to build within an area they are less familiar with, the model does not take a step back and examine the "why" of what is being built from an architectural standpoint, it simply performs the expected task in a direct manner, ultimately creating sloppy work that may be easy to ship but difficult to maintain.
A good example of this was a recent interaction I had with a Dev who was very familiar with how to develop embedded and system level applications. He and every other dev are being asked for increasingly more due to AI, and he had to bring something he had built as a single-user desktop application into a distributed cloud environment. He ended up rsyncing a copy of his working directories including multiple credentials and sensitive internal project documents to a virtual machine binding it to a public ip address. Thankfully our tooling detected this before he could get any farther but it illustrates how the AI model isn't doing any real thinking or engineering at the end of the day. Unless the operator knew to instruct the model about proper cloud architecture and understood best practices around deployment of public systems, the model simply did what it was being told to do by a user who didn't know any better.
Another example of this is the sheer amount of unsophisticated users we've been detecting using Javascript injection into their web browser sessions as a form of automation for web services they may use. These users would never know to ask how to request an API token which may allow them to accomplish things in a much easier and approved way, and instead are relying on the frailest possible automations that expose them to risks of credential exposure.
We've got to be careful with how we engineer things with AI models. Just because we've made boilerplate easier to generate doesn't mean that we can avoid the actual engineering of what we do. And I can't help but think that firms which are fully committed to AI code generation, won't just be introducing an avalanche of slop into their product which will explode the costs of maintenance over time.
When you code, do you understand the asm code being built? What are the cache line access patterns? Most software developers have already given up the details of how things work, and lean on tools to handle them.
Which is fine, usually. Depends on what you are doing.
The things that always mattered were the core system, the trunk of a tree if you will. The branches less so, and the leaves not at all (though that is what people see and appreciate! The irony!).
Now the question becomes what happens when those LLM become very good at abstraction?
How do you deal with code other people wrote you don’t understand?
Same method.
if i was working for meta i would be more concerned about my culpability in undermining american democracy.
If you don't understand it, then you haven't built it.
Do not
It's Meta. Shipping crap is par for the course. You're fine.
This was something I personally struggled with for a very long time, so much that we ended up abandoning the product we were working on to build a solution:
https://theseus.dev
Basically, Theseus reads your pull request and your codebase, categorizes the kinds of edits that were made, and writes human-readable documentation that describes what changed. Then, it shows the explanation side-by-side with the code, but presented in a way where you can decide what you want to skim and what you want to deeply review.
I don't think engineers should have to choose between wading through thousands of lines of slop and just smashing LGTM on every pull request. The problem is that the tools for code review are built for an age where code was expensive to write. Now that code is cheap, we need to start experimenting with tools that allow us to stay in sync with what's going on, while also not needing to review every single line individually.
no one can force you, take responsibility for what you ship, what you choose to ship, how you choose to work, you signed that contract you go to work every day, your company is composed by people like you
don’t wash your hands, or at least don’t expect us to wash them for you
Replace "AI agents" with "a bunch of human coders" and you'll see the answer. Your product needs decent testing and it's your job as the responsible person in charge to make sure that's in place and working properly. So if anything you probably want to be reviewing the test code. But often that isn't necessary since you can do things like introduce bugs deliberately and see if tests fail; check test logs for information that confirms the tests were run as expected; try some manual testing once in a while; ask for new more advanced tests (e.g. test performance not just functionality); and so on.
> How to deal with shipping AI-written code you don't understand?
Recognise you aren't the one shipping it.
The part that makes me uneasy is when the AI writes both the code and the tests. They might agree with each other and still miss the same thing. How are people here checking for that without doing the whole job twice?
Not sure about that. This was structurally the same before AI: the author of the code wrote the tests. The tests still helped.
The author of the code was physically touching the internals and potentially intuiting obvious shortcomings as they worked on it. That very crucial part is now gone.
I like fault injection (fuzzing, chaos), and mutation testing. I think introducing these helps the AI write better tests and helps having some confidence in the tests that are written.
You should be using two (or even three) different LLMs. For example: Claude to do the coding, and Codex to do an adversarial review. This can go back and forth for several iterations before converging on an acceptably "correct" version of the code...
Occasionally, Claude may not be able to fix the issue – and it may turn out that Codex can, because it has a different approach.
Either way, at least two LLMs is the only way to get (mostly) reliable code.
Claude, ChatGPT, Google Gemini, then Replit...
You can automate this entire orchestration with zeroshot.sh, mentioning it since it is relevant here.
We split them. The agent writing the code never writes the checks it's judged by, and those separate checks caught way more than its own tests did.
Yes, this is exactly the problem that used to worry me. Most of my current repo is written by Claude, and I need to have a method to tests the tests.
I've started using Stryker. We have a CI job that mutates the code before running the tests. In the first run, it has returned hundreds of code changes confirming that the tests are biased. I haven't yet fixed those issues, but for now i am banking on this approach.
> I'm writing code these days and it all feels like a black box.
When you write C++ or Rust do you try to understand the generated assembly code?
Any software engineer shipping A.I. code should stop calling himself an "engineer."
Imagine the carnage if real engineers started vibe-designing bridges.
I disagree here. Software engineering is a very different form of engineering than something like building a bridge. This has always been true. Even before LLMs, there was a lot of hobbled together code going out there from "real engineers."
I think it's silly to make strong statements like this. _Most_ professional software engineers (women too, not just him!) are using LLMs and are moving some amount of faster as a result.
This is OT and a cheap shot, but if I were an engineer at Meta I would have felt pretty uncomfortable well before AI showed up...
The people doing this work as a career and not performative art, who were already good at their job, had no worries about this to begin with.
The code was always a black box. Always.
Specs come in, passing tests come out. If you find an issue, your specs were shit.
Anyone that has ever had to outsource work to someone else knows this. If you've ever worked with another team whose codebase you didn't touch - you know this.
You write your specs, you launch an agent to implement them. You launch a 2nd agent to keep the first one honest. When done, you launch as many agents as you have budget to try and poke holes in the implementation. As it always was the case.
You can thrash around (and you will), you can fight it (and you will). Like it or not, the genie is out of the box, and the realization you were never really good at your job to begin with is gonna set in eventually.
We're going to get downvoted to hell for saying stuff like this. It's like the group of people who went around telling everyone else that they were awesome and godlike and irreplaceable are now offended. I comment every now and then about the end of programming, and different ways get different reactions. If I say programming is dead, its downvote. If I say I replaced a bunch of SaaS with AI produced replacements, it's upvoted. Surprise! I don't care about programming and I don't look at the code in the successful replacements either.
> You can thrash around (and you will), you can fight it (and you will). Like it or not, the genie is out of the box, and the realization you were never really good at your job to begin with is gonna set in eventually.
I was with you until this sentence. You know you can have an opinion without having to put anyone down?
In a thread where people are feeling existential dread, it’s imperative to get sober.
Okay little man, whatever lets you sleep at night.
100% agree with you. Don't understand the downvotes
See last line in my comment. They're fighting it. They're thrashing around.