Use AI to Become a Better Software Developer, Not Just a Faster One

Use a Think, Challenge, Build, Verify, Reflect loop to strengthen engineering judgment with AI without outsourcing your learning.

2026-09-09 12:47:08 - Mohamad Abuzaid

Use AI to Become a Better Software Developer, Not Just a Faster One

AI can help you produce code faster. That is useful, but it is not the same as becoming a better software developer.

A faster developer can close a ticket sooner. A better developer notices that the ticket is missing a failure rule, questions whether the proposed abstraction belongs in the system, chooses a smaller change, verifies the behavior, and can explain what the team should remember afterward.

AI can support both outcomes. The difference is how you use it.

If every session begins with “implement this” and ends when the generated tests turn green, the tool is mainly compressing execution. If you use it to expose assumptions, compare designs, predict failures, review evidence, and test your own understanding, it can also sharpen the judgment behind the code.

The practical loop I use for that distinction is:

Think → Challenge → Build → Verify → Reflect

The developer remains responsible for the problem, the decisions, and the proof. AI helps make each of them easier to examine.

Being faster is not the same as becoming better

Speed is visible. Engineering growth is quieter.

You can measure how quickly a branch appeared or how many lines were generated. It is harder to measure whether you became better at recognizing an unsafe migration, selecting the right test boundary, or resisting an abstraction that the product does not need.

Current research gives us a useful reason to care about the difference, without pretending the question is settled.

Anthropic’s 2026 analysis of roughly 400,000 interactive Claude Code sessions found that task-specific domain expertise was associated with more successful sessions. In a typical session, people made most of the planning decisions while the agent made most of the execution decisions. Users who appeared more knowledgeable about the task also gave more precise direction, asked for stronger verification, and recovered from trouble more often.

That does not prove expertise caused every successful result. The study is observational, its classifications are model-generated, and it cannot tell whether the resulting code was valuable in production. It does suggest a practical point: an agent can execute more effectively when the person directing it understands the problem.

A separate controlled study looked at learning rather than delivery. Fifty-two mostly junior developers used or did not use AI while learning the unfamiliar Python library Trio. The AI-assisted group finished only slightly faster—a difference that was not statistically significant—and averaged 50% on an immediate mastery quiz, compared with 67% for the hand-coding group. The researchers also observed stronger scores among some participants who asked conceptual questions or requested explanations, but they explicitly did not claim those interaction patterns caused the better learning outcomes.

The study was small, covered one library, and measured understanding shortly after the task. It does not tell us what happens after months of professional AI use. Still, it captures a risk that many developers can recognize: code may arrive before understanding does.

The goal, then, is not to slow every task down. It is to decide where speed is valuable and where thinking is the work.

Think: expose assumptions before requesting code

Imagine you are adding account deletion to an existing application.

“Implement account deletion” looks like a feature request. It is actually a container full of unanswered questions:

An AI assistant can generate a route, service, and database calls without resolving any of these questions. That is precisely why implementation should not be the first prompt.

Start with an assumption review:

We need to add account deletion to this application.

Do not propose code yet.
Inspect the existing authentication, ownership, storage, audit, and background-job flows.
List the product, privacy, data-retention, authorization, and recovery decisions
that are missing from the request.

Separate facts you can prove from the repository from questions that require
a product, legal, security, or operational decision.

This changes the role of AI. It is no longer a code vending machine. It is helping you build a map of what is known, what is inferred, and what must be decided by a responsible person.

Do not accept the map blindly. Check every “existing behavior” claim against the repository, schema, configuration, and documentation. The agent is useful because it can search broadly; you are accountable for deciding what the evidence means.

Challenge: ask for alternatives, trade-offs, and failure scenarios

Once the requirements are clear enough, ask for more than one plausible design.

For account deletion, reasonable approaches might include immediate hard deletion, a soft-delete period followed by a purge, or pseudonymization of records that must be retained. Each changes recovery, privacy, implementation complexity, and operational work.

A useful design prompt makes those costs explicit:

Propose three designs that satisfy the confirmed account-deletion requirements.

For each design, explain:
- the data lifecycle
- authorization and re-authentication boundaries
- behavior when an external deletion fails
- retry and idempotency strategy
- recovery and rollback limits
- operational burden
- privacy and security risks
- tests and production signals needed for confidence

Recommend one option against the stated constraints.
Do not treat additional infrastructure as free.

Then challenge the recommendation:

Act as a skeptical reviewer of the recommended design.
Find the three assumptions most likely to be wrong.
Describe one realistic failure scenario for each.
Explain what evidence would change the recommendation.

The second prompt matters because an assistant often becomes committed to its first coherent answer. Asking it to criticize that answer creates another angle, but it does not create an independent authority. The same model can repeat the same blind spot in more confident language.

For consequential decisions, involve the right humans. Security, privacy, legal, accessibility, domain, and operations expertise are not optional review personas that a prompt can fully replace.

Build: work through small, verifiable changes

After the design is approved, keep the implementation narrow enough to understand.

For the hypothetical deletion feature, that might mean separate changes for:

  1. documenting ownership and retention rules;
  2. adding characterization tests around current data relationships;
  3. introducing the deletion request and re-authentication boundary;
  4. implementing a retryable cleanup workflow behind a disabled flag;
  5. adding user-facing status and recovery behavior;
  6. enabling the feature gradually, observing it, then removing temporary paths.

That sequence is illustrative, not a universal architecture. A small application may need fewer steps. A regulated system may need more. The important property is that each change has a clear purpose, preserves a usable system state, and can be reviewed and reversed without understanding the entire feature at once.

