There’s a charged debate happening right now about whether or not coding agents are worth a damn.
I’m going on the record and saying, yes, yes they are.
There are some people who just tried coding assistants at various stages of development and didn’t like their output.
I hear often is that AI code is slop; AI can’t produce anything beyond toy software; that when you reach a certain level of complexity, the assistant and the code base just falls apart. I still run into this, but vastly further down the line than I did even six months ago. There’s a whole host of things you can do to make coding assistants get further along:
- Set up proper context that explains the purpose and architecture of the software you are making. This can be as simple as text files you seed the AI chat session with before you start working.
- Also add your own coding philosophy and patterns to this context.
- Have automated linting and code quality checks run after each code rewrite.
- Have the assistants write thorough tests as you complete various milestones, and then make sure they all get run after code changes.
- Have the assistants decorate the code with semantic comments. If you are punting on a particular item, have it write TODO comments. If you chose a specific design and want it to be that way, add an IMPORTANT comment, etc.
- Perhaps most importantly, design your software before you start building it.
These are actually all things software teams have argued about for years. I’ve probably had a thousand discussions with engineers about why proper comments, linting, best practices, patterns, testing, and designing before coding are essential for collaborating on teams. You can get away without doing any of this if you working solo, maintaining all this context in your own brain, but as soon as you start collaborating, these practices become essential. Historically, most engineers I’ve worked with resist many of these practices and will sometimes fight you to the death on them: “self documenting code”, “linting nazis”, “test driven development” have all been hornets nests. They tend to be seen as the most productive engineers so they’re given leeway. I think this correlation and causation goes the other way, though, many of them maintain their “most productive engineer” status precisely because they don’t play nice, keeping their design decisions close to their chest, keeping control of “their” code ensuring their essentiality. They LIKE it when others don’t know how their code works.
So, I’m actually quite satisfied (hopefully not smug) that these practices are demonstrably being shown to be essential for collaboration now. There is no more debate. When you implement some of them in a coding framework, the coding framework massively improves in capability.
The most essential practice I run into these days, now that linting, tests, documentation, automated scripts, etc. have been mostly ironed out, is design. This isn’t surprising, we’ve told junior engineers for years they need to design their software before they start building it. On some teams, we’ve taken this to an extreme, having every engineer write out an entire plan in enough detail that another engineer would be able to follow their instructions successfully. We’ve seldom done the hand-off but we generally do get feedback from someone more familiar with the system or architecture before implementing. Even as an individual practice, one tends to find crucial mistakes in their approach that would have invalidated the entire implementation, wasting days or weeks of time.
It IS surprising, though, how much design effects how far coding frameworks can get with large projects. Most of the times my codebase falls apart these days are because I didn’t make some important design decisions up front. Last week I was held up for a few hours because one of the components I build was not initially designed for concurrent access–which I didn’t need when I built it. This is normal. You don’t always know what you’re going to need up front, and the act of building makes these considerations appear. With the pace of AI development now, though, our patterns need to change. When coding by hand, we would take considered approaches to reworking the component with the more defined design. Today, we have a few choices: either ask the assistant to change the code to work in the new way, or, what often works better, just delete the component and ask the assistant to rebuild it with the new design requirements in mind.
I guess what I’m saying is simply, “AI assistants can’t read your mind”. If you don’t tell them what the important parts of your design are, they generally won’t build them. This is a temporary state of affairs, because we can expect assistants to encode more and more architectural and design expertise, and to interview you, the software developer, when it matters.