CS/ETC

일급 컬렉션이 무엇인가요?

kevin_01 2024. 12. 7. 19:54
728x90

일급 컬렉션


💡 하나의 컬렉션을 감싸는 클래스를 만들고, 해당 클래스에서 컬렉션과 관련된 비지니스 로직을 관리하는 패턴을 말한다.

// 예시
// 일급 컬렉션
public class Orders {

    private final List<Order> orders;

    public Orders(List<Order> orders) {
        validate(orders); // 검증 수행
        ...
    }

    public void add(Order order) {
        if (order == null) {
            throw new IllegalArgumentException("Order cannot be null");
        }
        orders.add(order);
    }

    public List<Order> getAll() {
        return Collections.unmodifiableList(orders);
    }

    public double getTotalAmount() {
        return orders.stream()
                     .mapToDouble(Order::getAmount)
                     .sum();
    }
}
public class OrderService {

    private final Orders orders = new Orders();

    public void addOrder(Order order) {
        orders.add(order);
    }

    public Orders getOrders() {
        return orders;
    }

    // 추가 비즈니스 로직...
}

일급 컬렉션을 사용해야 하는 이유는 무엇인가?

  • 일급 컬렉션 클래스에 로직을 포함하거나 비지니스에 특화된 명확한 이름을 부여할 수 있다
  • 불필요한 컬렉션 API를 외부로 노출하지 않도록 할 수 있으며 컬렉션을 변경할 수 없도록 만든다면 예기치 않은 변경으로부터 데이터를 보호할 수 있다.

 

일급 컬렉션의 특징

  • 컬렉션을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다.
  • 컬렉션과 관련된 로직을 클래스내에 캡슐화 해야 한다.

 

왜 일급 컬렉션인가?

1. 캡슐화와 관심사의 분리


public class ProductionCollection {
    private final List<product> products;

    public ProductCollection(List<Product> products) {
        this.products = new ArrayList<>(products);
    }

    public ProductCollection filterByCategory(String category) {
        return new ProductCollection(
            products.stream()
                .filter(product -> product.getCategory().equals(category))
                .collect(Collectors.toList())
        );
    }
}

일급 컬렉션을 사용하면 컬렉션에 대한 모든 조작과 로직을 해당 컬렉션 클래스 내부에 구현할 수 있다. 이로써 로직이 분산되는 것을 방지하고, 관련 로직을 한 곳에서 관리할 수 있다.

또한 클래스가 단 하나의 책임만을 갖게된다. 이 클래스에서는 products 컬렉션을 관리하는 책임만을 가짐으로써 코드의 가독성과 유지 보수성이 향상된다.

 

2. 일급 컬렉션의 불변성 보장


public class TeamMembers {
    private final List<Member> members;

    public TeamMebmers(List<Member> members) {
        this.members = new ArrayList<>(members);
    }

    public void addMember(Member member) {
        members.add(member);
    }

    public void removeMember(Member member) {
        members.remove(member);
    }

    public List<Member> getMembers() {
        return Collections.unmodifiableList(members);
    }
}

일급 컬렉션을 사용하면 불변성 보장을 더욱 용이하게 할 수 있어 외부에서의 컬렉션 상태 변경을 방지할 수 있다.

이를 통해 데이터의 데이터의 안정성과 예측 가능성이 증가한다. 또한 불변성이 보장되면 사이드 이펙트의 가능성이 줄어들며, 멀티 스레드 환경에서의 안정성이 향상된다.

이 코드에서 TeamMembers 클래스는 어떠한 팀의 멤버들의 리스트를 관리한다.

여기서 멤버를 추가하거나 제거하는 메서드가 클래스 내부에 구현되어 있고 일반적인 List.add() 와 같은 메서드를 통해 상태 변경이 불가능하다. 즉, 이 클래스의 메서드를 통해서만 상태 변경이 이루어질 수 있다. getMembers() 메서드는 불변 리스트를 반환하여 외부에서 컬렉션을 변경하는 것을 방지한다.

이처럼 일급 컬럭션을 사용하면 컬렉션의 불변성을 내부 로직을 통해 더욱 강력하게 관리할 수 있다.

 

3. 비지니스 규칙과 검증 로직의 중앙화


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

    public StudentCollection(List<Student> students) {
        this.students = new ArrayList<>();
        for (Student student : students) {
            addStudent(student);
        }
    }

    public void addStudent(Student student) {
        validateStudent(student);
        students.add(student);
    }

    private void validateStudent(Student student) {
        if (student.getAge() < 18) {
            throw new IllegalArgumentException("학생 중 18세 이상만 팀에 들어올 수 있습니다");
        }
    }
}

일급 컬렉션을 통해서 컬렉션에 적용되어야 할 비지니스 규칙을 클래스 내부에 정의함으로써 일관된 규칙 적용이 가능하다.

컬렉션에 추가되거나 변경되는 요소들에 대한 검증 로직을 일급 컬렉션 내부에 구현함으로써, 데이터의 정합성을 보다 체계적으로 관리할 수 있다.

addStudent 메서드에서 학생을 추가할 때 validationStudent 메서드를 통해 학생의 나이가 만 18세이상인지 검증한다. 이렇게 모든 학생 객체가 일관된 규칙을 따를수 있다.

 

 

일급 컬렉션을 사용할 때 주의사항

오버엔지니어링의 위험


  • 일급 컬렉션을 사용할 때 주의해야 할 중요한 점 중 하나는 오버엔지니어링의 위험이다.
  • 모든 컬렉션을 일급 컬렉션으로 만드는 것이 항상 좋은 것은 아니다.
public class SimpleDataCollection {
    private final List<Data> dataList;

    public SimpleDataCollection(List<Data> dataList) {
        this.dataList = dataList;
    }
}

이 예시에서 SimpleDataCollection은 복잡한 로직 없이 데이터만을 저장한다. 이런 경우 일급 컬렉션을 사용하는 것은 오버엔지니리어링이 될 수 있다.

이 처럼 일급 컬렉션은 컬렉션에 복잡한 비지니스 로직이나 규칙이 적용될 때 가장 유용하다.

단순히 데이터를 저장하는 용도라면 굳이 일급 컬렉션을 사용할 필요는 없다.

따라서 일급 컬렉션을 도입하기 전에 해당 컬렉션에 어떤 로직이나 규칙이 필요한지 고려해야 한다.

컬렉션의 복잡성과 유지보수의 편의성을 균형있게 고려하는 것이 중요하다

728x90

'CS > ETC' 카테고리의 다른 글

equals와 hashCode는 왜 함께 정의해야 하는가?  (0) 2024.12.17
트랜잭션 격리수준  (0) 2024.12.11