ITEM 15
클래스와 멤버의 접근 권한을 최소화하라.
서론
잘 설계된 컴포넌트와 어설프게 설계된 컴포넌트의 차이는 클래스의 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 은닉화을 했는가 이 부분에서 결정된다 (정보은닉 , 캡슐화)
정보 은닉의 장점.
- 시스템 개발속도를 높인다(여러 컴포넌트를 병렬로 개발할 수 있기 때문)
- 시스템 관리 비용을 낮춘다.(컴포넌트가 분리되어있기 때문에 디버깅과 교체가 쉬움)
- 정보은닉 자체가 성능을 높여주지는 않지만 성능 최적화에 도움을 준다.(아이템 67)
- 소프트웨어 재사용성을 높인다(컴포넌트 간 의존성이 낮아지기 때문에)
- 큰 시스템을 제작하는 난이도를 낮춰준다(개별 컴포넌트의 동작을 검증할 수 있기 때문 1번 장점이랑 비슷한 느낌? )
자바에서 정보은닉을 위한 기본 원칙과 방법
-
핵심
모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다.(가장 낮은 접근 수준을 부여)
-
톱 레벨 클래스와 인터페이스에 부여할 수 있는 접근 수준은(public, package-private) 이 두 가지다.
public -> 공개 API(하위 호완을 위해 영원히 관리해줘야 함)
package-private ->패키지 내에서만 사용 가능 (클라이언트에 피해 없이 다음 릴리즈에서 수정 교체 제거 가능)
이처럼 패키지를 외부에서 사용할 일이 없다면 package-private를 사용하자.
-
한 클래스에서만 사용하는 package-private 클래스 , 인터페이스는 이를 사용하는 클래스 안에 private static으로 중첩시키자
-
클래스의 공개 API를 설계 후 그 외의 모든 클래스의 멤버는 private으로 만들자
만약 같은 패키지의 다른 클래스가 접근해야 하는 멤버에 한하여 package-private으로 풀어주자
위와 같은 행동이 자주 있을 시 컴포넌트 분해 여부를 생각해보자
(주의: Serializabl을 구현한 클래스에서는 의도치 않게 (package-private, private 멤버가) 공개 API가 될 수 있다)
주의점
-
코드를 테스트하려는 목적으로 클래스 , 인터페이스 멤버를 공개 API로 만들어서는 안 된다.
private 멤버를 package-private 까지는 허용! 그 이상은 절대 안 됨
-
public 클래스의 인스턴스 필드는 되도록 public이 아니어야 한다.(아이템 16)
-
public 필드로 선언 시 필드와 관련된 모든 것은 불변식을 보장할 수 없게 됨
-
public 가변 필드를 갖는 클래스는 일반적으로 스레드 세이프하지 않다.
-
정적 필드도 똑같다.(단 예외가 있음)
-
-
정적 필드 예외 상황
- 클래스가 표현하는 추상 개념일 경우 상수 라면 public static final 필드로 공개해도 좋다.
- 단 이런 상수 일 경우 각 단어 사이에 밑줄( _ )을 넣어 관례를 지키자
- 만약 상수가 아닌 가변 객체를 참조한다면 클라이언트 측에서 배열의 내용을 수정할 수 있으니 기본 타입 값과 불변 객체만 참조하자
-
클래스에서 public static final 배열 필드를 두거나 이 필드를 반환하는 접근자 메서드를 제공해서는 안된다.
public class Foo { // 클라이언트가 얼마든지 배열의 요소 값을 변경 가능함 public static final String[] fooList = {"foo1","foo2","foo3"}; }
이러한 경우 두 가지 방법이 있다.
-
배열 public 접근 지정자를 private으로 변경 후 public 불변 리스트를 추가
public class Foo { private static final String[] fooList = {"foo1","foo2","foo3"}; public static List<String> immutableList = Collections.unmodifiableList(List.of(fooList)); //불변 리스트를 제공해주자 }
-
배열을 private으로 선언 후 그 복사본을 반환(방어적 복사)
public class Foo { private static final String[] fooList = {"foo1","foo2","foo3"}; // 방법 2) public static String[] copyList(){ return fooList.clone(); }
-
용어
-
톱 레벨 클래스
가장 바깥에 존재하는 클래스를 말한다.
//public,package-private 만 부여가능 public class TopLevelClass { static class SubClass{} static class SubClass2{} }
이해하지 못한 부분
- 자바 9 모듈 시스템 개념의 도입 구절 -> 아직 모듈이라는 개념이 부족한 거 같다.
'Book Review > effective-java' 카테고리의 다른 글
[ITEM17]변경 가능성을 최소화하라 (0) | 2021.02.14 |
---|---|
[ITEM16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) | 2021.02.12 |
[ITEM14] Comparable 을 구현할지 고려하라 (0) | 2021.02.09 |
[ITEM13] clone 재정의는 주의해서 진행하라 (0) | 2021.02.07 |
[ITEM12] toString을 항상 재정의 하라 (0) | 2021.02.05 |