대형 메서드란? 🤔
한 메서드에 너무 많은 일을 하고 있는 코드를 말합니다.
마치 주방에서 한 명의 요리사가 전처리, 조리, 플레이팅까지 모든 것을 혼자 하려고 하는 것과 같죠!
왜 메서드를 분리해야 할까요? 📝
코드 가독성 향상
- 작은 단위로 나누면 각 부분의 역할이 명확해짐
- 마치 책의 목차처럼 구조화된 코드 생성
유지보수 용이성
- 버그 수정이 쉬워짐
- 기능 확장이 편리해짐
코드 재사용성
- 분리된 작은 메서드는 다른 곳에서도 활용 가능
메서드 분리 기법 🎯
1. 추상화 수준별 분리
// 개선 전
public void processOrder(Order order) {
// 주문 유효성 검증
if (order == null || order.getItems().isEmpty()) {
throw new IllegalArgumentException("주문이 유효하지 않습니다.");
}
// 재고 확인
for (OrderItem item : order.getItems()) {
if (stockRepository.getStock(item.getProductId()) < item.getQuantity()) {
throw new OutOfStockException("재고가 부족합니다.");
}
}
// 결제 처리
Payment payment = paymentService.process(order.getTotalAmount());
// 주문 저장
orderRepository.save(order);
}
// 개선 후
public void processOrder(Order order) {
validateOrder(order);
checkStock(order);
processPayment(order);
saveOrder(order);
}
private void validateOrder(Order order) {
if (order == null || order.getItems().isEmpty()) {
throw new IllegalArgumentException("주문이 유효하지 않습니다.");
}
}
private void checkStock(Order order) {
order.getItems().forEach(this::validateStock);
}
private void validateStock(OrderItem item) {
if (stockRepository.getStock(item.getProductId()) < item.getQuantity()) {
throw new OutOfStockException("재고가 부족합니다.");
}
}
2. 단일 책임 원칙 적용
// 개선 전
public void handleUserRegistration(UserDto userDto) {
// 사용자 정보 검증
if (!isValidEmail(userDto.getEmail())) {
throw new InvalidEmailException();
}
// 비밀번호 암호화
String encodedPassword = passwordEncoder.encode(userDto.getPassword());
// 이메일 중복 체크
if (userRepository.existsByEmail(userDto.getEmail())) {
throw new DuplicateEmailException();
}
// 사용자 저장
User user = new User(userDto.getEmail(), encodedPassword);
userRepository.save(user);
// 환영 이메일 발송
emailService.sendWelcomeEmail(user.getEmail());
}
// 개선 후
public void handleUserRegistration(UserDto userDto) {
validateUserInput(userDto);
User user = createUser(userDto);
saveUser(user);
sendWelcomeEmail(user);
}
3. 조건문 분리
// 개선 전
public double calculateDiscount(Order order) {
double discount = 0;
if (order.getTotalAmount() > 100000) {
if (order.getCustomer().isVip()) {
discount = order.getTotalAmount() * 0.1;
} else if (order.getCustomer().isMember()) {
discount = order.getTotalAmount() * 0.05;
}
} else {
if (order.getCustomer().isFirstOrder()) {
discount = order.getTotalAmount() * 0.03;
}
}
return discount;
}
// 개선 후
public double calculateDiscount(Order order) {
if (isEligibleForPremiumDiscount(order)) {
return calculatePremiumDiscount(order);
}
return calculateBasicDiscount(order);
}
private boolean isEligibleForPremiumDiscount(Order order) {
return order.getTotalAmount() > 100000;
}
private double calculatePremiumDiscount(Order order) {
if (order.getCustomer().isVip()) {
return order.getTotalAmount() * 0.1;
}
return order.getCustomer().isMember() ?
order.getTotalAmount() * 0.05 : 0;
}
분리 시 고려사항 ⚠️
메서드 이름
- 동사+명사 형태 권장
- 기능을 명확하게 표현
- 예:
processPayment
,validateUserInput
매개변수 개수
- 4개 이하 권장
- 많다면 DTO 사용 고려
응집도
- 하나의 메서드는 하나의 작업만
- 관련 있는 코드끼리 모으기
리팩토링 체크리스트 📋
- 메서드가 한 가지 일만 하는가?
- 메서드 이름이 기능을 잘 설명하는가?
- 중복 코드가 제거되었는가?
- 테스트가 용이한가?
- 코드의 재사용성이 향상되었는가?
참고문헌
- Clean Code (Robert C. Martin)
- Refactoring: Improving the Design of Existing Code (Martin Fowler)
- Effective Java (Joshua Bloch)
#Java #CleanCode #Refactoring #개발자성장 #코드품질
728x90
'800===Dev Docs and License > Clean Code' 카테고리의 다른 글
SOLID 원칙 완벽 가이드 🚀 (1) | 2024.12.06 |
---|