IT/Programming / / 2023. 4. 27. 09:47

<Effective Java> RULE 13 클래스와 멤버의 접근 권한은 최소화 하라

반응형

 

잘 설계된 모듈과 그렇지 못한 모듈을 구별 짓는 가장 중요한 속성 하나는 모듈 내부의 데이터를 비롯한 구현 세부사항을 다른 모듈에 잘 감추느냐의 여부이다.
잘 설계된 모듈은 구현 세부사항을 전부 API 뒤쪽으로 감춘다.

 

정보은닉

 의존성을 낮춰서 각자 개별적으로 개발하고 시험, 최적화할 수 있도록 하는데 기초한다.

 시스템 개발 속도를 높이고 각각 모듈을 병렬적으로 개발할 수 있다.

 유지보수의 부담을 낮추고 모듈을 각각 좀더 빨리 이해할 수 있을 뿐만 아니라 다른 모듈에 영향없이 디버깅을 할 수 있다.

 어떤 모듈이 성능에 문제를 일으키는지 프로파일링 하기 용이하다.

 소프트웨어의 재사용 가능성을 높인다.

 대규모 시스템 개발 과정의 위험성도 낮춘다.

 

자바는 정보은닉을 실현할 수 있도록 다양한 도구를 제공한다.

 접근제어 메커니즘 : 클래스와 인터페이스, 멤버들의 접근 권한을 규정한다.

 어떤 개체의 접근 권한은 해당 개체가 선언된 위치와 권한 수정자에 의해 결정된다.(public, protected,public등)

 

각 클래스와 멤버는 가능한 한 접근 불가능하도록 만들어야한다.

 소프트웨어가 동작을 보증하는 한 가장 낮은 접근권한으로 설정한다.

 최상위 레벨 클래스나 인터페이스는 가능한 package-private으로 선언해야 한다.

 

접근권한

 private : 최상위 레벨 클래스 내부에서만 접근 가능하다.

 package-private : 같은 패키지 내의 아무 클래스나 사용할 수 있다. 기본 접근 권한

 protected : 선언된 클래스 및 그 하위 클래스에서만 사용할 수 있다.

 public : 어디서도 사용이 가능하다.

 

private와 package-private 멤버들은 클래스의 구현 세부사항이며 공개 API의 일부가 아니지만 ,

Serializable을 구현하는 멤버라면 공개 API속으로 새어나갈(leak) 수 있다.

 

상위 클래스 객체를 사용할 수 있는 곳에는 하위 클래스 객체도 사용할 수 있어야 하기 때문에

상위 클래스 메서드를 재정의 할 때에는 원래 메서드의 접근 권한보다 낮은 권한을 설정할 수 없다.

 

따라서 특정한 인터페이스를 구현하는 클래스를 만들 때는

인터페이스에 속한 모든 메서드를 해당 클래스의 public메서드로 선언해야 한다. 인터페이스의 모든 멤버는 원래 public이기 때문이다.

 

객체 필드는 절대로 public으로 선언하면 안된다.

비-final 필드나 변경 가능한 객체에 대한 final 참조 필드를 public으로 선언하면 필드에 저장될 값을 제한 할 수 없되되기 때문에 그 필드에 관계된 불변식을 강제할 수 없다.

필드가 변경될 때 특정한 동작이 실행이 되도록 할 수 없으므로 다중 스레드에도 안전하지 않다.

 

public static final 배열 필드를 두거나 배열 필드를 반환하는 접근자를 정의하면 안된다.

길이가 0이 아닌 배열은 언제나 변경 가능가능하며

클라이언트가 배열내용을 변경할 수 있으므로 보안에 취약해 진다.

public static final Things[] VALUES = { ... }; //보안 취약성 코드

/*
1. public으로 선언된 배열을 private로 바꾸고 변경 불가능한 public 리스트를 하나 생성
*/
private static final Thing[] PRIVATE_VALUES = {...}

public static final List<Thigs> VALUES =
  Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
  
/*
2. 배열을 Private로 선언하고 해당 배열을 복사해서 반환하는 public메서드 추가 
*/
private static final Thing[] PRIVATE_VALUES = {...}
public static final Thing[] PRIVATE_CLONE_VALUES = {
   return PRIVATE_VALUES.clone();
}
 

 

결론

 접근 권한은 가능한 낮추어라.

 최소한의 public API를 설계한 다음 모든 클래스 인터페이스 멤버는 API에서 제외하라.

 public static final필드를 제외한 어떤 필드도 public 필드로 선언하지 마라.

 public static final 필드가 참조하는 객체는 변경 불가능 객체로 만들라.

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유