상수를 정의하기위한 인터페이스를 갖는 것은 나쁜 습관입니까?


40

Java로 junit 테스트 클래스 세트를 작성 중입니다. 다른 테스트 클래스에 필요한 문자열과 같은 몇 가지 상수가 있습니다. 나는 그것들을 정의하는 인터페이스를 생각하고 있으며 모든 테스트 클래스가 그것을 구현할 것입니다.

내가 볼 수있는 이점은 다음과 같습니다.

  • 상수에 쉽게 액세스 : MY_CONSTANT대신ThatClass.MY_CONSTANT
  • 각 상수는 한 번만 정의 됨

이 접근법은 오히려 좋은 습관입니까? 나는 인터페이스의 개념을 조금 남용하는 느낌이 든다.

인터페이스 / 상수에 대해 일반적으로 대답 할 수 있지만, 특별한 것이 있다면 단위 테스트에 대해서도 대답 할 수 있습니다.


"메소드 서명"이 아닌 X 인 "X를 정의하는 인터페이스를 갖는 것은 나쁜 습관입니다"라는 대답은 거의 항상 "예"입니다.
T. Sar-복직 모니카

답변:


79

Joshua Bloch는 그의 책 Effective Java 에서 이것에 대해 조언합니다 .

클래스가 내부적으로 일부 상수를 사용한다는 것은 구현 세부 사항입니다. 상수 인터페이스를 구현하면이 구현 세부 사항이 내 보낸 API로 누출됩니다. 클래스가 상수 인터페이스를 구현하는 것은 클래스 사용자에게는 아무런 영향을 미치지 않습니다. 실제로, 그것들은 혼란 스러울 수도 있습니다. 더 나쁜 것은, 그것은 약속을 나타냅니다. 차후 릴리스에서 클래스가 더 이상 상수를 사용할 필요가 없도록 수정되면 여전히 바이너리 호환성을 보장하기 위해 인터페이스를 구현해야합니다.

상수를 정의하는 일반 클래스와 동일한 효과를 얻은 다음 import static com.example.Constants.*;


13

상수 값이 서비스 구현이 제공해야하는 최종 상태에 대한 계약을 나타 내기 때문에이 작업을 수행합니다. 이러한 상수를 인터페이스에 넣으면 계약의 일부로 종료 상태가 지정되며 인터페이스의 구현에서이를 사용하지 않으면 해당 작업이 수행되지 않습니다.

SOMETIMES 상수는 구현 세부 사항입니다. 때때로 그들은 그렇지 않습니다. 평소와 같이 엔지니어는 자신의 두뇌를 사용하여 무엇을해야할지 결정해야하며, 패턴이나 연습에 의존하지 않아야합니다.


7

상수에 대해서만 인터페이스를 갖는 것이 좋지 않다고 생각합니다 .

그러나 동작을 정의하는 인터페이스 (클래스를 구현하는 메소드가 구현해야 함)에 상수가 있으면 괜찮습니다. 그것이 "일부 구현 자의 세부 사항을 API에 유출" 한다면 , 그것이 있어야하는 방식이기 때문입니다. 그들은 또한 구현자가 foo 및 bar 메소드를 구현한다는 사실을 누설하고 있습니다.

java.awt.Transparency 인터페이스를 예로 들어 보겠습니다. OPAQUE, BITMASK 및 TRANSLUCENT 상수가 있지만 getTransparency () 메소드도 있습니다.

디자이너가 이러한 상수를 설정하면 getTransparency ()와 같이 인터페이스의 일부가 될만큼 안정적이라고 생각했기 때문입니다.


2

계약에 의한 디자인이 우세한 장소에서 가장 인기있는 관점이라고 생각하십시오.
인터페이스는 계약입니다. 인터페이스에 상수를 배치한다는 것은 계약을 준수하는 모든 클래스가 상수로 식별 된 값 / 개념에 동의한다는 것을 의미합니다.


1
인터페이스는 공공 계약입니다. 상수 값은 개인의 관심사이므로 공개 인터페이스는 최대 이름을 공개해야합니다. 그것은 추상 수업에 가장 좋습니다.
jwenting

사례 : javax.naming.Context, javax.ims.Session 및 수백 가지 인터페이스 ...
CMR

2
@jwenting 또한 "at most expose their names"값을 노출시키지 않고 공용 인터페이스를 사용할 수 있습니까?
CMR

그것은 내가 생각하는 프로그래밍 언어에 달려 있습니다. Java의 경우 아니요.
jwenting

2

내가 일한 회사는 인터페이스에서 가져온 상수 1 개를 많이 사용했습니다 . 나는 어떤 피해도 느끼지 않았다.

당신이 스스로 물어봐야 할 질문은, 당신에게 네임 스페이스가 얼마나 중요한가? 상수의 경우 실제로 모든 클래스가 작동합니다. 상수가 수천 개인 경우 해당 상수를 모두 사용할 수있는 것은 아닙니다.

인터페이스의 멋진 점은 필요한 모든 네임 스페이스를 가져 오거나없는 네임 스페이스를 가져 와서 명시 적으로 액세스하여 작업 할 수 있다는 것 MyInterface.CONSTANT입니다. 와 거의 동일 import static MyInterface.*하지만 조금 더 분명합니다.


1 : Java에 익숙하지 않다면 import키워드를 의미하는 것이 아니라implements MyConstantsInterface


1

나는 주로 'Ada Way'와 '.Net Way'에 주로 영향을받는 배경에서 왔습니다. 인터페이스 내에서 상수를 선언하는 것이 가장 좋지 않을 수도 있습니다. C #에서는 기술적으로 허용되지 않습니다.

내가 거절하는 이유는 인터페이스가 상태 나 구조가 아니라 행동을 정의하는 계약 형태이기 때문입니다. 상수는 어떤 종류의 상태 (기본) 또는 상태의 측면 (복합 또는 집계)을 의미합니다.

인터페이스를 구현하는 모든 사람이 기본값과 사전 정의 된 값을 사용할 수있게하려는 충동에 감사 할 수 있지만, 기본 상태는 최소한 최소한의 컨텍스트를 갖는 추상 또는 값 객체 또는 템플릿에서 더 잘 설명 될 수 있습니다.

자세한 기술 안내서 : download.oracle.com/javase/1.5.0/docs/guide/language/static-import.html


정적 가져 오기를 참조 더 많은 링크를 추가 (1.5) : 1. 위키 백과 2. 오라클 문서 @Justinc를 참조
Abhijeet

1
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Oracle Docs의
Abhijeet

1

아니, 그것은 일반적인 나쁜 연습이 아닙니다.

요점은 최소한의 가시성과 적절한 추상화 수준의 규칙에 따라 다른 인공물과 같은 상수를 도입해야한다는 것입니다.

실제 문제 일 수 있으므로 구문 만 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.