Home [Effective Java] Item21. 인터페이스는 구현하는 쪽을 생각해 설계하라!
Post
Cancel

[Effective Java] Item21. 인터페이스는 구현하는 쪽을 생각해 설계하라!

Item21. 인터페이스는 구현하는 쪽을 생각해 설계하라!

자바 8 전에는 기존 구현체를 깨뜨리지 않고는 인터페이스에 메서드를 추가할 방법이 없었다.

  • 기존 인터페이스에 메서드 추가하는 경우, 그 메서드가 이미 존재할 가능성은 미비하니 보통 컴파일 에러가 난다.

자바 8에 와서 기존 인터페이스에 메서드를 추가할 수 있도록 디폴트 메서드가 추가됨.

  • 위험이 사라진 것은 아니다.
  • 기존 인터페이스에 메서드를 추가하는 길이 열렸으나 모든 기존 구현체와 매끄러운 연동을 보이지는 못한다.
    • 기존 구현체들은 디폴트 메서드에 대한 존재조차 알지 못했으니(이전엔 그냥 없었음) 전혀 대응하지 않았기 때문
  • 보통 자바 라이브러리의 디폴트 메서드는 코드 품질이 높고 범용적이라 대부분 상황에서 잘 작동한다.
    • 하지만 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하기란 어렵다.

SynchronizedCollection

  • 아파치 버전의 경우, 클라이언트가 제공한 객체로 락을 거는 능력을 추가로 제공함.
    • 모든 메서드에서 주어진 락 객체로 동기화 -> 내부 컬렉션 객체에 기능 위임 => 래퍼 클래스
  • 해당 클래스는 모든 메서드 호출을 알아서 동기화 해준다.
  • 해당 클래스는 removeIf 메서드의 문제가 있다.
    • 재정의 하지 않아서(이전 버전) 모든 메서드 호출을 알아서 동기화 해주지 못함.
    • 따라서 SynchronizedCollection 인스턴스를 여러 스레드가 공유하는 환경에서 한 스레드가 removeIf를 호출하면 ConcurrentModificationException이 발생하거나 다른 예기치 못한 결과로 이어질 수 있다.
    • 버전이 올라가며 현재는 removeIf를 재정의하고 있다.

정리

디폴트 메서드는 (컴파일에 성공하더라도) 기존 구현체에 런타임 오류를 일으킬 수 있다.

  • 자바 8은 컬렉션 인터페이스에 꽤 많은 디폴트 메서드를 추가함
    • 그 결과 기존에 짜여진 많은 자바 코드가 영향을 받음
  • 기존 인터페이스에 디폴트 메서드로 새 메서드를 추가하는 일은 꼭 필요한 경우가 아니면 피해야 한다.
  • 새로운 인터페이스를 만드는 경우라면 표존 메서드 구현 제공에 아주 유용한 수단이다.
    • 인터페이스를 더 쉽게 구현해 활용할 수 있게 해준다.
  • 디폴트 메서드는 인터페이스로부터 메서드를 제거하거나, 기존 메서드의 시그니처를 수정하는 용도가 아니다.

인터페이스를 설계할 때는 여전히 세심한 주의를 기울여야 한다.

  • 디폴트 메서드로 기존 인터페이스에 새로운 메서드 추가 시, 인터페이스가 잘못된 인터페이스라면 이를 포함한 API 어떤 재앙을 몰고 올지 알 수 없다.
  • 만드시 테스트하여 검증하자.

인터페이스를 릴리즈한 후라도 결함을 수정하는 게 가능한 경우도 있겠지만, 절대 그 가능성에 기대서는 안 된다.

This post is licensed under younghwani by the author.

[Effective Java] Item20. 추상 클래스보다는 인터페이스를 우선하라!

[Effective Java] Item22. 인터페이스는 타입을 정하는 용도로만 사용하라!

Comments powered by Disqus.