Algorithm Study

아이템15. 클래스와 멤버의 접근 권한을 최소화하라

hyun-1200 2022. 6. 24. 14:56

아이템15. 클래스와 멤버의 접근 권한을 최소화하라

잘 설계된 컴포넌트의 가장 큰 핵심은 클래스 내부 데이터와 내부 구현정보를 외부 컴포넌트로부처 얼마나 잘 숨겼느냐 다. 모든 내부 구현을 완벽히 숨겨, 구현과 API를 분리하고 오직 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작에는 전혀 개의치 않는다. 정보은닉, 혹은 캡슐화라고 한다.

정보은닉 (= 캡슐화) 의 장점

  1. 시스템 개발 속도를 높인다.
  2. 시스템 관리 비용을 낮춘다.
  3. 정보 은닉 자체가 성능을 높여주진 않지만, 성능 최적화에 도움을 준다. 완성된 시스템을 프로파일링해 최적화할 컴포넌트를 정한 다음, 다른 컴포넌트에 영향을 주지 않고 해당 컴포넌트만 최저화할 수 있기 때문이다.
  4. 소프트웨어 재사용성을 높인다. 낯선환경에서도 유용하게 쓰일 가능성이 있기 때문이다.
  5. 큰 시스템을 제작하는 난이도를 낮춰준다.

정보은닉을 위한 장치 : 접근제한자 사용

모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다.

  • 소프트웨어가 올바로 동작하는 한 항상 가장 낮은 접근 수준을 부여해야 한다.

접근제한자 정리자료 참고

  • 해당 책에 표현되는 package-private는 default 이다.
  • (가장 바깥이라는 의미의) 톱레벨 클래스와 인터페이스에 부여할 수 있는 접근수준은 package-private와 public 두 가지다. 톱레벨 클래스나 인터페이스에 public으로 선언하면 공개 API가 되며, package-private으로 선언하면 해당 패키지 안에서만 이용할 수 없다. 패키지 외부에서 쓸 이유가 없다면 package-private으로 선언하자.
  • 클래스의 공개 API를 설계한 후, 그 외 모든 멤버는 private으로 만들자. 그런 다음 오직 같은 패키지의 다른 클래스가 접근해야 하는 멤버에 한하여 package-private으로 풀어주자. private과 package-private멤버는 모두 공개 API에 영향을 주지 않는다.
  • 멤버접근성을 방해하는 한가지 제약 : 상위클래스 메서드를 재정의하는 경우, 접근수준을 상위클래스보다 같거나 넓게 설정해야 한다.
  • public 클래스의 인스턴스 필드는 되도록 public이 아니어야 한다 (아이템 16). public 가변 필드를 갖는 클래스는 일반적으로 스레드 안전하지 않다.
    • 상수라면 public static final필드로 공개해도 좋지만, 배열필드를 두거나 이 필드를 반환하는 접근자 메서드는 제공하면 안된다.

자바9에서는 모듈 시스템이라는 개념이 도입되면서 두 가지 암묵적 접근 수준이 추가되었다.

모듈은 패키지들의 묶음이다.

  1. 모듈에 속하는 패키지 중 공개(export)할 것들을 선언한다. protected 혹은 public 멤버라도 해당 패키지를 공개하지 않았다면 모듈 외부에서는 접근할 수 없다. 모듈 안에서는 exports로 선언했는지 여부에 아무런 영향을 받지 않는다.
  2. 패키지 안에 있는 public 클래스의 public 혹은 protected멤버이다. 이 암묵적 접근 수준들은 각각 public수준과 protected 수준과 같으나, 그 효과가 모듈 내부로 한정되는 변종인 것이다. 이런 형태로 공유해야 하는 상황은 흔하지 않다. 그래야 하는 상황이 벌어지더라도 패키지들 사이에서 클래스들을 재배치하면 대부분 해결된다.
  • 모듈을 사용하기 위해서는 패키지들을 모듈 단위로 묶고, 모듈 선언에 패키지들의 모든 의존성을 명시한다. 그런 다음 소스 트리를 재배치하고, 모듈 안으로부터 일반 패키지로의 모든 접근에 특별한 조치를 취해야 한다.. 그러니 꼭 필요한 경우가 아니라면 당분간은 사용하지 않는게 좋다.

정리

프로그램 요소의 접근성은 가능한 한 최소한으로 하라. 꼭 필요한 것만 골라 최소한의 public API를 설계하자. 그 외에는 클래스, 인터페이스, 멤버가 의도치 않게 API로 공개되는 일이 없도록 해야한다. public클래스는 상수용 public static final 필드 외에는 어떠한 public 필드도 가져서는 안 된다. public static final 피드가 참조하는 객체가 불변인지 확인하라.