KotlinInAction/함수 정의와 호출

로컬 함수와 확장

webmaster 2022. 7. 29. 02:01
728x90

자바에서는 메서드를 분리하기 쉽지 않다 

너무 많이 나눠서 분리하게 되면 각 메서드 사이의 관계가 파악하기 어려워져 코드가 어려워진다. -> 내부 클래스로 어느 정도 해결되지만 이것도 부가적인 코드가 늘어난다

코틀린에서는 함수에서 추출한 함수를 원 함수 내부에 중첩시킬 수 있다.

class User(val id: Int, val name: String, val address: String) {
}
fun saveUser(user: User){
    if(user.name.isEmpty()){
        throw IllegalArgumentException("Can't save user ${user.id} : empty name")
    }
    if(user.address.isEmpty()){
        throw IllegalArgumentException("Can't save address ${user.id} : empty address")
    }
    //user 저장
}
fun main(args: Array<String>) {
    saveUser(User(1, "", ""))
}
  • 필드를 검증 할 때 메서드가 중복되는 경우가 많다.
fun saveUser(user: User){
    fun validate(user: User, value: String, fileName: String){
        if(value.isEmpty()){
            throw IllegalArgumentException("Can't save user ${user.id} : empty $fileName")
        }
    }
    //user 저장
    validate(user, user.name, "Name")
    validate(user, user.address, "Address")
}
  • 검증 로직 중복이 제거되었고 필요하면 User의 다른 필드에 대한 검증도 쉬워졌다
  • User객체를 하나씩 로컬 함수로 전달되는 부분은 여전히 아쉽다
  • 로컬 함수는 자신이 속한 바깥 함수의 모든 파라미터, 변수를 사용할 수 있다
fun saveUser(user: User){
    fun validate(value: String, fileName: String){
        if(value.isEmpty()){
            throw IllegalArgumentException("Can't save user ${user.id} : empty $fileName")
        }
    }
    //user 저장
    validate(user.name, "Name")
    validate(user.address, "Address")
}

검증 로직을 User클래스를 확장한 함수로 만들 수도 있다

fun User.validateBeforSave(){
    fun validate(value: String, fileName: String){
        if(value.isEmpty()){
            throw IllegalArgumentException("Can't save user $id : empty $fileName")
        }
    }
    validate(name, "Name")
    validate(address, "Address")
}
fun saveUser(user: User){
    user.validateBeforSave()

    //user 저장

}
  • 코드를 확장 함수로 뽑아 가독성이 훨씬 좋아졌다
  • 검증 로직은 User를 사용하는 다른 곳에서는 쓰이지 않는 기능이기에 User에 포함시키지 않는다
  • 확장 함수를 로컬 함수로 정의할 수도 있다
    • 중 첨 함수가 길어지면 복잡하므로 한 단계만 함수를 중첩시킬 것을 권장
728x90