본문 바로가기
🛠 백엔드/Spring

[Java] 일급 컬렉션을 왜 사용할까?

by meteorfish 2024. 5. 5.
728x90
Collection을 Wrapping 하면서, 그 외 다른 멤버 변수가 없는 상태

 

이번 로또 문제를 풀면서 맞이했던 문제들을 살펴보자.

 

1.  Validation 처리

LottoNumber는 List<Integer> numbers를 wrapping하는 일급 컬렉션이다.

numbers는 6개의 중복되지 않는 숫자만 포함해야 한다.

 

일급 컬렉션의 개념을 이해하기 전엔, "입력 시 Validation 처리해야 하는가?" 라는 고민을 했다.

 

View 차원에서 "입력받는 값에 최소한의 유효성 검증을 진행한다." 의 규칙이 존재하기 때문에 상관이 없을 것이라 생각했다.

MVC Pattern에서의 유효성 검사 (velog.io)

 

MVC Pattern에서의 유효성 검사

책임 전가 패스

velog.io

 

그런데 조사를 더 해보니 일급 컬렉션은 이를 완벽하게 보완하는 개념으로 사용되고 있다.

일급 컬렉션은 하나의 컬렉션만 Wrapping하기 때문에, 이 곳에 해당 Collection의 Validation 처리를 하기 더할나위 없이 완벽한 곳이다.

다시 말해, 나는 6개의 중복되지 않는 요소만 같은 List를 만들 수 있는 셈이다.

public class LottoNumber {
    private static final int LOTTO_NUMBERS_SIZE = 6;
    private final List<Integer> numbers;

    public LottoNumber(List<Integer> numbers) {
        validateSize(numbers);
        validateDuplicate(numbers);
        this.numbers = numbers;
    }

    private void validateSize(List<Integer> numbers){
        if(numbers.size() != LOTTO_NUMBERS_SIZE){
            throw new IllegalArgumentException("로또는 6개의 숫자로 구성되어야 합니다.");
        }
    }

    private void validateDuplicate(List<Integer> numbers){
        Set<Integer> uniqueNumbers = new HashSet<>(numbers);
        if(uniqueNumbers.size() != LOTTO_NUMBERS_SIZE){
            throw new IllegalArgumentException("로또의 숫자들은 중복되지 않아야 합니다.");
        }
    }
}

 

2. 컬렉션에 이름을 줄 수 있다.

Lotto라는 로또 묶음을 가지는 클래스를 선언했다.

해당 Lotto 안에 6개의 숫자를 가지는 List를 만들 수 있을까?

 

Lotto -> List<List<Integer>>

이런 식으로 주는 것보다 일급 컬렉션으로 Wrapping하는 쪽이 훨씬 구현하기 수월하다.

 

Lotto -> List<LottoNumber> -> List<Integer>

이렇게 보면, LottoNumber는 List<Integer>를 보다 알아보기 쉽게 이름을 줄 수 있는 역할도 한다.

 

 

3. 불변성을 보장한다.

우리가 사용하는 final Collection은 재할당만 금지하고, 값 변경이 가능하다.

// 재할당 금지
final List<Integer> list = new ArrayList<>();
list = new ArrayList<>();

 

해당 코드에서 2번째 줄은 당연히 빨간색 줄이 뜨며 오류가 발생한다.

 

// 값 추가 가능
final List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);

그러나 위 코드는 아무 문제 없이 입력이 가능하다.

 

그러면 이런 경우 어떻게 해결해야 하나요?

public class LottoNumber {
    private static final int LOTTO_NUMBERS_SIZE = 6;
    
    private final List<Integer> numbers;
    
    public List<Integer> getNumbers() {
        return numbers;
    }
}

위 일급 컬렉션 내부에 값을 직접적으로 변경하는 메소드를 추가하지 않으면 된다.

해당 LottoNumber의 List<Integer> numbers를 직접적으로 건드릴 위험이 매우 줄어들기 때문에,

불변성을 보장할 수 있다.


참고

 

일급 컬렉션 (First Class Collection)의 소개와 써야할 이유 (tistory.com)

 

일급 컬렉션 (First Class Collection)의 소개와 써야할 이유

최근 클린코드 & TDD 강의의 리뷰어로 참가하면서 많은 분들이 공통적으로 어려워 하는 개념 한가지를 발견하게 되었습니다. 바로 일급 컬렉션인데요. 왜 객체지향적으로, 리팩토링하기 쉬운 코

jojoldu.tistory.com

 

728x90