본 챕터는 '규약은 개발자들의 단순한 합의' 라는 내용으로 시작한다.
규약이란 것은 한쪽이 위반할 수도 있으며, 기술적으로는 모든 부분에서 규약 위반이 발생할 수도 있다.
규약을 위반한 코드는 시한 폭탄을 설치한 것과 같으며, 코드가 작동을 멈췄을 때 문제가 된다.
상속된 규약
규약을 반드시 지켜야 하는 경우는 1) 클래스 상속, 2) 다른 라이브러리의 인터페이스 구현을 하게되는 시점이다.
예를 들어 모든 클래스는 equals, hashCode 메서드를 가진 Any 클래스를 상속 받는데, 이러한 메서드는 지켜야하는 규약을 가지고 있다.
만약 hashCode가 제대로 구현되지 않으면, HashSet과 함께 사용할 때 제대로 동작하지 않는다.
아래 코드에서 보여주는 바는 equals가 제대로 구현되지 않았을 경우에 대한 예시이다.
원래 Set은 중복을 허용하지 않는데, equals가 제대로 구현되지 않아서 중복을 허용해 버린다.
class Id(val id: Int) {
override fun equals(other: Any?) =
other is Id && other.id == id
}
val set = mutableSetOf(Id(1))
set.add(Id(1))
set.add(Id(1))
print(set.size) // 3
위의 문제 코드는 아래와 같이 개선될 수 있다.
class Id(val id: Int) {
override fun equals(other: Any?) =
other is Id && other.id == id
override fun hashCode() = id.hashCode() // hashCode 추가
}
val set = mutableSetOf(Id(1))
set.add(Id(1))
set.add(Id(1))
print(set.size) // 1 (올바르게 동작함)
또 다른 방법은 data class 를 사용하면, 코틀린에서 equals와 hashCode가 자동으로 생성된다.
data class Id(val id: Int)
val set = mutableSetOf(Id(1))
set.add(Id(1))
set.add(Id(1))
print(set.size) // 1
정리
1. 프로그램을 안정적으로 유지하고 싶다면, 규약을 지켜라
2. 규약을 깰 수 밖에 없다면, 문서화해라
'Study OR Book > Book' 카테고리의 다른 글
[이펙티브 코틀린] 아이템43: API의 필수적이지 않는 부분을 확장 함수로 추출하라 (0) | 2025.02.18 |
---|---|
[이펙티브 코틀린] 아이템40: equals의 규약을 지켜라 (0) | 2025.02.10 |
[이펙티브 코틀린] 아이템29: 외부 API를 랩(wrap)해서 사용하라 (0) | 2025.01.21 |
[이펙티브 코틀린] 아이템19: knowledge를 반복하여 사용하지 말라 (0) | 2025.01.15 |
[이펙티브 코틀린] 아이템17: 이름 있는 아규먼트를 사용하라 (0) | 2025.01.08 |