MODULE 04 / 18 · PART 2 · BUILD & REFACTOR
Refactoring & Code Quality
Change the shape of the code without changing what users observe.
THE SHORT ANSWER
What this module changes.
A refactor without a stated invariant becomes a rewrite. Start with ‘behavior stays the same’, then ask for a change list, a seam, and a test suite that stays green at every step.
Refactoring prompts must state the invariant: behavior stays the same. Without that sentence, the agent will "improve" things you did not ask it to touch.
Many regional teams maintain inherited PHP, WordPress, Laravel or Excel-backed systems with one person who understands them. Refactoring is safe when every commit leaves the system working and the next maintainer can stop halfway without a crisis.
THE MODULE PROMPT LIBRARY
40 prompts for refactoring & quality.
Copy any prompt, replace the [bracketed] slots with your own project context, and attach the files the agent needs. Use “Copy all prompts” when you want the full module in one place.
40 copy-ready prompts. Bracket text is a slot for your own context — replace it before you send the prompt.
Refactor this for readability without changing behavior. Behavior is the invariant. List every change you made and why it is safe.
Why it worksNaming the invariant is what keeps a refactor from becoming a rewrite.
Extract the duplicated logic in [files] into a single well-named function. Show me the call sites before and after.
Why it worksDeduplication with visible call sites is reviewable; silent extraction is not.
This function does too much: [function]. Split it by responsibility and name each part after what it does, not how.
Why it worksNaming by responsibility is what makes the split meaningful rather than cosmetic.
Replace the nested conditionals in [function] with early returns and guard clauses. Keep the same behavior and the same error messages.
Why it worksFlattening control flow is the highest-value readability win in most codebases.
Identify the code smells in [module] and rank them by how much they slow down future changes, not by how ugly they look.
Why it worksPrioritizes refactoring by cost of change rather than aesthetic preference.
Refactor this to make the dependencies explicit: [code]. No hidden globals, no implicit singletons, no ambient state.
Why it worksExplicit dependencies are what make code testable and reasoning possible.
Convert this class hierarchy to composition: [code]. Show me what becomes easier and what becomes harder.
Why it worksHonest trade-off reporting prevents cargo-culting composition everywhere.
Rename everything in [module] to match the domain language in [glossary]. Show the rename map.
Why it worksAligning code with domain language is the cheapest long-term readability investment.
Find the dead code in [module]: unreachable branches, unused exports, obsolete flags. Prove each is dead before removing it.
Why it worksRequiring proof prevents deleting something that is only rarely reached.
Refactor this to remove the temporal coupling: [code]. Make it impossible to call things in the wrong order.
Why it worksOrdering bugs are invisible in review; making them unrepresentable is the fix.
Replace the boolean parameters in [function] with explicit named options or separate functions. Show the new signatures.
Why it worksBoolean parameters are unreadable at the call site; this fixes the call site, not just the definition.
This module has grown a god object: [module]. Propose the split, the new boundaries, and the migration order.
Why it worksA split without a migration order is a plan that stalls halfway.
Refactor [code] to fail fast: validate at the boundary, then assume validity inside. Remove the defensive checks that become redundant.
Why it worksRedundant defensive checks hide bugs; boundary validation exposes them.
Make this code testable without changing its behavior: [code]. Show me the seam you introduced and why it is the right one.
Why it worksTestability seams are design decisions worth reviewing explicitly.
Consolidate the error handling in [module] into a consistent strategy. Show the before/after for each call site.
Why it worksInconsistent error handling is a reliability bug waiting for a bad day.
Refactor this to eliminate the primitive obsession: [code]. Introduce the value objects and show where validation now lives.
Why it worksValue objects move validation from scattered checks to a single construction point.
Simplify this abstraction: [code]. If the indirection does not earn its keep, remove it and tell me what it was protecting against.
Why it worksRemoving unearned abstraction is as valuable as adding needed abstraction.
Refactor [module] so that the public surface is smaller. List what becomes private and what breaks for external callers.
Why it worksA smaller surface is a smaller contract to maintain and a smaller blast radius.
Apply the boy-scout rule to [file]: fix the small things you touch, but list anything larger as a separate follow-up rather than doing it now.
Why it worksKeeps opportunistic cleanup from ballooning the diff.
Show me the refactoring sequence for [module] as a series of commits, each of which leaves the tests green.
Why it worksA refactor that is green at every step is a refactor you can stop halfway.
Refactor [module] to make the module boundary enforceable: define the public interface, then tell me which imports would violate it and how to fail the build when they appear.
Why it worksAn architecture rule that is not enforced by tooling decays within a quarter.
Replace the inheritance in [code] with a strategy or policy object. Show me the extension points that become available and the ones we lose.
Why it worksMakes the trade-off explicit instead of assuming composition is always better.
Refactor [code] to separate the pure logic from the I/O. Show me the pure core, the imperative shell, and what is now trivially unit-testable.
Why it worksPure cores are testable without mocks, which is where most test pain comes from.
Find the hidden coupling in [module]: shared mutable state, implicit ordering, and knowledge of another module's internals. Rank by how hard each is to discover.
Why it worksHidden coupling is the defect that survives every review and every test suite.
Refactor [code] to make invalid states unrepresentable. Show me the type changes and what runtime checks become unnecessary.
Why it worksMoving a check from runtime to the type system removes a whole class of bug.
This code has grown a long parameter list: [function]. Introduce a parameter object and show me which call sites become clearer and which become more obscure.
Why it worksHonest reporting prevents a mechanical fix that trades one readability problem for another.
Refactor [module] to remove the feature flags that are now permanently on. Show me the code that becomes unreachable and the tests that can be deleted.
Why it worksStale flags are dead code with a maintenance cost and a false sense of safety.
Show me the strangler-fig refactor for [module]: the seam, the facade, the incremental replacement order, and the point of no return.
Why it worksGives a large refactor a stopping point and a rollback path at every stage.
Refactor [code] to make the failure modes explicit in the type signature. Show me the callers that must now handle each case.
Why it worksErrors in the type system cannot be ignored the way exceptions can.
Consolidate the configuration in [module] into a single validated schema. Show me what is currently read from where, and what breaks if a value is missing.
Why it worksConfiguration scattered across the codebase is an outage waiting for a typo.
Refactor [module] to reduce the number of concepts a new engineer must hold in their head to make a safe change. Name each concept you removed.
Why it worksCognitive load, not line count, is the real measure of maintainability.
Show me the before/after dependency graph for this refactor: [module]. Which cycles disappear and which new edges appear?
Why it worksA refactor that introduces a new cycle has moved the problem, not solved it.
Refactor [code] to make the side effects visible at the call site. No function should mutate something its name does not mention.
Why it worksSurprising side effects are the hardest bugs to find in review.
Review this refactor for behavior drift: [diff]. For each change, tell me the input that would produce a different result than before.
Why it worksTurns "looks equivalent" into a falsifiable claim about specific inputs.
Refactor [module] to remove the duplication between the test setup and the production path, without making the tests depend on production internals.
Why it worksShared setup that mirrors production hides the divergence it was meant to catch.
Propose the deprecation path for [API]: the shim, the warning, the telemetry that proves nobody uses it, and the removal date.
Why it worksA deprecation without usage evidence is a guess that breaks someone.
Refactor [code] to make the concurrency model explicit: what is shared, what is immutable, and what is confined to one thread or actor.
Why it worksImplicit concurrency assumptions are the ones that fail under load.
Show me the refactor that would let us delete the most code. Deletion is the strongest evidence that an abstraction was right.
Why it worksOptimizing for deletion finds over-engineering that addition never will.
Refactor [module] to make the invariants checkable in tests rather than documented in comments. Show me the assertions you would add.
Why it worksAn invariant in a comment is a wish; an invariant in a test is a guarantee.
Give me the refactoring plan for [module] as a risk-ordered list: what to do first, what to defer, and what to never touch without a rewrite.
Why it worksNot all code deserves the same effort; this spends the effort where it pays.
PRACTICE · 20–30 MINUTES
Try it on a project you actually own.
Choose a module with no tests. Run prompt 2 (characterization tests) first, then prompt 1 (readability). Keep behavior changes in a separate commit.
- Pick one prompt from this module that matches a real task.
- Replace every bracketed slot with context from the feature you are working on now.
- Attach only the files the agent needs. Keep secrets, credentials and personal data out of the chat.
- Ask for the artifact — a spec, diff, test, runbook or decision note — and the evidence that it works.
- Record what changed and what remains unverified in the repository.
Want the same prompts across every module? Search the full prompt library or return to the course overview.