본문 바로가기
독서/모던 자바 인 액션

동작 파라미터화1

by kriorsen 2023. 9. 24.

동작 파라미터화란?

아직은 어떻게 실행할 것인지 결정하지 않은 코드 블록을 의미한다.

변화하는 요구사항에 대응하는 법

우리가 현재 도서부의 일원이고 사서 선생님의 요구에 맞는 책들을 모두 찾아내야 하는 상황이라고 가정해 보자.

1.1 과학 책 분류하기

// 책의 카테고리를 정의하는 enum
enum Category { Science, Economy, Literature } 

public static List<Book> filterScieneBooks(List<Book> bookshelf) {
    List<Book> scienceBooks = new ArrayList<>();
    for (Book book : bookshelf) {
        if (Science.equals(book.getCategory()) {
            scienceBooks.add(book);
           }
    }
    return scienceBooks;
}

이렇게 과학 책을 찾아내는 코드를 작성했는데, 갑자기 선생님께서 경제에 관련된 책 또한 분류를 요구한다면 어떻게 해야 할까? 물론 제일 간단한 방법으로는 filterEconomyBooks라는 메서드를 만드는 방법도 있겠지만 분류를 요구하는 카테고리가 다섯 개, 열 개 혹은 그 이상이 된다면 모든 카테고리에 대해 각각의 메서드를 작성하는 방식은 효율적이지 않다. * 만약 비슷한 코드가 반복된다면 그 코드를 추상화하는 방법을 택할 수 있다. *

1.2 카테고리를 파라미터화

public static List<Book> filterBooksByCategory(List<Book> bookshelf, Category category) {
    List<Book> result = new ArrayList<>();
    for (Book book : bookshelf) {
        if (book.getCategory().equals(category)) {
            result.add(book);
           }
    }
    return result;
}

그럼 이제 다음과 같이 언제든 원하는 카테고리에 맞는 책을 찾을 수 있다.

List<Book> scienceBooks = filterBooksByCategory(bookshelf, Science);
List<Book> economicBooks = filterBooksByCategory(bookshelf, Economy);

그런데 선생님께서 이번에는 페이지가 500 이상인 책을 요구한다면 코드를 어떻게 작성해야 할까?

public static List<Book> filterBooksByPage(List<Book> bookshelf, int page) {
    List<Book> result = new ArrayList<>();
    for (Book book : bookshelf) {
        if (book.getPage() >= page) {
            result.add(book);
           }
    }
    return result;
}

위 코드처럼 Page로 책들을 분류하는 메서드를 새로 정의할 수 있지만 이렇게 할 경우 filterBooksByCategory와 중복되는 부분이 많다는 것을 알 수 있다. 그렇다면 필터링할 기준에 대한 플래그 정보까지 인자로 추가해서 메서드 작성을 시도해 볼 수 있다.

public static List<Book> filterBooks(List<Book> bookshelf, Category category,
                                    int page, boolean flag) {
    List<Book> result = new ArrayList<>();
    for (Book book : bookshelf) {
        if ((flag && book.getCategory().equals(category)) || 
            (!flag && book.getPage() >= page)) {
            result.add(book);
           }
    }
    return result;
}

그렇다면 코드 호출은 다음과 같이 이루어질 수 있다.

List<Book> scienceBooks = filterBooks(bookshelf, Science, 0, true);
List<Book> thickBooks = filterBooks(bookshelf, null, 500, false);

늘어난 인자들로 인해 코드 가독성이 급격하게 떨어졌고 마지막 boolean 값은 뭘 의미하는지도 와닿지 않는다. 무엇보다 필터링의 조건이 더 늘어난다고 매번 메서드를 수정하는 것도 번거로운 일이다. 이에 대한 해결책은 다음 포스트에서 구체적으로 다루도록 하겠다.