아이템 22 인터페이스는 타입을 정의하는 용도로만 사용하라
메서드 없이 상수 필드만 가득한 상수 인터페이스를 만들지마라. 안티 패턴이다.
상수 인터페이스의 구현은 외부 인터페이스가 아닌 내부 구현에 해당한다. 즉, 내부 구현을 외부로 노출하는 꼴이다.
이는 사용자에게 혼란을 주며 클라이언트 코드가 내부구현에 해당하는 상수에 종속적이게 될 수 있다.
상수를 공개하고 싶다면 상수전용 인터페이스를 구현하지 말고 그와 연관된 클래스나 인터페이스에서 공개하도록 하자.
아니면 인스턴스화를 막은 클래스에 담아서 공개하자.
public final class StringConstants{
public static final String BLANK = "";
private StringConstants(){}
}
아이템 23 태그 달린 클래스보다는 클래스 계층구조를 활용하라
여기서 의미하는 태그란 해당 클래스가 어떠한 타입인지에 대한 정보를 담고있는 필드(멤버 변수)를 의미한다.
이러한 태그를 가지고 있으면 여러가지 단점이 존재하게 된다.
- 태그에 대한 선언이 필요하다.
- 그로 인해 태그 필드를 가지고 있어야한다.
- 태그에 따른 메서드의 행동이 달라져야 하기 때문에
switch
문이 많아진다.- 그로 인해 코드를 읽기 힘들어 진다.
- 만약 필드를 final로 선언한다면 해당 태그에서 사용되지 않는 필드들을 위해 불필요한 초기화가 필요하다.
- 이러한 부분에서 컴파일러가 도와줄 수 있는 부분이 별로 없다.
결국 태그 달린 클래스는 읽기 어렵기만 하고 오류는 발생하기 쉬우며 비효율적이다.
이러한 태그 달린 클래스의 구현은 클래스의 계층구조를 어설프게 흉내 낸 아류이다.
이를 개선하기 위해 다음과 같은 순서를 밟도록 하자.
- root가 될 추상 클래스를 정의하자.
- 태그에 따라 행동이 달라지던 메서드는 추상 메서드로 구현하자.
- 그렇지 않다면 일반 메서드로 구현하자.
- 공통된 필드는 모두 root 클래스로 올리자.
- root 클래스를 확장한 구체 클래스를 의미별로 정의하자.
- 각 의미에 해당하는 데이터 필드를 구체 클래스에 정의하자.
- 구체 클래스에서 추상 메서드를 의미에 맞게 구현하자.
이렇게 함으로써 컴파일러가 override 메서드를 모두 구현했는지에 대한 도움을 받을수 있고, 각 구체 클래스의 멤버변수 또한 final로 선언 할 수 있다.
'Reading Record > 이펙티브자바' 카테고리의 다른 글
[아이템 34] int 상수 대신 열거 타입을 사용하라 (0) | 2020.04.17 |
---|---|
[아이템 24] 멤버 클래스는 되도록 static으로 만들라 (0) | 2020.04.14 |
[아이템 21] 인터페이스는 구현하는 쪽을 생각해 설계하라 (0) | 2020.04.14 |
이펙트브자바 제네릭 (item 26,27,28) (0) | 2020.04.07 |
[아이템 31] 한정적 와일드카드를 사용해 API 유연성을 높여라 (0) | 2020.03.29 |