티스토리 뷰
반응형
정보은닉과 접근제한자
정보은닉이란,
잘 설계된 컴포넌트는 바로 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐이다.
즉, 오직 API를 통해서만 다른 컴포넌트와 소통하고 서로의 내부 동작 방식에는 개의치 않는 것을 말한다.
그럼, 정보은닉의 장점을 살펴보자
- 시스템 개발 속도를 높여준다. 여러 컴포넌트들이 독자적이어서 병렬로 개발할 수 있기 때문이다.
- 시스템 관리 비용을 낮춰준다. 다른 컴포넌트로 교체하는 부담이 적기 때문이다.
- 정보은닉 자체가 성능을 줄여주지는 않지만 성능 최적화에는 도움을 준다. 다른 컴포넌트에 영향을 주지않고 해당 컴포넌트만 최적화할 수 있는 기회가 생기기 때문이다.
- 소프트웨어 재사용성을 높여준다. 외부에는 거의 의존하지 않고 독자적으로 동작할 수 있는 컴포넌트라면 낯선 환경에서도 재사용이 가능하다.
- 시스템 전체가 완성되어있지 않더라도 개별 컴포넌트의 동작을 검증할 수가 있다.
그런데 이런 정보은닉을 제대로 사용하려면은 접근제한자를 잘 활용해야한다.
외적으로 정보은닉과 캡슐화에 대해서 헷갈리는 부분이 많은데, 정의해보자(간략히 살펴보자)
- 정보은닉은 private을 사용하여 주요 사항이 드러나지 않도록 감추는 것이다.
- 캡슐화는 메소드(Getter/Setter/public method)를 활용하여 외부에서 접근할 수 있는 부분만 설정한 후 외부와 직접적으로 소통하는 것을 말한다.
클래스와 접근제한자
모든 클래스와 멤버의 접근성을 가능한 좁혀야한다.
-
소프트웨어가 올바로 동작하는 한 항상 가장 낮은 접근 수준을 부여해야 한다.
-
톱레벨 클래스(클래스명)의 접근제한자는 public과 package-private만 사용할 수 있다.
- public을 선언한 경우에는 공개 API가 된다.
- package-private을 선언한 경우에는 해당 패키지 안에서만 사용 가능하다.
-
멤버의 접근성을 좁히기 위한 클래스 구현 시 주의
- 일단 처음에는 모든 멤버를 private으로 만들어야한다.
- 같은 패키지에서 접근해야하는 멤버가 있을 시에는 package-private으로 변경한다.
- 그러나, Serializable을 구현한 클래스에서는 의도치 않게 공개 API가 될 수도 있다.
- 멤버의 접근 제한을 package-private에서 protected로 변경하는 순간 그 멤버에 접근할 수 있는 대상 범위가 넓어지니 주의해야한다. 따라서, protected 멤버의 수는 적을수록 좋다.
-
멤버 접근성을 좁히지 못하게 하는 방해 제약
- 상위 클래스의 메서드를 재정의할 때는 그 접근 수준을 상위 클래스에서보다 좁게 설정할 수가 없다.
- 즉, 상위 클래스가 public, protected인데 하위클래스에서 재정의 시 package-private이나 private으로 변경이 불가능하다는 것이다.
- 상위 클래스의 메서드를 재정의할 때는 그 접근 수준을 상위 클래스에서보다 좁게 설정할 수가 없다.
- 코드를 테스트하려는 목적으로 클래스, 인터페이스의 접근 범위를 결정할 때 주의해라
- public 클래스의 private 멤버를 package-private까지 풀어주는 것은 상관이 없는데, 그 이상은 안된다. 그 이상은 공개 API가 될 수 있다.
- public 클래스의 인스턴스 필드는 public이 아니어야 한다.
- public 필드를 가지게 되면 불변식을 보장할 수 없으므로, thread safe하지가 않는다.
- 상수라면
public static final
필드로 둬도 괜찮다. 단, 이 필드는 반드시 기본 타입 값이나 불변 객체를 참조해야 한다.
-
클래스에서
public static final
배열 필드를 두지 마라public static final Thing[] VALUES = {...}; //이 경우 배열내의 변경이 가능하다..
- 배열 필드의 해결책
//해결 1. 배열 필드를 private으로 선언 후 public 불변 리스트를 추가 private static final Thing[] PRIVATE_VALUES = {...}; public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES)); //해결 2. 배열 필드를 private으로 선언 후 그 복사본을 반환하는 public 메서드를 추가 private static final Thing\[\] PRIVATE\_VALUES = {...}; public static final Thing\[\] values() { return PRIVATE\_VALUES.clone(); //방어적 복사본 }
정리
접근제한자를 활용하여 클래스와 멤버의 접근성을 최대한 좁히고, 독자적인 컴포넌트를 만드는 것이 정보은닉인 것이다.
반응형
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] 아이템 69. 예외는 진짜 예외 상황에서만 사용하라 (0) | 2020.02.06 |
---|---|
[Effective Java] 아이템 61. 박싱된 기본 타입보다는 기본 타입을 사용해라 (0) | 2020.02.03 |
[Effective Java] 아이템6. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2019.12.22 |
[Effective Java] 아이템5. 불필요한 객체 생성을 피하라 (0) | 2019.12.22 |
[Effective Java] 아이템 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2019.12.14 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Effective Java
- try catch finally
- mustache
- effectivejava
- 이펙티브 자바
- 빌더 패턴
- 점층적 생성 패턴
- 자바8
- 이펙티브자바
- @Lazy
- junit
- ifPresent
- 연관관계
- Spring
- try with resources
- springboot
- 복사 팩토리
- 생성자
- 빈 순환 참조
- java
- 정적팩터리메서드
- 인프런
- package-private
- java8
- 스프링부트
- 팩토리 메소드 패턴
- JPA
- jdk버전
- flatMap
- 김영한
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함