First Class Collection

이태곤·2024년 1월 23일
0

CS

목록 보기
15/23

1. First Class Collection

  • First Class Collection (일급 컬렉션): Collection을 Wrapping 하면서, 그 외 다른 멤버 변수가 없는 상태

  • 일급 컬렉션을 적용하지 않은 경우: Study 클래스의 멤버 변수로 스터디원을 의미하는 member에 대한 리스트를 가지고 있는 경우

public class Study {

    private String name;
    List<Member> members;
    // ...
}
  • 일급 컬렉션을 적용한 경우: members 리스트를 Wrapping 하는 클래스를 만들고, 해당 클래스는 members 리스트 외에 다른 멤버 변수를 가지고 있지 않은 상태
public class Study {
    private Members members;

    public Study(Members members) {
        this.members = members;
    }

    public Members getMembers() {
        return members;
    }
}

class Members {
    private List<Member> members;

    public Members(List<Member> members) {
        this.members = members;
    }
}

class Member {
    String name;
    String sex;
    int age;
}

2. First Class Collection 이점

1. 가독성과 유지보수성 향상

  • 스터디 구성원(member)가 최대 10명이라는 조건이 생겼을 경우, 일급 컬렉션을 적용하지 않으면 Study 클래스가 members 검증에 대한 역할까지 맡게 된다.
  • Study class가 Member에 관련된 데이터와 검증을 모두 관리하게 된다.
    → 비지니스 종속적이지 않다!
public class Study {

    private String name;
    private boolean isFree;
    private List<Member> members;

    public Study(String name, boolean isFree, List<Member> members) {
        validate(members);
        this.name = name;
        this.isFree = isFree;
        this.members = members;
    }

    private void validate(List<Member> members) {
        if (members.size() > 10) {
            throw new IllegalArgumentException("멤버는 최대 10명입니다.");
        }
    }
}
  • 일급 컬렉션을 사용하게 되면, Member에 대한 검증 로직을 Study class가 아닌 Member class에서 할 수 있게 된다.
  • Member에 대한 새로운 비지니스 로직이 추가된다하더라도, Member class 내에서 추가 및 수정 작업이 이루어지므로 비지니스 종속적인 코드를 작성할 수 있다.
public class Study {

    private String name;
    private boolean isFree;
    private Members members;

    public Study(String name, boolean isFree, Members members) {
        this.name = name;
        this.isFree = isFree;
        this.members = members;
    }
}

//일급 컬렉션
class Members {
    private List<Member> members;

    public Members(List<Member> members) {
        validate(members);
        this.members = members;
    }

    private void validate(List<Member> members) {
        if (members.size() > 10) {
            throw new IllegalArgumentException("스터디원은 최대 10명입니다.");
        }
    }
}

2. 캡슐화

  • 일급 컬렉션을 사용하지 않고 스터디 멤버 중에서 성인인 멤버만 조회하는 기능을 추가하는 경우, Study class에 대한 역할이 늘어나게 된다.
    또한, 다른 클래스에서 Member 클래스를 사용하면 중복 코드가 늘어나게 된다.
public class Study {

    private String name;
    private boolean isFree;
    private List<Member> members;

    // ...

    public List<Member> findAdults() {
        return members.stream()
                .filter(m -> m.getAge() >= 20)
                .collect(Collectors.toList());
    }
}
  • 중복 발생 경우
public class Study {
    private List<Member> members;

    // ...

    public List<Member> findAdults() {
        return members.stream() // 중복 코드
                .filter(m -> m.getAge() >= 20)
                .collect(Collectors.toList());
    }
}

public class Club {

    private List<Member> members;

    // ...


    public List<Member> findAdults() {
        return members.stream() // 중복 코드
                .filter(m -> m.getAge() >= 20)
                .collect(Collectors.toList());
    }
}
  • 스터디 구성원(Member)과 관련된 데이터와 검증 로직은 Member class에 캡슐화되어 있기 때문에 코드의 가독성과 유지보수성이 향상된다.
    스터디, 동아리 클래스가 가지고 있던 members에 대한 역할과 책임을 분리할 수 있고 중복된 코드의 작성을 방지할 수 있게 된다.
public class Study {

    private Members members;

    // ...

    public List<Member> findAdults() {
        return members.findAdults();
    }
}

public class Club {

    private Members members;

    // ...

    public List<Member> findAdults() {
        return members.findAdults();
    }
}

//일급 컬렉션
class Members {
    private List<Member> members;

    // ...

    public List<Member> findAdults() {
        return members.stream()
                .filter(m -> m.getAge() >= 20)
                .collect(Collectors.toList());
    }
}

3. 컬렉션의 불변성 보장

  • 일급 컬렉션과 private 접근 제어자를 사용하여 외부에서 컬렉션에 직접 접근할 수 없도록 막고, 메서드를 통해서만 컬렉션의 값을 읽을 수 있게 만들면 컬렉션을 불변으로 만들 수 있다.
class Members {
    private List<Member> members;

    public Members(List<Member> members) {
        this.members = members;
    }

    public Member findMember(int index) {
        return members.get(index);
    }
}
  • 컬렉션을 반환해야 하는 경우, Collections.unmodifiableList를 사용하여 읽기 전용 불변 리스트로 반환할 수 있다.
class Members {
    private List<Member> members;

    public Members(List<Member> members) {
        this.members = members;
    }

    // ...

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

[출처]

https://developer-hm.tistory.com/227
https://jojoldu.tistory.com/412
https://tecoble.techcourse.co.kr/post/2020-05-08-First-Class-Collection/

1개의 댓글

comment-user-thumbnail
2024년 2월 12일

단점은 어떤 게 있을까요 태곤님

답글 달기