일급 (”First-class”) 이란?
- 다음과 같은 조건을 만족하는 요소
- 변수에 할당될 수 있음
- 함수의 매개변수로 전달할 수 있음
- 함수의 반환값으로 사용할 수 있음
- 자료구조(배열, 객체 등) 에 저장할 수 있음
일급 컬렉션
- 컬렉션 자체를 하나의 클래스로 감싸놓은 것
- 위 “일급 객체”의 “일급”과 다르다.
- 컬렉션 자체에 하나의 “비즈니스적 이름”을 지어줘야 할 때 사용하는 일종의 패턴
일급 컬렉션의 구조
- 리스트를 클래스로 감싸놓음
- List에 대한 직접 접근을 막고, Users 클래스의 메소드로만 List에 접근을 허용하도록 접근을 제어
- List 내부의 원소에 적용해야 하는 연산에 대해, 지정된 메소드로만 내부 원소들에 연산을 적용하도록 한다
일급 컬렉션을 만들어야 하는 이유
컬렉션 자체에 비즈니스적 특징이 주어질 때 → 컬렉션에 이름 부여
- 만약 유저들을 묶어 처리해야 할 일이 잦다면?
- 동작의 “근거지”를 마련한다!
상태와 메소드의 “응집”
- 리스트는 자체적 비즈니스 로직 메소드를 가질 수 없다
- 스태틱 메소드가 리스트를 매개변수로 받아서 기능을 수행해야 한다면, 이미 하나의 메시지가 된 것
컬렉션의 “불변성” 이 필요할 때
- 데이터의 집합이 그 모임의 존재 자체적으로 의미를 가질 때
- 불변성을 걸어, 동일한 구조의 다른 리스트와 “차별점”을 만든다.
동일한 원소를 갖는 리스트라도, lotto1와 lotto2 는 다른 의미를 갖도록
구현 시 주의할 점
내부 원소에 대한 불변성은 제공하지 않는다.
- 만약 내부 원소를 참조하는 다른 변수에서 값을 변경하면?
- 리스트의 연산 결과도 달라질 수 있음!
- 이런 상황이 껄끄럽다면, 내부 원소 자체도 불변으로 만드는 것이 옳음.
- 이런 상황도 괜찮다면, 굳이 내부 원소 자체를 불변으로 만들 필요는 없다는 뜻.
컬렉션 자체에 대한 Getter 는 제공하지 않아야 한다.
- 컬렉션 자체에 Getter 를 추가하게 되면, 리스트에 직접 사용 가능한 연산들이 사용 가능하게 되어버린다.
- add(), remove(), get(), etc.
생성 성공에 대한 검증은?
- 일급 컬렉션이 제공하는 자체적인 메소드로 간접 검증해야 한다.
- 리플렉션을 통한 검증이나, default 접근제어자를 이용한 테스트 전용 메소드를 추가하는 방법도 있지만
- 권장하지 않는다.
- 구현 코드가 테스트 코드에 종속됨