잘 설계된 소프트웨어는 캡슐화가 잘 되어있어 개발, 테스트, 최적화 등의 과정을 개별적으로 할 수 있게 해준다.

정보 은닉의 장점

  • 여러 컴포넌트를 병렬로 개발할 수 있어, 시스템 개발 속도를 높인다.
  • 컴포넌트별로 기능 파악이 가능해, 디버깅이나 교체가 부담스럽지 않다.
  • 완성된 시스템을 컴포넌트별로 프로파일링할 수 있어 시스템 관리 비용을 낮춘다.
  • 외부에 의존하지 않도록 설계된 컴포넌트는 다른 프로그램에서도 재사용될 수 있다.
  • 개별 컴포넌트 동작을 검증할 수 있어 대규모 시스템 제작 난이도를 낮춘다.

접근 제어

자바는 정보 은닉을 위한 다양한 장치를 제공한다. 특히 접근 제어 메커니즘은 클래스, 인터페이스, 멤버의 접근 허용 범위를 명시한다.

  • private: 멤버를 선언한 톱레벨 클래스에서만 접근
  • package-private: 멤버가 소속된 패키지 안의 모든 클래스에서 접근
  • protected: package-private의 접근 범위를 포함하며, 이 멤버를 선언한 클래스의 하위 클래스에서도 접근할 수 있다.
  • public: 모든 곳에서 접근할 수 있다.

접근제한자 관리

최소한으로 좁혀라

가장 중요한 원칙은 모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다는 것이다. 공개 API를 만들 것이 아니라면, 톱레벨 클래스와 인터페이스를 package-private로 선언해야 한다. 이렇게 하면 API가 아닌 내부 구현이라 클라이언트에 아무 피해를 주지 않고 언제든 수정할 수 있다.

  1. 클래스에서 공개 API로 만들 부분을 설계한다.
  2. 나머지 모든 부분을 private로 만든다.
  3. 오직 같은 패키지의 다른 클래스가 접근해야 하는 상황에만 package-private으로 푼다.
만약 3번 상황이 너무 자주 발생하면 컴포넌트를 더 분리해야 하는 것이 아닌지 고려해야 한다.

또한 한 클래스에서만 사용하는 package-private 톱레벨 클래스나 인터페이스는 이를 사용하는 클래스 안에 private static으로 중접시킬 수 있다. 이렇게 하면 꼭 필요한 클래스에서만 접근할 수 있도록 함으로써 클래스 간 긴밀한 관계를 가질 수 있다.

 

주의할 사항

  • public 클래스 멤버를 가능한 protected로 두지 마라.
    • protected 멤버는 공개 API이므로 영원히 지원되어야 한다.
  • 리스코프 치환 원칙에 주의하라.
    • 상위 클래스 메서드를 재정의할 때는 그 접근 수준을 더 좁게 설정할 수 없다. 리스코프 치환 원칙을 지키기 위해 접근성을 좁히지 못할 수 있다.
  • 테스트 목적으로 접근제한자를 풀지 마라.
    • 테스트 코드를 테스트 대상과 같은 패키지에 둔다면 package-private 멤버에 접근할 수 있다.
  • public 메서드의 필드는 되도록 public이 아니어야 한다.
    • 해당 필드에 담긴 값은 모두 불변식을 보장할 수 없고 스레드 안전하지 않다.
    • 정적 필드에서는 추상 개념을 완성하기 위해 꼭 필요하다면 사용할 수 있다. 그러나 반드시 기본 타입 값이나 불변 객체를 참조해야 한다.
  • 길이가 0이 아닌 배열은 모두 변경 가능하다.
    • 따라서 public static final 배열 필드를 두거나 접근자를 두면 보안 허점이 생길 수 있다.
    • public 불변 리스트를 추가하거나 복사본을 반환하도록 변경할 수 있다.
  • 자바9에서의 모듈 개념이 생김에 따라, public/protected이지만 공개되지 않는 멤버/클래스가 생길 수 있다.

 

 

+ Recent posts