워밍업 클럽 4기 BE 클린코드 & 테스트 < Day4 미션 - 리팩토링, SOLID >
Day4 미션 - 1. 리팩토링 하기✔ 사용자가 생성한 '주문'이 유효한지를 검증하는 메서드.✔ Order는 주문 객체이고, 필요하다면 Order에 추가적인 메서드를 만들어도 된다. (Order 내부의 구현을 구체적으로 할 필요는 없다.)✔ 필요하다면 메서드를 추출할 수 있다.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; } 리팩토링한 코드public class Day4 { public boolean validateOrder(Order order) { try { if (order.notExistItem()) { throw new IllegalArgumentException("주문 항목이 없습니다."); return false; } if (order.incorrectTotalPrice()) { throw new IllegalArgumentException("올바르지 않은 총 가격입니다."); return false; } if (order.notExistCustomerInfo()) { throw new IllegalArgumentException("사용자 정보가 없습니다."); return false; } return true; } catch (IllegalArgumentException e) { log.error("주문 검증 중 예외 발생: {}", e.getMessage()); return false; } } } class Order { private List<Item> items; private Customer customer; public boolean notExistItem() { // 아이템 있는지 확인하는 로직 return true; // 예시로 true 반환 } public double totalPrice() { // 총 가격 계산 로직 return totalPrice; } public boolean incorrectTotalPrice() { return totalPrice() < 0; } public boolean notExistCustomerInfo() { // 사용자 정보가 있는지 확인하는 로직 return true; // 예시로 true 반환 } }중첩 조건문을 분해해서 Early Return을 적용했다.부정어 제거 + 객체 설계. 객체 설계는 섹션3의 내용은 아니지만 함께 적용했다. 부정어를 사용하는 대신 부정의 의미를 나타내는 메서드를 만들고, 해당 메서드는 Order 객체 내에서 처리했다.if문 조건문의 추상화 수준을 같게 설정했다.단순 로그만 찍는 코드에서 예외처리로 변경했다. Day4 미션 - 2. SOLID 나만의 언어로 정의하기SOLID란, 객체지향 설계에서 지켜줘야 할 5개의 소프트웨어 개발 원칙이다. 1. Single Responsibility Principle; 단일 책임 원칙하나의 객체에 하나의 책임만!객체가 갖는 책임이 많아질수록 다른 객체들과의 관계가 깊어지게 된다. 즉, 결합도(의존성)가 늘어난다.결합도(의존성)가 크면 해당 객체의 변경에 따른 영향도와 범위가 커지게 된다.따라서 객체 하나에는 하나의 책임만 부여하여 응집도는 높게, 결합도(의존성)는 낮게 설계해야 한다. 2. Open-Closed Principle; 개방-폐쇄 원칙확장에는 열려있고, 수정에는 닫혀있게.신규 기능이 추가되어야 할 때, 기존 코드의 변경 없이 시스템 확장이 가능하게 설계해야 한다. 3. Liskov Substitution Principle; 리스코프 치환 원칙상속 구조에서, 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 치환할 수 있어야 한다.즉, 가업승계 하듯이 부모 클래스가 일하던 곳에 자식 클래스가 가더라도 문제가 없어야 한다.자식 클래스는 부모의 모든 책임을 준수하며, 부모 클래스를 변경하지 않아야 한다.만약 LSP를 위반하면, 오동작하거나 예상 밖의 예외가 발생하게 된다. 4. Interface Segregation Principle; 인터페이스 분리 원칙기능 단위로 인터페이스를 분리 설계할 것하나의 인터페이스에 추상 메서드들을 이것저것 구현한다면,그 인터페이스를 상속받은 클래스는 자신이 사용하지 않는 메서드마저 억지로 구현해야 하는 상황이 올 수 있다.이런 불필요한 의존성으로 인해 결합도가 높아지고, 특정 기능이 여러 클래스에 영향을 미치게 된다. 5. Dependency Inversion Principle; 의존 역전 원칙객체들이 서로 정보를 주고 받을 때 의존 관계가 형성되는데, 이 때 하나의 약속이 있다.나(객체)보다 추상화 례벨이 높은 상위 수준의 모듈과 통신해야 한다는 약속이다.의존 역전 원칙은 고수준 모듈과 저수준 모듈 모두 추상화된 인터페이스에 의존해야 한다는 원칙이다.이 원칙을 지키면 저수준 모듈(구현체)가 바뀌어도 고수준 모듈에는 영향이 없다는 장점이 있다.== 결합도가 낮아짐 == 유지보수가 쉬워짐