티스토리 뷰
Item19는 일반 개발자에게는 생소한 내용이 담겨있다, 물론 나에게도 그렇다
작성하는 클래스가 상속용인지 아닌지 결정하라는 것인데 이 것이 중요한 이유는 라이브러리 사용자에게
상속했을 때 신경 써야 할 부분을 알려주기 위함이다
이전 아이템에서 나온 HashSet 상속 시 발생할 수 있는 문제는 명세를 꼼꼼히 살펴봤다면 일어나지 않았을 것이다
이전 아이템은 아래 글 참고
Javadoc까지 완벽하게 작성할 것이 아니라면 @implSpec, @throws 등은 스킵하자
클래스를 상속용으로 설계했을 때 중요한 건 유연성을 제공하는 것이다
유연성을 적절히 제공하지 못한 사례는 이동욱 님의 QueryDslItemReader 작성 글에서 알 수 있다
Spring Batch에서 정식으로 QuerydslPagingItemReader를 지원하지 않기 때문에
AbstractPagingItemReader를 상속받아 직접 작성하는데
이 중 로직 변경이 필요한 createQuery() 메서드는 private이라 재정의해 작성할 수 없고 코드 복붙이 들어간다
오타나 상위 클래스의 구현에 직접 의존하게 되는 복붙의 위험성은 말할 것도 없고 확장성을 제공하지 못했다
Batch 버전이 올라가면서 protected로 바뀔 수도 있고 아니라면 정식으로 QueryDslItemReader 지원하기를 바라야겠다
따라서 상속용이라면 private으로 깔되 변경이 필요할 수 있는 부분은 protected로 열어야 한다
이 부분은 트레이드 오프라 처음부터 깊게 고민하기보단 작성 후 사용하는 시점에 계속 검증 & 수정이 필요하다
Comparable, Serializable, Cloneable을 구현한 클래스를 상속받게 된다면 주의점이 더 많아진다
하나의 예로 Comparable 구현한 클래스를 상속받았을 때 순서 비교가 필요한데
상위 클래스와의 비교를 허용해서는 안 된다면 재정의가 필요할 것이고 다른 녀석들도 마찬가지다
상속용이 아니라면 간단한 방법으로 표현할 수 있다
1. 클래스 선언 시 final 키워드 넣기
2. 빈 생성자를 private으로 막아두기
둘 모두 상속을 금지한다는 점은 똑같지만 미묘한 차이가 있다
상속은 안 되지만 인스턴스가 여러 개 생길 수 있는 경우 final 키워드를 사용하고
상속도 안 되지만 인스턴스화도 되선 안 되는 Util 클래스들은 빈 생성자를 막아두도록 한다
하위 클래스의 생성 과정에서 암묵적으로 상위 클래스의 빈 생성자 super()를 호출하는데 이를 막기 위함이다
지금 당장부터 위 내용을 모두 체화해서 사용하긴 힘드니 간단한 Util 클래스부터 적용해보도록 하자
롬복을 사용해 간단하게 적용할 수 있다, 꼼꼼한 코딩으로 한 발자국 다가섰다
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Utils {
}
'Java > Effective Java' 카테고리의 다른 글
[Item21] 인터페이스 default method는 만능이 아니다 (0) | 2022.02.28 |
---|---|
[Item20] 항상 인터페이스로 (0) | 2022.02.26 |
[Item18] extends 멈춰 (0) | 2022.02.24 |
[Item17] 가변으로 할까, 불변으로 할까 (0) | 2022.02.23 |
[Item16] 잘 숨겨야 발전한다 (0) | 2022.02.22 |