본문 바로가기

Backend

[Java] 일급 컬렉션 학습 내용 정리

반응형

 

 

학습 목적 : 멤버 테이블과 멤버가 가진 코인 정보 테이틀간 ERD 설계 및 개발 방향 고민 중에, 홈 화면에서 코인 조회 빈도가 많다보니, 코인정보는 캐싱하는 편이 나아보였다. Redis Cache 방향을 이야기하던 중, 일급 컬렉션이라는 말이 나왔고 처음 들어보는 워딩이다보니 공부를 해보고자 검색해보게 되었다.


 정의 : 일급 컬렉션은 소트웍스 앤솔로지의 객체지향 생활체조 규칙 8. 일급 콜렉션 사용에서 언급되었다. 다른 객체와 동등한 지위를 갖는 컬렉션 객체를 의미한다. 즉, 컬렉션에 대한 처리를 하면서, 컬렉션 외 다른 멤버 변수가 없는 상태를 일급 컬렉션이라고 한다.

 

예시코드:

public class Student {
    private List<String> subjects;

    public Student(List<String> subjects) {
        this.subjects = subjects;
    }

    public List<String> getSubjects() {
        return subjects;
    }
}

 

위 코드에서 Student 클래스에서 List<String> 타입의 subjects를 직접 다룬다. 이 경우 Student 클래스는 List 타입에 의존성을 갖게 되며, List의 구현이 변경될 경우 Student 클래스도 함께 변경되어야 하는 문제점을 가지고 있다.

 

 

public class Student {
    private Subjects subjects;

    public Student(Subjects subjects) {
        this.subjects = subjects;
    }

    public Subjects getSubjects() {
        return subjects;
    }
}

public class Subjects {
    private List<String> subjects;

    public Subjects(List<String> subjects) {
        this.subjects = subjects;
    }

    public void addSubject(String subject) {
        subjects.add(subject);
    }

    public List<String> getSubjects() {
        return new ArrayList<>(subjects);
    }
}

위 코드는 Student 클래스에서 Subjects 클래스를 사용하도록 변경했다. Subjects 클래스는 List<String> 타입의 Subjects를 감싸고 있으며, Subject 개체를 추가하거나, 모든 Subject 객체를 가져올 수 있도록 메서드를 제공한다. 이렇게 할 경우 Student 클래스는 Subjects 클래스와만 의존성을 가지게 되고, 이전에 지닌 List 타입에 대한 의존성을 제거할 수 있다.

 


장점: 비지니스에 종속적인 자료구조, 컬렉션의 불변성 보장, 상태와 행위를 한 곳에서 관리할 수 있다는 점들을 들 수 있다.

 

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

ㄴ 비지니스 로직 : 사용자의 요구사항을 해결하기 위한 실질적인 코드

// 서비스 로직
public class StudentGroupService {
    public void createStudentGroup() {
        List<Student> studentGroup = List.of(
            new Student(1, "John", 20, Department.MATH),
            new Student(2, "Jane", 21, Department.PHYSICS),
            new Student(3, "Max", 22, Department.MATH)
        );

        // 비즈니스 로직
        // 동일한 Id가 있는지 검증
        if (studentGroup.stream().map(Student::getId).distinct().count() != studentGroup.size()) {
            throw new IllegalArgumentException("중복된 아이디가 있습니다.");
        }

        // 19살 이하 학생이 있는지 검증
        if (studentGroup.stream().anyMatch(student -> student.getAge() <= 19)) {
            throw new IllegalArgumentException("19살 이하의 학생이 있습니다.");
        }
    }
}

StudentGroup을 다른 곳에서도 활용할 경우, 검증 로직을 중복해서 작성해야한다는 단점이 있다.

 

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

    public StudentGroup(List<Student> students) {
        validateDuplicateId();
        validateAgeLimit();
        this.students = students;
    }

    private void validateDuplicateId() {
        if (students.stream().map(Student::getId).distinct().count() != students.size()) {
            throw new IllegalArgumentException("Duplicate Id exists");
        }
    }

    private void validateAgeLimit() {
        if (students.stream().anyMatch(student -> student.getAge() < 19)) {
            throw new IllegalArgumentException("Age should be greater than 19");
        }
    }
}

 

StudentGroup이라는 일급 컬렉션을 만들고, 멤버 변수로 List를 두었다. 위처럼 작성하면, 검증 로직이 필요하다는 것도 알 수 있고, 중복되는 코드들도 최소화시킬 수 있다.

 

* 컬렉션의 불변성 보장

일급 컬렉션은 내부 상태가 변경되지 않기 때문에 다른 곳에서 변경을 시도할 수 없다. 불변성을 굳이굳이 지킬 필요는 없지만 프로그램의 안정성이나 예측 가능성을 높이기 위해선 필요해보인다. 

ㄴ 생성자 함수에서 인자로 들어온 값을 this. 에 대입하는게 아닌 new ArrayList<>(args); 를 this.에 대입한다. 

ㄴ 더하여 getter함수에서도 멤버변수를 리턴하는게 아닌 Collections.unmodifiableList(args);로 수정불가능한 상태로 리턴한다. 

public class Order {
    private final OrderItems items;

    public Order(OrderItems items) {
        this.items = items;
    }

    public OrderItems getItems() {
        return items;
    }
}

public class OrderItems {
    private final List<String> items;

    public OrderItems(List<String> items) {
        if (items == null) {
            throw new IllegalArgumentException("Items cannot be null.");
        }
        this.items = Collections.unmodifiableList(new ArrayList<>(items));
    }

    public List<String> getItems() {
        return items;
    }
}

 

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

일급 컬렉션의 장점은 상태와 행위를 한 곳에서 관리할 수 있다는 점이다. 

 

 


https://dkswnkk.tistory.com/696

 

일급 컬렉션(First-Class Collection)이란?

일급 컬렉션(First-Class Collection)이란? Java에서 일급 컬렉션(First-Class Collection)은 다른 객체와 동등한 지위를 갖는 컬렉션 객체를 말합니다. 일급 컬렉션은 다음과 같은 특징을 가집니다. 컬렉션 객

dkswnkk.tistory.com

 

반응형