우테코 프리코스 커뮤니티에서 객체지향 생활체조를 알게되었고 때문에 일급 컬렉션을 처음 접했다.
일단 일급 컬렉션이 뭔지부터 알아보았다.
https://jojoldu.tistory.com/412
일급 컬렉션 (First Class Collection)의 소개와 써야할 이유
최근 클린코드 & TDD 강의의 리뷰어로 참가하면서 많은 분들이 공통적으로 어려워 하는 개념 한가지를 발견하게 되었습니다. 바로 일급 컬렉션인데요. 왜 객체지향적으로, 리팩토링하기 쉬운 코
jojoldu.tistory.com
https://tecoble.techcourse.co.kr/post/2020-05-08-First-Class-Collection/
일급 컬렉션을 사용하는 이유
일급 컬렉션이란? 본 글은 일급 컬렉션 (First Class Collection)의 소개와 써야할 이유를 참고 했다. 일급 컬렉션이란 단어는 소트웍스 앤솔로지의 객체지향 생활체조 규칙 8. 일급 콜렉션 사용에서 언
tecoble.techcourse.co.kr
여러 사이트를 참고하며 알게된 일급 컬렉션의 특징은 다음과 같다.
- 비즈니스에 필요한 형태의 자료구조를 만들어 비즈니스에 종속적인 자료구조가 됨
- 불변성을 보장하지 않음
- Collection 원본에 접근해 값을 변경하지 않는다면 불변성 보장
- 값과 로직이 함께 존재해 상태와 행위를 한 곳에서 관리함
- 이름이 있는 컬렉션
나는 숫자를 담는 일급 컬렉션을 만들었다.
public class Numbers {
private final List<Integer> numbers;
public Numbers(List<Integer> numbers) {
validateSize(numbers);
validateRange(numbers);
validateDuplication(numbers);
this.numbers = numbers;
}
...
}
그리고 각각 따로 만들어진 객체의 숫자들을 비교해야했는데, 숫자 자체에 접근하려면 getter를 사용해야했다.
jojoldu님은
저 역시 일급컬렉션에 필요한 값만 반환하는 별도의 메소드들을 만들어서 사용하고 있습니다.
(컬렉션 그대로 반환하지 않고, 외부에선 컬렉션 내부 필드에 단독 접근은 불가능한 형태죠)
생성자로 받은 컬렉션값을 그대로 반환하는 기능은 두지 않고, 가공된 값 or 목적에 맞는 값만 반환하는 형태로 구현하고 있습니다.
라고 하셨다.
그래서 검증된 값만 반환하도록 getter를 사용했다. 그런데 객체지향 생활체조는 도메인 객체 모델에 getter/setter를 지양하라고 했다.
나는 고민 끝에 "Numbers는 서비스 로직을 수행하는 도메인 객체 모델이 아니기 때문에 getter를 사용해도 된다!"라고 결론내렸다.
Numbers는 숫자들을 검증하고 규격에 맞는 숫자들을 만든다. 서비스 로직에 포함시킬 수 있지만, 나는 숫자들을 비교하는 부분부터 서비스 로직이라고 생각했다.
getter로 원본 값에 접근해도 값이 바뀌는 불상사를 막기위해 티거님의 글을 참고해서 unmodifiableList()를 사용했다. 그리고 아래와 같이 getter를 추가했다.
...
public List<Integer> getNumbers() {
return Collections.unmodifiableList(numbers);
}
...
그럼 일급 컬렉션 객체를 어떻게 생성해야 할까?
객체 생성방식은 초기화된 컬렉션 객체를 반환하는 메서드를 일급 컬렉션 객체 생성자의 파라미터로 넘겨주면 된다.
나는 코드의 중복을 줄이기 위해 템플릿 메서드 패턴을 적용했다.
UserNumbersGenerator와 ComputerNumbersGenerator가 NumbersGenerator를 상속받고 createNumbers()를 오버라이딩한다.
public abstract class NumbersGenerator {
public List<Integer> generate() {
Numbers numbers = new Numbers(createNumbers());
return numbers.getNumbers();
}
abstract List<Integer> createNumbers();
}
public class UserNumbersGenerator extends NumbersGenerator{
public List<Integer> createNumbers() {
List<Integer> userNumbers = new ArrayList<>();
System.out.print("숫자를 입력해주세요 : ");
String userInput = readLine();
for (int i = 0; i < userInput.length(); i++) {
String str = userInput.substring(i, i + 1);
userNumbers.add(Integer.parseInt(str));
}
return userNumbers;
}
}
그리고 NumbersGenerator객체의 generate()를 호출하면 Numbers객체의 원본 List를 반환한다.
List<Integer> userNumbers = numbersGenerator.generate();
일급 컬렉션을 어떻게 적용할지 많이 고민했지만 이렇게 하는게 맞는지 잘 모르겠다.
그래도 일급 컬렉션을 사용해봤다는데 의의를 두고 싶다.
'Java' 카테고리의 다른 글
| Java 기초 문법(1) (0) | 2023.12.20 |
|---|---|
| Java 구동 방식 (1) | 2023.12.20 |
| 팩토리 메서드 패턴을 적용해보자 (0) | 2023.10.26 |
| 템플릿 메서드 패턴을 적용해보자 (0) | 2023.10.26 |
| static 메서드는 언제 사용해야할까? (1) | 2023.10.26 |