800===Dev Docs and License/Clean Code

코드 품질 향상을 위한 대형 메서드 분리 기법 🚀

블로글러 2024. 12. 6. 00:27

대형 메서드란? 🤔

한 메서드에 너무 많은 일을 하고 있는 코드를 말합니다.
마치 주방에서 한 명의 요리사가 전처리, 조리, 플레이팅까지 모든 것을 혼자 하려고 하는 것과 같죠!

왜 메서드를 분리해야 할까요? 📝

  1. 코드 가독성 향상

    • 작은 단위로 나누면 각 부분의 역할이 명확해짐
    • 마치 책의 목차처럼 구조화된 코드 생성
  2. 유지보수 용이성

    • 버그 수정이 쉬워짐
    • 기능 확장이 편리해짐
  3. 코드 재사용성

    • 분리된 작은 메서드는 다른 곳에서도 활용 가능

메서드 분리 기법 🎯

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;
}

분리 시 고려사항 ⚠️

  1. 메서드 이름

    • 동사+명사 형태 권장
    • 기능을 명확하게 표현
    • 예: processPayment, validateUserInput
  2. 매개변수 개수

    • 4개 이하 권장
    • 많다면 DTO 사용 고려
  3. 응집도

    • 하나의 메서드는 하나의 작업만
    • 관련 있는 코드끼리 모으기

리팩토링 체크리스트 📋

  1. 메서드가 한 가지 일만 하는가?
  2. 메서드 이름이 기능을 잘 설명하는가?
  3. 중복 코드가 제거되었는가?
  4. 테스트가 용이한가?
  5. 코드의 재사용성이 향상되었는가?

참고문헌

  • 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