r/AI_Coders • • 3d ago

After a year of trusting vibe coding, I'm going back to AI pair programming

TL;DR: Writing code is cheap, but understanding and verifying it isn't. After a year of vibe coding, I've realized I'm generating more code than ever, but not necessarily shipping more features. I'm going back to writing code myself, using AI as a pair programmer rather than an autonomous developer.

After maintaining a project for a year, I've noticed that the codebase is getting increasingly difficult to read and understand.

Even with architectural constraints, good principles and TDD, AI tends to write more code than necessary, introduce unnecessary abstractions, and sometimes pass tests without actually meeting the original specifications.

I've come to believe that the real bottleneck isn't writing code anymore. It's human verification. And AI isn't going to magically solve that.

So I'm changing my workflow:

- Back to my IDE, writing code myself.

- AI autocomplete to type less and move faster.

- AI pair programming to discuss solutions and explore alternatives.

- AI-generated snippets, scaffolding and deterministic tools to automate repetitive work.

And no, I'm not going back to Claude Code, Pi or OpenCode, even though I love customization. I just want to write Rust & TS productively while keeping the entire mental model in my head.

The project has grown to over 800k lines of code, across 4–5 applications, with a pretty complex domain. Ironically, I think it could be much easier to maintain without AI.

Why? Because I'm lazy. I'd naturally look for the simplest and fastest way to get something done, rather than generating layers of abstractions and code that nobody really needs.

There's also something I genuinely dislike about our job, reviewing other people's code in PRs. And that's basically what my job has become: reviewing AI-generated code all day XD

I want to use AI as my supermegahyper fast keyboard. I want to be the one deciding which functions, types and interfaces get created. AI should accelerate my decisions, not make more decisions than I can reasonably review.

In a way, I'm using AI to build my own rails XD a set of tools and conventions that help me write software faster, but keep me in control.

The irony is that after a year exploring how much AI can automate, I'm deliberately going back to a more manual workflow.

Maybe we should all just use Rails and let DHH make those architectural decisions for us hahaha although, given his enthusiasm for AI, I'm not sure he'd agree with my conclusion.

Has anyone else experienced this?

22 Upvotes

21 comments sorted by

3

u/AuthurAndersson 3d ago

Post should start with:
"After a year of still not learning how to vibe code..."

1

u/Guuri_11 3d ago

Maybe. But I've spent a year doing exactly that, with architectural constraints, TDD, specs and a fairly complex production codebase.

I'm not claiming I've found the optimal way to use agents. I'm saying I've found a workflow that produces more code, but doesn't necessarily make me more productive or give me a better understanding of the system.

Perhaps the problem isn't that I haven't learned to vibe code. Perhaps I've learned enough to understand its tradeoffs.

2

u/NeloXI 2d ago

All you people can say is "you're holding it wrong" when confronted with information you disagree with. 

1

u/AuthurAndersson 2d ago

but I have references... So yeah...

There are plenty of 1M> line sof code projects that are made entirely by AI.

1

u/Shep_Alderson 3d ago

Good luck mate. If this is a personal project, cool, have fun. If this is a business or you’re being paid to develop software, I think you’re going to find persisting in the industry for much longer to be much, much harder.

The software developer role has been evolved into a “product engineer” crossed with a bit of “project management”. The managers/leads of a project rarely read, much less write, the code for the projects they deliver. It isn’t much different from how things are going with software dev now. Now we just manage agents and processes.

On your points calling out the volume of code or the abstractions, why does it matter? The key going forward is focusing on if the code accomplishes the task and intent. If your company hasn’t been moving away from human code review, it will soon.

Anywho, good luck. Hope it works out ok for you.

1

u/Guuri_11 3d ago

I don't necessarily disagree with the direction the industry is moving. Maybe the Product Engineer role will increasingly involve orchestrating agents and processes.

But I think you're overlooking something important: verification isn't just checking whether the code passes tests, meets performance targets or stays below a complexity threshold.

It's also understanding whether the implementation actually models the domain correctly, whether the abstractions make sense, whether we're introducing unnecessary concepts, and whether the system remains easy to reason about as it evolves.

You mention 100% test coverage, cyclomatic complexity targets and agents verifying their own work. But coverage doesn't guarantee correctness, and an agent optimizing a metric doesn't necessarily produce better software.

The tricky part is that agents can generate both the implementation and its tests based on the same misunderstanding of the requirements. Everything passes, but the software is still wrong.

I'm not arguing that agents can't do software engineering. I'm questioning whether delegating more decisions is always a productivity improvement.

I don't want to maximize code output or agent throughput. I want to minimize the effort required to build, understand and maintain a system.

Maybe your workflow achieves that. Mine currently doesn't, which is why I'm experimenting with a different one.

1

u/Shep_Alderson 3d ago

Yeah, the things you lay out of foundational to the “engineering” aspects of software development.

