티스토리 뷰

반응형

위 제목처럼 고민하게 된 계기는 다음과 같습니다.

 

서비스를 운영하면서 어떤 특정 클래스의 라인수가 길어지게 되고 해당 라인 수를 쪼개고 싶어지는 순간이 오게 됩니다.

 

예를 들어 설명해보겠습니다.

 

라면 레시피 관련 클래스가 있다고 생각해봅시다.

 

이 때 라면 종류는 다양합니다.

- 빨간 국물 라면

- 짜장 라면

- 짬뽕 라면

- 비빔면

- 불닭 볶음면

등 다양한 레시피가 존재합니다.

 

그리고 빨간 국물 라면의 종류도 다양합니다.

 

- 신라면

- 삼양라면

- 진라면

 

등 다양한 제품이 존재하게 됩니다.

 

이러한 정보를 하나의 클래스를 담는다고 생각해봅시다. 가령 다음과 같이 말이죠.

@Getter
@RequiredArgsConstructor
public enum RamenRecipe {
    RED_SHIN(RamenType.RED, Brand.N, "신라면"),
    // ...
    RED_SAM(RamenType.RED, Brand.S, "삼양라면");
    private final RamenType type;
    private final Brand brand;
    private final String description;
}

다음과 같이 적을 때는 별 문제가 없으며 description 이란 필드가 단순히 설명으로 되어 있으니 상관은 없지만

만일 description 대신 

- receipe의 내용을 담고 있는 클래스를 맵핑

- suppier를 통해 라면을 생성하는 람다식

등 다양한 옵션이 붙게 되면 하나 하나의 enum의 크기가 커지게 되고 이러한 갯수가 많아지면 관리하기 힘들어진다는 단점이 존재합니다.

 

그랬을 때 내가 생각한 방안은 다음과 같습니다.

 

enum 필드에 대한 getterMethod 인터페이스 구성

 

public interface Recipe {
    RamenType getType();

    Brand getBrand();

    String getDescription();
}

 

각 관심사에 맞는 enum 클래스 생성

@Getter
@RequiredArgsConstructor
public enum SamRecipe implements Recipe{
    RED_SAM_1(RamenType.RED, Brand.S, "삼양라면"),
    RED_SAM_2(RamenType.RED, Brand.S, "삼양라면"),
    RED_SAM_3(RamenType.RED, Brand.S, "삼양라면"),
    RED_SAM_4(RamenType.RED, Brand.S, "삼양라면");
    private final RamenType type;
    private final Brand brand;
    private final String description;
}

 

@Getter
@RequiredArgsConstructor
public enum ShinRecipe implements Recipe{
    RED_SHIN_0(RamenType.RED, Brand.N, "신라면"),
    RED_SHIN_1(RamenType.RED, Brand.N, "신라면"),
    RED_SHIN_2(RamenType.RED, Brand.N, "신라면"),
    RED_SHIN_3(RamenType.RED, Brand.N, "신라면"),
    RED_SHIN_4(RamenType.RED, Brand.N, "신라면");
    private final RamenType type;
    private final Brand brand;
    private final String description;
}

aggregation class 구성

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class RecipeAggregation {
    public static Collection<Recipe> values;
    private static final String PACKAGE_NAME = "com.vixx.springground.ramen";
    private static final Reflections reflections = new Reflections(PACKAGE_NAME);
    static {
        final List<Recipe> recipes = new LinkedList<>();
        reflections.getSubTypesOf(Recipe.class).forEach(clazz -> recipes.addAll(Arrays.asList(clazz.getEnumConstants())));
        values = recipes;
    }
}

 

 

테스트

    @Test
    void name() {
        final Collection<Recipe> values = RecipeAggregation.values;
        Assertions.assertThat(values.size()).isEqualTo(9);
        values.forEach(System.out::println);
    }
RED_SAM_1
RED_SAM_2
RED_SAM_3
RED_SAM_4
RED_SHIN_0
RED_SHIN_1
RED_SHIN_2
RED_SHIN_3
RED_SHIN_4

 

간단하지만 간혹 하위클래스를 가져오는 방법에 대해 고민하셨던 분들이라면 다음과 같은 방법도 고려하면 좋을 것 같아 작성해봤습니다.

읽으시면서 부족한 점이 있거나 수정할 부분이 있으면 댓글 부탁드립니다.

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함