[아이템 15] 클래스와 멤버의 접근 권한을 최소화하라
잘 설계된 컴퓨넌트는 내부 구현 정보를 캡슐화하여 숨기고 외부 컴포넌트는 API를 통해 외부와 정보를 주고 받을 수 있도록 분리되어 설계된다. 정보 은닉이 잘된 시스템은 아래와 같은 장점이 있다.
- 컴포넌트별 캡슐화가 잘 되어 있어 병렬 개발할 수 있으며 이는 시스템 개발 속도를 높인다.
- 시스템 관리 비용을 낮춘다. 캡슐화로 인해 오류 발생 시 컴포넌트별로 빠르게 파악할 수 있고 디버깅 시 연관도가 낮아 수정 개발이 편리하다.
- 성능 최적화를 할 수 있다. 완성된 시스템을 프로파일링해 최적화할 컴포넌트를 정해 해당 컴포넌트만 수정 & 변경을 통해 최적화할 수 있다.
- 소프트웨어 재사용성을 높일 수 있다.
- 큰 시스템을 제작하는 난이도를 낮춰준다.
접근 제한자(private, protected, public)와 선언된 위치로 접근성이 제한된다. 접근 제한자를 활용하여 정보 은닉의 이점을 누릴 수 있다. 모든 클래스와 멤버의 접근성을 좁히면 된다.
클래스, 인터페이스의 접근 제한자
package-private | public |
패키지 외부에서 쓸 이유가 없다 | 공개 API가 되어 서비스를 종료할 때까지 계속 버전 관리 필요 |
다음 릴리즈에서 수정, 교체, 제거 가능 |
* 외부 공개 API를 제공하는 목적이 아니면 public으로 선언하는 것은 고려해야한다.
접근 제어자(Access Modifier)
- private : 멤버를 선언한 클래스에서만 접근할 수 있다.
- package-private(default) : 멤버가 소속된 패키지 안의 모든 클래스에서 접근할 수 있다.
- protected: package-private의 접근 범위를 포함하고 해당 멤버를 상속한 하위 클래스에서도 접근할 수 있다.
- public : 모든 곳에서 접근할 수 있어 공개 API이다.
해당 클래스, 클래스가 속한 패키지내의 구현 범위에 해당하는 private과 package-private는 공개 API에 영향을 주지 않는다. * Serializable을 구현한 클래스에서는 의도와 달리 공개 API가 될 여지가 있다.
테스트를 위해서 멤버 접근 범위를 넓히려 하는데 private -> package-private까지는 괜찮지만 그 이상은 적용하지 않는게 좋다. 테스트를 위함이라면 테스트 코드를 같은 패키지에 두면 package-private 요소에 접근할 수 있기에 package-private은 가능하다.
public 클래스의 인스턴스 필드는 public을 지양하는 게 좋다.
- 가변 객체를 참조하거나 final이 아닌 경우 필드의 값을 제한할 수 없다.
- 따로 스레드 처리를 하지 않을 경우 public 인스턴스 필드는 락 획득을 할 수 없어 어느 곳에서나 접근하여 값을 변경할 수 있는 thread safe하지 않다.
예외도 존재하는데 클래스의 추상 개념을 표현하는데 꼭 필요한 구성요소로의 상수라면 public static final필드로 공개해도 좋다. * public static final String DATE_FORMAT 대문자 알파벳으로 작성하며 단어 사이에 밑줄(_)을 작성한다. 이런 타입은 불변 객체나 기본 타입 값을 참조해야한다.
- 가변 객체를 참조할 경우 setter를 통해 final이 아닌 필드의 값은 변경될 수 있다. 이럴 경우 의도하지 않게 값을 변경할 수 있는 가능성을 열어두게 된다. *final로 인스턴스를 생성했을 때의 동작방식에 대해 살펴보면 알 수 있다.
클래스에서 public static final 배열 필드를 두거나 이 필드를 반환하는 접근자 메서드를 제공해서는 안 된다. * 길이가 0이 아닌 배열은 모두 변경 가능하기 때문이다.
- 배열을 private으로 만들고 clone()으로 복사본을 반환하는 public static final 메서드를 제공하는 방법
- 동일하게 배열을 private으로 만들고 public 불변 리스트를 추가
자바 버전 9부터는 모듈 시스템(패키지들의 묶음이며 같은 모듈 안에 패키지들은 자유롭게 공유할 수 있다.)이라는 개념이 도입되면서 public 클래스의 public, protected 멤버에 한하여 같은 모듈 내부에서만 접근 가능하도록 한정했다. 이 같은 개념을 가장 잘 활용하는 사례가 JDK인데 자바라이브러리에서 공개하지 않는 패키지들은 해당 모듈 밖에서는 절대로 접근할 수 없다.
뒷 장에서 확인해야할 내용
한 클래스에서만 사용하는 package-private 톱레벨 클래스나 인터페이스는 이를 사용하는 클래스 안에 private static으로 중첩시켜보자
단 Serializable을 구현한 클래스에서는 그 필드들도 의도치 않게 공개 API가 될 수 있다.(아이템 86,87)
'IT 개발 > 개념 정리' 카테고리의 다른 글
[아이템 17] 변경 가능성을 최소화하라 (0) | 2022.05.14 |
---|---|
[아이템 16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) | 2022.05.14 |
[이펙티브 자바 3장] 모든 객체의 공통 메서드 (0) | 2022.05.02 |
[ssh known_hosts] (0) | 2022.03.16 |
[네트워크] telnet, netstat -tnlp 명령어 (0) | 2022.03.04 |