fastcampus: 실무 프로젝트로 배우는 Kotlin & Spring - Part 4/Ch02/03 오류 발견
위치: https://fastcampus.app/courses/211160/clips/779520?position=1248&organizationProductId=13720
Part 4. 실제 예제를 기반으로 자바 프로젝트에 코틀린 도입해보기
ch02. 자바 프로젝트(ToDo프로젝트) 코틀린으로 리팩토링 하기
03. 컨트롤러 레이어 리팩토링 22:51
자바로 되어 있는 코드를 코틀린으로 옮기는 것을 예제로 보여 주는 강좌였다.
18:04경에 Assert.notNull 을 코틀린의 checkNotNull로 바꾸는 부분이 있었다.
이 부분을 보면서 저 변환은 계약 위반이라고 생각했다.
그 이유는 무엇일까?
기존에 Assert.notNull 는 스프링이 제공해주는 Assertion utility이다.
코드를 보면 다음과 같다.
package org.springframework.util;
public abstract class Assert {
public static void notNull(@Nullable Object object, String message) {
if (object == null) {
throw new IllegalArgumentException(message);
}
}
다음은 코틀린 코드이다.
package kotlin
@kotlin.internal.InlineOnly
public inline fun <T : Any> checkNotNull(value: T?): T {
contract {
returns() implies (value != null)
}
return checkNotNull(value) { "Required value was null." }
}
@kotlin.internal.InlineOnly
public inline fun <T : Any> checkNotNull(value: T?, lazyMessage: () -> Any): T {
contract {
returns() implies (value != null)
}
if (value == null) {
val message = lazyMessage()
throw IllegalStateException(message.toString())
} else {
return value
}
}
어떤 계약이 깨졌는지 보이는가?
이전에 Assert.notNull 로 단정하는 경우에는 todo가 null 일 경우에 IllegalArgumentException 가 발생한다.
그런데 코틀린으로 전환한 Preconditions 인라인 함수의 경우 IllegalStateException 이 발생하게 된다.
언어의 전환은 리팩터링
리팩터링 2판의 294쪽에 다음과 같은 내용이 있다.
수정 전과 수정 후의 겉보기 동작이 달라지면 더 이상 리팩터링이 아니다.
언어의 전환은 세부사항(기술)의 변경이지 비즈니스 로직이 변경이 되어서는 아니다. 따라서 동작은 동일하게 유지되어야 하며 이 글에서 이것을 계약(contract)라는 용어로 표현했다.
그렇다면 제대로 변환을 한다면 어떻게 해야 할까?
코틀린의 Preconditions 유틸리티에도 IllegalArgumentException 를 발생시키는 함수가 있다.
바로 requireNotNull 이다.
@kotlin.internal.InlineOnly
public inline fun <T : Any> requireNotNull(value: T?, lazyMessage: () -> Any): T {
contract {
returns() implies (value != null)
}
if (value == null) {
val message = lazyMessage()
throw IllegalArgumentException(message.toString())
} else {
return value
}
}
만약 테스트 코드를 꼼꼼하게 작성했다면 전환하는 data class 의 테스트 코드는 예외의 변화에 대해서 제대로 알려주었을 것이다.
이상했던 것은 04. 서비스 레이어 리팩토링에서 checkNotNull의 구현을 이미 강사는 보여주고 있었다.