ZH version is available. Content is displayed in original English for accuracy.
Advertisement
Advertisement
⚡ Community Insights
Discussion Sentiment
68% Positive
Analyzed from 6186 words in the discussion.
Trending Topics
#code#more#comments#review#write#claude#don#llms#things#still

Discussion (144 Comments)Read Original on HackerNews
Mine starts with “Enter plan mode. Examine the differences on this branch vs. main. Consider: ...” and proceeds to a bullet list of things.
Any time I notice something in code review and have to get the agent to fix it.. I throw it on the list!
My list is like 200 items now. Know what? Agents don’t care that they just got a wall of generic feedback, they happily look into all the bullet points.
I added “ensure the new things aren’t duplicating code that already exists elsewhere” and it gave me such a surprise - it really truly started planning cleanups!
We are just scratching the surface. We have to give tools to our tools so they can use them to be better tools for us.
This is a gripe I've had with AI tools for a while now. Though it's gotten somewhat better in time, but we don't really know what to expect from the tool in terms of quality. Ex. I'd expect a human engineer to probably not use a brand new assertion library for a new test when there are 200 tests using an existing one. But Claude has done this to me multiple times. So I have to add yet another item to the list, like you have, and tell it to look for testing conventions before writing. But, there is plenty we don't have to tell it, like what a function is or a test should probably cover the change in the diff. But we don't really have a list of what things are on each side so we're just left to sort of hunt and peck to build a viable solution.
I am curious what does it contain, for me a lot of times its a back and forth with agent until it "looks good to my eyes and taste", but haven't written any such list yet, because it is context dependant, in some projects I forgive minor issues, or allow magical numbers, but in other projects I force agent to use constants with meaningful names `SECONDS_IN_A_DAY = 24 * 60 * 60`
https://en.wikipedia.org/wiki/Code_smell
*edit: that wikipedia page ^ itself is a pretty answer to your request for a list of things to avoid when writing maintainable code.
* https://github.com/alibaba/open-code-review
** https://layandreas.github.io/personal-blog/posts/beyond-vide...
Good way to double your token use though, if you’re concerned about that.
Will try your approach to distill the code to bullet points.
One thing I usually keep having to point out directly is to remove all “progress tracking” code comments and make sure all comments are appropriate for long term maintenance in the code base. Claude tends to leave comments like “button click causes save now, no longer uses onBlur” when the code really never used onBlur, that was just a thing Claude wanted to do earlier in the same task/branch and I redirected it at some point.
I haven't used them so far but maybe these would work better than basic instructions for such cases.
The models will interpret this willynilly; but nonetheless, it's often a better than doing nothing.
The reason prompting it to review its own work for loose ends, record any new undocumented or noteworthy behavior, suggest changes to tests/processes to make it go more smoothly the next time, etc is that it’s prescriptive and process-oriented (and thus easily verifiable/done in-context) rather than descriptive and outcome oriented (which to do properly could require way more context than the model has, because it doesn’t know what it doesn’t know about your particular work, only what it’s seen so far).
Even promoting it to do these after-the-fact vs as an upfront requirement can have a big impact IMO. If you make “maintainability” part of the task before it’s seen the real work it will focus on general “best practices” crap rather than the real work, so either way if this is something you care about it doing you have to give it guidance for how you want it done.
If you were to review the logs of a model after the fact, you’d also not really save on input tokens unless you compressed the context or sharded it out, which can easily miss the small details that constitute the difference between “what actually happened” vs “how the LLM models this general class of problems” unless the first pass involves the entire context anyway. That said I do think there’s a lot of value in building some kind of pipeline for validating and aggregating these “learnings” across sessions.
I am following similar steps from this article https://www.lucasfcosta.com/blog/backpressure-is-all-you-nee...
disagree, then you end up with something this this
function checkAll(target, conditions) { return Object.entries(conditions).every(([path, expected]) => { const value = path.split('.').reduce((o, k) => o?.[k], target); return typeof expected === 'function' ? expected(value, target) : value === expected; }); }
and const ok = checkAll({ user, account }, { 'user.isActive': true, 'user.isSuspended': false, 'account.status': 'open', 'user': u => u.hasPermission('read'), // predicate for the trickier bit });
how is that better?
"Add comments to your code under the assumption that the next person to maintain it is a homicidal maniac who knows where you live"
I recently reacted angrily in a PR review comment after encountering one for the umpteenth time... that caught me off guard. I didn't know I was capable of that.
> Only write comments to explain the why when it is not obvious from the code (rationale, gotchas, constraints). Do not comment on the what — well-named code already says it. Do not comment on how a framework works.
It still keeps adding these bad comments. When I then ask it to review the comments based on my preferences it then deletes most of them or improves them.
Today I asked Claude why it disrespects my preference and it said that the surrounding code was like that and it followed that style. It suggested I add this line to my global CLAUDE.md file:
> The comment rule above beats the style of the surrounding code: neighboring files with what-style comments are not license to write more of them, and comments carried along when porting or copying code must be re-judged against the rule, not kept for consistency.
Let's see if that improves things.
Maybe these would work better for such cases.
so that can be useful information in some situations.
On the other hand, what a horrible out of date mess of comment that can turn out to be a little bit later. Taken as gospel by the next entity (human or llm) to massage that function.
Normally when I can't get claude to follow a prompt I try a lint hook, but it's tough to lint something that subjective.
Years ago I would often write comments first. I.e. start with describing the overall goals. Then break it down into routines and order of operations, all still in plain english. Once I was happy with that, I'd break up the comments with blocks of code. I guess this is sort of like "literate programming" though I was doing it long before I ever heard that term and I still have never read much about it. It's almost more like I was prompting myself towards the end goal. The downside of this approach is that the comments do end up more or less just explaining in english what the code is doing, so maybe aren't quite as useful to future maintainers.
The big problem is folks misunderstood it as documentation (arguably plain.tex should have also been the sourcecode for _The TeXbook_ and that it wasn't is a big part of this) --- it could be, but usually that's better as a separate text/chapter....
I've been trying to collect books on Literate Program/notable Literate Programs published as books:
https://www.goodreads.com/review/list/21394355-william-adams...
and I will note that my own programming took a quantum leap forward when I purchased and read:
https://www.goodreads.com/book/show/39996759-a-philosophy-of...
and applied its principles one chapter at a time to a project which I was able (w/ a bit of help) to get into Literate Programming form:
https://github.com/WillAdams/gcodepreview/blob/main/literati...
I've also seen a lot of comments that restate what the code already says and that's just noise, more work to keep in sync, an additional thing that can fail, and more cognitive load because you have to read twice the same thing (best case, if code and comment are still in sync). That's the result you risk when you think you must comment your code.
I appreciate the occasional comment that explains why something seems overly tricky or weird or not immediately intuitive. Once, I had left such a comment that saved myself years later from making a mistake. Of course, this should be kept at a minimal level. It leads to me liking clear code with few comments the most. (Some guidelines, even if it's not perfect, to limit complexity and spaghetti code help a lot).
Function, class, module documentation is also useful so you don't have to read the whole thing and you know what it's intended to provide (which is slightly different than simply what it provides, and this differences is important).
Or is it more about the review process and a context reset?
1. Created a "coding" skill with every practice I posted on my blog website, as well as a bunch I had in the queue to blog about but never got a chance, summarized into "do this" kind of language. This is more or less good for any PL, but a bit Ruby-slanted.
2. Created a "rails" skill because that's my framework, where similarly I explained my approach to architecting Rails apps.
3. Created a "writing" skill where I literally fed it my entire blog, and tried to get it to write more like me (mixed success, weaker models did better for some reason, but I haven't tried the GPT-5.6 series yet).
4. Next, I really wanted it to format code exactly like I would, even things like "let's make this `if` into a ternary, let's split these assignment groups with a line break, let's vertically align here, but not there", but with GPT-5.5 (my primary driver up until yesterday) there's almost no way to make a skill of reasonable size that will be consistently applied. So instead I instructed the agent to write me a Rubocop cop for every single situation I ever encounter where I would've formatted code slightly differently. This was quite powerful, because I usually thought of linters as enforcers of objective consistency decisions in the codebase, but this was me going full format nazi on the agent. And the nice part is that these cops can contain some non-autocorrectable feedback, which AI will follow.
5. I'm working on a review loop where the most easily missed parts above get double checked. This is the first thing I'm doing with pi subagents. (I feel like I'm getting better results if I don't use subagents for code exploration, other tool calls). The idea here is that I want reviews to be in the implementation loop. I always read/review code in the end, but so want it to have gone through the review loop before it gets to me. Since implementation is already context-heavy, I want to be able to orchestrate this loop without adding to the implementation context.
6. I'm also adjusting all of the above for GPT-5.6, because it requires less guidance, so I'm carefully trimming the verbiage to save tokens.
So far the results have been surprisingly good. I want to experiment with GLM-5.2 running under these constraints.
One invariant in all of this: I read the code. My end product is not working software, it's good code (which also incidentally produces working software).
The standards most "good developer" humans demand were learned from many decades of painful experience about what happens when you do it the other way. These are not only compromises for human convenience, they often are things that we have learned will come back to bite you later even though they just add more work today for no gain.
Another thing is competitive edge, if you use claude and your competitors use claude then nothing really gives you an edge. AI is a commodity, not competitive edge.
The competitive pressure should drive human work because it's unique.
In that case, humans with superior skills who can write code become the advantage.
That is important for companies that compete with each other.
I started using AI with the best intentions. Checking everything before committing. Improving output by hand if it didn't quite follow the existing code style guidelines or variables were not named as well as they should be. Or if it did something sloppy or hacky.
Now, AI GOES BURRRRRRRRRRRR! If the tests pass it's good to ship. AI can deal with the problems it may create. No problems so far.
To make up some hypothetical numbers in order to illustrate with math: if you ship bugfixes 10x faster but then have 11x more bugs you need to fix, that's not a net improvement. Even if it's only 5x more bugs, maybe you could reduce that to 2x if you changed how you worked to only be 8x as fast in a way that produced higher quality code. Similarly, maybe you could cut the time it needed to produce a new feature by 50% if your code were higher quality by moving 20% slower.
My point in all of this isn't that you literally need to work the same way you did before you had these tools, but that framing it as either "move fast and ignore the code" and "use the same exact heuristics you would in the pre-LLM days for what code is acceptable" is a false dichotomy. If you aren't thinking about how effectively you're using these tools and whether there are changes you could make to move even faster because "AI go brrr", I think you've lost the plot in the same way you probably think that other people in this thread have.
Manual edits literally aren’t possible. You can’t grok the code growth and the new patterns fast enough to be productive.
This does work. I’ve seen it in real products. Nobody has a real mental model of the code flows. But with enough money in Claude credits it doesn’t matter.
The spend to support this development model is something like $50/day/developer.
This work great until you reach a certain size, then good (or even "not bad") code is required otherwise the model spins its wheel trying to ensure the change is correct.
The way I've measured how good/bad the code is (for AI) is to have one "baseline fixed change" that I measure how long time it takes to implement. Always in the beginning (less than 10K LOC, as just some measurement), this baseline change will take 2-3 minutes. As you add more code, the same change starts to take 5-6 minutes, and once you hit 1 million LOC, it can take as long as 10 minutes, even though the change is the same.
It's when this baseline task starts to take longer time, that you need to update the design/architecture/layout/whatever, to better fit the task/domain, and to actually make it easy to maintain and still possible to add changes without spending 10 minutes. So its at this point you refactor, and once done, the baseline task will again be easy for the model to do.
So yeah, if all you do is smaller projects, then "shipping 10x as many features" is easy and doable, for the lifetime of the projects. But once the projects start to accumulate technical debt, the model will have a harder time making sure the changes are correct, and suddenly "shipping 2x as many features" is maybe doable, but you could still have had 10x if you just spend slightly more time on the actual design and architecture of the program.
The solution, as you say, is probably to break it down into isolated sub-components that are only aware of each other's APIs and nothing more.
I understand you're excited about the tool, but for the sake of earnest discussion here, maybe commenters like yourself can tone the hype down to plausibility?
Claims like this are just nonsense. It's not how product development works.
How do you even have so many bugs left to fix if the tool is so fast and productive? Surely, you didn't have a backlog of tens of thousands of bugs that you're still chewing through? And of course, the volume of new bugs much be minimal since the AI-composed additions introduce "no problems so far". If it works like you say, which we'll accept in good faith per HN guidelines, you must have exhausted your backlog long ago.
And if you've indeed exhausted your bug backlog long ago (incredible!), you're left to talking about shipping "10x as many features". Yet no product has a limitless capacity for features. Nobody would want to use software so bloated and churning that was gaining features at such a pace. And who is designing and specifying them so quickly anyway? If it works like you say, which we again accept in good faith, you must have stalled out on your feature list long ago.
If the AI indeed allows you to "[ship] 10x as many features and bugfixes", and we take what you say in good faith, then one of the following seems to be implied:
* you've fixed all your bugs and blew through your mature feature designs already, leaving your AI agents sitting idle for all but a few hours a week, while you're bottlenecked on feature design and your software product is bloated beyond imagination
* your coding productivity before AI was absolutely glacial by industry standards such that "10x" productivity for you is actually much closer to "0.5-2x" for others
Any insight into which of those it might be?
Anthropic themselves have admitted you don’t need much to poison LLMs¹. I can’t wait for us to discover the backdoors that are being introduced. I hope it happens soon so people get to their senses. Bah, what am I saying, when (not if) that happens, the response will just be to throw more LLMs at it.
¹ https://www.anthropic.com/research/small-samples-poison
(Because it's true.)
Where it really, really struggles for me is in existing complex infra codebases.
https://arxiv.org/abs/2605.20049 https://arxiv.org/abs/2605.13280
> we are not going back to hand-writing these functions
do you really think there isn't a good chunk, if not the majority outside some bubbles, of developers that still hand code? Crazy to hear, I bet you're not a programmer
You'd be surprised how readable this makes the code when XXX is about the size of your vertical screen and Y is relatively small.
At a minimum, there should be precommit checks and CI workflows that cause PRs to fail if the documentation is not up-to-date and synced with the other docs.
Then regular codebase analysis for improvement. This is where you find the bug sources, make new modules for consolidation, and get those +5000/-4000 PRs that people stuck in the world of manual code review hate.
One pattern I've really been enjoying lately has to do with a language called haxe. It's designed to be compiled into other languages (java, python, others). There's this extension called reflaxe which lets you make mini compilers for compiling haxe into pretty much anything.
So if I have anything with duplicate structure... like maybe I want the CLI subcommands to resemble the http API.
...and `docs/generated/foo.md#bar` should have documents both the CLI and the http usage. Then I have the LLM maintain a haxe source of truth and then have it compile that source of truth to the other stuff.Previously I was using OpenAPI spec's and generators for this, but they wound up feeling like a black box that I ended up debugging all the time. The reflaxe setup is much more generic. So you end up with this mountain of generated code, but unlike LLM-generated code it's obviously generated (in .../generated/thingy.py or whatever) and a comment at the top of the file says where to look to learn how it's generated). I'm generating docs this way, accessor functions for database tables and SQL for making those tables, matching clients and servers in different languages... it replaces a lot of purpose built tools with just one, and LLMs are pretty good at it.
So even though the repo is large, the parts of it that are authoritative remain small. I find LLM's manage this boundary much better because it's so crisp an in their face. But they have to be told to do this, otherwise they'll just create context-size problems that they'll later struggle with.
Of course you could do this with yaml files or some such, but unlike yaml, haxe has a type system, you can write tests in it, so the agent can notice fundamental flaws before the generation happens... with yaml those flaws would be propagated into the generated code before they'd get noticed.
* define the software layers, their function, and the max depth allowed
* establish a corp code formatter for each language, along with a process to PR it
* establish a business vocabulary and what the terms mean
* establish a data dictionary, make it part of the database schema/table/col comments
Are far more successful with LLMs. You _should_ have been doing this years ago, but with LLMs its a super power.
Maybe someone has the perfect claude.md that solves this problem but I have not seen it.
Instead modularize the knowledge with skills and specialized MD files. Agent should lazy load what is needed to do focused work.
Skills have usage description metadata, but with free files you can simply instruct agent with CLAUDE.md to load them, e.g.: "Before you attempt to change any frontend code first load and follow `docs/{JS|HTML|CSS}_coding_rules.md`".
Taken from: https://github.com/zakirullin/cognitive-load/blob/main/READM...
Easier said than done to be honest, especially if there are many people (and their agents) pushing code. It’s hard to keep up these days.
I think I would prefer code that is clear, understandable and simple even if it doesn’t compile and needs some straightforward polishing.
Getting away from stuff like this is exactly why I want to use AI. When I say "implement this for idle but active users," I _want_it to define isUserActiveIdle() and stuff these 4 conditionals in it. Having to check the generated code for stuff like this undoes, like .... all the benefit of using AI.
AI makes all these little decisions for us. I can about some of these decisions. I just want to notice when it's doing this without having to make my eyes bleed reading 10k lines of generated code a day.
Otherwise what I have found is that the LLM will add a new if statement which will handle the newly discovered issue and you start stacking them ifs. As the article mentions LLM's unlike humans aren't lazy, they will copy, paste add patches for every issue, why bother think and understand root cause :d.
So as part of our review we have a rule against that as well.
Of course, this doesn't solve the overall issue that agents don't write code like you and still requires a lot of human attention in planning and code review out to clean up leftover issues, and e.g. challenge bad assumptions about architecture and real-world context. A human is still very much needed to cull the slop (or, more gratuitously: align the agent). But IME it does help avoid a lot of pitfalls and makes the code high quality a lot more quickly.
Funny enough, discussed this yesterday
Stop Optimizing Code for Humans https://youtube.com/live/eLn4-XA-KdQ?feature=share
For personal projects, I can trust that I myself will be maintaining things so I still write things like it matters, but I do not extend the trust to others.
You can have all the prompts you want on top of this, but if you don't have this automated stuff running behind the scenes, you aren't serious about these issues.
Looking through some of these comments here, I see lots of people rewriting concrete rules in markdown willing to spend tokens on the hope AI won't miss it where an actual program won't.
— John F. Woods (1991)
bottom up AI use seems a godsend compared to the corporate AI rat race.
i setup some slop reporting systems and ensured my boss knows theyre great starting points but serious use requires real time investment.
I’m pretty sure many people who use AI to write emails or blog posts add "make it sound like a human wrote it" to their prompts. We all know what the result usually looks like.
If AI is writing my code, I'd rather have it focus purely on correctness and efficiency than on making the code easy to read.
heck! I might even ask it to imitate Arthur Whitney’s style.
/s