Act as a senior engineer reviewing a proposed refactor. Refactor the code below to address [REFACTORING GOAL] while preserving externally observable behavior. Code and relevant files: [CODE OR FILES] Runtime, language, and framework: [TECH STACK] Existing interfaces, contracts, and compatibility constraints: [CONSTRAINTS] Current tests or expected examples: [TESTS OR EXAMPLES] Work in this order:
1. Briefly map the current control flow, dependencies, mutable state, and public entry points. State the highest-risk behavior changes. 2. Propose the smallest viable refactor. Explain why it improves the stated goal and name alternatives you rejected if they would increase scope. 3. Provide a patch or complete replacement code, clearly separating changed files. Preserve public signatures, error behavior, return shapes, logging, and configuration defaults unless I explicitly authorize a change. 4. Provide targeted tests or test cases for normal flow, boundary inputs, errors, and regressions most likely from this refactor. 5. Give a concise migration note only if callers must change. Do not invent repository files, APIs, dependencies, test results, or performance measurements. Do not combine a refactor with unrelated formatting, package upgrades, architecture rewrites, or feature work. If the code is insufficient to determine behavior, ask up to 3 clarifying questions before writing the patch. Before answering, perform two self-checks: trace every original branch to confirm its result, side effects, and error path remain accounted for; then inspect the proposed code for null or empty values, async ordering, resource cleanup, concurrency, and backwards-compatibility risks relevant to the supplied stack. Flag assumptions instead of silently making them.
Fill in
| Placeholder | What to enter | Example |
|---|---|---|
| [REFACTORING GOAL] | State the maintainability, duplication, complexity, testability, or performance problem to improve. | Split validation from order creation and remove duplicated address checks without changing API responses |
| [CODE OR FILES] | Paste the relevant code and include nearby callers or dependencies when they define behavior. | src/orders/createOrder.ts and src/orders/createOrder.test.ts, plus the validateAddress helper |
| [TECH STACK] | List the language, runtime version, framework, and key libraries. | TypeScript 5.6, Node 22, Express, Vitest |
| [CONSTRAINTS] | Describe public APIs, compatibility rules, performance limits, and files that must not change. | POST /orders response body and 400 error messages are public API; do not add dependencies |
| [TESTS OR EXAMPLES] | Paste existing tests or concrete input-output examples that capture current behavior. | Existing tests cover valid orders, missing postalCode, and payment gateway rejection |
How to use
- Include callers and tests, not just the function that looks messy, because they reveal its real contract.
- Write constraints as observable behavior, such as exact error shapes or ordering requirements.
- Apply the patch in a branch and run the existing suite plus the proposed focused tests.
- Follow up with: “Now show a smaller alternative that changes only this file, and compare its maintenance tradeoffs.”
Variations
Legacy function split
Use when one long function mixes parsing, validation, I/O, and business rules.
Analyze [FUNCTION CODE] in [TECH STACK] and split it into focused units without changing [PUBLIC CONTRACT]. Show a dependency map, then provide the smallest patch and tests for [CRITICAL CASES]. Keep I/O boundaries explicit, preserve error timing and messages, and do not add dependencies. State which extracted functions should remain private. Ask up to 3 questions only if behavior is unclear. Before answering, trace every return and throw path and flag any hidden dependency on mutable state or execution order.
Performance-safe cleanup
Use when improving readability in a hot path with a latency or allocation budget.
Refactor [HOT-PATH CODE] for readability and maintainability while meeting [PERFORMANCE CONSTRAINT]. Context: [TECH STACK]. Preserve [BEHAVIORAL CONTRACT] and use [AVAILABLE BENCHMARKS OR PROFILING DATA] only as evidence; do not claim speed improvements you cannot measure. Provide a patch, an explanation of allocation and complexity changes, and benchmark cases to run. Ask up to 3 questions only if needed. Check error behavior, cache semantics, input extremes, and that no extra I/O or repeated work was introduced.
Testable dependency seams
Use when hidden globals or direct SDK calls make unit testing difficult.
Refactor [CODE] so its interaction with [EXTERNAL DEPENDENCY] can be unit tested, while preserving [CURRENT API AND BEHAVIOR]. In [TECH STACK], propose the smallest injection or adapter boundary, then provide code and tests using [TEST FRAMEWORK]. Do not introduce a broad dependency-injection framework or alter production configuration without reason. Ask up to 3 questions only if inputs are missing. Check that the default production path still uses the current dependency and that failure, retry, and cleanup behavior remain unchanged.
Tips
- Start from behavior, not aesthetics: snapshot public responses, exception types, ordering, and side effects before extracting code.
- Keep a refactor narrow enough that a failing test points to a behavioral change rather than a package upgrade or unrelated rewrite.
- Ask the model to distinguish confirmed contracts from inferred intent; legacy code often contains accidental behavior that callers still rely on.
- Treat generated tests as hypotheses until they run against the current implementation and fail for the expected reason when a regression is introduced.
FAQ
Can AI safely refactor code without tests?
It can suggest a plan, but safety is much lower. Supply concrete input-output examples and add characterization tests before changing ambiguous behavior.
Should I ask for a full rewrite?
Usually not for a refactor. A small patch is easier to review, benchmark, revert, and merge while keeping behavior stable.
How do I keep an AI from changing the API?
State the public signatures, response schemas, error messages, and compatibility targets explicitly, then ask it to list any proposed contract change before code.