View
자바 8 이전에는 기존 구현체를 깨트리지 않고 인터페이스에 메서드를 추가할 방법이 없었다. 자바 8부터 디폴트 메서드를 제공하여 메서드를 추가할 수 있도록 됐지만, 위험이 완전히 사라진 것은 아니다.
생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하기란 어렵다.
자바 8부터 Collection에 새로 추가된 removeIf() 메서드는 Predicate 결과에 따라 원소를 제거하는 메서드이다.
범용적인 코드이지만, 모든 Collection의 구현체와 잘 어우러지는 것은 아니다. 아파치의 SynchronizedCollection 클래스는 지금도 활발히 관리되고 있지만 removeIf 메서드를 재정의하지 않는다. 그 이유는 만약 removeIf의 디폴트 구현을 물려받는다면 모든 메서드 호출을 알아서 동기화해주지 못한다.
멀티 스레드환경에서 SynchronizedCollection이 removeIf를 호출하면 ConcurrentModificationException과 같은 런타임 에러를 발생시키거나 예기치 못한 결과로 이어질 수 있다. 즉, 본인의 약속을 지킬 수 없게 되는 것이다.
기존 인터페이스에 디폴트 메서드로 새 메서드를 추가하는 일은 꼭 필요한 경우가 아니라면 피해야한다. 또 디폴트 메서드를 기존 인터페이스의 메서드를 제거하거나, 시그니처를 수정하는 용도로 사용하면 클라이언트가 망가질 수 있다.
핵심은 명확하다.
인터페이스를 설계할 때는 세심한 주의를 기울여야 한다.
인터페이스를 릴리스한 후라도 결함을 수정하는게 가능한 경우도 있겠지만, 절대 그 가능성에 기대서는 안된다.
'BackEnd > 이펙티브 자바' 카테고리의 다른 글
[이펙티브 자바] Item23- 태그 달린 클래스보다는 클래스 계층구조를 활용하라 (0) | 2021.03.13 |
---|---|
[이펙티브 자바] Item22- 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2021.03.09 |
[이펙티브 자바] Item20- 추상클래스보다는 인터페이스를 우선시하라 (0) | 2021.03.07 |
[이펙티브 자바] Item19- 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. (0) | 2021.02.21 |
[이펙티브 자바] Item18- 상속보다는 컴포지션을 사용하라 (0) | 2021.02.14 |