Home [Effective Java] Item15. 클래스와 멤버의 접근 권한을 최소화하라!
Post
Cancel

[Effective Java] Item15. 클래스와 멤버의 접근 권한을 최소화하라!

Item15. 클래스와 멤버의 접근 권한을 최소화하라!

  • 컴포넌트의 설계는 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼는지로 평가한다.
  • 잘 설계된 컴포넌트는 모든 내부 구현을 완벽히 숨겨, 구현과 API를 깔끔히 분리한다.
  • 정보 은닉, 캡슐화라고 하는 이 개념은 소프트웨어 설계의 근간이 되는 원리다.

정보 은닉의 장점

  • 시스템 개발 속도를 높인다.
    • 여러 컴포넌트를 병렬로 개발할 수 있기 때문
  • 시스템 관리 비용을 낮춘다.
    • 각 컴포넌트의 파악이 빨라져 디버깅 속도 증가하고, 다른 컴포넌트로 교체하는 비용도 작기 때문
  • 정보 은닉 자체가 성능 향상을 보이진 않지만, 성능 최적화에 도움을 준다.
    • 시스템 프로파일링 후 최적화 필요한 컴포넌트를 정해 다른 컴포넌트에는 영향을 주지 않고 해당 컴포넌트만 최적화할 수 있기 때문
  • 소프트웨어 재사용성을 높인다.
    • 외부에 거의 의존하지 않는 독자적 컴포넌트라면 낯선 환경에서도 유용하게 쓰일 수 있기 때문
  • 큰 시스템 제작의 난이도를 낮춰준다.
    • 시스템 전체가 완성되지 않았어도 개별 컴포넌트의 동작 확인이 가능하기 때문

접근 제어 메커니즘

  • 클래스, 인스턴스, 멤버의 접근성을 명시한다.
  • 각 요소의 접근성은 그 요소가 선언된 위치와 접근 제한자로 정해진다.

기본원칙

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

접근 수준

클래스,인터페이스

  • top-level 클래스와 인터페이스에 부여할 수 있는 접근 수준은 package-private, public 두 가지다.
    • public으로 선언 시, 공개 API가 된다.
    • package-private로 선언 시, 해당 패키지 안에서만 이용 가능하다.
    • 외부에서 사용할 일 없으면 package-private으로 선언해 내부 구현으로 사용한다. 그럼 언제든 수정, 교체, 제거가 가능하다.
  • 한 클래스에서만 사용하는 package-privatetop-level 클래스나 인터페이스는 클래스 안으로 이동시키고, private static으로 중첩시켜 사용하자.

멤버

 같은 클래스 접근같은 패키지 접근상속 클래스 접근외부에서 접근
publicYesYesYesYes
protectedYesYesYesNo
package-privateYesYesNoNo
privateYesNoNoNo

유의 사항

  • 클래스의 공개 API를 세심히 설계한 후, 그 외의 모든 멤버는 private으로 만들자.

    • 그 후 오직 다른 패키지의 다른 클래스가 접근해야 하는 멤버에 한해 package-private으로 변경한다.
    • private, package-private 멤머는 모두 해당 클래스의 구현에 해당해 공개 API에 영향을 주지 않는다.
  • public 클래스에서 멤버 수준을 package-private에서 protected로 바꾸는 순간 접근할 수 있는 대상이 확 늘어난다. 고려 필요하다.

  • 상위 클래스의 메서드 재정의 시, 상위 클래서 메서드보다 좁은 범위의 제한자 사용은 불가하다.(리스코프 치환 원칙) 이 경우는 멤버 접근성을 좁히지 못하는 특별한 예외이다.

  • 코드를 테스트하는 목적으로 클래스, 인터페이스, 멤버의 접근 범위를 넓히는 경우, 적당 수준까지는 괜찮다. 하지만 이를 공개 API로 만들어서는 안된다.

  • public 클래스의 인스턴스 필드는 되도록 public이 아니어야 한다.

    • 불변식을 보장할 수 없게 됨을 주의해야 한다.
    • public static final 필드의 상수라면 예외적으로 공개해도 좋다.
  • 길이가 0이 아닌 배열은 모두 변경이 가능하다. 따라서 클래스에 public static final 배열 필드를 두거나 이 필드를 반환하는 접근자 메서드 제공을 해서는 안된다.

    1
    2
    
    // 문제 있음. 불변 보장 안됨.
    public static final Thing[] VALUES = {...};
    
    • public 배열을 private로 만들고, public 불변 리스트를 추가해 해결한다.

      1
      2
      3
      
      private static final Thing[] PRIVATE_VALUES = {...};
      public static final List<Thing> VALUES = 
      		Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
      
    • 배열을 private로 만들고, 그 복사본을 public 메서드로 반환해 해결한다.

      1
      2
      3
      4
      
      private static final Thing[] PRIVATE_VALUES = {...};
      public static final Thing[] values() { 
      		return PRIVATE_VALUES.clone();
      }
      

핵심 정리

  • 프로그램 요소의 접근성은 가능한 한 최소한으로 하자.
  • 꼭 필요한 것만 최소한의 public API로 설계하자.
  • 클래스, 인터페이스, 멤버가 의도치 않게 API로 공개되는 일은 없어야 한다.
  • public 클래서는 public static final 상수 필드 외에는 어떠한 public 필드도 허용해서는 안된다.
    • public static final 필드가 불변인지 확인하자.
This post is licensed under younghwani by the author.

[Effective Java] Item14. Comparable을 구현할지 고려하라!

[Effective Java] Item16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라!

Comments powered by Disqus.