Home/ Part II — Google AI Studio: First Contact/5. Your First "Hello, Vibe" Session/5.3 The first refactor prompt (make it clean, not clever)

5.3 The first refactor prompt (make it clean, not clever)

Overview and links for this section of the guide.

Goal: improve structure without changing behavior

Your calculator runs. That’s the hard part. Now you refactor it so future changes are safe and easy.

This page is about a specific skill: getting the model to clean code without rewriting the world.

The refactor trap

If you ask “make it better,” the model may do a full rewrite. Your goal is the opposite: small changes, stable behavior, improved readability.

What refactoring means in vibe coding

Refactoring is a behavior-preserving transformation. In vibe coding, refactoring has extra constraints:

  • Preserve the contract: CLI behavior + public API stay consistent.
  • Keep diffs reviewable: prefer a sequence of small diffs.
  • Use tests as the truth source: “it seems fine” is not enough.
A good refactor output

Less clever code, clearer boundaries, better errors, same inputs and outputs.

Prep: freeze behavior with tests

Before refactoring, make sure:

  • all existing tests pass,
  • you have at least a few “golden” acceptance tests (from 5.1),
  • you can run the CLI quickly to confirm behavior.
If tests are weak, strengthen them first

The fastest refactor is the one you can trust. Add 2–3 extra tests for edge cases (whitespace, unary minus, parentheses) before moving code around.

A refactor prompt that works

Use a prompt that explicitly forbids rewrites and requires a plan + diff-only changes.

I have a working Python CLI calculator project with tests.

Task: refactor for clarity and maintainability WITHOUT changing external behavior.

Hard constraints:
- Preserve CLI behavior and exit codes
- Do not add new features
- Do not introduce third-party dependencies
- Keep changes small and reviewable
- Output diff-only changes (no full-file rewrites unless truly necessary)

Process:
1) Propose a refactor plan with 3–6 steps.
2) For each step, explain why it helps and what files it touches.
3) Stop and ask me to confirm the plan before outputting diffs.

Context:
- Here is the file tree: (paste)
- Here are the key files: (paste the current versions)
- Here are the tests: (paste)

Goal qualities:
- simpler parser/evaluator separation
- clearer error types
- fewer cross-module imports
- improved naming

Start by proposing the plan only.
Why “confirm the plan” is powerful

It prevents the model from committing to a bad direction. You approve the architecture first, then let it type.

High-value refactor targets (calculator edition)

These are common quality wins for small parsers:

1) Clear boundaries: tokenize → parse → evaluate

  • Tokenizer returns a sequence of tokens (type + value).
  • Parser returns an AST (small node classes or tuples).
  • Evaluator takes an AST and returns a number.

2) Explicit error types

Instead of generic exceptions, use a dedicated exception type (e.g., CalcSyntaxError) so the CLI can reliably map errors to exit code 2.

3) A testable CLI entrypoint

If your CLI is hard to test, refactor toward a function that can accept injected streams:

def main(argv: list[str] | None = None, *, stdin=None, stdout=None, stderr=None) -> int:
    ...

This makes future “add a REPL mode” changes much easier to verify.

4) Naming and small functions

Parsing code gets unreadable fast. Short functions with meaningful names beat “one clever parser function” every time.

How to review the refactor quickly

Review is how you keep architectural control. A fast review loop looks like:

  • scan for behavior changes (new flags, different outputs, new dependencies),
  • run tests,
  • run 2–3 CLI examples manually,
  • ensure errors still map to the same exit codes.
Watch for “refactor by rewrite”

If the diff replaces most files, stop. Ask for a smaller step (e.g., “only extract tokenizer first”).

Ship point: commit the refactor

Once tests pass and the diff is reviewed, commit:

git add .
git commit -m "Refactor: clarify parser/evaluator boundaries"

Where to go next