Large Language Models (LLMs) have become the default “coding assistant” for many developers.
A quick function, debug something weird at 3 a.m.? Surely the model has seen this before.
And sometimes—it genuinely helps.
But there’s an uncomfortable truth that often gets glossed over: LLMs are not consistently good at helping you write code, especially beyond trivial or well-trodden problems. In many real-world scenarios, they introduce friction, risk, and hidden costs that can easily outweigh their benefits.
LLMs Don’t Understand Code — They Reproduce Patterns
The core issue is simple: LLMs do not reason about code the way humans do.
They generate responses based on probability and pattern matching, heavily influenced by:
-
Blog posts
-
Stack Overflow answers
-
GitHub snippets
-
Documentation (often outdated)
This means that when an LLM gives you code, it’s often:
-
A remix of multiple sources
-
Slightly outdated
-
Missing edge cases
-
Incorrect in subtle but dangerous ways
Worse, the model often presents the answer with high confidence, even when it’s wrong.
You’ll frequently see things like:
-
APIs that no longer exist
-
Deprecated functions
-
Assumptions that don’t match your runtime or environment
-
“Best practices” from five years ago
The result? Code that looks right, feels right, but fails quietly—or catastrophically—later.
Overengineering Is the Default Failure Mode
Another common pattern: LLMs love to overcomplicate things.
Ask for a small utility function and you may get:
-
Three helper classes
-
A design pattern you didn’t ask for
-
Configuration options you’ll never use
-
Abstractions that actively reduce readability
Why? Because the model has learned that “complex” often correlates with “professional.”
Humans optimize for clarity.
LLMs often optimize for impressiveness.
This is especially dangerous in production systems, where:
-
Simpler code is easier to audit
-
Fewer dependencies mean fewer breakpoints
-
Explicit logic beats clever abstractions
AI Can Only Help If You Keep Explaining Yourself
LLMs don’t have long-term understanding of your system architecture, constraints, or intent—unless you continuously feed it context.
To get useful results, you often need to explain:
-
What the system does
-
Why certain decisions were made
-
What must not be changed
-
What has already been tried
-
What constraints exist (performance, legal, security, legacy)
In other words: you become the documentation layer for the AI.
And if the conversation resets, context is lost.
If you forget to mention a constraint, the output is wrong.
If the problem evolves, you must re-explain everything.
At that point, you have to ask:
If I already understand the problem well enough to explain it in detail…
why am I not just writing the code myself?
Progress Depends on Keeping the AI “In Sync”
Real development is iterative. You test, observe, adjust, and refactor.
With an LLM involved, you add another dependency:
-
The model must understand where you currently are
-
It must know what changed since last time
-
It must align with your mental model
That means keeping the conversation alive, consistent, and accurate.
This creates a strange workflow where:
-
You debug the AI’s understanding
-
You correct its assumptions
-
You rephrase questions multiple times
-
You spend time steering instead of building
At scale, this is not free.
Time Cost and Token Cost Add Up Quickly
There’s a hidden economic reality here.
Using AI effectively for non-trivial coding requires:
-
Long prompts
-
Iterative clarifications
-
Multiple corrections
-
Back-and-forth explanations
That translates into:
-
Time cost (reading, correcting, re-prompting)
-
Cognitive load (tracking what the AI “knows”)
-
Token cost (which directly maps to money)
Ironically, the more complex and interesting the problem, the less cost-effective AI assistance becomes.
For simple boilerplate? Great.
For complex systems? Often a net loss.
AI Works Best as a Tool, Not a Copilot
The biggest mistake is treating LLMs as:
“Someone who understands my codebase.”
They don’t.
Where AI does shine:
-
Generating boilerplate you already understand
-
Explaining unfamiliar syntax
-
Summarizing documentation
-
Translating between languages
-
Rubber-duck debugging (forcing you to articulate the problem)
Where it struggles:
-
System design
-
Architecture decisions
-
Performance trade-offs
-
Security-sensitive code
-
Deep refactors
In those areas, human judgment still dominates.
The key is this:
If you don’t already understand the code, you shouldn’t trust the AI writing it for you.
LLM’s like ChatGPT are extremly powerful to help you construct an idea and the ways it could go forward, meaning in a way like a therapy session helps you help yourself, the LLM can do just that as well extremly well, if you are willing to keep it in the loop of everything you have made afterwards.
AI is a powerful assistant—but it’s not a substitute for thinking.
And in software engineering, thinking is still the most valuable skill we have.