AI coding assistants went from novelty to default tooling faster than almost any developer technology in memory. Used well, they remove drudgery and let you stay in flow. Used carelessly, they flood your codebase with plausible-looking code nobody fully understands, quietly eroding the quality that took years to build. The tool is not the problem; the workflow around it is. This is an opinionated guide to capturing the speed without paying for it in technical debt, security holes, and a team that no longer understands its own system.
How to stay fast without going feral
- Treat AI output as a draft from a fast junior, not a finished answer
- Where assistants genuinely shine, and where they quietly hurt you
- Review discipline: the line you must never cross
- Context, tests, and prompts that raise the quality of suggestions
- Team norms that stop AI-generated debt from accumulating
Info
The core principle
You are still the engineer. The assistant accelerates typing and recall; it does not transfer responsibility. Every line you accept, you own in code review, in production, at 3am during an incident. Internalise that and most bad outcomes disappear.
The trap: plausible code you do not understand
AI assistants are extraordinary at producing code that looks right. That is precisely the danger. A suggestion can compile, pass a happy-path test, read cleanly and still be subtly wrong: an off-by-one in an edge case, a missing authorization check, a swallowed error, a dependency you did not need. If you accept it without understanding it, you have inserted a defect you cannot debug because you never modelled how it works. Velocity that you cannot maintain is not velocity; it is a loan.
Danger
Never merge code you cannot explain
If you could not write this code yourself and explain why each part is there, do not merge it. "The AI wrote it" is not an answer in a code review, a post-mortem, or a security audit. Understanding is non-negotiable; the assistant just gets you there faster.
Where assistants genuinely shine
✓ Pros
- Boilerplate: DTOs, mappers, config, repetitive CRUD scaffolding
- Tests: generating cases, especially edge cases you would skip
- Unfamiliar syntax: a new language, a library API you rarely touch
- Explaining and exploring: "what does this regex/function do?"
- Mechanical refactors and renames across many files
✕ Cons
- Core domain logic where correctness is subtle and load-bearing
- Security-sensitive code: auth, crypto, input handling, permissions
- Architecture decisions that shape the system for years
- Anything requiring deep, current knowledge of your specific codebase
- Concurrency and performance-critical paths where details decide everything
Review discipline: the non-negotiable
The single behaviour that separates teams who benefit from AI from teams it harms is review rigor. AI-generated code deserves more scrutiny than human code, not less because the author (the model) cannot answer questions, did not consider your constraints, and optimised for "looks like working code," not "is correct for this system."
Read every line before accepting
No bulk-accepting large blocks. If a suggestion is too big to read carefully, it is too big to accept in one go.
Check the edges, not the happy path
The assistant nails the obvious case. Your job is the empty input, the null, the concurrent call, the failure mode, the malicious input.
Verify dependencies and APIs
Assistants hallucinate plausible package names and method signatures. Confirm libraries exist, are maintained, and that the API call is real not a convincing invention.
Run the tests, then read the tests
AI-written tests can assert the wrong thing or test nothing meaningful. A green check on a hollow test is worse than no test.
Raising the quality of what you get
Suggestion quality is largely a function of context and constraints. Give the assistant more of both and it produces dramatically better output.
Weak prompt: "write a function to upload a file"
Strong prompt: "Write a TypeScript function to upload a file to S3.
Constraints: validate MIME type against an allowlist, max 10MB,
stream (don't buffer the whole file), throw a typed UploadError
on failure, and return the object key. Match the style of the
existing s3Client in lib/storage.ts."
Pro tip
Let your tests drive the assistant. Write the test (or describe the contract) first, then ask for an implementation that satisfies it. You get code aimed at a real specification instead of the model's guess at what you wanted and you end up with the test either way.
In practice that looks like writing the failing test by hand, then asking the assistant to make it pass. The test is your specification and your acceptance check in one the assistant has a concrete target instead of guessing, and you keep a regression guard either way:
# 1. YOU write the contract as a test — including the edge cases you care about.
def test_parse_money():
assert parse_money("$1,234.50") == 123450 # cents, comma-stripped
assert parse_money("0") == 0
with pytest.raises(ValueError):
parse_money("free") # non-numeric must reject, not return 0
# 2. THEN prompt: "implement parse_money to satisfy test_parse_money".
# 3. You read the result and run the test. A green bar on YOUR cases — not the
# model's idea of "probably fine" — is the bar for accepting the suggestion.
def parse_money(text: str) -> int:
cleaned = text.replace("$", "").replace(",", "").strip()
return int(round(float(cleaned) * 100)) # raises ValueError on "free" — good
Tip
Feed it your conventions
Point the assistant at existing, well-written examples from your codebase and ask it to match them. Most assistants honour project context and style files. Code that matches your patterns is code your team can actually maintain.
Security: a specific, serious warning
AI assistants learned from the public internet, including its mountains of insecure code. They will cheerfully suggest string-concatenated SQL, missing authorization checks, weak crypto, secrets in source, and outdated, vulnerable dependencies. They are also a fresh vector for supply-chain mistakes when they confidently recommend a package that does not exist or is typo-squatted. Treat every security-relevant suggestion as guilty until proven safe.
The classic example is data access. Ask for "a function to find users by name" and a careless suggestion interpolates the input straight into SQL a textbook injection. You have to recognise it and demand the parameterised version:
# ❌ What an assistant may happily suggest — looks fine, is exploitable.
def find_users(name):
q = f"SELECT * FROM users WHERE name = '{name}'" # SQL injection
return db.execute(q).fetchall()
# ✅ What you accept instead — parameterised, the driver escapes the value.
def find_users(name):
return db.execute(
"SELECT id, email, name FROM users WHERE name = %s", # placeholder, not f-string
(name,),
).fetchall() # also: select columns, not *
And before you accept any new import, verify the package actually exists, is the one you meant, and is maintained hallucinated and typo-squatted package names are a real supply-chain risk the assistant introduces with total confidence:
# Don't trust a suggested dependency — check it before it enters your lockfile.
pip index versions requests # does it exist? what's the latest, real version?
pip-audit # any known vulnerabilities in what you're pulling in?
# Confirm the name character-for-character — 'python-requests' vs 'requests' matters.
Warning
Assistants do not know your threat model
A suggestion can be perfectly idiomatic and still wrong for your context missing a tenant check, trusting a client value, logging sensitive data. Security review of AI code is your job; the model has no idea what "sensitive" means in your domain.
Team norms that prevent debt
Individual discipline is not enough at team scale; you need shared norms so AI-generated debt does not accumulate invisibly across dozens of PRs.
✓ Pros
- A team agreement: authors must understand and own AI-assisted code
- Code review standards that apply equally regardless of how code was written
- Dependency review and lockfiles to catch hallucinated/risky packages
- A shared library of strong prompts and project context files
✕ Cons
- No "the AI wrote it" as a defence in review
- No relaxing review because "it's probably fine"
- No accepting new dependencies without a human check
- No measuring productivity by lines or PR count measure shipped value
remain accountable for every line the assistant writes
The healthy mental model
Picture a brilliant, tireless junior engineer with encyclopaedic recall, zero context on your business, no memory of yesterday's decisions, and a habit of stating guesses with total confidence. You would never merge that person's work unread but you would absolutely use them to move faster on the right tasks. That is exactly how to use an AI coding assistant: delegate the mechanical, review everything, and keep the thinking, the architecture, and the accountability firmly with yourself.
! Common mistakes to avoid
-
✕Merging AI code you cannot fully explain.
✓If you could not write and justify each line, do not merge it "the AI wrote it" is not a review answer.
-
✕Bulk-accepting large suggested blocks.
✓Read every line; if a suggestion is too big to read carefully, it is too big to accept at once.
-
✕Trusting suggested packages and APIs blindly.
✓Assistants hallucinate package names and method signatures verify each one exists and is maintained.
-
✕Assuming security-relevant suggestions are safe.
✓Treat them as guilty until proven safe; the model has no idea what "sensitive" means in your domain.
? Frequently asked questions
Will AI coding assistants make my code worse? +
Only if you accept code you do not understand. Used with review discipline, they remove boilerplate and let you spend attention on the hard parts. The risk is plausible-looking code that hides subtle bugs.
Where do assistants help most? +
Boilerplate, tests (especially edge cases), unfamiliar syntax, explaining existing code, and mechanical refactors. They are weakest on core domain logic, security, architecture, and concurrency.
How do I get better suggestions? +
Give more context and constraints: specify the language, the error handling, performance limits, and point the assistant at existing well-written examples to match your conventions.
Are AI assistants a security risk? +
Yes — they learned from insecure public code and will suggest string-concatenated SQL, missing auth checks, and even non-existent or typo-squatted packages. Review every security-relevant suggestion and audit new dependencies.
How should I measure productivity with AI assistance? +
By shipped, working value — not lines of code or PR count. The winning teams understand everything they ship; they just get there faster.
Success
Speed and quality are not opposites
Used with discipline, AI assistants let you write more tests, explore more options, and spend your attention on the hard parts instead of the boilerplate. The teams who win are not the ones who accept the most suggestions they are the ones who understand everything they ship and just got there faster.
Comments
0No comments yet. Be the first to share your thoughts.