Code Refactoring Prompt Templates
AI prompt templates for refactoring code. Improve code quality, readability, and maintainability.
Overview
Refactoring improves code structure without changing behavior, but knowing what to refactor and how is the hard part. These prompts help you identify code smells, apply design patterns appropriately, and make incremental improvements that don't break things. The goal is code that's easier to understand, modify, and extend.
Best Practices
Share the full context, including related code, interfaces, and how the code is used elsewhere
Specify your constraints: Can you change the public API? Do you need to maintain backward compatibility?
Mention if you have tests covering this code, refactoring without tests is risky
Describe why you want to refactor: readability, performance, extensibility, or removing duplication
Ask for incremental changes rather than complete rewrites, easier to review and less risky
Prompt Templates
1. Code Smell Identifier
Analyze this code for code smells and refactoring opportunities: ```[LANGUAGE] [PASTE YOUR CODE] ``` **Context:** - This code: [WHAT IT DOES] - Pain points: [ANY SPECIFIC ISSUES YOU'VE NOTICED] - Test coverage: [YES/NO/PARTIAL] Identify: 1. Code smells present (name each smell) 2. Why each is problematic 3. Specific refactoring to fix each issue 4. Priority order (what to fix first) For each refactoring, show the before and after code.
Language: JavaScript Code: 200-line function that handles user checkout Pain points: Hard to test, keeps growing when we add features Test coverage: No
## Code Smells Identified
### 1. Long Method (Critical)
**The smell:** `processCheckout()` is 200 lines handling validation, inventory, payment, shipping, and email.
**Why it's a problem:** Impossible to test individual behaviors, hard to understand, changes risk breaking unrelated features.
**Refactoring: Extract Method**
```javascript
// Before: one massive function
async function processCheckout(order) {
// 200 lines of mixed concerns...
}
// After: composed of focused functions
async function processCheckout(order) {
const validatedOrder = await validateOrder(order);
await reserveInventory(validatedOrder);
const payment = await processPayment(validatedOrder);
const shipment = await createShipment(validatedOrder);
await sendConfirmationEmail(validatedOrder, payment, shipment);
return { order: validatedOrder, payment, shipment };
}
```
### 2. Feature Envy (High)
**The smell:** Lines 45-78 are all manipulating `order.customer` properties.
**Refactoring: Move Method**
```javascript
// Before: checkout function knows too much about Customer
const fullName = order.customer.firstName + ' ' + order.customer.lastName;
const address = formatAddress(order.customer.address);
// After: Customer handles its own formatting
const fullName = order.customer.getFullName();
const address = order.customer.getFormattedAddress();
```
### Priority Order
1. Extract Method (enables testing)
2. Move Method for Customer logic
3. Extract shipping calculation to strategy pattern (you mentioned adding new carriers)When code feels hard to work with but you're not sure exactly why, or before starting a major refactor
- •Fix code smells in priority order, some fixes enable other fixes
- •Always write tests before refactoring, or you won't know if you broke something
2. Extract and Simplify
Refactor this code to be more modular and readable: ```[LANGUAGE] [PASTE CODE] ``` **Goals:** - [SPECIFIC GOALS - e.g. make testable, reduce complexity, extract reusable parts] **Constraints:** - [CONSTRAINTS - e.g. can't change public API, must maintain compatibility] **Apply these techniques as appropriate:** - Extract method/function - Extract class/module - Replace conditionals with polymorphism - Introduce parameter object - Remove duplication Show the refactored code with comments explaining each change.
Goals: Make this testable and reduce the 5-level nested if statements Constraints: Can't change the function signature, called by external systems Language: Python
```python
# BEFORE: Deeply nested conditionals
def process_order(order):
if order:
if order.items:
if order.customer:
if order.customer.active:
if order.payment_method:
# actual logic buried 5 levels deep
...
# AFTER: Guard clauses flatten the structure
def process_order(order):
# Early returns for invalid states (guard clauses)
if not order:
raise ValueError("Order is required")
if not order.items:
raise ValueError("Order must have items")
if not order.customer:
raise ValueError("Order must have a customer")
if not order.customer.active:
raise InactiveCustomerError(order.customer.id)
if not order.payment_method:
raise ValueError("Payment method is required")
# Main logic at the top level, easy to read
return self._execute_order(order)
def _execute_order(self, order):
"""Handles the actual order processing. Extracted for testability."""
validated = self._validate_inventory(order)
charged = self._charge_payment(validated)
return self._create_shipment(charged)
```
**Changes made:**
1. Replaced nested ifs with guard clauses (early returns)
2. Extracted core logic to `_execute_order()` for easier testing
3. Each step is now a separate method that can be tested/mocked independentlyWhen you have working but messy code that's hard to read, test, or modify
- •Guard clauses at the top of functions eliminate nesting and make the happy path obvious
- •Extract until each function does one thing, if you need 'and' to describe it, extract more
3. Design Pattern Application
Suggest design patterns to improve this code: ```[LANGUAGE] [PASTE CODE] ``` **Current problems:** - [PROBLEM 1 - e.g. adding new types requires changing multiple files] - [PROBLEM 2 - e.g. hard to test because of tight coupling] **Requirements:** - [FUTURE NEEDS - e.g. need to add more payment providers] - [CONSTRAINTS - e.g. can't introduce new dependencies] For each pattern you suggest: 1. Explain why it fits this situation 2. Show the implementation 3. Explain the tradeoffs (when NOT to use it)
Language: TypeScript Problems: Switch statement with 10 cases for different report types, adding new reports requires modifying this file Requirements: Need to add 5 more report types, different teams own different reports Constraints: Keep it simple, no heavy frameworks
## Recommended Pattern: Strategy + Factory
**Why it fits:** You have multiple algorithms (report generators) that need to be selected at runtime, and you want teams to add new ones without modifying central code.
### Before: Switch Statement
```typescript
function generateReport(type: string, data: ReportData): Report {
switch (type) {
case 'sales':
return generateSalesReport(data);
case 'inventory':
return generateInventoryReport(data);
case 'financial':
// 10 more cases...
}
}
```
### After: Strategy Pattern
```typescript
// 1. Define the strategy interface
interface ReportGenerator {
type: string;
generate(data: ReportData): Report;
}
// 2. Each team implements their own generator
class SalesReportGenerator implements ReportGenerator {
type = 'sales';
generate(data: ReportData): Report {
// Sales team owns this implementation
}
}
// 3. Registry allows adding generators without modifying core code
class ReportRegistry {
private generators = new Map<string, ReportGenerator>();
register(generator: ReportGenerator) {
this.generators.set(generator.type, generator);
}
generate(type: string, data: ReportData): Report {
const generator = this.generators.get(type);
if (!generator) throw new Error(`Unknown report type: ${type}`);
return generator.generate(data);
}
}
// 4. Registration (can be in separate files per team)
const registry = new ReportRegistry();
registry.register(new SalesReportGenerator());
registry.register(new InventoryReportGenerator());
```
### Tradeoffs
**Use this when:** You have 5+ variants, different teams/people own different variants, or variants change frequently.
**Don't use when:** You have 2-3 simple variants that rarely change, a switch statement is fine and simpler.When code grows repetitive patterns, when changes require touching many files, or when you need to make code more extensible
- •Don't apply patterns preemptively, wait until you feel the pain the pattern solves
- •The simplest pattern that solves the problem is the best pattern
4. Incremental Refactoring Plan
Create a safe, incremental refactoring plan for this code: ```[LANGUAGE] [PASTE CODE] ``` **Current state:** - Test coverage: [NONE / PARTIAL / GOOD] - In production: [YES / NO] - Team size: [HOW MANY PEOPLE WORK ON THIS] **Target state:** - [WHAT YOU WANT TO ACHIEVE] **Constraints:** - Can't break production - [OTHER CONSTRAINTS] Create a step-by-step plan where: 1. Each step is small and independently deployable 2. Tests are added before changes 3. Each step can be rolled back 4. Progress is measurable
Code: Monolithic 2000-line OrderService class Test coverage: Partial (30%) In production: Yes, handles $5M/month Team size: 4 developers Target: Split into focused services, increase test coverage to 80%
## Incremental Refactoring Plan ### Phase 1: Stabilize (Week 1-2) **Goal:** Establish safety net before making changes **Step 1.1:** Add characterization tests - Write tests that capture current behavior (even if messy) - Target: Cover the 10 most critical code paths - Deliverable: 50% coverage on OrderService **Step 1.2:** Add integration test for main flows - End-to-end test: create order → payment → fulfillment - This catches breaks that unit tests miss ### Phase 2: Extract Vertical Slices (Week 3-6) **Goal:** Pull out self-contained functionality **Step 2.1:** Extract PaymentProcessor - Lines 450-680 all handle payment logic - Create PaymentProcessor class - OrderService delegates to it (no behavior change) - Add focused tests for PaymentProcessor - Deploy, monitor for 1 week **Step 2.2:** Extract InventoryManager - Lines 800-950 handle inventory - Same pattern: extract, delegate, test, deploy **Step 2.3:** Extract ShippingService - Lines 1100-1400 ### Phase 3: Clean Core (Week 7-8) **Goal:** Simplify remaining OrderService **Step 3.1:** Replace direct database calls with repository **Step 3.2:** Remove dead code (now safe with test coverage) **Step 3.3:** Simplify public API methods ### Rollback Strategy Each extracted service: 1. Lives behind a feature flag initially 2. Old code path preserved for 2 weeks 3. Flag enables gradual rollout (10% → 50% → 100%) ### Success Metrics - [ ] Test coverage: 30% → 80% - [ ] OrderService lines: 2000 → <500 - [ ] Zero production incidents during refactor
When you need to refactor critical production code safely, or when refactoring will take multiple sprints
- •Never refactor and add features at the same time, do one or the other
- •Deploy refactoring changes frequently, small, frequent deploys are safer than big bangs
Common Mistakes to Avoid
Refactoring without tests, you won't know if you broke something until production tells you
Trying to refactor everything at once instead of making small, incremental improvements
Applying design patterns prematurely, adding complexity before you need the flexibility
Frequently Asked Questions
Refactoring improves code structure without changing behavior, but knowing what to refactor and how is the hard part. These prompts help you identify code smells, apply design patterns appropriately, and make incremental improvements that don't break things. The goal is code that's easier to understand, modify, and extend.
Related Templates
Code Review Prompt Templates
AI prompt templates for thorough code reviews. Get comprehensive feedback on code quality, security, and best practices.
Debugging Prompt Templates
AI prompt templates for debugging code. Identify issues, understand errors, and find solutions faster.
Code Documentation Prompt Templates
AI prompt templates for writing code documentation. Create clear comments, READMEs, and API docs.
Have your own prompt to optimize?