일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Connection Pool
- Spring Boot
- deleteById
- Service Locator
- @ControllerAdvice
- java
- Item04
- 트랜잭션
- 이펙티브 자바
- Service Locator 패턴
- 플라이웨이트
- springboot
- Web
- multi module
- Effetive Java
- @SpyBean
- NotEmpty
- Proxy Patter
- 데이터베이스
- NotBlank
- @Valid
- Firebase
- 디자인 패턴
- @MockBean
- Effective Java
- restTemplate
- JPA
- SQL 삽입 공격
- db
- FCM
- Today
- Total
NoTimeForDawdling
일급 컬렉션(First Class Collection) 본문
예전에 스터디를 참여하면서 일급 컬렉션에 대해 공부하고, 적용해 본 적이 있었습니다.
일급 컬렉션이 무엇인지, 어떤 장점이 있는지 지금부터 알아보겠습니다.
일급 컬렉션이란?
- 일급 컬렉션은 Collection을 Wrapping 하면서, 그 외 다른 멤버 변수가 없는 상태를 뜻합니다.
- 중요한 점은 Collection을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다는 겁니다.
간단한 코드 예제
List<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
위의 코드를 아래와 같이 Wrapping 하는 것을 얘기합니다.
public class Numbers {
private List<Integer> numbers;
public FirstClass(List<Integer> numbers){
this.numbers = numbers;
}
}
일급 컬렉션의 장점
-
비즈니스에 종속적인 자료구조입니다.
-
Collection의 불변성을 보장합니다.
-
상태와 행위를 한 곳에서 관리합니다.
-
이름이 있는 컬렉션입니다.
1. 비즈니스에 종속적인 자료구조
레이싱 게임을 한다고 가정하겠습니다.
레이싱 게임을 하기 위해서는 경주를 할 자동차들이 필요합니다. 자동차의 최대 개수는 10개로 제한합니다.
public class RacingGame {
private static final int MAX_SIZE = 10;
public void raceStart() {
List<Car> cars = createCars();
validateSize(cars);
// race logic start
}
private void validateSize(List<Car> cars) {
if (cars.size() > MAX_SIZE) {
throw new IllegalArgumentException(String.format("Exceeded maximum number of cars. input cars size: %d", cars.size()));
}
}
private List<Car> createCars() {
// createCars
}
}
위 코드를 보면 RacingGame 클래스에서 race에 관련된 로직뿐만 아니라 자동차에 관한 검증 로직까지 처리합니다. 이렇게 된다면 자동차를 사용하는 모든 메서드에서 검증 로직을 추가해야 합니다.
이 문제를 해결하기 위해서 해당 조건을 만족하는 객체를 만들어주면 됩니다. 이게 바로 일급 컬렉션입니다.
// 일급 컬렉션
public class Cars {
private final int MAX_SIZE = 10;
private final List<Car> cars;
public Cars(List<Car> cars) {
validateCount(cars);
this.cars = cars;
}
private void validateCount(List<Car> cars) {
if (cars.size() > MAX_SIZE) {
throw new IllegalArgumentException(String.format("Exceeded maximum number of cars. input cars size: %d", cars.size()));
}
}
}
public class RacingGame {
public void startRace() {
final Cars cars = new Cars(createCars());
// race logic start
}
private List<Car> createCars() {
// createCars
}
}
이처럼 Car 관련 비즈니스 로직(여기서는 최대 개수)을 Cars라는 일급 컬렉션에서 해결할 수 있는, 비즈니스에 종속적이 자료구조가 만들어졌습니다.
2. Collection의 불변성을 보장
일급 컬렉션은 컬렉션의 불변성을 보장해 줍니다. 그렇다면 final과의 차이점은 무엇일까요?
- final은 단순히 재할당만 금지할 뿐, 구조적 변경은 허용합니다.(add, remove 허용)
-
일급 컬렉션은 단순히 final을
-
구조적 변경의 허용 유무는 불변 객체를 만드는데 매우 중요합니다.
-
불변 객체를 만들기 위해서는 해당 객체의 값을 변경할 수 있는 메서드가 없어야 하기 때문입니다.
-
public class Cars {
private final List<Car> cars;
public Cars(List<Car> cars) {
this.cars = cars;
}
public int getTotalPrice() {
return cars.stream()
.mapToInt(Car::getPrice)
.sum();
}
}
위 코드는 일급 컬렉션입니다.이 코드를 보면 구조적 변경을 할 수 없고, 내부 값도 변경할 수 있는 메서드는 존재하지 않습니다.
3. 상태와 행위를 한 곳에서 관리
일급 컬렉션은 값과 로직이 함께 존재합니다. 즉, 응집도가 높다는 걸 의미합니다.
예를 들어 여러 Car들이 모여있고, 이 중 우리나라에서 생성한 Car의 개수를 얻어야 한다고 가정해보겠습니다.
public class Cars {
private final List<Car> cars;
public Cars(List<Car> cars) {
this.cars = cars;
}
public Long getKrCarCount() {
return cars.stream()
.filter(car -> car.isKrCar())
.count();
}
}
위와 같이 Cars라는 일급 컬렉션을 만들고, 그 안에 우리나라의 Car 개수를 가져올 수 있는 코드를 구현했습니다.
즉, 일급 컬렉션을 사용함으로써 상태와 로직을 한 곳에서 관리할 수 있게 됐습니다.
4. 이름이 있는 컬렉션
예를 들어 한국 자동차 그룹과 미국 자동차 그룹을 구분해야 한다고 가정해보겠습니다.
다음과 같이 변수명을 다르게 하여 구분했습니다.
List<Car> KrCars = createKrCars();
List<Car> UsaCars = createUsaCars();
위 코드의 문제점은 다음과 같습니다.
- 한국 자동차의 그룹이라는 뜻은 개발자마다 다르게 지을 수 있습니다. 그렇기 때문에 변수명으로 유추한 그룹이 원하는 그룹이 아닐 수도 있습니다.
-
변수명에 불과하기 때문에 의미를 부여하기 어렵습니다.
-
중요한 값임에도 이를 표현할 명확한 단어가 없습니다.
위 문제의 해결책으로 각각의 그룹을 일급 컬렉션으로 만들면 됩니다.
KrCars krCars = new KrCars(createKrCars());
UsaCars usaCars = new UsaCars(createUsaCars());
위와 같이 한국 자동차와 미국 자동차 각각의 일급 컬렉션을 만들어서 해당 문제점들을 해결할 수 있습니다.
참고
'Java' 카테고리의 다른 글
hashCode()와 equals() (0) | 2021.03.05 |
---|---|
기본형(Primitive Type)과 참조형(Reference Type) (0) | 2021.03.02 |
얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy) (0) | 2021.02.25 |
접근 제어자(Access Modifier) (0) | 2021.02.24 |
Enum 클래스 파헤치기 (0) | 2021.02.23 |