Dailelog

일급 컬렉션(우테코 7기 프리코스 대비 6기 1주차) 본문

JAVA

일급 컬렉션(우테코 7기 프리코스 대비 6기 1주차)

Daile 2024. 7. 6. 00:01

일급 컬렉션이란?

일급 컬렉션은 소트윅스 앤솔로지의 객체지향 생활체조 파트의 규칙 8에서 언급이 되었다고 합니다.

규칙 8: 일급 콜렉션 사용

이 규칙의 적용은 간단하다.

콜렉션을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다.

각 콜렉션은 그 자체로 포장돼 있으므로 이제 콜렉션과 관련된 동작은 근거지가 마련된셈이다.

필터가 이 새 클래스의 일부가 됨을 알 수 있다.

필터는 또한 스스로 함수 객체가 될 수 있다.

또한 새 클래스는 두 그룹을 같이 묶는다든가 그룹의 각 원소에 규칙을 적용하는 등의 동작을 처리할 수 있다.

이는 인스턴스 변수에 대한 규칙의 확실한 확장이지만 그 자체를 위해서도 중요하다.

콜렉션은 실로 매우 유용한 원시 타입이다.

많은 동작이 있지만 후임 프로그래머나 유지보수 담당자에 의미적 의도나 단초는 거의 없다.

일급 컬렉션을 왜 사용할까?

일급 컬렉션을 사용하면서 얻는 이점은 다음과 같습니다.

1. 비지니스에 종속적인 자료구조

우아한 테크 코스 7기를 대비하기 위해서 지금 현재 6기 1주차 미션을 수행하고 있습니다. BaseBall에서 숫자 객체의 “숫자의 크기를 3자리 숫자로 해야한다”, “서로 다른 숫자로 구성되어야한다.” 라는 조건을 가지고 있습니다. 자료구조에 위 조건을 충족하는가 에 대하여 유효성을 검증하는 코드가 들어가야 합니다. 이러한 문제는 아래의 코드와 같이 일급 컬렉션을 만들어 특정 조건으로 만들 수 있는 새로운 자료구조를 생성하면 해결할 수 있습니다.

Number.java

public class Number {
    protected static final int BASE_BALL_NUMBER_SIZE = 3;

    protected final List<Integer> baseBallNumbers;

    public Number(List<Integer> baseBallNumbers) {
        validateSize(baseBallNumbers);
        validateDuplicate(baseBallNumbers);
        this.baseBallNumbers = baseBallNumbers;
    }

    private void validateSize(List<Integer> baseBallNumbers) {
        if (baseBallNumbers.size() != BASE_BALL_NUMBER_SIZE) {
            throw new IllegalArgumentException("3자리 수만 가능합니다.");
        }
    }

    private void validateDuplicate(List<Integer> baseBallNumbers) {
        Set<Integer> duplicateSet = new HashSet<>(baseBallNumbers);
        if (duplicateSet.size() != BASE_BALL_NUMBER_SIZE) {
            throw new IllegalArgumentException("서로 다른 수로 이루어진 3자리수만 가능합니다.");
        }
    }
}

일급 컬렉션을 만든 위의 코드를 보면 carList는 생성된 이후 getter, setter가 따로 없어 내부 값의 변경이 불가능 한 것을 확인할 수 있습니다.

2. Collection의 불변성을 보장

Java의 final은 불변을 만들어주는 것이 아니라 재할당만을 금지합니다. 그리하여 final List<Car> carList;와 같이 만들어도 carList은 재할당만 불가능 할 뿐이지 add, remove와 같은 메서드로 내용을 변경할 수는 있습니다.

Java에서 final로 만들 수 없는 불변 객체는 일급 컬렉션과 래퍼 클래스의 방법으로 해결해야합니다.

그런데 의문점!! 일급 컬렉션은 Getter,setter이 없어서 변경이 불가능 한건 알겠는데 getter이 없으면 일급 컬랙션끼리 비교하는 로직을 쓸대 내부데이터 정보를 어떻게 가지고 오는 것인지 궁금합니다. getter은 상관이 없는 것 같은 데 더 공부해봐야 할것 같습니다.

3. 상태와 행위를 한 곳에서 관리

일급 컬렉션은 값과 로직이 함께 존재하여 외부에서의 중복된 메서드의 생성과 같은 문제를 해결해줍니다.

일급 컬렉션을 생성하고 해당 메서드들을 일급 컬렉션 내에 만들어두고 외부에서는 호출을 하여 사용하도록 프로그래밍하면 상태와 행위를 한 곳에서 관리할 수 있습니다.

4. 이름이 있는 컬렉션

  1. 해당 객체들을 검색을 할 때 변수명으로만 검색을 할 수 있어 변수명을 모를 시 검색을 하기 어렵다

2.단순히 변수명에 불과하여 의미 부여가 어렵다.

활용

ComputerNumber.java

public class ComputerNumber extends Number {

    public ComputerNumber(List<Integer> baseBallNumbers) {
        super(baseBallNumbers);
    }

    public Score getScore(PlayerNumber playNumbers) {
        int[] baseBallComputerNumberArr = getBaseBallNumberArr();
        int[] baseBallPlayNumberArr = playNumbers.getBaseBallNumberArr();
        int strike = 0;
        int ball = 0;

        for(int i = 0; i < BASE_BALL_NUMBER_SIZE; i++) {
            Integer num =baseBallComputerNumberArr[i];
            for(int j = 0; j < BASE_BALL_NUMBER_SIZE; j++) {
               if(num == baseBallPlayNumberArr[j]) {
                   if (i == j) {
                       strike++;
                   }
                   if (i != j) {
                       ball++;
                   }
                   break;
               }
            }
        }
        return new Score(strike, ball);
    }
}

PlayerNumber.java

public class PlayerNumber extends Number {

    public PlayerNumber(List<Integer> baseBallNumbers) {
        super(baseBallNumbers);
    }
}

 

LIST