Simplify and refactor code while preserving behavior, improving clarity, and reducing complexity. Use when simplifying complex code, removing duplication, or applying design patterns. Handles Extract Method, DRY principle, SOLID principles, behavior validation, and refactoring patterns.
87
82%
Does it follow best practices?
Impact
96%
1.11xAverage score across 3 eval scenarios
Passed
No known issues
Before (long function):
function processOrder(order: Order) {
// Validation
if (!order.items || order.items.length === 0) {
throw new Error('Order must have items');
}
if (!order.customerId) {
throw new Error('Order must have customer');
}
// Price calculation
let total = 0;
for (const item of order.items) {
total += item.price * item.quantity;
}
const tax = total * 0.1;
const shipping = total > 100 ? 0 : 10;
const finalTotal = total + tax + shipping;
// Inventory check
for (const item of order.items) {
const product = await db.product.findUnique({ where: { id: item.productId } });
if (product.stock < item.quantity) {
throw new Error(`Insufficient stock for ${product.name}`);
}
}
// Create order
const newOrder = await db.order.create({
data: {
customerId: order.customerId,
items: order.items,
total: finalTotal,
status: 'pending'
}
});
return newOrder;
}After (method extraction):
async function processOrder(order: Order) {
validateOrder(order);
const total = calculateTotal(order);
await checkInventory(order);
return await createOrder(order, total);
}
function validateOrder(order: Order) {
if (!order.items || order.items.length === 0) {
throw new Error('Order must have items');
}
if (!order.customerId) {
throw new Error('Order must have customer');
}
}
function calculateTotal(order: Order): number {
const subtotal = order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
const tax = subtotal * 0.1;
const shipping = subtotal > 100 ? 0 : 10;
return subtotal + tax + shipping;
}
async function checkInventory(order: Order) {
for (const item of order.items) {
const product = await db.product.findUnique({ where: { id: item.productId } });
if (product.stock < item.quantity) {
throw new Error(`Insufficient stock for ${product.name}`);
}
}
}
async function createOrder(order: Order, total: number) {
return await db.order.create({
data: {
customerId: order.customerId,
items: order.items,
total,
status: 'pending'
}
});
}Before (duplication):
async function getActiveUsers() {
return await db.user.findMany({
where: { status: 'active', deletedAt: null },
select: { id: true, name: true, email: true }
});
}
async function getActivePremiumUsers() {
return await db.user.findMany({
where: { status: 'active', deletedAt: null, plan: 'premium' },
select: { id: true, name: true, email: true }
});
}After (extract common logic):
type UserFilter = {
plan?: string;
};
async function getActiveUsers(filter: UserFilter = {}) {
return await db.user.findMany({
where: {
status: 'active',
deletedAt: null,
...filter
},
select: { id: true, name: true, email: true }
});
}
// Usage
const allActiveUsers = await getActiveUsers();
const premiumUsers = await getActiveUsers({ plan: 'premium' });Before (long if-else):
class PaymentProcessor {
process(payment: Payment) {
if (payment.method === 'credit_card') {
// Credit card processing
const cardToken = this.tokenizeCard(payment.card);
const charge = this.chargeCreditCard(cardToken, payment.amount);
return charge;
} else if (payment.method === 'paypal') {
// PayPal processing
const paypalOrder = this.createPayPalOrder(payment.amount);
const approval = this.getPayPalApproval(paypalOrder);
return approval;
} else if (payment.method === 'bank_transfer') {
// Bank transfer processing
const transfer = this.initiateBankTransfer(payment.account, payment.amount);
return transfer;
}
}
}After (polymorphism):
interface PaymentMethod {
process(payment: Payment): Promise<PaymentResult>;
}
class CreditCardPayment implements PaymentMethod {
async process(payment: Payment): Promise<PaymentResult> {
const cardToken = await this.tokenizeCard(payment.card);
return await this.chargeCreditCard(cardToken, payment.amount);
}
}
class PayPalPayment implements PaymentMethod {
async process(payment: Payment): Promise<PaymentResult> {
const order = await this.createPayPalOrder(payment.amount);
return await this.getPayPalApproval(order);
}
}
class BankTransferPayment implements PaymentMethod {
async process(payment: Payment): Promise<PaymentResult> {
return await this.initiateBankTransfer(payment.account, payment.amount);
}
}
class PaymentProcessor {
private methods: Map<string, PaymentMethod> = new Map([
['credit_card', new CreditCardPayment()],
['paypal', new PayPalPayment()],
['bank_transfer', new BankTransferPayment()]
]);
async process(payment: Payment): Promise<PaymentResult> {
const method = this.methods.get(payment.method);
if (!method) {
throw new Error(`Unknown payment method: ${payment.method}`);
}
return await method.process(payment);
}
}Before (many parameters):
function createUser(
name: string,
email: string,
password: string,
age: number,
country: string,
city: string,
postalCode: string,
phoneNumber: string
) {
// ...
}After (grouped into object):
interface UserProfile {
name: string;
email: string;
password: string;
age: number;
}
interface Address {
country: string;
city: string;
postalCode: string;
}
interface CreateUserParams {
profile: UserProfile;
address: Address;
phoneNumber: string;
}
function createUser(params: CreateUserParams) {
const { profile, address, phoneNumber } = params;
// ...
}
// Usage
createUser({
profile: { name: 'John', email: 'john@example.com', password: 'xxx', age: 30 },
address: { country: 'US', city: 'NYC', postalCode: '10001' },
phoneNumber: '+1234567890'
});Single Responsibility:
// ❌ Bad example: multiple responsibilities
class User {
constructor(public name: string, public email: string) {}
save() {
// Save to DB
}
sendEmail(subject: string, body: string) {
// Send email
}
generateReport() {
// Generate report
}
}
// ✅ Good example: separated responsibilities
class User {
constructor(public name: string, public email: string) {}
}
class UserRepository {
save(user: User) {
// Save to DB
}
}
class EmailService {
send(to: string, subject: string, body: string) {
// Send email
}
}
class UserReportGenerator {
generate(user: User) {
// Generate report
}
}- [ ] Function does one thing only (SRP)
- [ ] Function name clearly describes what it does
- [ ] Function is 20 lines or fewer (guideline)
- [ ] 3 or fewer parameters
- [ ] No duplicate code (DRY)
- [ ] if nesting is 2 levels or fewer
- [ ] No magic numbers (extract as constants)
- [ ] Understandable without comments (self-documenting)Fully understand current behavior before refactoring:
## Behavior Analysis
### Inputs
- [list of input parameters]
- [types and constraints]
### Outputs
- [return values]
- [side effects]
### Invariants
- [conditions that must always be true]
- [edge cases]
### Dependencies
- [external dependencies]
- [state dependencies]# 1. Run tests
npm test -- --coverage
# 2. Type check
npx tsc --noEmit
# 3. Lint check
npm run lint
# 4. Compare with previous behavior (snapshot tests)
npm test -- --updateSnapshot## Refactoring Summary
### Changes Made
1. [Change 1]: [reason]
2. [Change 2]: [reason]
### Behavior Preserved
- [x] Same input → same output
- [x] Same side effects
- [x] Same error handling
### Risks & Follow-ups
- [potential risks]
- [follow-up tasks]
### Test Status
- [ ] Unit tests: passing
- [ ] Integration tests: passing
- [ ] E2E tests: passingCause: Behavior change occurred Solution: Revert and isolate the change, then retry
Cause: Multiple responsibilities mixed in one function Solution: Extract into smaller units with clear boundaries
Cause: Inefficient abstraction introduced Solution: Profile and optimize the hot path
| Agent | Role |
|---|---|
| Claude | Refactoring plan, code transformation |
| Gemini | Large-scale codebase analysis, pattern detection |
| Codex | Test execution, build verification |
# 1. Gemini: Codebase analysis
ask-gemini "@src/ extract list of high-complexity functions"
# 2. Claude: Refactoring plan and execution
# Work based on IMPLEMENTATION_PLAN.md
# 3. Codex: Verification
codex-cli shell "npm test && npm run lint"#refactoring #code-quality #DRY #SOLID #design-patterns #clean-code
c033769
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.