- 잘 설계된 컴포넌트는 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼는가로 정해진다
시스템 개발 속도 향상
- 여러 컴포넌트 병렬 개발
시스템 관리 비용 절약
- 컴포넌트 이해도가 높아져 디버깅이 쉽고 컴포넌트 교체 부담이 적다
성능 최적화 도움
- 최적화할 컴포넌트를 정해 다른 컴포넌트 영향을 주지않고 해당 컴포넌트만 수정 가능
소프트웨어 재사용성 높임
- 외부에 거의 의존하지 않고 독자적으로 동작해 다른 환경에서 유용하게 쓰임
큰 시스템을 제작하는 난이도 낮춤
- 시스템 전체가 개발되지 않아도 개별 컴포넌트의 동작을 검증할 수 있음
-
접근 제한자는 클래스, 인터페이스, 멤버의 접근성을 명시한다.
-
멤버에 부여할 수 있는 접근 제한자는 총 4가지 이를 제대로 활용하는 것이 정보 은닉의 핵심이다.
- private, package-private, proteced, public
-
모든 클래스와 멤버의 접근성을 가능한 좁혀야 한다.
private
- 멤버를 선언한 톱레벨 클래스에만 접근 가능
package-private
- 접근 제한자를 명시하지 않은 경우 적용 됨
- 단 인터페이스는 기본적으로 public
- 멤버가 소속된 패키지 안의 모든 클래스에서 접근 가능
proteced
- package-private의 접근 범위 포함
- 동일 패키지 및 상속받은 하위 클래스에서 접근 가능
public
- 모든 곳에서 접근 가능
- 클래스와 멤버의 접근 권한을 최소화하라
- 톱레벨 클래스와 인터페이스에 사용할 수 있는 접근 제한자는 public과 package-private 뿐이다
- 톱레벨 클래스란 가장 바깥 클래스를 의미한다.
public
- 공개 API가 된다
- 하위 호환을 위해 영원히 관리해야 한다
package-private
- 해당 패키지 안에서만 이용할 수 있다
- 패키지 외부에서 쓸 이유가 없다면 package-private으로 선언하라
- 공개 API가 아니기 때문에 언제든 수정 가능하다
- 클라이언트에 아무런 피해 없이 다음 릴리즈에서 수정, 교체 , 제거 할 수 있다
- 한 클래스에서만 사용하는 private-package 톱레벨 클래스나 인터페이스는 이를 사용하는 클래스 안에 private static으로 중첩하라
- 이렇게 하면 같은 패키지의 모든 클래스가 접근하는 것에서 바깥 클래스 하나만 접근하는 것으로 접근 범위가 줄어든다.
- public일 필요가 없는 클래스를 private-package 톱레벨 클래스로 좁히는 일이 중요하다
- public 클래스는 공개 API private-package 톱레벨 클래스는 내부 구현이기 때문
- 공개 API를 세심히 설계하고 그 외의 모든 멤버는 private으로 만든다
- 오직 같은 패키지의 다른 클래스가 접근해야하는 멤버에 대하여 package-private를 적용한다
- 위와 같은 일이 자주 발생하면 시스템에서 컴포넌트를 분리해야 되는지 고민해야한다
- public 클래스에서 멤버의 접근 제한자를 package-private에서 protected로 변경하면 그 멤버에 접근할 수 있는 대상이 넓어진다
- public 클래스의 protected 멤버는 공개 API라 영원히 관리되어야 하며 내부 동작 방식을 문서화해서 사용자에게 공개해야한다
- 따라서 protected 멤버는 적을 수록 좋다
- 상위 클래스의 메서드를 재정의 할 때 접근 수준을 더 좁게 설정할 수 없다
- 이 제약은 상위 클래스의 인스턴스는 하위 클래스의 인스턴스로 대체해 사용할 수 있어야한다는 규칙(리스코프 치환 원칙)을 지키기 위해 필요
- 테스트만을 위해 클래스, 인터페이스, 멤버를 공개 API로 만들면 안된다
- 테스트 목적으로 private 멤버를 package-private까지 풀어주는 것은 허용한다.
- package-private은 내부 구현이다.
- 내부 구현을 테스트 하는 것이 좋을까?
- 내부 구현을 테스트하게 되면 내부 구현을 변경할 때 테스트 또한 같이 깨진다.
- 이를 리팩터링 내성이 부족하다고 한다.
- 테스트를 위해 접근 범위를 늘리기보다 public api를 테스트하면서 간접적으로 private 멤버도 테스트할 수 있는 코드를 작성하는게 좋을 것
- public클래스의 인스턴스 필드는 상수가 아니라면 되도록 public이 아니여야 한다
- 필드가 가변 객체를 참조하거나 final이 아닌 인스턴스 필드를 public으로 선언하면 불변식을 보장할 수 없게 된다
- 해당 필드에 담을 수 있는 값을 제한하지 못하기 때문
- 필드가 수정될 때 다른 작업을 할 수 없으므로 public 가변 필드를 갖는 클래스는 Thread Safe하지 않다
- 클래스에 길이가 0이 아닌 public static final배열 필드를 두거나 이 필드를 반환하는 접근자 메서드를 제공하면 안된다
- 해당 클래스가 표현하는 추상 개념을 완성하는데 꼭 필요한 구성요소로써 상수라면 public static final 필드로 공개해도 좋다
- 관례상 이런 상수의 이름은 대문자 알파벳으로 쓰며 단어 사이
_를 넣는다 - 이런 필드는 반드시 기본 타입이나 불변객체를 참조해야한다
상수로 public static final 배열을 사용하면 안된다
- 길이가 0이 아닌 배열은 모두 변경 가능하니 주의하라
- public static final 배열을 두거나 이 필드를 반환하는 접근자 메서드를 제공하면 안된다
- 클라이언트가 배열의 내용을 수정할 수 있게 된다
참고