Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

일급 컬렌션에 대하여(황대선) #188

Open
hwangdaesun opened this issue Aug 13, 2024 · 0 comments
Open

일급 컬렌션에 대하여(황대선) #188

hwangdaesun opened this issue Aug 13, 2024 · 0 comments
Assignees

Comments

@hwangdaesun
Copy link
Collaborator

hwangdaesun commented Aug 13, 2024

문제가 무엇인가?

일급 컬렌션에 대해서 알아보자

왜 이런 문제를 선정하였는가?

이번 장에서는 "공유된 가변 데이터"의 위험성에 대해 다루면서, 여러 클래스가 동일한 리스트에 접근하는 상황을 예시로 설명했습니다. 이로 인해 발생할 수 있는 문제점과 이를 방지하기 위한 방법으로, 부작용 없는 메서드를 작성하거나 불변 객체를 사용하는 것이 권장되었습니다.

이러한 맥락에서, 컬렉션(Collection)의 불변성을 보장하기 위한 하나의 방법으로 "일급 컬렉션"이라는 개념을 소개하고자 합니다.

자신이 생각한 답변은 무엇인가?

Collection을 Wrapping하면서, 그 외 다른 멤버 변수가 없는 상태를 일급 컬렉션이라 한다.

Wrapping함으로써 다음과 같은 이점을 가진다.

  • 비즈니스에 종속적인 자료구조
  • Collection의 불변성을 보장
  • 상태와 행위를 한 곳에서 관리
  • 이름이 있는 컬렉션
/**
 * 하루에 먹은 식사들의 칼로리,단,탄,지를 계산
 *
 * @author hwangdaesun
 * @version 1.0
 * @throws NotSameDateException : 식사들의 날짜가 다를 경우
 */
@Getter
@ToString
public class DailyMeal {

    private final List<Meal> meals;

    public DailyMeal(List<Meal> meals) {
        validateSameDateIfNotEmpty(meals);
        this.meals = meals;
    }

    public double calculateCurrentCalorie() {
        return meals.stream().mapToDouble(Meal::getCurrentCalorie).sum();
    }

    public double calculateCurrentCarbohydrate() {
        return meals.stream().mapToDouble(Meal::getCurrentCarbohydrate).sum();
    }

    public double calculateCurrentProtein() {
        return meals.stream().mapToDouble(Meal::getCurrentProtein).sum();
    }

    public double calculateCurrentFat() {
        return meals.stream().mapToDouble(Meal::getCurrentFat).sum();
    }

    private void validateSameDateIfNotEmpty(List<Meal> meals) {
        if (!meals.isEmpty() && !isSameDate(meals)) {
            throw NotSameDateException.EXECPTION;
        }
    }

    private boolean isSameDate(List<Meal> meals) {
        int size =
                meals.stream()
                        .map(meal -> meal.getMealDateTime().toLocalDate())
                        .collect(toSet())
                        .size();
        if (size != 1) {
            return false;
        }
        return true;
    }

}

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

EATCeed는 저체중을 위한 증량 서비스로 하루 식사 에는 아래와 같은 조건이 있습니다.

  • 하루에 식사를 하지 않을 수도 있다.
  • 하루에 식사를 했을 경우에는 식사한 날짜가 같아야한다.

하루 식사 가 필요한 모든 장소에서는 위와 같은 검증 로직이 필요합니다. 또한, 해당 도메인의 특징을 인수인계 받는 사람이 모를 수도 있습니다.

따라서, 위와 같은 조건으로만 생성할 수 있는 자료구조를 만들면 위와 같은 문제가 해결됩니다.

불변

일급 컬렉션은 컬렉션의 불변을 보장합니다.

final을 사용하여 List 타입의 컬렌션의 재할당을 금지합니다.

또한, 컬렉션의 값을 변경할 수 있는 메소드가 없게 만듭니다.

이렇게 함으로써, 해당 클래스를 사용하는 방법은 새로 만들거나 값을 가져오는 것 뿐 값을 변경 및 추가하는 것은 안 됩니다.

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

값과 로직이 한 곳에 존재한다.

만약, 일급 컬렉션을 사용하지 않는다면 아래와 같이 하루 식사 라는 값과 이를 사용한 계산을 한 곳에 사용할 수 없습니다.

List<Meal> meals = Arrays.asList(
	...
);

double currentCalorie = meals.stream()
  .mapToDouble(Meal::getCurrentCarbohydrate)
  .sum();

이는 똑같은 기능을 하는 메소드를 중복으로 생성할 수 있습니다.

같은 기능을 하는 메서드를 잘못 만들어 사용할 수 있습니다.

이름이 있는 컬렉션

컬렉션에 이름을 붙일 수 있습니다.

만약, 일급컬렉션을 사용하지 않았더라면 같은 의미임에도 불구하고 개발자에따라 변수명이 다 다를 수도 있습니다.

반면에, DailyMeal 이라고 명확하게 이름을 부여한다면 팀원들끼리 더 정확한 의사소통이 가능합니다.

공부한 출처 : https://jojoldu.tistory.com/412

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant