이펙티브 자바 #item15 클래스와 멤버의 접근 권한을 최소화해라

임현규·2023년 1월 17일
0

이펙티브 자바

목록 보기
15/47
post-thumbnail

캡슐화

객체 지향하면 떠오르는 3가지가 있다. 바로 다형성, 캡슐화, 상속 이다. 이 중 캡슐화는 잘 설계된 컴포넌트 설계에 필수적인 요소이다.

캡슐화란 정보은닉이라고도 하며 클래스의 내부 구현을 숨겨 구현과 API를 깔끔하게 분리하는 과정이다.

오직 API를 통해서만 서로 다른 컴포넌트와 소통하며 내부 동작에 대해서는 전혀 모른다.

이러한 캡슐화의 장점은 다음과 같다.

캡슐화의 장점

  • 시스템 개발 속도를 높인다.
    • 여러 컴포넌트를 병렬로 개발 가능하기 때문
  • 시스템 관리 비용을 낮춘다.
    • 각 컴포넌트를 빠르게 파악하여 디버깅할 수 있고, 다른 컴포넌트로 교체하는 부담이 적어짐
  • 캡슐화 자체가 성능을 최적화하지는 않지만 최적화 타겟팅에 큰 도움을 준다.
  • 소프트웨어의 재사용성을 높인다.
    • 외부에 거의 의존하지 않는 컴포넌트라면 그 컴포넌트와 함께 개발되지 낯선 환경에서도 유용하게 쓸 수 있기 때문이다.
  • 큰 시스템을 설계하는 난이도를 낮춘다.

모든 클래스와 멤버의 접근 가능성을 최대한 좁혀라

소프트웨어 객체가 올바르게 정의되려면 항상 최대한 낮은 수준의 접근 권한을 가지도록 해야한다. 톱 레벨 클래스나 인터페이스에 부여할 수 있는 접근 수준은 package-private와 public 두 가지이다. 톱 레벨 클래스나 인터페이스를 public으로 선언하면 공개 API가 되며, package-private으로 설정하면 해당 패키지에서만 이용할 수 있다.

공개 API가 아닌 경우는 노출되지 않는 내부 구현이므로 언제든지 수정할 수 있다. 그러나 public으로 선언한다면 API가 되기 때문에 하위 호환을 위해 영원히 관리해주어야 한다.

protected는 신중하게 사용해라

클래스 멤버의 접근 수준을 private, package-private에서 protected로 변경하면 protected는 외부에 멤버가 노출된다. 정확히는 상속하는 클래스에 한해서긴 하지만 이 경우도 멤버가 그대로 노출되기 때문에 해당 멤버에 필요한 문서를 작성해야 한다.

테스트하는 목적으로 접근 범위를 높이는 작업은 신중히 해라

단지 테스트를 목적으로 클래스, 인터페이스, 멤버의 접근 범위를 높이려 할 때가 있다. private -> package-private 까지는 괜찮지만, 그 이상은 안된다. 테스트만을 위한 공개 API를 만들어서도 안된다. 이런 문제가 발생한다면, 객체를 분리하는 것이 차라리 낫다.

클래스의 인스턴스 필드는 되도록 public이면 안된다.

public 가변 필드를 가지는 것은 일반적으로 스레드에 안전하지 않다. final를 붙여도 문제가 생긴다. 내부 구현을 바꾸고 싶어도 public 필드를 없애는 방식으로는 리펙토링이 불가능하기 때문이다.

static final을 이용해 공개 상수를 적용하는 경우 public을 사용하기도 한다. 그러나 이 경우 enum이 조금 더 효과적이다.

기본적인 방법은 private으로 필드를 두고 접근자를 활용해 필요에 따라 방어적 복사를 하는 방법이 있다.

// 외부에서 VALUES를 수정할 수 있음..
public static final Thing[] VALUES = {}

이를 해결하는 방법은 두 가지 방법이 있다.

private static final Thing[] PRIVATE_VALUES = {}

// 불변 리스트를 추가하는 방법
public static final List<Thing> VALUES = 
	Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES);
    
public static final Thing[] values() {
	return PRIVATE_VALUES.clone();
}
profile
엘 프사이 콩그루

0개의 댓글