Java ☕

[Effective Java] 아이템 15 클래스와 멤버의 접근 권한을 최소화하라

z.zzz 2024. 3. 3. 01:34

아이템 15 클래스와 멤버의 접근 권한을 최소화하라

프로그램 요소의 접근성은 가능한 한 최소한으로 하라. 꼭 필요한 것만 골라 최소한의 public API를 설계하자. 그 외에는 클래스, 인터페이스, 멤버가 의도치 않게 API로 공개되는 일이 없도록 해야 한다. public 클래스는 상수용 public static final 필드 외에는 어떠한 public 필드도 가져서는 안 된다. public static final 필드가 참조하는 객체가 불변인지 확인하라.

 

⎮프로그램 요소의 접근성은 가능한 한 최소한으로 하라. 

접근성을 최소화해야 하는 이유는 정보 은닉의 장점 때문이다.

 

[정보 은닉의 효과]

1. 시스템 개발 속도 향상 : 서로의 구현을 몰라도 되기 때문에 병렬로 개발이 가능하여 개발 속도가 빨라진다.

2. 잘 분리되어있는 컴포넌트는 관리포인트가 작다. 디버깅도 빨리 할 수 있고 다른 컴포넌트로의 교체도 빠르게 할 수 있다.

3. 잘 분리되어있는 컴포넌트는 최적화도 그 컴포넌트만 하면 되기 때문에 좋다.

4. 외부 컴포넌트에 종속되지 않기 때문에 재사용성이 높다.

5. 전체 시스템이 완성되지 않아도 개별 컴포넌트를 검증할 수 있기 때문에 큰 시스템을 개발하는 난이도를 낮춰준다.

 

[정보 은닉의 핵심 : 접근 제어자]

- private: 해당 클래스에서만 접근 가능

- package-private: 클래스와 같은 패키지에서 접근 가능
- protected: 같은 패키지 + 하위 클래스의 패키지에서 접근 가능
- public: 모든 곳에서 접근 가능

 

⎮꼭 필요한 것만 골라 최소한의 public API를 설계하자. 그 외에는 클래스, 인터페이스, 멤버가 의도치 않게 API로 공개되는 일이 없도록 해야 한다.

[캡슐화 방법]

1. 클래스의 공개 API를 설계한다

2. 공개 API 외의 모든 멤버는 private으로 만든다

3. 같은 패키지의 다른 클래스가 접근해야 하는 멤버에 한하여 private 제한자를 제거하고 package-private을 추가한다

→ private, package-private 멤버는 모두 해당 클래스의 구현에 해당하므로 보통은 공개 API에 영향을 주지 않게 된다

 

⎮public 클래스는 상수용 public static final 필드 외에는 어떠한 public 필드도 가져서는 안 된다.

필드가 가변 객체를 참조하거나 final이 아닌 인스턴스 필드를 public으로 선언하면, 그 필드와 관련된 모든 것은 불변식을 보장할 수 없게 된다. 외부에서 직접 필드에 접근하여 값을 변경할 수 있기 때문에 객체의 상태가 변경될 수 있고, 불변식이 깨질 수 있다.

또한 가변 필드가 public으로 노출되면 해당 필드에 여러 스레드가 동시에 접근하여 수정할 수 있기 때문에 예상치 못한 상태 변화가 발생할 수 있다.  따라서 public 가변 필드를 갖는 클래스는 일반적으로 thread-safe하지 않다.

 

⎮public static final 필드가 참조하는 객체가 불변인지 확인하라.

public class A {
  public final int[] arr = {1, 2, 3};
}

@Test
public void test() {
  A a = new A();
  a.arr[1] = 3;
  assertThat(a.arr[1]).isNotEqualTo(2);
}

길이가 0이 아닌 배열은 모두 변경 가능하다. 위 코드는 배열의 참조가 불변일뿐, 배열의 내용은 변경될 수 있다. 따라서 외부에서 배열의 내용을 수정할 수 있기 때문에 보안 허점이 존재한다.