Java 공부를 시작하고 일급 컬렉션(First Class Collection)이라는 개념을 처음 알게되었다.
일급 컬렉션의 정의와 필요성에 대해 공부하고 코드에 적용해보던 중, 일급 컬렉션의 장점이 값 객체(VO, Value Object)와 비슷하다는 생각이들었다. 그리고 왜 Collection만 "일급 컬렉션"이라는 이름을 붙이면서 특별취급을 할까? 라는 의문이 들었다.
이와 관련해 알아본 내용을 글로 정리해두려고 한다.
일급 컬렉션(First Class Collection)이란?
일급 컬렉션이란 컬렉션을 포장(wrapping)하면서 그 외 다른 멤버 변수가 없는 클래스를 의미한다.
여기서 컬렉션은 데이터의 집합이나 그룹. 즉 여러개의 데이터를 담을 수 있는 자료구조를 의미하는데, Java Collection Framework(JCF)의 Collection과 Map 인터페이스라고 이해했다.
예시 코드
로또 프로그램을 구현할 때 6개의 숫자와 보너스 숫자가 있는 당첨번호 도메인을 아래와 같이 작성했다.
public class LottoWinningNumber {
private final List<Integer> numbers;
private final int bonus;
public LottoWinningNumber(List<Integer> numbers, int bonus) {
this.numbers = numbers;
this.bonus = bonus;
}
}
위 코드에서 멤버 변수 `numbers`를 일급 컬렉션 `Lotto`로 감싸면 다음과 같은 코드가 된다.
// LottoWinningNumber.java
public class LottoWinningNumber {
private final Lotto numbers;
private final int bonus;
public LottoWinningNumber(Lotto numbers, int bonus) {
this.numbers = numbers;
this.bonus = bonus;
}
}
// Lotto.java
public class Lotto {
private final List<Integer> numbers;
public Lotto(List<Integer> numbers) {
this.numbers = numbers;
}
}
일급 컬렉션의 장점
일급 컬렉션은 아래 4가지의 장점들을 가지고있다.
1. 불변 객체로 구현해 컬렉션의 불변성을 보장한다.
일급 컬렉션은 `setter`등 외부에서 컬렉션을 직접 수정할 수 있는 메서드를 공개하지 않는다. 따라서 컬렉션의 불변성을 보장할 수 있다.
첫번째 예시 코드에서도 `numbers` 멤버 변수를 `final`로 선언했지만, 컬렉션의 불변성을 보장할 수는 없다.
java의 `final` 키워드가 수정을 막는 범위는 그 변수의 값에 한정한다. 즉, 컬렉션은 참조형 변수이기 때문에 재할당만 불가능하고 컬렉션 내부의 값은 `final` 영향 밖에 있기 때문에 `add` 연산 등으로 컬렉션의 값을 변경할 수 있게된다.
2. 검증된 자료구조임을 보장한다.
두번째는 로또 프로그램을 구현할 때 가장 유용하게 느껴진 장점이다.
위의 로또 클래스는 주어진 조건에 의해 생성자에서 유효성 검사 로직을 가지고있다.
public class Lotto {
private final List<Integer> numbers;
public Lotto(List<Integer> numbers) {
validate(numbers);
this.numbers = numbers;
}
private void validate(final List<Integer> numbers) {
validateSize(numbers); // numbers의 사이즈가 6이어야함을 검증
validateIsDuplicated(numbers); // numbers에 중복인 숫자가 없음을 검증
validateRange(numbers); // numbers의 모든 숫자가 1~45 사이임을 검증
}
}
이렇게 구현함으로써 `Lotto` 객체는 컬렉션 사이즈, 컬렉션 내부값들의 중복 여부, 컬렉션 내부값들의 수 범위 조건을 만족하는 자료구조임을 보장할 수 있게 된다. 그렇기 때문에 예시 코드의 당첨 번호 도메인과 사용자가 구매한 로또 복권 도메인을 구현할 때 `Lotto` 클래스를 활용해 간단하게 구현할 수 있었다.
정리하면
- Lotto 클래스를 일급 컬렉션으로 설계해 중복 코드(검증 로직)를 줄일 수 있다.
- 생성자의 유효성 검사 로직으로 비즈니스 규칙을 보장하게 되어 같은 규칙을 만족하는 자료구조가 필요할 때 안전하게 사용할 수 있다.
3. 컬렉션과 관련된 비즈니스 로직을 캡슐화해 응집도를 높일 수 있다.
일급 컬렉션의 주된 책임은 컬렉션 데이터를 관리하는 것이다. 따라서 3번과 같은 검증 로직 뿐만 아니라, 컬렉션에 관련한 비즈니스 로직을 일급 컬렉션 내부로 캡슐화하여 응집도를 높일 수 있다.
편의점 주문 프로그램을 만들 때, 사용자의 주문 목록 도메인을 `Order`라는 일급 컬렉션으로 설계했다.
public class Order {
private final List<OrderItem> items;
public Order(List<OrderItem> items) {
validateHasDuplicated(items);
this.items = items;
}
public int calculateTotalQuantity() {
List<Integer> quantities = items.stream()
.map(item -> item.getQuantity().value())
.toList();
return numbers.stream()
.mapToInt(Integer::intValue)
.sum();
}
public int calculateTotalPrice() {
//...
}
public int calculateMembershipDiscount() {
//...
}
}
그리고 사용자의 주문 목록에서 물건의 총 개수, 총 가격, 할인 가격을 구하는 로직을 클래스 내부에 구현해 응집도를 높일 수 있었다.
4. 컬렉션에 명시적인 의미를 부여할 수 있다.
컬렉션에 명시적인 의미를 부여하여 코드를 더 이해하기 쉽도록 하고 해당 컬렉션이 무엇을 나타내는지 명확하게 표현할 수 있다.
첫번째 예시 코드처럼 로또 번호를 표현할 때, `List<Integer>`로 되어있다면 코드를 처음 보는 개발자는 검증 로직등을 확인해야겠지만 `Lotto`라는 일급 컬렉션을 사용하면 "1~45 사이의 중복 없는 6개의 숫자겠다!"를 대략이라도 예측할 수 있을 것이다.
컬렉션만 특별취급하는 이유?
이후 Primitive Obession 개념에 대해 공부하다가 위의 4가지 장점이 primitive obession 문제를 해결하기위해 Value Object를 도입하는 이유와 비슷하다는 생각이 들었고, 그럼 왜 컬렉션만 특별취급하는걸까? 라는 의문을 가지게 됐다.
일급 컬렉션이라는 개념이 나온 이유는, 컬렉션이 다른 타입들보다 특별한 문제를 가지기 때문이라는 생각이 들었다.
첫번째로 컬렉션은 복잡도를 쉽게 증가시킨다.
컬렉션은 기본적으로 여러개의 데이터를 관리하기 위한 자료구조이다. 그 안에서 추가, 삭제, 조회, 정렬, 필터링과 같은 다양한 조작이 필요하고 특히 반복문을 돌며 수행하는 작업을 구현하는 경우가 잦은 것 같다.
그래서 컬렉션 자체를 조작하는 로직이 일반적인 클래스의 일부로 존재한다면 클래스의 복잡도를 쉽게 증가시키고 책임이 분산될 가능성이 커진다.
두번째로 컬렉션은 일관성을 유지하기 어렵다.
위에서 살펴본 것처럼 다른 타입의 변수들과 달리 컬렉션은 `final` 선언만으로 불변성을 보장할 수 없어 추가적인 관리가 필요하다. 외부에서 컬렉션을 조작할 수 있다면 데이터 무결성을 해칠 가능성이 높아진다. 컬렉션이 다른 멤버 변수와 함께 관리될 경우 데이터의 일관성을 유지하기 위한 관리가 더 어려워질 것이다.
참고 자료
https://jojoldu.tistory.com/412
일급 컬렉션 (First Class Collection)의 소개와 써야할 이유
최근 클린코드 & TDD 강의의 리뷰어로 참가하면서 많은 분들이 공통적으로 어려워 하는 개념 한가지를 발견하게 되었습니다. 바로 일급 컬렉션인데요. 왜 객체지향적으로, 리팩토링하기 쉬운 코
jojoldu.tistory.com
🧱 Java Collections Framework 종류 💯 총정리
Java Collection Framework 자바 새내기분들은 컬렉션 프레임워크라는 단어에 뭔가 거창하고 어려운 느낌이 들수 있겠지만, 그냥 자료 구조(Data Structure) 종류의 형태들을 자바 클래스로 구현한 모음집
inpa.tistory.com
https://sabarada.tistory.com/148
[Java] final 키워드에 대해서 알아보자
안녕하세요. 오늘은 여러분들과 java의 final 키워드에 대해서 알아보려고 합니다.finalfinal 키워드는 변수(variable), 메서드(method), 또는 클래스(class)에 사용될 수 있습니다. 이 final 키워드는 어떤 곳
sabarada.tistory.com
'개발 > Spring Boot, Java' 카테고리의 다른 글
[Java] 함수형 인터페이스(Functional Interface)를 활용해 중복 코드 줄이기 (0) | 2024.11.24 |
---|---|
[번역] JUnit5 Parameterized Test 가이드 (0) | 2024.10.27 |