추상화 규약을 지켜라
규약은 개발자들의 단순한 합의이므로 한쪽에서 규약을 위반할 수 있다.
예를 들어 리플렉션을 활용하면, 우리가 원하는 것을 열고 사용할 수 있다.
class Employee {
private val id: Int = 2
override fun toString(): String = "User(id = $id)"
private fun privateFunction() = println("Private function called")
}
fun callPrivateFunction(employee: Employee) {
employee::class.declaredMemberFunctions
.first { it.name == "privateFunction" }
.apply { isAccessible = true }
.call(employee)
}
fun changeEmployeeId(employee: Employee, newId: Int) {
employee::class.java.getDeclaredField("id")
.apply { isAccessible = true }
.set(employee, newId)
}
fun main() {
val employee = Employee()
callPrivateFunction(employee) // 출력: Private function called
changeEmployeeId(employee, 1)
print(employee) // 출력 User(id = 1)
}
현재 코드는 함수 이름과 같은 세부적인 정보에 의존하고 있다. 이는 언제든지 변경될 수 있으므로 좋은 코드는 아니다.
상속하거나 인터페이스를 구현할 때는 규약을 반드시 지켜야 한다.
예를 들어 모든 클래스는 equals
와 hashCode
메서드를 가진 Any
클래스를 상속받는다. 이 메서드는 반드시 지켜야하는 규약이 있다.
equals를 재정의할 때 hashCode도 재정의하지 않는다면 set에서 문제가 발생할 수 있다.
프로그램을 안정적으로 유지하고 싶다면 규약을 지켜라. 규약을 깰 수 밖에 없다면 문서화를 잘해라