Item 15. 클래스와 맴버의 접근 권한을 최소화하라

심규환·2022년 1월 23일
0

Effective Java

목록 보기
14/29
post-thumbnail

어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 클래스의 내부 데이터와 구현 정보를 얼마나 잘 숨겼는지이다. 잘 설계된 컴포넌트의 경우, 모든 내부 구현 정보를 완벽히 숨겨 구현과 API를 깔끔하게 분리한다.
오직 공개 API를 통해서만 소통하며 내부 동작 방식은 몰라도 되도록 만든다. 이를 정보 은닉 또는 캡슐화라고 한다.

정보 은닉의 장점을 아래와 같다.

  • 시스템 개발 속도 향상 : 여러 컴포넌트를 병렬적으로 개발 가능
  • 시스템 관리 비용을 낮춘다 : 각 컴포넌트를 더 빨리 파악해서 디버깅할 수 있다. 또 각각 관리되기 때문에 교체하는 부담이 적어진다.
  • 성능 최적화 : 다른 컴포넌트에 영향을 주지 않고 하나의 컴포넌트에 집중해서 최적화를 진행할 수 있다.
  • 재사용성 : 다른 컴포넌트와 분리되어 독자적으로 동작할 수 있는 컴포넌트라면 낯선 환경에서도 유용하게 사용 가능하다.
  • 큰 시스템을 제작하는 난이도를 낮춰준다 : 시스템이 아직 완성되지 않더라도 개별적으로 컴포넌트의 동작을 검증할 수 있다.

다음은 정보은닉을 하기 위한 접근 제한자들이다.

private : 맴버를 선언한 클래스에서만 사용 가능
pakage-private : 맴버가 속한 클래스의 패키지 안에서 사용 가능
protected : pakage-private를 포함하여 하위 클래스에서도 접근 가능하다.
public : 모든 곳에서 접근 가능

먼저 공개 API를 세심하게 설계한 후, 대부분의 맴버들을 private로 설정해주자. 그 다음 같은 패키지 안에서 다른 클래스에 사용할 맴버가 있다면 pakage-private로 변경하자.
하지만 pakage-private에서 protected로 변경하는 순간 공개 API가 되어 영원히 관리해야 하고 관리해야 할 범위가 증가하게 된다. 따라서 protected 맴버의 수는 적을수록 좋다.

한가지 주의해야 할 점은 맴버 접근성을 좁히지 못하는 제약이 있는데. 바로 상위 클래스 보다 좁아져서는 안된다. 이는 리스코프 치환 원칙에 위배되며 컴파일 시 에러가 난다.

public 클래스의 인스턴트 필드는 public이어서는 안된다. 필드가 가변 객체 필드를 참조하거나 final이 아닌 인스턴트 필드를 public으로 선언한다면 해당 필드를 제한할 수 있는 힘을 잃는다. 만약 수정중이라면 다른 작업이 불가능하다.
한 가지 예외는 클래스가 표현하는 추상 개념을 완성하는 데 꼭 필요한 구성요소로써의 상수라면 public static final 필드로 공개해도 좋다.
관례상 이런 상수의 이름은 대문자 알파벳으로 쓰며, 각 단어 사이에 밑줄(_)을 넣는다.
이런 필드는 반드시 기본 타입이거나 불변 객체를 참조해야 한다.

길이가 0이 아닌 배열은 모두 변경이 가능하니 주의하자.

public static final Thing[] VALUES = {.....};

final로 선언하더라도 보안상 허점이 있기 때문에 수정이 가능하다. 그러니 아래와 같이 사용하자.
첫 번째 방법은 배열을 private로 바꾸고 불변 리스트를 반환하는 것이다.

private static final Thing[] PRIVATE_VALUES = {...};
public static final List<Thing> VALUES = 
	Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

두 번째는 배열을 private로 만들고 그 복사본을 반환하는 public 메서드를 추가하는 방법이다.(방어적 복사)

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 필드가 참조하는 객체가 불변인지 확인하라

profile
장생농씬가?

0개의 댓글