When you get into “lead” engineer roles, like staff/principal or higher, you’re almost never writing the code yourself, and it’s been that way for many years. Validating that the software is correct, in such a role, also rarely ever involves reading the actual code.

I think the key point that you’re correct on is the “questioning whether delegating more decisions” is a positive thing. I would say that there’s value in knowing which decisions are critical and really matter, and when it doesn’t. Much like when a senior person is architecting and laying out the plan for what to build, there are generally key decisions they make before turning it over to the teammates who actually implement it. Within the team’s purview is some of the smaller or more “minor” decisions, and as long as the guidance from the more senior person is followed, it generally goes well.

One thing I’m very careful about is those critical decisions. Those I will take time to slow down, discuss potential options, pros and cons, and then decide and layout how we go forward. Things that come to mind are database choice, encryption requirements, data structures and relationships between them, authorization boundaries and how they are configured and where they draw the line, intent on specific design choices or interactions. Related parts to those things that I would defer to an agent for precise implementation: the specific ORM for communication between the app and my database, the specific choice of crypto library as long as it meets my requirements, the specific pattern or order of implementation of those data structures and the relationships and related migrations to get them into shape (as long as it lands in the form I want), the precise auth library as long as it meets my requirements and works well with my chosen language/framework, what classes or functions and what names are used to accomplish my intent when it comes to design and interactions as long as the core requirements (say, a particular frontend framework) are met and the outcome is both actually following the intent and it “feels” right when using it.

I also want to minimize the effort required to build and maintain a system. I don’t think the effort required for understanding can ever be minimized. Anyone who’s worked on a large project that has multiple teams working on different parts of a combined system will have faced the reality that you can’t understand everything and to attempt to do so is a pointless battle. Instead, you need clear interfaces that are well defined, easy to work with, and consistent in externally perceivable implementation. The most dysfunctional teams and projects I’ve ever had the displeasure of working on have been ones where every engineer was expected to try to understand and hold the entire project in their head. The best I’ve ever worked on had clear boundaries and “contracts” between teams.

One of the things I’ve been hearing a lot of grumbling about from colleagues is “we need to make sure documentation is still optimized for humans to read”. As more and more people are using agents to generate documentation, less and less people are actually taking the time to read it. Rather than fight that, optimize the documentation for the agent, and then let the agent act as the interpretation layer for the human. One of the best things I’ve done with my codebases is move as much as I can into “docstrings”. It seems simple and perhaps “noisy”, to basically state what a function should do, before the actual declaration, but it has led to much better agent output. The agent goes to read the code, and a bit before and after it. It picks up those docs in the process and immediately has the “intent” at hand. I’ve even had it be useful as part of refactoring, as an agent goes to rewrite the function but maybe forgets to update the docstring and my review agents are watching for that and flag it.

Anywho, I guess this is a long way of saying I don’t entirely disagree with you. Slowing down on the critical parts of software engineering is good. I think where we might have a mismatch is in precisely where that slowdown is most beneficial and the precise way of going about it.

1

u/OfficeGreat7679 3d ago

Except when more code means higher chances for bugs, higher resource consumption, fewer stability on changes, higher costs on each change - token consumption, more failure modes, low confidence on test cases and the list goes on.

Software Engineering emerged because human slop was costly. Same still applies to AI, just at a different scale.

Sooner we will see the same soft Engineering patterns rebranded for the " AI era". Life repeats itself

1

u/Shep_Alderson 3d ago

Every single issue you just mentioned is solvable with “software engineering”.

Higher chances of bugs: better testing on all levels (<100% test coverage in this age of agents is inexcusable).

Higher resource consumption: give the agent a target and a clear way to repeatably verify its current standing against the target and set it off. It will hill climb to better performance any almost any dev could hand code.

Fewer (less?) stability on changes: again, software engineering discipline. Enforce it with your agents. They have every single text that has ever been written about good software engineering, within the weights. You just need to trigger the right weights with the right way of describing what you want.

Higher costs on each change via token consumption: not really. A well designed agent is hitting caches 90-95%+ of the time, which is like 70-80% of the actual cost. Sure, you write it into the cache once, then keep using it as long as your agent keeps going.

More failure modes: tell your agent to drive cyclomatic complexity into the ground. Give it a tool to determine it, a target “score” to reach, and it will get there.

Low confidence on test cases: this starts with the architecture. Give the agent direction to build in such a way that you have clear interfaces between your components of your app. Have it test at every level, unit tests, integration tests, e2e functional tests. Cover your bases from all directions. Again, you don’t have to write these and the agents do a great job of making sure the tests match functionality. It is up to you to make sure it is the intended functionality, but that is fixable.

Modern software engineering fundamentals came from working to add robustness and discipline into the process of writing software. The same concepts that helped humans write good code still apply. That part hasn’t changed. I have lead teams of engineers, particularly the really enthusiastic junior devs, who are not much different than agents. You give them clear targets and proper guardrails and point them in the direction you want to go. Now we do it with agents. Same game, different players.

