티스토리 뷰
https://edu.nextstep.camp/c/8fWRxNWU/
TDD, 클린코드 코드리뷰를 하다보면 '원시값과 문자열을 포장하라', '일급콜렉션을 쓴다'와 같은 피드백을 주곤한다. Wrapper Class를 작성하는 데에는 어려움이 없지만, 일급콜렉션을 학습하는 과정에서 보통 동욱님의 블로그를 접하는데 두번째 특징인 '불변성'으로 인해 혼란을 겪는다.
객체지향 생활체조에 제시된 일급콜렉션(First Class Collection)은 일급 시민(First Class Citizen)을 연상시킨다. 그리고 일급시민은 함수형 프로그래밍과 더불어 불변객체를 연상시킨다. 우선 일급시민은 무엇이고, 불변객체는 무엇일까?
일급시민은 1) 변수나 데이타에 할당 할 수 있고, 2) 객체의 인자로 넘길 수 있으며, 3) 객체의 리턴값으로 리턴 할수 있어야 한다. 자바는 1.8부터 동작을 파라미터화하여 전달할 수 있게 되었다.
1
2
3
|
getNumber(elm);
Function result = getResult();
List list = Arrays.asList(elm, result);
|
그렇다면, 불변객체는 무엇일까?
1) 객체를 변경하는 메소드를 제공하지 않는다.
2) 재정의할 수 있는 메소드를 제공하지 않는다.
3) 모든 필드를 final로 만든다.
4) 모든 필드를 private으로 만든다.
5) 가변 객체를 참조하는 필드는 배타적으로 접근해야 한다
즉, 객체의 상태를 바꿀 수는 없으므로 새로운 상태로 변경해야 할 경우 새로운 불변 객체를 만들어 기존의 불변 객체를 대체 시켜야 한다. 이를 통해 불변객체는 Side-effect 및 동시성 이슈에 노출되지 않는다. 따라서 함수형 프로그래밍에서 Side-effect를 발생시키지 않기 위해 불변객체를 사용하는 것이지, 일급시민의 특징이 불변성을 보장하는 것은 아니다.
그렇다면, 일급콜렉션은 무엇일까?
소트웍스 앤솔리지 설명을 토대로 보면, 우선 동욱님 블로그에서 설명하듯 '비지니스에 종속적인 자료구조', '상태와 행위를 한 곳에서 관리', '이름이 있는 컬렉션'의 특성을 가지고 있다. 이에 '원시값과 문자열을 포장하라'의 연장선상에서 자신만의 자료구조를 만들라는 의미에서 가이드를 한다고 이해하고 있다. 따라서 불변성을 반드시 보장해야 하는지는 알 수 없다. 물론 불변성을 지향할 경우 Side-effect는 발생하지 않겠지만, Collection 요소가 추가될 때마다 Collection을 새로 생성하는 등의 비효율성이 발생한다.
추가적으로, Collection이 불변성을 가질 수 있기 위해서는 어떻게 구현해야할까?
java에서 final 예약어는 해당 객체를 가리키는 포인터를 바꿀 수 없게하는 의미이다. 따라서 1) primitive type의 경우 불변이다. 2) reference type의 경우 값의 재할당은 안되지만, 속성을 변경하는 것은 가능하다. 이에 reference type을 불변으로 구현하기 위해서는 새로운 객체를 생성하여 반환하여야 한다. - [참고링크]
보통 일급컬렉션을 구현할 때 Collections.unmodifiableList를 활용한다. 이 경우 일급컬렉션이 속성으로 가지고 있는 Collection 값이 외부에 노출될 경우 값의 변경/추가/삭제는 불가하기에 불변성을 띄는 것으로 오해할 수 있다. 하지만 Collection에 담겨있는 Item의 속성은 변경이 가능하다. 따라서 Collections.unmodifiableList(new ArrayList<>(값))으로 한번 더 감싸 불변객체를 작성하거나, 값.stream().map(값의아이템::Clone).collect(toList()) 등과 같이 깊은 복사를 하여야 한다.
'Programming > .java' 카테고리의 다른 글
불변객체란 (2) | 2020.04.12 |
---|---|
스프링 프레임워크에 이르기까지 <2> MVC (0) | 2017.10.02 |
스프링 프레임워크에 이르기까지 <1> All-in-one (0) | 2017.09.23 |
[Java]Collections Class (0) | 2017.08.26 |
[Java]String vs StringBuffer vs StringBuilder (0) | 2017.08.25 |