This is where AI’s speed becomes genuinely valuable. Give it a bounded change with a fixed definition of done:

Implement only the characterization tests for account-owned data.

Do not add the deletion endpoint yet.
Use the existing test style and fixtures.
Cover the relationships identified in the approved data map.
Run the focused test suite and report the exact command and result.
If current behavior contradicts the map, stop and show the evidence.

Small steps reduce the cost of correction. They also make it easier for you to read the change while the context is fresh. My article Small Pull Requests Are a Technical Strategy, Not a Team Preference goes deeper into how to preserve compatibility and system integrity while splitting real features.

“Small” does not mean arbitrary line limits. A tiny database constraint can carry more risk than a large generated file. Size the change around one decision and one verification story.

Verify: test behavior instead of trusting the explanation

An AI assistant can explain why its solution works even when the solution is incomplete. Confidence is a property of the response style, not evidence about the system.

Verification should come from independent signals appropriate to the change:

Ask the agent to run the real project commands, but read what actually ran. A summary that says “all tests pass” is weaker than the command, exit code, relevant output, and an explanation of what the suite covers.

In Claude Code Meets Android CLI: Build, Run, and Test, I use the phrase “Claude proposes; the toolchain proves.” The principle is broader than Android. Source review, automated checks, UI inspection, and production signals answer different questions. One green test cannot represent all of them.

Google’s code-review guidance makes the same boundary clear: reviewers should examine design, user-facing behavior, complexity, tests, documentation, and the surrounding system. It also warns that tests need human evaluation. A generated test can pass while asserting the wrong behavior, reproducing the implementation instead of the requirement, or missing the failure that matters.

Before accepting a verification result, ask:

  1. Which claim does this check support?
  2. Would the check fail if that claim became false?
  3. Which important behavior remains untested?
  4. Did the agent change the test, configuration, or environment to make the result easier to pass?
  5. Can another developer reproduce the result?

The last question turns a private success into team knowledge.

Challenge again: review the solution after it works

Passing checks are the beginning of review, not the end.

Once the feature works, clear the implementation momentum and inspect the result as a maintainer:

Review this change as if you will operate and modify it for the next two years.

Check:
- whether the design still matches the approved requirements
- hidden coupling and unnecessary abstraction
- authorization and privacy boundaries
- failure, retry, cancellation, and partial-success behavior
- test quality, not only test presence
- observability and recovery
- documentation and migration impact

Rank findings by user or operational risk.
Do not rewrite working code for personal style.

This review should include the diff and enough surrounding code to understand the system. A model that sees only changed lines may miss an existing invariant. A model given the whole repository may lose focus. Curating the right context is part of engineering judgment.

Also separate critique from automatic repair. Review the findings first. Some will be wrong, some will be optional, and some will reveal that the original requirement was incomplete. Automatically applying every suggestion can turn a focused solution into a larger, less coherent one.

Protect your learning with prediction, explanation, and reconstruction

If AI always removes the moment when you have to retrieve knowledge, make a prediction, or debug a mistake, it can also remove the friction that builds understanding.

You do not need to reject AI to protect that learning. Change the interaction.

Predict before you ask

Before running the test or showing the error to AI, write down what you expect and why:

I expect the second deletion request to return the existing operation rather than create another purge job, because the endpoint is intended to be idempotent.

Then compare the result with the prediction. A wrong prediction is useful: it identifies the exact part of your mental model that needs repair.

Ask for explanations with boundaries

“Explain this code” often produces a tour of syntax. Ask questions that reveal behavior:

Reconstruct without the answer

After completing an unfamiliar change, close the generated explanation and reconstruct the important part yourself. Draw the data flow. Rewrite the failure sequence. Explain the design to another developer without reading the diff.

If you cannot explain the boundary, you are not ready to own it in production.

This is not about memorizing every API. It is about retaining the concepts required to diagnose, change, and review the system later.

Reflect: record decisions worth remembering

The final step is short, which is why teams skip it.

Ask what changed in your understanding:

Record the answer in the smallest durable place that fits: an Architecture Decision Record, a code comment explaining why, a test name, a runbook, a pull-request summary, or a focused README section.

The artifact should preserve the decision, not the entire conversation. AI transcripts are noisy and often contain abandoned ideas. Future maintainers need the confirmed constraint, the chosen option, the consequences, and the evidence.

This is also good portfolio material. A strong developer portfolio explains decisions and evidence, not merely which tools generated the final code.

Know what not to delegate

AI can gather context, propose options, implement bounded changes, run checks, and challenge a solution. Some responsibilities still need a named human owner.

Do not silently delegate:

This is not because a model can never contribute to those areas. It can identify questions, summarize policies, model threats, or prepare a review. The boundary is authority: advice can be generated; responsibility cannot.

The more consequential the action, the more explicit the approval and evidence should be.

A reusable AI-assisted development workflow

You can apply the loop to a feature, bug, refactor, migration, incident follow-up, or learning task.

1. Think

2. Challenge

3. Build

4. Verify

5. Reflect

The loop is deliberately not “prompt → generate → merge.” It keeps AI inside the engineering process without putting it in charge of the engineering responsibility.

Final thoughts

The best use of AI is not the one that produces the most code. It is the one that leaves the system easier to trust and the developer more capable of changing it next time.

Use AI for speed where the work is understood and reversible. Use it for challenge where assumptions are hidden. Use tools and real behavior for verification. Keep enough productive friction to learn the parts you will later have to debug, review, and defend.

AI can carry more of the execution. Your job is to improve the quality of the decisions around it.

Where in your current workflow could you add one deliberate pause to think, challenge, verify, or reflect before accepting the next generated change?

More Posts