티스토리 뷰

Java/Effective Java

[Item35] ordinal 금지

ryumodern 2022. 3. 15. 19:16

책에 나온 enum 사용의 안 좋은 예시를 가져왔다

public enum Ensemble {
  SOLO, DUET, TRIO, QUARTET, QUINTET,
  SEXTET, SEPTET, OCTET, NONET, DECTET;

  public int numberOfMusicians() {
    return ordinal() + 1;
  }
}

 

왜 안 좋은 것인가?

열거 타입 상수와 연결된 위치 값을 반환하는 ordinal() 메서드를 사용하기 때문이란다

코드는 멋들어진 API를 사용해 걸작을 만들어내는 것보다 모르는 사람이 봐도 이해할 수 있도록 만드는 게 어렵다

numberOfMusicians() 메서드를 이해하기 위해서는 위치값에 1을 더해 반환하는데

ordinal()이 위치 값을 반환한다는 사실도 알아야 하고, 0부터 시작하는 것도 알아야 한다

ordinal() 찍고 들어가 어떻게 돌아가는지 보면 끝나는 문제니 별게 아닐 수도 있지만 더 큰 문제는 유지보수와 관련되어 있다

 

요구사항으로 2.5중주, 1.75중주가 들어왔다고 치면 ordinal()로는 표현할 방법이 없다

게다가 2.5중주라면 DUET, TRIO 사이에 들어가야 하니 TRIO부터 DECTET까지의 위치 값이 변하는 건 덤이다

2.5중주가 말도 안 되는 건 알지만 현실은 녹록치 않은 것이다, 어떤 기상천외한 요구사항이 있을지 모른다

 

Spring + JPA 개발에도 타입 안전성을 위해 인스턴스 필드로 enum을 사용하는 경우가 종종 있는데

이 때도 마찬가지로 ordinal() 값으로 DB에 저장하는 순간 지옥문이 열린다

예를 들어 회원의 권한을 표현하기 위해 USER, MANAGER, ADMIN으로 관리하는 상황에서

요구사항으로 ANONYMOUS, DEVELOPER 등이 추가된다고 가정하면 개념 상

ANONYMOUS, USER, DEVELOPER, MANAGER, ADMIN의 흐름이 알맞으나

ordinal을 쓰고 있는 상황이라면 개념이고 뭐고 기존 값 뒤에 덧붙여야 한다, 안 그럼 하위 호환성이 박살 나기 때문

 

위 같은 문제를 예방하고자 한다면 항상 @Enumerated(value = EnumType.STRING)을 바르는 걸 추천한다

단 언제나 그렇듯 예외는 존재하는데 enum의 위치값을 때려죽여도 바꿀 생각 없고

극강의 DB 저장 효율화를 위해서는 ordinal을 쓰는 것이 낫겠다

 

ordinal()은 주로 Enum을 다루는 컬렉션에서 사용하기 위해 만들어졌다고 한다

책에서는 친절하게도 우리가 쓰라고 만든게 아니니 쓰지 말라고 알려주신다

EnumMap은 빠른 성능을  위해 내부적으로는 배열을 만들어 사용한다 

index를 가르키는 것이 ordinal()이기에 아래와 같은 방식으로 key에서 index를 뽑아낼 때 사용하고 있다

 

 

 

마지막으로 enum의 적절한 예시를 보자

핵심은 enum 안에 private 필드 변수를 만들어두고 얘를 활용해서 값을 반환하는 것이다

값이 중복되더라도 문제없고, 중간에 껴넣더라도 반환하는 것은 위치 값과 관련이 없어 안전하다

public enum Ensemble {
  SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
  SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8), NONET(9), 
  DECTET(10), TRIPLE_QUARTET(12);

  private final int numberOfMusicians;

  Ensemble(int numberOfMusicians) {
    this.numberOfMusicians = numberOfMusicians;
  }

  public int numberOfMusicians() {
    return numberOfMusicians;
  }
}
댓글
링크
글 보관함
«   2024/04   »
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
Total
Today
Yesterday