1급 컬렉션

김경태·2024년 4월 17일

1급 컬렉션(First-Class Collection)은 객체지향 프로그래밍에서 컬렉션을 감싸는 단 하나의 클래스로만 이루어진 설계 기법이다.

컬렉션(Collection)

자바 컬렉션 프레임워크는 자바 데이터 구조를 처리하기 위한 표준 방법이다.
주요 인터페이스로는 List, Set, Map....

장점

  1. 비즈니스 규칙의 명확한 표현
    1급 컬렉션을 사용하면 컬렉션에 적용되는 비즈니스 규칙이나 로직을 컬렉션을 감싸는 클래스 내부에 명확하게 표현할 수 있습니다. 이로 인해 코드의 가독성과 유지보수성이 향상됩니다.
  2. 불변성의 보장
    컬렉션을 불변 객체로 만들어 부작용(side effect)을 줄일 수 있습니다. 이는 컬렉션의 상태가 객체 생성 후 변경되지 않도록 보장함으로써, 코드의 안정성을 높이고 예기치 않은 버그를 방지하는 데 도움이 됩니다.
  3. 재사용성의 향상
    특정한 비즈니스 규칙이나 로직을 적용한 컬렉션을 하나의 클래스로 만들어 두면, 같은 규칙이 필요한 다른 부분에서도 쉽게 재사용할 수 있습니다. 이는 코드의 중복을 줄이고 프로젝트의 일관성을 유지하는 데 기여합니다.

예시

public class Students {
    private final List<Student> students;

    public Students(List<Student> students) {
        this.students = Collections.unmodifiableList(new ArrayList<>(students));
    }

    // 여기에 학생들에 대한 비즈니스 로직 추가
    public double averageGrade() {
        return students.stream()
                       .mapToDouble(Student::getGrade)
                       .average()
                       .orElse(0.0);
    }
}

방어적 복사(Defensive Copying): 이것은 객체 내부의 필드가 외부 참조에 의해 간접적으로 변경되는 것을 방지합니다. 즉, 객체를 생성할 때 제공된 외부 리스트의 복사본을 만들어, 원본 리스트가 나중에 변경되어도 객체 내부의 상태에는 영향을 주지 않습니다. 그러나 이 방법만으로는 객체 내부의 리스트 자체가 직접 변경되는 것은 막을 수 없습니다.

불변 리스트(unmodifiableList): 이 메서드는 리스트를 불변으로 감싸, 리스트에 대한 모든 변경 시도가 예외를 발생시키도록 합니다. 이렇게 함으로써 객체의 메서드를 통해 내부 리스트에 접근하는 사용자가 리스트를 변경할 수 없게 됩니다. 그러나 이 방법만 사용할 경우, 객체 생성 시 제공된 외부 리스트가 변경되면 객체 내부의 리스트도 영향을 받을 수 있습니다.

일급 컬렉션을 사용하지 않는 경우

public class School {
    private final List<Student> students;

    public School(List<Student> students) {
        // 여기서는 불변 리스트로 만들지 않음으로써 외부에서 변경 가능
        this.students = new ArrayList<>(students);
    }

    // 학생 추가
    public void addStudent(Student student) {
        students.add(student);
    }

    // 학생 제거
    public void removeStudent(Student student) {
        students.remove(student);
    }

    // 평균 성적 계산
    public double averageGrade() {
        return students.stream()
                       .mapToDouble(Student::getGrade)
                       .average()
                       .orElse(0.0);
    }
}
  1. 불변성의 부재: School 클래스는 students 리스트의 불변성을 보장하지 않습니다. 이로 인해 students 리스트가 예기치 않게 변경될 위험이 있으며, 이는 버그의 원인이 될 수 있습니다.
  2. 코드의 중복: 다른 클래스에서도 비슷한 형태의 Student 리스트를 다루어야 한다면, 비슷한 메서드(addStudent, removeStudent, averageGrade 등)를 여러 클래스에 중복해서 구현해야 합니다. 이는 코드의 중복을 초래하고 유지보수를 어렵게 만듭니다.
  3. 책임의 분산: School 클래스는 학생들을 관리하는 것뿐만 아니라 평균 성적을 계산하는 등의 비즈니스 로직도 함께 담당하고 있습니다. 이는 단일 책임 원칙(Single Responsibility Principle)에 어긋나며, 클래스가 과도한 책임을 지게 되어 관리가 복잡해질 수 있습니다.
profile
잊지 않기 위해 기록

0개의 댓글