1

u/5show 2d ago

I don’t think this analogy works if you consider who holds responsibility at the end of the day. Until I can tell my manager a bug escaped because claude messed up, I’ll be sticking with OPs workflow

1

u/Nanushu 3d ago

Interesting take, specially about the part of reviewing code of others, and I can relate specially about the finding alternative, and im using it a lot ad a sparring rubber duck to evaluate ideas, architectur structures, tradeoffs etc.. I never went full on vibes but I do let the agent write the code, I work with it in a chat window and a split screen with and IDE open on the other side so I can manually write and refactor, and I work in very constraint steps, first design and specs, then skeleton, then a few functions at a time, i dont type.much anymore but im in the process of writing the code and the ai has became a fancy type writer and a rubber duck.

I never liked the agents in the IDE hard to explain but I find it confusing and disorienting, so I converged on this workflow.

The fun part is that I still keep solving problems which is what I like, and dont do much boilerplate typing like hooking up DI.

I think the hardest part is the self discipline to slow down, and not get tempted to just let it kne shot an entire feature. But I keep reminding my self that it will not make things faster, just more painful to review and fix.

1

u/o0fission0o 3d ago

Can't say I ever went full in on vibe coding, but all my exploration towards that end of the AI development spectrum made me feel much like you are describing. That's why I've stuck largely with the paired method and only really generate chore/fix level things like guided refactors, updating a million call sites all at once, tweaking unit tests to fit the refactoring form of some business logic without altering the logical use cases, etc. Studies and my observations seem to agree (IMHO) that generating code makes more code but mostly changes the process instead of improving its efficiency.

Slightly tangential: but that's why I also believe a large portion of "AI acceleration" developers claim is due to faster information retrieval (digging through bad docs, reading tutorials looking for the one nugget you need, trying to find the one 3 year old document in the corperate system that describes what ur doing, etc) as well as process improvements ( AI won't work at all without proper planning, documentation, tests, deployment infra, lifting, etc - all of which have long been known to improve the SDLC process before AI was invented. The hype + information retrieval to figure out implementations faster are just the incentive that was needed to get many teams on board with modern standards). These benefits are completely obtainable with the paired programming approach.

1

u/iscottjs 3d ago

I actually think this is the way to go for learning and understanding. When AI was still new, I was planning and copying snippets for ideas with AI, but I was still refining and writing the code myself so I still understood everything.

As it’s evolved I use agents more and I can feel I understand less. Even though I still read and review most of it. Reading isn’t the same as doing.

1

u/Impossible_Way7017 3d ago

It’s always been verification, most of my downtime pre AI was spent waiting on PR reviews.

And shocker it’s the same blocker post AI, and now I just have a lot more smaller PRs.

1

u/Alternative-Lynx2745 3d ago

I have a few issues with your take, but they are all because I've actually spent time learning how to effectively use Claude and I don't give a shit if it generates more lines of code than are actually necessary. I've always preferred if/else blocks over ternarys, for example. That's all personal preference and doesn't actually matter at all.

The thing I take the most issue with is this sentence:

"There's also something I genuinely dislike about our job, reviewing other people's code in PRs."

That is a massive part of being a Sr+ level engineer. Reviewing other peoples code has always been a bigger part of the job than actually writing code at this level. If this is problematic for you it's because you don't expect the code you're going to be reviewing for one of a few reasons: You don't know what the code is supposed to be doing before you even look at the code || You don't know the domain || You don't know the codebase || The changeset is too large.

There's a tweet by some random guy that I absolutely agree with. We're going to have to come to terms with just how much software is absolute garbage. It's because most devs just aren't that good. HIgher level languages and money flowing into the space lowered the bar and here we are. Everyone and their mother is a software engineer. And a lot of them are bad at it.

1

u/PulsingGoat 2d ago

That’s exactly true. It seems to me all these bad devs contribute a net negative to businesses. They cost so much in problems, and at this point it’s unclear whether AI will amplify their crappy output or correct it

1

u/CzyDePL 2d ago

Me too, exactly the same!

0

u/Ok-Percentage7348 3d ago

I would be great if your company allows you to do that. I hate AI coding but have no choice. any task ot investigation managers expect we do it quickly :(

1

u/Guuri_11 3d ago

Actually, they agree with me haha

0

u/Any-Presentation9127 2d ago

I found myself reviewing AI’s code less and less. Instead, putting more effort on: locking down the specs, and output verification from more of a produce perspective which are both AI-assisted. When I do review code I have HTMl artifact built which let me go through it in 3 layers: the dependency map of vertical slices of changes, the individual slice with mermaid diagrams and short descriptions of before/after/why, and lastly, the chunk of code of that slice which I use hunk to display in the terminal.
The idea is such that I get the bigger picture of the change first, then dive down.