워밍업 클럽 4기 - 백엔드 Day 4

워밍업 클럽 4기 - 백엔드 Day 4

수정내역

  • 썸네일 추가

과제

1. 읽기 좋은 코드로 리팩토링해 보기

AS-IS

public boolean validateOrder(Order order) {
    if (order.getItems().size() == 0) {
        log.info("주문 항목이 없습니다.");
        return false;
    } else {
        if (order.getTotalPrice() > 0) {
            if (!order.hasCustomerInfo()) {
                log.info("사용자 정보가 없습니다.");
                return false;
            } else {
                return true;
            }
        } else if (!(order.getTotalPrice() > 0)) {
            log.info("올바르지 않은 총 가격입니다.");
            return false;
        }
    }
    return true;
}

  

TO-BE

  • Early Return 적용

    • if else 문에 대한 조건에 대하여 if문 별 return이 존재하다는걸 파악하였고 조건에 맞게 Early Return적용

       

    • order가 null일 경우 추가 적용

  • 공백 라인 적용

    • if문에 대한 공백 라인을 적용함으로서 코드의 분기점을 명확하게 구분

  • 부정연산자를 메서드안에 포함하여 메서드명으로 확인할 수 있도록 변경

    • !(order.getTotalPrice() > 0), !order.hasCustomerInfo() 의 가독성 향상을 위한 메서드화

       

  • 예외 처리

    • return false; 에 대해서 각 메서드에서 IllegalArgumentException 예외를 던지도록 수정하였고

    • 예외처리를 통해 log를 try-catch문으로 한번에 처리하도록 수정(1번버전)

 1. 예외처리 버전 ( 다소 엄격 )

public boolean validateOrder(Order order) {
    
    if (order == null) {
       log.info("Order 객체가 null입니다.");
       return false;
    }

    try{
        validateOrderItemsExist(order);
        validateTotalPrice(order);
        validateCustomerInfoPresent(order);
        
        return true;
    }catch(IllegalArgumentException e) {
        log.info(e.getMessage());
        return false;
    }
    
}
public void validateOrderItemsExist(Order order) {
    if (order.getItems().size() == 0) { //order.getItems().isEmpty()도 고려
        throw new IllegalArgumentException("주문 항목이 없습니다.");
    }
}

public void validateTotalPrice(Order order){
    if((order.getTotalPrice() <= 0)){ 
         throw new IllegalArgumentException("올바르지 않은 총 가격입니다.");
    }
}


public void validateCustomerInfoPresent(Order order) { 
    if (!order.hasCustomerInfo()) {
        throw new IllegalArgumentException("주문에 사용자 정보가 필요합니다.");
    }
}

 2. 예외처리 미적용

public boolean validateOrder(Order order) {
    if (isOrderNull(order)) return false;
    if (isOrderItemsEmpty(order)) return false;
    if (isTotalPriceInvalid(order)) return false;
    if (isCustomerInfoMissing(order)) return false;

    return true;
}
public boolean isOrderNull(Order order) {
    if (order == null) {
       log.info("Order 객체가 null입니다.");
       return true;
    }
    return false;
}
public boolean isOrderItemsEmpty(Order order) {
    if (order.getItems().size() == 0) { //order.getItems().isEmpty()도 고려
        log.info("주문 항목이 없습니다.");
        return true;
    }
    return false;
}

public boolean isTotalPriceInvalid(Order order) {
    if((order.getTotalPrice() <= 0)){ 
        log.info("올바르지 않은 총 가격입니다.");
        return true;
    }
    return false;
}

public boolean isCustomerInfoMissing(Order order) {
    if (!order.hasCustomerInfo()) {
        log.info("사용자 정보가 없습니다.");
        return true;
    }
    return false;
}

  

2. SOLID에 대하여 자기만의 언어로 정리해 봅시다.

 

1.  SRP - Single Responsibility Principle(단일 책임 원칙)

한 클래스는 딱 하나의 역할만 하자.

  • 하나의 클래스가 너무 많은 일을 하려고 하지 말자.

     

 

2.  OCP- Open/Closed Principle(개방/폐쇄 원칙)

기존 코드를 고치지 않고, 기능을 확장할 수 있어야 한다.

  • 수정에는 닫혀 있고, 확장에는 열려 있어야 한다.

  • 조건문을 늘리기보다는 새로운 클래스를 추가해 기능을 확장하자.

 

3.  LSP - Liskov Substitution Principle(리스코프 치환 원칙)

부모 타입을 사용하는 곳에 자식 타입을 써도 제대로 작동해야 한다.

  • 부모 클래스의 역할을 자식이 완전히 대체할 수 있어야 한다.

  • 자식 클래스가 부모의 약속을 깨면 안 된다.

     

 

4. ISP - Interface Segregation Principle(인터페이스 분리 원칙)

쓸데없는 인터페이스는 나눠서 큰 종합세트를 주지말고 작은 인터페이스 여러개가 좋다

  • 클라이언트가 사용하지 않는 메서드에 의존하게 하지 말자.

  • 하나의 거대한 인터페이스보다는, 작은 인터페이스 여러 개가 좋다.

     

     

5. DIP - Dependency Inversion Principle(의존 역전 원칙)

고수준 모듈은 저수준 모듈에 의존하지 말고, 추상(인터페이스)에 의존하자.

  • 핵심 로직(고수준)이 세부 구현(저수준)에 끌려다니면 유연성이 떨어진다.

  • 인터페이스를 사이에 두고 서로 느슨하게 연결하자.

     

     

 


강의

Readable Code: 읽기 좋은 코드를 작성하는 사고법

댓글을 작성해보세요.

채널톡 아이콘