Loading...
Loading...
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.
npx skill4agent add supercent-io/skills-template code-refactoringfunction processOrder(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');
}
// 가격 계산
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;
// 재고 확인
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}`);
}
}
// 주문 생성
const newOrder = await db.order.create({
data: {
customerId: order.customerId,
items: order.items,
total: finalTotal,
status: 'pending'
}
});
return newOrder;
}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'
}
});
}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 }
});
}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 }
});
}
// 사용
const allActiveUsers = await getActiveUsers();
const premiumUsers = await getActiveUsers({ plan: 'premium' });class PaymentProcessor {
process(payment: Payment) {
if (payment.method === 'credit_card') {
// 신용카드 처리
const cardToken = this.tokenizeCard(payment.card);
const charge = this.chargeCreditCard(cardToken, payment.amount);
return charge;
} else if (payment.method === 'paypal') {
// PayPal 처리
const paypalOrder = this.createPayPalOrder(payment.amount);
const approval = this.getPayPalApproval(paypalOrder);
return approval;
} else if (payment.method === 'bank_transfer') {
// 은행 이체 처리
const transfer = this.initiateBankTransfer(payment.account, payment.amount);
return transfer;
}
}
}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);
}
}function createUser(
name: string,
email: string,
password: string,
age: number,
country: string,
city: string,
postalCode: string,
phoneNumber: string
) {
// ...
}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;
// ...
}
// 사용
createUser({
profile: { name: 'John', email: 'john@example.com', password: 'xxx', age: 30 },
address: { country: 'US', city: 'NYC', postalCode: '10001' },
phoneNumber: '+1234567890'
});// ❌ 나쁜 예: 여러 책임
class User {
constructor(public name: string, public email: string) {}
save() {
// DB 저장
}
sendEmail(subject: string, body: string) {
// 이메일 발송
}
generateReport() {
// 리포트 생성
}
}
// ✅ 좋은 예: 책임 분리
class User {
constructor(public name: string, public email: string) {}
}
class UserRepository {
save(user: User) {
// DB 저장
}
}
class EmailService {
send(to: string, subject: string, body: string) {
// 이메일 발송
}
}
class UserReportGenerator {
generate(user: User) {
// 리포트 생성
}
}- [ ] 함수는 한 가지 일만 한다 (SRP)
- [ ] 함수 이름이 하는 일을 명확히 설명한다
- [ ] 함수는 20줄 이하 (가이드라인)
- [ ] 매개변수는 3개 이하
- [ ] 중복 코드 없음 (DRY)
- [ ] if 중첩은 2단계 이하
- [ ] 매직 넘버 없음 (상수로 추출)
- [ ] 주석 없이도 이해 가능 (자기 문서화)## Behavior Analysis
### Inputs
- [입력 파라미터 목록]
- [타입 및 제약사항]
### Outputs
- [반환값]
- [부수 효과 (side effects)]
### Invariants
- [항상 참이어야 하는 조건들]
- [경계 조건 (edge cases)]
### Dependencies
- [외부 의존성]
- [상태 의존성]# 1. 테스트 실행
npm test -- --coverage
# 2. 타입 체크
npx tsc --noEmit
# 3. 린트 확인
npm run lint
# 4. 이전 동작과 비교 (스냅샷 테스트)
npm test -- --updateSnapshot## Refactoring Summary
### Changes Made
1. [변경 1]: [이유]
2. [변경 2]: [이유]
### Behavior Preserved
- [x] 동일한 입력 → 동일한 출력
- [x] 부수 효과 동일
- [x] 에러 처리 동일
### Risks & Follow-ups
- [잠재적 위험]
- [후속 작업]
### Test Status
- [ ] Unit tests: passing
- [ ] Integration tests: passing
- [ ] E2E tests: passing| Agent | Role |
|---|---|
| Claude | 리팩토링 계획, 코드 변환 |
| Gemini | 대규모 코드베이스 분석, 패턴 탐지 |
| Codex | 테스트 실행, 빌드 검증 |
# 1. Gemini: 코드베이스 분석
ask-gemini "@src/ 복잡도 높은 함수 목록 추출"
# 2. Claude: 리팩토링 계획 및 실행
# IMPLEMENTATION_PLAN.md 기반 작업
# 3. Codex: 검증
codex-cli shell "npm test && npm run lint"#refactoring#code-quality#DRY#SOLID#design-patterns#clean-code