티스토리 뷰

이펙티브 자바 Effective Java 2/E
국내도서
저자 : 조슈아 블로크(Joshua Bloch) / 이병준역
출판 : 인사이트 2014.09.01
상세보기



때로 두 가지 이상의 기능을 가지고 있으며, 그중 어떤 기능을 제공하는지 표시하는 태그(tag)가 달린 클래스를 만날 때가 있다.

class Figure {
  enum Shape { RECTANGLE, CIRCLE };

  // 어떤 모양인지 나타내는 태그 필드
  final Shape shape;

  // 태그가 RECTANGLE일 때만 사용되는 필드
  double length;
  double width;

  // 태그가 CIRCLE일 때만 사용되는 필드
  double radius;

  // 원을 만드는 생성자
  Figure(double radius) {
    shape = Shape.CIRCLE;
    this.radius = radius;
  }

  // 사각형을 만드는 생성자
  Figure(double length, double width) {
    shape = Shape.RECTANGLE;
    this.length = length;
    this.width = width;
  }

  double area() {
    switch(shape) {
      case RECTANGLE:
        return length * width;
      case CIRCLE:
        return Math.PI * (radius * radius)
      default:
        throw new AssertionError();
    }
  }
}

태그 달린 클래스는 enum 선언, 태그 필드, switch 문 등의 상투적 코드가 반복되며 생성자에서 관련 없는 필드를 초기화하지 않는 한, 필드들을 final로 선언할 수도 없으므로 상투적인 코드(boilerplate)는 더 늘어난다.

태그 기반 클래스(tagged class)는 너저분한데다 오류 발생 가능성이 높고, 효율적이지도 않는다. 태그 기반 클래스는 클래스 계층을 얼기설기 흉내 낸 것일 뿐이다.

abstract class Figure {
  abstract double area();
}

class Circle extends Figure {
  final double radius;

  Circle(double radius) { ... }

  double area() { ... }
}

class Rectangle extends Figure {
  final double length;
  final double width;

  Rectangle(double length, double width) {
    ...
  }

  double area() { ... }
}

클래스 계층으로 변환한 결과, 단순하고 명료하며 원래 클래스에 있던 난잡하고 상투적인 코드도 없다.

또한 자료형 간의 자연스로운 계층 관계를 반영할 수 있어서 유연성이 높아지고 컴파일 시에 형 검사(type checking)를 하기 용이하다.

요약

  • 태그 기반 클래스 사용은 피해야 한다
  • 태그 필드가 있는 클래스를 만나게 되면, 리팩터링을 통해 클래스 계층으로 변환할 방법이 없는지 고민


댓글