반응형

이전 블로그에서 2017년 7월 20일에 작성한 글


 

프로젝트 소스를 보다가 상수(Constant)를 인터페이스(Interface)에 정의한 것을 발견했다. 학교 수업과 책으로 자바를 배웠을 때, 항상 상수는 클래스에 정의한 것만 봐왔던 나는 생소했다. 당연히 초보 개발자로서, 특별한 장점이 있으므로 실무에서는 인터페이스를 사용하지 않을까 생각해 자료를 찾아보았다. 결론부터 말하면 사용을 추천하지 않는 Anti 패턴이다.

 

Constant Interface

Constant Interface란 오직 상수만 정의한 인터페이스이다. 인터페이스의 경우, ​변수를 등록할 때 자동으로 public static final​이 붙는다. 따라서 상수처럼 어디에서나 접근할 수 있다. 그 뿐만 아니라 하나의 클래스에 여러 개의 인터페이스를 Implement 할 수 있는데, Constant Interface를 Implement 할 경우, ​인터페이스의 클래스 명을 네임스페이스로 붙이지 않고 바로 사용할 수 있다. 이러한 편리성 때문에 Constant Interface를 사용한다. 아래는 간단한 예이다. 

public interface Constants {
 double PI = 3.14159;
 double PLANCK_CONSTANT = 6.62606896e-34;
}

public class Calculations implements Constants {

 public double getReducedPlanckConstant() {
  return PLANCK_CONSTANT / (2 * PI);
 }
}

 

Constant Interface 문제점

Constant Interface를 써도 컴파일이 안 되는 것도 아니고 그렇게 잘못된 것 같지는 않아 보인다. 하지만 위키 Effective Java (규칙19) 책을 보면 다음과 같은 이유로 Anti 패턴으로 간주한다.

 

1. Implement 할 경우 사용하지 않을 수도 있는 상수를 포함하여 모두 가져오기 때문에 계속 가지고 있어야 한다.

 

2. 컴파일할 때 사용되겠지만, 런타임에는 사용할 용도가 없다. (Marker Interface는 런타임에 사용할 목적이 있으므로 다름)

 

3. Binary Code Compatibility (이진 호환성)을 필요로 하는 프로그램일 경우, 새로운 라이브러리를 연결하더라도, 상수 인터페이스는 프로그램이 종료되기 전까지 이진 호환성을 보장하기 위해 계속 유지되어야 한다.

 

4. IDE가 없으면, 상수 인터페이스를 Implement 한 클래스에서는 상수를 사용할 때 네임스페이스를 사용하지 않으므로, 해당 상수의 출처를 쉽게 알 수 없다. 또한 상수 인터페이스를 구현한 클래스의 하위 클래스들의 네임스페이스도 인터페이스의 상수들로 오염된다.

 

5.  인터페이스를 구현해 클래스를 만든다는 것은, 해당 클래스의 객체로 어떤 일을 할 수 있는지 클라이언트에게 알리는 행위이다. 따라서 상수 인터페이스를 구현한다는 사실은 클라이언트에게는 중요한 정보가 아니다. 다만, 클라이언트들을 혼동시킬 뿐이다.

 

6. 상수 인터페이스를 Implement 한 클래스에 같은 상수를 가질 경우, 클래스에 정의한 상수가 사용되므로 사용자가 의도한 흐름으로 프로그램이 돌아가지 않을 수 있다. 아래는 간단한 예제이다.

public interface Constants {
 public static final int CONSTANT = 1;
}

public class Class1 implements Constants {

 public static final int CONSTANT = 2; // *

 public static void main(String args[]) throws Exception {
  System.out.println(CONSTANT);
 }
}

 

Constant Interface 대안

자바문서에서 Constant Interface를 Anti 패턴으로 명시하였고 이 방안으로 ​import static 구문​ 사용을 권장한다.​ Constant Interface와 동일한 기능과 편리성을 제공한다. 아래는 간단한 예제이다.

public final class Constants {
 private Constants() {
  // restrict instantiation
 }

 public static final double PI = 3.14159;
 public static final double PLANCK_CONSTANT = 6.62606896e-34;
}



import static Constants.PLANCK_CONSTANT;
import static Constants.PI;

public class Calculations {

 public double getReducedPlanckConstant() {
  return PLANCK_CONSTANT / (2 * PI);
 }
}

 

반응형

+ Recent posts