Effective Java - item15
[effective java] 4장 클래스와 인터페이스
추상화의 기본 단위인 클래스와 인터페이스는 자바 언어의 심장이다.
item15. 클래스와 멤버의 접근 권한을 최소화하라.
클래스 내부 데이터와 내부 구현과 API를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐가 잘 설계된 컴포넌트의 핵심이다. 오직 API를 통해서만 다른 컴포넌트와 소통하고 서로의 내부 동작 방식에는 개의치 않아야 하는 것이다.
컴포넌트들을 서로 독립시켜 개발, 테스트, 최적화, 적용, 분석, 수정을 개별적으로 할 수 있게 해주는 것과 연관있다.
정보 은닉의 장점은 아래와 같다.
- 시스템 개발 속도 높이기
- 시스템 관리 비용 낮추기
- 성능 최적화에 도움을 준다. 최적화할 컴포넌트를 정하고 다른 컴포넌트에 영향을 주지 않고 그 컴포넌트만 최적화할 수 있기 때문
- 소프트웨어 재사용성 높이기
- 큰 시스템을 제작하는 난이도 낮추기
자바에서 제공하는 정보 은닉을 위한 장치로 제어 메커니즘이 있다. 클래스, 인터페이스, 멤버의 접근성을 접근 제한자(private, protected, public)로 명시한다.
모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다. 정상 동작하는 가장 낮은 수준으로 접근 제한자를 두어야 한다는 말이다.
가장 높은 제한자는 package-privater과 public이다. 해당 패키지 안에서만 사용하든지, 공개 API로 사용하든지 하는 것이다. 한 클래스에서만 사용하는 경우 그 클래스 안에 private static으로 중첩시켜보자. 그러면 바깥 클래스 하나에서만 접근할 수 있기 때문이다.
그 외에는 private(선언 된 클래스 내부에서만 사용), protected(package-private 포함 하위 클래스에서 사용)이 있다.
public을 세심히 설계하고 private, package-private으로 설계하도록 하자. 하지만 Serializable를 구현한 경우 공개가 될 수 있으니 주의하자. public 내에 있는 protected도 공개가 되기 때문에 줄이는 것이 좋다.
하지만 상위 클래스의 메서드 재정의 시 상위 클래스보다 좁게 할 수 없다는 제약이 하나 있다. 이는 리스코프 치환 원칙을 지키기 위해 필요하다. 이를 어기면 하위 클래스를 컴파일할 때 오류가 발생한다. 클래스가 인터페이스를 구현하는 건 특별한 예고 이때는 모든 메서드를 public으로 선언해야 한다.
테스트를 위해서는 package-private 정도까지만 풀어주도록 하자.
public 클래스의 인스턴스 필드는 되도록 public이 아니어야 한다. 불변값을 주어 스레드 안정성을 갖추도록 하자. 정적 필드에서도 마찬가지로 추상 개념을 완성하는데 꼭 필요한 상수일때만 공개로 하도록 하자. 이때는 대문자, 스네이크로 작성한다. 기본 타입이나 불변 객체로 참조해야 한다.
배열을 사용할 때는 private으로 배열을 선언하고 public 불변 리스트를 추가하거나, private으로 만들고 복사본을 반환하는 public 메서드를 추가하는 방법(방어적 복사)이 있다.
java9부터 생겨난 모듈 시스템에 따라 모듈은 패키지들의 묶음으로 자신에 속하는 패키지 중 공개할 것들을 관례상 module-info.java 파일에 선언한다. public 이더라도 해당 패키지를 공개하지 않았다면 외부에서 접근할 수 없다.
모듈을 사용할 때에 먼저 패키지들을 모듈 단위로 묶고 모듈 선언에 패키지들의 모든 의존성을 명시한다. 그러고 소스 트리를 재배치하고 모듈 안으로부터 일반 패키지로의 모든 접근에 특별한 조치를 취해햐 하는 작업을 해야 하니 주의하자.