Item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라
1. 들어가기
인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 합니다.
그렇기 때문에 어떤 인터페이스를 구현한다는 것은
자신의 인스턴스로 무엇을 할 수 있는지 클라이언트에게 말해주는 것입니다.
이 지침에 맞지 않는 예로 제가 사용을 고민해봤던 상수 인터페이스가 있습니다.
SNS 로그인을 연동해 보았을 때, 저는 상수를 많이 사용하게 되었습니다.
그 때 했던 고민 중 하나로 상수 인터페이스를 만들어서 설계하면 어떨까? 라는 고민을 했던 적이 있습니다.
예를 들면 다음과 같습니다.
public interface Kakao {
// 카카오 로그인에 필요한 RESTAPI KEY
static final String REST_API_KEY = "...";
// 카카오 로그인 인증 URL
static final String AUTH_URL = "...";
// 카카오 로그인 request parameter key
static final String CLIENT_ID = "client_id";
}
public class KakaoLogin implements Kakao {
public String getKakaoAuthUrl() {
return new URIBuilder(AUTH_URL, StandardCharsets.UTF_8)
.setPath("/oauth/authorize")
.addParameter(CLIENT_ID, REST_API_KEY)
.build().toString();
}
}
하지만 이는 인터페이스의 안티 패턴입니다.
클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라 내부 구현에 해당되기 때문입니다.
따라서 상수 인터페이스를 구현하는 것은 내부 구현을 클래스의 API로 노출하는 행위로
사용자에게 혼란을 줄 가능성이 있고, 더 심하게는 클라이언트 코드가 이 상수들에 종속되게 합니다.
그럼 상수는 어떻게 구현할 수 있을까요?
2. 상수 구현 방법
-
특정 클래스나 인터페이스와 강하게 연관된 상수
이런 경우는 클래스나 인터페이스 자체에 상수를 추가합니다.
대표적인 예로 Integer와 Double에 선언된 MIN_VALUE, MAX_VALUE가 있습니다.
-
열거 타입으로 나타내기 적합한 상수
Enum을 사용해 상수를 추가합니다.
-
둘 다 아닌 경우
인스턴스화할 수 없는 유틸리티 클래스에 담아 상수를 추가합니다.
package example.sns; public class KakaoConstants { private KakaoConstants() {} // 인스턴스화 방지 static final String REST_API_KEY = "..."; static final String AUTH_URL = "..."; static final String CLIENT_ID = "client_id"; }
만약, 유틸리티 클래스의 상수를 빈번히 사용한다면 static import를 사용할 수 있습니다.
import static example.sns.KakaoConstants.*; public class KakaoLogin { public String getKakaoAuthUrl() { return new URIBuilder(AUTH_URL, StandardCharsets.UTF_8) .setPath("/oauth/authorize") .addParameter(CLIENT_ID, REST_API_KEY) .build().toString(); } }
3. 정리
이번 포스트는 인터페이스를 타입을 정의하는 용도로 사용하지 않은 안티패턴으로
상수 인터페이스에 대해 알아보았습니다.
인터페이스를 상수 공개용 수단으로 제공하게 된다면 사용자에게 혼란을 줄 가능성이 있고,
더 심하게는 클라이언트 코드가 이 상수들에 종속되게 합니다.
그렇기 때문에 인터페이스는 타입을 정의하는 용도로만 사용해야 하고
상수를 정의할 때는 다음의 3가지에 맞는 상수 구현 방법을 사용하도록 합시다.
-
특정 클래스나 인터페이스와 강하게 연관된 상수
🎯 클래스나 인터페이스 자체에 상수 추가
-
열거 타입으로 나타내기 적합한 상수
🎯 Enum
-
둘 다 아닌 경우
🎯 유틸리티 클래스
📕 개인 기록용 블로그입니다.
😊 오타나 잘못된 정보가 있을 경우 댓글이나 메일로 말씀해주시면 바로 수정하겠습니다! 😊
댓글남기기