ETC

[Refactoring] 12 ~ 14. 반복되는 switch 문 / 반복문 / 성의없는 요소

mxruhxn 2025. 1. 4. 16:38
728x90
반응형

반복되는 switch 문(Repeated Swithces)

  • 반복해서 동일한 switch 문이 존재할 경우
    • => 새로운 조건을 추가하거나 기존의 조건을 변경할 때 모든 switch 문을 찾아서 코드를 고쳐야 할지도 모름
    • 반복해서 등장하는 것이 아니라면 굳이 리팩토링을 적용할 필요는 없다
    • => 이전 시간에 사용한 "조건부 로직을 다형성으로 바꾸기(Replace Conditional with Polymorphism)" 리팩토링 적용

요즘에는 switch 문이 arrow function 형태로 세련되게 나오기 때문에 이를 사용하는 것을 권장한다 (ex. jdk 17 버전 이상)
이를 switch 문이 아니라, switch-expression 이라고 한다.

// switch 문 (아래 코드엔 break가 없어서 버그 존재)
public int vacationHours(String type) {
    int result;

    switch (type) {
        case "full-time": result = 120;
        case "part-time": result = 80;
        case "temporal": result = 32;
        default: result = 0;
    }

    return result;
}

---

// switch expression
public int vacationHours(String type) {
    return switch (type) {
        case "full-time" -> 120;
        case "part-time" -> 80;
        case "temporal" -> 32;
        default -> 0;
    };
}

반복문(Loops)

  • 최근 함수형 프로그래밍을 지원하면서 반복문에 비해 더 나은 대안책이 생겼다
    • => "반복문을 파이프라인으로 바꾸기(Replace Loop with Pipeline)" 을 적용하면 필터나 매핑과 같은 파이프라인 기능을 사용해 보다 빠르게 어떤 작업을 하는지 파악할 수 있다.
  • 반복문이 나쁘다는 것이 아니다!!

반복문을 파이프라인으로 바꾸기(Replace Loop with Pipeline)

  • Collection Pipeline (ex. Java 8의 Stream, C#의 LINQ)
  • 고전적인 반복문을 파이프라인 오퍼레이션을 사용해 표현하면 코드를 더 명확하게 만들 수 있음
    • 필터(filter): 전달받은 조건의 true에 해당하는 데이터만 다음 오퍼레이션으로 전달
    • 맵(map): 전달받은 함수를 사용해 입력값을 원하는 출력값으로 변환하여 다음 오퍼레이션으로 전달

예제 코드

static public List<String> TwitterHandles(List<Author> authors, String company) {
    var result = new ArrayList<String> ();
    for (Author a : authors) {
        if (a.company.equals(company)) {
            var handle = a.twitterHandle;
            if (handle != null)
                result.add(handle);
        }
    }
    return result;
}

 

위 코드의 고전적인 반복문을 Stream으로 더 명확하게 변경해보자.

static public List<String> TwitterHandles(List<Author> authors, String company) {
    return authors.stream()
            .filter(author -> author.company.equals(company))
            .map(author -> author.twitterHandle)
            .filter(Objects::nonNull)
            .toList();
}

성의없는 요소(Lazy Element)

  • 가끔 변수, 메서드, 클래스 등을 만들어 놓았지만 불필요해지는 경우가 있는데, 그런 경우 해당 요소들을 제거해야 함
  • 관련 리팩토링 기술
    • "함수 인라인(Inline Function)"
    • "클래스 인라인(Inline Class)"
    • "계층 합치기(Collapse Hierarchy)" -> 불필요한 상속 구조 제거

계층 합치기(Collapse Hierarchy)

  • 상속 구조를 리팩토링 하는 중에 기능을 올리고 내리다 보면, 하위클래스와 상위 클래스 코드에 차이가 없는 경우가 발생하기도 함
    • => 그 둘을 합치자!
  • 하위 클래스와 상위 클래스 중에 어떤 것을 없애야 하는가?
    • 둘 중에 보다 이름이 적절한 쪽을 선택하지만, 애매하다면 어느 쪽을 선택해도 문제 X
public class Reservation {

    private LocalDateTime startDateTime;

    private LocalDateTime endDateTime;

    private List<String> members;

    private String owner;

    private boolean paid;

}

---

public class CourtReservation extends Reservation {

    private String courtNumber;

}

 

CourReservation 이라는 정보를 다른 용도로 사용하지 않는다면, courtNumber를 상위 클래스로 올릴 수 있다. 혹은, CourtReservation 이라는 이름이 더 적절하다고 생각되면, Reservation의 모든 필드를 CourReservation으로 내릴 수도 있다.

// Reservation은 비어있으므로 삭제
public class CourtReservation {

    private String courtNumber;
    private LocalDateTime startDateTime;
    private LocalDateTime endDateTime;
    private List<String> members;
    private String owner;
    private boolean paid;
}
728x90
반응형