일급컬렉션

YEON·2022년 3월 15일
0

CleanCode 미션

목록 보기
5/5

일급 컬렉션 (First Class Collection)

일급 컬렉션이란?
다른 멤버 변수 없이, Collection만을 Wrapping 한 상태

소트웍스 앤솔로지 - 객체지향 생활체조 파트에서 언급
⁃ Collection을 포함한 클래스는 반드시 다른 멤버 변수가 없어야한다.
⁃ Collection은 그 자체로 포장된 상태가 되므로, 관련된 동작의 모든 근거지가 된다.

public class Lotto {
    private List<Integer> lotto;   - Collection Wrapping
    // private int matchCount = 0; - 일급 컬렉션에 위배
    ...
}


Q. 왜 객체지향적인 코드를 위해서 일급 컬렉션이 필요할까 ?

사용하는 이점

  • Collection 의 불변성 보장
    • 불변성이란? : 값을 변경 할 수 없다
      불변 컬렉션이란? : 컬렉션의 값을 변경할 수 있는 메소드가 없는 컬렉션
      불변 객체가 중요한 이유? : 객체들의 값이 바뀌지 않는다는 보장이 생기면, 코드를 수정하는 사이드 이펙트가 최소화될 수 있다.

    • 일급컬렉션이 아니더라도 final 키워드로 불변성을 줄 수 있지 않나?
      자바의 final 은 Collection 에 대하여 재할당만 금지시킨다. (즉, 값이 변경될 수 있다)
      그러므로 Java의 final 로 불변성을 해결할 수 없기에, 일급 컬렉션과 래퍼 클래스의 방법으로 해결해야한다.

    • 일급 컬렉션으로 불변성을 보장하는 방법
      생성자와 get 메소드만 구성하게 된다면, lottos 의 값을 변경하거나 추가할 방법이 없다.
      결국, 값을 새로 생성하거나 가져오는 방법밖에 할 수 없다.
      public class Lotto {
          private List<LottoNumber> lottos;
          
          public Lotto(List<LottoNumber> lottos) {
          	this.lottos = lottos;
          }
          public List<LottoNumber> getLottos(){
          	return lottos;
          }
      }

  • 비지니스에 종속적인 자료구조
  • 값과 로직을 한 곳에서 관리
    • 인스턴스들을 모두 함께 관리해야할 때, 일급 컬렉션을 통하여 관리하기 용이하다

    • 매번 Lotto의 필요한 로직들은 LottoTicket 에서 Lotto 인스턴스들의 묶어서 관리 할 수 있다.

    • 인스턴스의 조건들로 구성된 하나의 자료구조를 만든다고 생각할 수 있다.

    • 비즈니스 로직이 외부에서 관리된다면 코드가 흩어지며 관리 포인트가 증가하게 될 수 있지만,
      비즈니스 로직을 도메인에서 함께 관리함으로써 이를 방지할 수 있다.

    • 같은 비지니스 로직에 따라 관리됨으로써, 객체의 상태를 동일하게 관리할 수 있다.

      public class Lotto {
      	private List<LottoNumber> lottos;
      
      	public Lotto(List<LottoNumber> lottos) {
      		this.lottos = lottos;
      	}
      	public boolean validationNumber(int number) {
          	return lottos.contains(number);
      	}
      }
      
      public class LottoTickets {
      	private List<Lotto> tickets;
      
      	public LottoTickets(List<Lotto> tickets) {
      		this.tickets = tickets;
      	}
      	public List<LottoNumber> getTickets(){
      		return tickets;
      	}
      }
      			```



전략 패턴

전략 패턴(Strategy Pattern) 이란?

같은 문제를 해결하는 여러 알고리즘이 클래스별로 캡슐화되어 있고 이들이 필요할 때 교체할 수 있도록 함으로써 동일한 문제를 다른 알고리즘으로 해결할 수 있게 하는 디자인 패턴

로또 생성의 문제

  • 랜덤 메서드를 사용하여 로또를 발급받다보면 테스트시에 제대로 된 테스트가 복잡하다.
    (랜덤으로 번호가 생성되므로 제대로 로또가 돌아가고 있는지 확인하기가 어렵다.)
  • 자동으로 로또를 발급받다가 수동으로 로또를 발급받는 시스템으로 확장하고자 할 때 확장성이 매우 떨어진다.

전략 패턴을 통한 해결

‘전략 패턴’을 활용하여 로또 생성 정책을 별도의 객체로 분리 하였다.

로또 번호 생성 을 추상화하는 인터페이스(Strategy)와 로또 번호를 직접 생성 하는 컨텍스트(Context)를 별도로 분리하여 구현함으로써 테스트하기 좋은 메서드로 만들 수 있었다.

때문에 이때 전략패턴을 사용하여 로또 생성 정책을 인터페이스로 별도의 객체로 분리하여
실제 구현체에서는 랜덤 생성을 진행하지만 test는 구체적인 번호로 진행할 수 있게 되었다.




📝 Lotto 미션에 관한 피드백

  • 처음엔 Lotto<Integer> lotto 로 관리함으로써 자동,수동생성에 따라 LottoNumber 에 대한 비즈니스 로직이 흩어져서 관리되었다.
  • 생성된 Lotto 객체는 6개의 숫자와 범위를 (유효성)보장해야하는데, LottoNumber 객체가 이 원시값에 대한 유효성 검사 역할을 맡을 수 있다.
  • 객체지향 생활 체조 원칙인 '모든 원시값과 문자열을 포장한다' 에 따라
    LottoNumber 을 통해서 원시값(Integer)을 포장하고, LottoNumber 에 대한 validation 비즈니스 로직을 함께 관리함으로써 객체 상태는 동일하게 관리된다.
  • 그럼 이제Lotto 는 LottoNumber 에 대한 인스턴스들을 일급 콜렉션으로 관리할 수 있다.
    Lotto<Integer> lottoList<LottoNumber> lotto








[참조]
https://jojoldu.tistory.com/412
https://jackjeong.tistory.com/107
https://pjh3749.tistory.com/m/249

profile
- 👩🏻‍💻

0개의 댓글