규칙 13. 클래스와 멤버의 접근 권한은 최소화하라

정보은닉,캡슐화

잘 설계된 모듈과 그렇지 못한 모듈을 구분짓는 중요한 속성은 세부사항을 구현사항을 다른 모듈에 잘 감추느냐의 여부이다. 잘 설계된 모듈은 구현 세부사항을 전부 API 뒤쪽에 감춘다. 모듈들은 이를 API를 통해서만 서로 통신하며 각자 내부정으로 무슨짓을 하는지는 신경쓰지 않는다. 이를 바로 정보은닉 또는 캡슐화라고 알려져있다.. 이는 소프트웨어 설계의 기본적인 원칙 가운데 하나이다,.

정보은닉의 중요성

모듈사이의 의존성을 낮춰서(decouple), 각자 개별적으로 개발하고, 시험하고, 최적화하고, 이해하고, 변경할 수 있도록 한다는 사실에 기초한다. 이를통해 개발속도 향상, 병렬개발 가능, 유지보수 부담 저하, 모듈에 대한 쉬운이해가능, 다른 모듈에 영향없이 디버깅 진행가능이라는 장점이 있다. 또한 정보은닉 원칙이 좋은 성능을 자동적으로 보장하는 것은 안지만 효과적인 성능 튜닝을 가능하게 한다. 시스템이 완성된 다음에 어떤 모듈이 성능문제를 일으키는지 프로파일링 하기 용이하기 때문에,. 또한 이는 소프트웨어의 재사용 가능성을 높이고 대규모 시스템 과정의 위험성도 낮춘다(전체 시스템은 성공적이지 않더라도, 각각의 모듈은 성공적으로 구현 될수 있기 때문에)

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

개발중인 소프트웨어의 정상적인 동작을 보증하는 한도 내에서 가장 낮은 접근 권한을 설정할것.
최 상위 레벨 클래스와 인터페이스에 부여할 수 있는 접근 권한은 package-private(default)와 public 두 가지다.
최상위 레벨 클래스나 인터페이스에 public를 붙일 경우 해당 개체는 전역적 개체가 되고 public을 붙이지 않으면 해당패키지 안에서만 유효한 겍체가 된다. 최상위 레벨 클래스나 인터페잇는 가능한 package-private로 선언해야한다. 이를 통해 API 일부가 아니라 구현 세부사항에 속하게 되므로 다음번 릴리스에 클라이언트 코드를 깨뜨릴 걱정없이 자유로이 변경하거나 삭제하거나 대체할 수 있게된다. public으로 선언하게 되면 호환성을 보장하기 위해 해당객체를 계속 지원해야 한다.

package-private(default)로 선언된 최상위 레벨 클래스 혹은 인터페이스를 사용하는 클래스의 사용자 클래스가 하나라면 사용자 클래스의 private 중첩 클래스로 만들것을 고려해 보자. 이를 통해 하나의 클래스만이 해당 클래스의 접근 권한을 갖게된다.

protected는 자제하자

package-private에서 protected로 변경하면 멤버를 사용할수 있는 범위가 엄청 넓어진다. 이는 해당 protected멤버에 대해 해당클래스의 구현 세부사항에 대한 공개적 약속과도 같으며 공개 API로서 영원히 유지되어야 한다.

원래 메서드의 접근보다 낮은 권한을 설정할 수없다.

원래 안되는것이다. 넓힐순 있어도 좁힐 수는 없다. 이걸 어기면 컴파일 오류가 발생한다. 따라서 인터페이스를 구현하는 클래스를 만들 때는 인터페이스에 속한 모든 메서드를 해당 클래스의 public메서드로 선언해야 한다. 인터페이스의 모든 멤버는 원래 public이기 때문에

겍체 필드는 절대로 public으로 하지마라

public로 할 경우 메서드를 통해 값을 변경할 수 있게된다. 따라서 그 필드에 관계된 불변식을 강제할 수 없다. 또한 public 필드를 가진 필드는 다중 스레드에 안전하지도 않다.

static으로 선언된 필드

특정 상수들을 public static final 필드들로 선언하여 공개할 수 있다. 이런 필드들은 반드시 기본 자료형 값들을 갖거나, 변경 불가능한 객체를 참조해야 한다. 변경 불가능한 객체를 public static final 필드가 가르키게 되면 참조대상 객체가 변경될 경우 끔찍한 결과가 초래된다.

public static final 배열필드는 정의하지 마라.

길이가 0이 아닌 배열은 언제나 변경 가능하므로 public static final 배열 필드를 두거나, 이를 반환하는 접근자를 정의하면 안된다. 이를 통해 배열 내용을 변경할 수 있게되므로, 보안에 문재가 생긴다.
public static final Thing[] VALUES={ … }; //보안 문제를 초래할 수 있는 코드
정의 했을경우 해결법.
1.public으로 선언했던 배열은 private로 바꾸고 변경이 불가능한 public 리스트를 하나 만든다,

default
1
2
3
4
public static final Thing[] VALUES={ ... };
public static final Thing[] values( ){
Collection.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
}

2.어느 자료형으로 반환해야 클라이언트가 성능을 낼 수 있을까를 생각해보자.

요약

접근권한은 가능한 낮추고 최소한의 public API를 설계하고 다른 모든클래스, 인터페이스, 멤버는 API에서 제외하라. public static final 필드를 제외한 어느 필드도 public 필드로 선언하지 마라. 그리고 public static final 필드가 참조하는 객체는 변경 불가능 객체로 만들어라

Share