우아한형제들/우아한테크코스

[우아한 형제들] 프리코스 마지막 피드백을 받고나서

Jay Tech 2019. 4. 15. 12:06
반응형

프리코스 미션 3주차 피드백을 받았다.

배웠던 것들을 실제로 제대로 활용하지 못했기에 나에게 실망스러웠다.

객체에 메세지를 보내라

2주차 때도 같은 피드백이 있었다. 객체에서 값을 꺼내지말고 메세지를 보내서 구하는 것. 그냥 피드백을 보고 '이해했어!'라고 끝나는 것이 아닌것 같다. 결국 3주차 미션에도 저 피드백을 활용하지 못했다. 프로젝트를 하면서 눈치를 채지 못한것이다. 그럼 난 이해한게 아니다.


public Rank match(Lotto userLotto) {
    int count = (int) userLotto.getNumbers().stream()
                        .filter(i -> lotto.getNumbers().contains(i))
                        .count();
    boolean isBonusMatch = userLotto.getNumbers().stream()
                .anyMatch(i -> i == bonusNo);

    return Rank.valueOf(count, isBonusMatch);
}        

위의 코드는 Lotto 라는 객체에서 몇 개 맞았는지 결과를 반환하여 count변수에 저장한다. Lotto 객체로 넘어왔는데 나는 그 객체에 있는 값을 뜯어서 계산했다.


public Rank match(Lotto userLotto) {
    int countOfMatch = userLotto.countOfMatch(lotto);
    boolean matchBonus = userLotto.isContains(bonusNo);
    return Rank.valueOf(countOfMatch, matchBonus);
}

피드백을 받은 부분이다. 객체에 countOfMatch라는 함수로 메세지를 보내서 결과를 달라고 요청한다. 훨씬 깔끔해졌다. 2주차 때도 같은 방식이었다.

한 번 맞아서 정신을 못차려서 두 대를 맞았다. 두 대를 맞으니까 정신이 드는 것 같다. 객체에 메세지를 보내라.

원시 타입과 문자열을 포장하라

감싸라라는 말을 많이 들었는데 결국 활용하지 못했기에 나는 알고 있는 것이 아니었다.

피드백을 받고 책에 있는 내용을 그제서야 알 것 같더라.

나는 돈이라는 것을 입력 받기 위해 long 타입의 변수를 선언했다. 그리고 그 변수를 입력받고 검증하고 예외처리를 하였다. 그래서 복잡해졌다.


public class Money {
    private static final int MONEY_PER_LOTTO = 1_000;
    private final int money;
    public Money(int money) {
        if (money < MONEY_PER_LOTTO) {
            throw new IllegalArgumentException ("로또 구입금액은 1000원 이상이어야 합니다.");
        }
    this.money = money;
}
...

하지만 저 원시 타입을 Money라는 객체로 포장하였다. 그리고 생성자에서 저렇게 검증을 하여 의도한 값으로 초기화를 시킨다. 저렇게 하면 예외 처리 로직이 반으로 줄어들고 훨씬 간결해짐을 느꼈다.

다음은 클린코드에서의 예제를 다시 복기해 보았다.

정상 흐름이라는 것의 정의


try {
    MealExpenses expenses = expenseReportDAO.getMeals(employee.getId());
    m_total += expenses.getTotal();
} catch (MealExpenseNotFound e) {
    m_total += getMealPerDiem();
}

위 코드는 식비를 비용으로 청구했다면 식비를 총계에 더하는 것이고 청구하지 않았다면 기본 식비를 반환하는 코드이다. 그런데 예외가 논리를 따라가기 어렵게 만든다. 더 간단하게 할 수 있다.


 MealExpenses expenses = expenseReportDAO.getMeals(employee.getId());
 m_total += expenses.getTotal();

과연 위 처럼 간결하게 가능할까? ExpenseReportDAO를 고쳐 언제나 MealExpense 를 반환하면 된다.


// 기본 값으로 일일기본 식비를 반환
public int getTotal() { ... }

이를 특수 사례 패턴 (Special Case Pattern)이라고 한다. 클래스를 만들거나 객체를 조작해 특수 사례를 처리하는 방식이다. 그러면 클라이언트 코드가 예외적인 상황을 처리할 필요가 없어진다. 왜냐하면 클래스나 객체가 상황을 캡슐화해서 처리하기 때문이다.

실제 프로젝트를 해보고 피드백을 받고 나니 이론적인 부분들이 보이는 것 같다. 다른 부분들도 실제로 적용해보면서 익혀나가자.

반응형