Why This Senior Developer Stopped Using AI for Coding
This article explores the reasons why a senior developer, after three years of heavy AI usage in coding, decided to drastically reduce reliance on these tools. The developer shares experiences, challenges, and lessons learned from writing approximately 150,000 lines of code with AI assistance. This includes a dive into the tools and models utilized, the initial allure of increased productivity, and the eventual realization of significant drawbacks.
The Initial Magic of AI Coding
Initially, the use of AI tools such as GitHub Copilot, GPT, Claude, Cursor, Windsurf, Dips, smaller models, and even Gemini felt revolutionary. The developer experienced a significant boost in productivity, shipping MVPs in a fraction of the time previously required. A single week's work with AI felt equivalent to a month's output from the entire team without it.
The Turning Point: A Frustrating Debugging Experience
The shift occurred three months prior to this writing, during the development of a large feature. Attempting to use AI (Windsurf) to "vibe code" the solution by pasting the ticket description resulted in a frustrating two-hour debugging loop. The AI made random changes across seven files, ultimately introducing a new bug. The cycle of attempting to fix the bug only led to more errors, until the developer had to discard all the generated code and start from scratch. This was not an isolated incident.
The Accumulation of Problems
The developer began to recognize a pattern: AI would generate code, modify files, and then enter a loop of finding and attempting to fix errors. This often resulted in a complex and problematic final product that required manual intervention. The developer found that starting from scratch and implementing the feature themselves, then potentially using AI to fill in smaller gaps, was often faster.
Codebase Issues Unveiled
A closer look at the codebase built over the preceding six months revealed significant issues:
-
Duplicated code: Lack of component reusability.
-
Over-engineering: Unnecessary complexity in components.
-
Useless files: Remnants from previous AI queries left in the project.
-
Redundant implementations: Reinventing the wheel instead of using existing libraries (e.g., writing a custom debounce function instead of using Lodash).
-
Side effects: Unrelated code changes caused by seemingly simple requests (e.g., fixing TypeScript types).
-
Useless Tests: Unit tests lacking meaningful assertions and often testing the same happy path redundantly.
-
Lack of consistency and coherence: Despite adding style guides and configs, the AI-generated code was inconsistent.
-
Technical Debt: Over-engineered and bloated code, including unnecessary custom hooks and middleware. The estimated technical debt required a 60% refactor.
Reasons for Abandoning AI Coding
The developer decided to stop using AI for coding due to:
-
Excessive wait times for buggy solutions.
-
Misleading test results (tests passing despite obvious bugs).
-
The feeling of a "pump and dump" mentality, similar to the rapid turnover of JavaScript frameworks.
-
Constant need to specify obvious details to the AI.
-
A growing lack of understanding of the codebase.
-
AI tools were often ineffective at implementing more complex tasks, such as using the d3 library.
Negative Impact on Technical Skills
The developer also noticed a decline in their technical skills and an increasing reliance on the AI as a "slot machine," querying it for code snippets and accepting the results without fully understanding them. The codebase was slowly becoming a mess of spaghetti code. The developer reasoned that if one doesn't make the effort to write the code, they are unlikely to properly review AI-generated code, leading to unchecked errors.
Three Key Lessons Learned
The developer outlined three important lessons learned from using AI in coding.
1. Mastering the Fundamentals is Crucial
The myth of AI handling repetitive tasks so developers can focus on complex architecture and design is misleading. To excel at system design and architecture, one must first master the fundamentals. Mastery of CSS, the box model, flexbox, borders, and shadows is paramount to developing front-end design systems. AI cannot replace the intelligent design built on a foundation of fundamental knowledge.
2. Less Code is Often More Productive
The story of Blackberry, with its cluttered interface of buttons, compared to the iPhone's simple single button, illustrates the principle that great design is often simple. Great engineers create simple, robust solutions. More code leads to more technical debt, longer code reviews, lower quality, longer builds, and useless features. Simplicity is the biggest value of great software.
3. Doing is Often Faster Than Explaining
Describing a problem in the level of detail required for an AI to produce a good solution often takes more time than simply solving it. AI lacks intuitive understanding and requires extensive context. Also, it struggles with tasks requiring true reasoning, such as math. Context, guidelines, and style configurations does not necessarily yield a more stable code, because the AI might pick on anything from it and hallucinate. It's important not to get lost in the fallacy of thinking that the more context you add, the better the solution will be.
Riding the AI Wave Responsibly
Even with these reservations, the developer acknowledges the pressure to use AI at work. They advocate for "riding the wave" but not getting "sucked into it." The key is to not let AI hinder the continuous improvement of one's skills.
Current AI Usage
Today, the developer primarily uses AI for:
-
Inference and Copying: Generating version two or version three of an existing solution (e.g., creating mocks for testing based on an existing interface).
-
Poor Documentation: Generating documentation for poorly documented packages.
-
Autocomplete: Using autocomplete features, but carefully reviewing every line of code before accepting it.
AI is most effective for simple, localized problems, such as array functions or individual components.