null이 아닌, 빈 컬렉션이나 배열을 반환하라

Hyunta·2022년 2월 28일
0

로또 미션

목록 보기
4/6
public enum LottoRank {
    FIFTH(3, 5000),
    FOURTH(4, 50000),
    THIRD(5, 1500000),
    SECOND(5, 30000000),
    FIRST(6, 2000000000);

    private final int correctNumber;
    private final int prizeAmount;

    LottoRank(final int correctNumber, final int prizeAmount) {
        this.correctNumber = correctNumber;
        this.prizeAmount = prizeAmount;
    }
    
    public static LottoRank valueOf(int sameCount, boolean bonus) {
    if (sameCount == 5) {
        return checkSecondOrThird(bonus);
    }
    return Arrays.stream(LottoRank.values())
            .filter(lottoRank -> lottoRank.getCorrectNumber() == sameCount)
            .findFirst()
            .orElse(null);
}

로또에 당첨된 사람들을 enum 값으로 표현했는데 당첨되지 않은 사람들은 따로 만들지 않았었다. 그래서 당첨되지 않은 사람들은 null을 반환해서 해결했었다. 하지만 null을 반환하면서 찜찜한 기분이 있었는데 마침 이펙티브 자바에 해당 내용이 있길래 읽으며 정리해봤다.


아이템 54. null이 아닌, 빈 컬렉션이나 배열을 반환하라

public class CandyStore {
    private final List<Candy> candiesInStock;

    public List<Candy> getCandiesInStock() {
        return candiesInStock.isEmpty() ? null : new ArrayList<>(candiesInStock);
    }
}

만약 사탕가게의 재고를 파악하는 프로그램에서 재고가 없을 경우 null 을 반환한다고 하면, 해당 메서드를 이용할 때 null 상황을 처리하는 코드를 추가로 작성해야한다.

List<Candy> candies = candyStore.getCandiesInStock();
if (candies != null && candies.contains(Candy.RED)) {
    System.out.println("빨간 사탕이 있지");
}

만약 null에 대해 처리를 안해준다면 NullPointerException 이 발생할 것이다. 그래서 저자는 빈 컬렉션이나 배열을 반환하라고 한다.

혹자는 빈 컨테이너를 할당하는 데도 비용이 드니 null을 반환하는 쪽이 낫다고 할 수 있다.하지만 이는 두가지 면에서 틀린 주장이다.

1. 이 정도의 성능 차이는 신경 쓸 수준이 못 된다.

빈 컨테이너를 할당하는 것이 성능 저하의 주범이라고 확인되지 않는 한 효율적인 프로그램보다는 유지보수에 적합한 설계를 가져가는 것이 좋다.

아이템 67 최적화는 신중히 하라 - 빠른 프로그램보다는 좋은 프로그램을 작성하라

2. 빈 컬렉션과 배열은 굳이 새로 할당하지 않고도 반환할 수 있다.

public List<Candy> getCandiesInStock() {
     return new ArrayList<>(candiesInStock);
}

혹여나 이 코드가 성능에 저하를 불러일으킨다 하더라도 아래 코드처럼 작성한다면 해결될 것이다. 그리고 꼭 개선 결과를 확인하자.

public List<Candy> getCandiesInStock() {
   return candiesInStock.isEmpty() ? Collections.emptyList()
   	: new ArrayList<>(candiesInStock);
}

적용 - LottoRank.NOTHING을 반환한다.

public enum LottoRank {
    NOTHING(0, 0),
    FIFTH(3, 5000),
    FOURTH(4, 50000),
    THIRD(5, 1500000),
    SECOND(5, 30000000),
    FIRST(6, 2000000000);

    private final int correctNumber;
    private final int prizeAmount;

    LottoRank(final int correctNumber, final int prizeAmount) {
        this.correctNumber = correctNumber;
        this.prizeAmount = prizeAmount;
    }

    public static LottoRank valueOf(int sameCount, boolean bonus) {
        if (sameCount == 5) {
            return checkSecondOrThird(bonus);
        }
        return Arrays.stream(LottoRank.values())
                .filter(lottoRank -> lottoRank.getCorrectNumber() == sameCount)
                .findFirst()
                .orElse(NOTHING);
}

null 로 반환하지 않고 NOTHING 을 반환해서 해결했다. 추가로 이번 미션 리뷰어인 던은 아래처럼 생각한다고 공유받았다.

Reference

이펙티브 자바 p.323 "nulll이 아닌, 빈 컬렉션이나 배열을 반환하라"

profile
세상을 아름답게!

0개의 댓글