들어가며 🌟
이번 시리즈에서는 파이썬 코드 리팩토링의 핵심 기법들을 자세히 살펴보겠습니다. Part 1에서는 코드 구조 개선에 초점을 맞춰보겠습니다.
1. 함수 추출 기법 (Extract Method) 🔍
문제 상황
def process_order(order):
# 100줄 이상의 복잡한 코드
# 주문 유효성 검사
if not order.items:
raise ValueError("주문 항목이 비어있습니다")
if order.total_amount <= 0:
raise ValueError("주문 금액이 유효하지 않습니다")
# 재고 확인
for item in order.items:
if item.quantity > item.product.stock:
raise ValueError(f"{item.product.name}의 재고가 부족합니다")
# 결제 처리
payment_result = payment_gateway.process_payment(order.total_amount)
if not payment_result.success:
raise PaymentError("결제 실패")
# 주문 저장
order.status = "PAID"
order.payment_id = payment_result.id
db.save(order)
개선된 코드
def process_order(order):
"""주문을 처리하고 결제를 진행합니다."""
validate_order(order)
check_inventory(order)
process_payment(order)
save_order(order)
def validate_order(order):
"""주문의 유효성을 검사합니다."""
if not order.items:
raise ValueError("주문 항목이 비어있습니다")
if order.total_amount <= 0:
raise ValueError("주문 금액이 유효하지 않습니다")
def check_inventory(order):
"""주문 항목의 재고를 확인합니다."""
for item in order.items:
if item.quantity > item.product.stock:
raise ValueError(f"{item.product.name}의 재고가 부족합니다")
def process_payment(order):
"""주문에 대한 결제를 처리합니다."""
payment_result = payment_gateway.process_payment(order.total_amount)
if not payment_result.success:
raise PaymentError("결제 실패")
order.payment_id = payment_result.id
def save_order(order):
"""처리된 주문을 저장합니다."""
order.status = "PAID"
db.save(order)
2. 매개변수 객체화 (Introduce Parameter Object) 📦
문제 상황
def calculate_shipping(weight, height, width, length, destination, is_express):
# 복잡한 배송비 계산 로직
pass
# 사용
shipping_cost = calculate_shipping(2.5, 10, 20, 15, "Seoul", True)
개선된 코드
from dataclasses import dataclass
from typing import Optional
@dataclass
class ShippingParameters:
"""배송 계산에 필요한 매개변수를 포함하는 클래스입니다."""
weight: float
height: float
width: float
length: float
destination: str
is_express: bool = False
def volume(self) -> float:
"""화물의 부피를 계산합니다."""
return self.height * self.width * self.length
@dataclass
class ShippingCalculator:
"""배송비 계산을 처리하는 클래스입니다."""
base_rate: float = 1000
express_multiplier: float = 1.5
def calculate_cost(self, params: ShippingParameters) -> float:
"""배송비를 계산합니다."""
volume_cost = params.volume() * 0.1
weight_cost = params.weight * 100
base_cost = self.base_rate + volume_cost + weight_cost
return base_cost * self.express_multiplier if params.is_express else base_cost
# 사용
params = ShippingParameters(
weight=2.5,
height=10,
width=20,
length=15,
destination="Seoul",
is_express=True
)
calculator = ShippingCalculator()
shipping_cost = calculator.calculate_cost(params)
3. 조건문 간소화 (Simplify Conditional) 🔀
문제 상황
def get_user_discount(user):
discount = 0
if user.is_registered:
if user.purchase_count > 100:
if user.total_amount > 1000000:
discount = 0.2
else:
discount = 0.1
else:
if user.total_amount > 500000:
discount = 0.05
else:
discount = 0.02
return discount
개선된 코드
from enum import Enum
from dataclasses import dataclass
class CustomerTier(Enum):
"""고객 등급을 정의합니다."""
BRONZE = "BRONZE"
SILVER = "SILVER"
GOLD = "GOLD"
PLATINUM = "PLATINUM"
@dataclass
class DiscountRule:
"""할인 규칙을 정의하는 클래스입니다."""
min_purchase_count: int
min_total_amount: int
discount_rate: float
class DiscountCalculator:
"""할인율을 계산하는 클래스입니다."""
def __init__(self):
self.discount_rules = {
CustomerTier.PLATINUM: DiscountRule(100, 1000000, 0.2),
CustomerTier.GOLD: DiscountRule(100, 500000, 0.1),
CustomerTier.SILVER: DiscountRule(50, 500000, 0.05),
CustomerTier.BRONZE: DiscountRule(0, 0, 0.02)
}
def get_customer_tier(self, user) -> CustomerTier:
"""사용자의 등급을 결정합니다."""
if not user.is_registered:
return 0
if user.purchase_count > 100 and user.total_amount > 1000000:
return CustomerTier.PLATINUM
elif user.purchase_count > 100:
return CustomerTier.GOLD
elif user.total_amount > 500000:
return CustomerTier.SILVER
return CustomerTier.BRONZE
def calculate_discount(self, user) -> float:
"""사용자의 할인율을 계산합니다."""
tier = self.get_customer_tier(user)
rule = self.discount_rules.get(tier)
return rule.discount_rate if rule else 0
# 사용
calculator = DiscountCalculator()
discount = calculator.calculate_discount(user)
정리 🎁
Part 1에서는 코드 구조를 개선하는 세 가지 핵심 기법을 살펴보았습니다:
- 함수 추출로 복잡한 로직 분리
- 매개변수 객체화로 데이터 구조화
- 조건문 간소화로 로직 명확화
다음 Part 2에서는 성능 최적화와 관련된 리팩토링 기법들을 다루겠습니다.
References:
- Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin) - Chapter 3, 6
- Python Clean Code Documentation - PEP 8
- Design Patterns: Elements of Reusable Object-Oriented Software (Gang of Four) - Chapter 1
- Python Design Patterns Guide (https://python-patterns.guide/)
728x90
'800===Dev Docs and License > Clean Code' 카테고리의 다른 글
파이썬 코드 리팩토링 마스터 가이드 - Part 3: 코드 테스트와 유지보수성 향상 🧪 (0) | 2025.01.07 |
---|---|
파이썬 코드 리팩토링 마스터 가이드 - Part 2: 성능 최적화 핵심 가이드 💫 (0) | 2025.01.07 |
파이썬 코드 리팩토링의 핵심 가이드 🎯 (0) | 2025.01.07 |
SOLID 원칙 완벽 가이드 🚀 (1) | 2024.12.06 |
코드 품질 향상을 위한 대형 메서드 분리 기법 🚀 (1) | 2024.12.06 |