반응형
728x90
반응형
로컬함수 확장
예제 : 데이터베이스에 사용자 객체를 저장하기전, 각 필드의 validation 을 검증하는 로직
1단계. 코드 중복을 보여주는 예제
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 User ${user.id}: empty Address"
)
}
}
fun main() {
saveUser(User(1, "", ""))
}
2단계. 코드 중복 줄이기
class User_2(val id: Int, val name: String, val address: String)
fun saveUser2(user: User) {
// 한 필드를 검증하는 로컬 함수를 정의한다.
fun validate(user: User,
value: String,
fieldName: String) {
if (value.isEmpty()) {
throw IllegalArgumentException (
"Can't save user ${user.id}: empty $fieldName"
)
}
}
// 로컬함수를 호출해서 각 필드를 검증한다.
/* 아쉬운점 : 로컬함수에게 User 객체를 하나하나 전달해야한다. */
validate(user, user.name, "Name")
validate(user, user.address, "Address")
}
2-1) 로컬 함수를 정의했다.
fun validate(user: User,
value: String,
fieldName: String) {
if (value.isEmpty()) {
throw IllegalArgumentException (
"Can't save user ${user.id}: empty $fieldName"
)
}
}
2-2) 로컬 함수를 호출한다.
validate(user, user.name, "Name")
validate(user, user.address, "Address")
문제점
로컬함수에게 User 객체를 하나하나 중복으로 전달해줘야한다.
3단계. 로컬함수에서 바깥 함수의 파라미터 접근하기
class User_3(val id: Int, val name: String, val address: String)
fun saveUser3(user: User) {
fun validate(value: String,
fieldName: String) {
if (value.isEmpty()) {
throw IllegalArgumentException (
// 바깥 함수의 user 파라미터에 직접 접근할 수 있다.
"Can't save user ${user.id}: empty $fieldName"
)
}
}
validate(user.name, "Name")
validate(user.address, "Address")
}
3-1) 바깥 함수 saveUser3의 user 파라미터에 직접 접근할 수 있다.
fun validate(value: String,
fieldName: String) {
if (value.isEmpty()) {
throw IllegalArgumentException (
// 바깥 함수의 user 파라미터에 직접 접근할 수 있다.
"Can't save user ${user.id}: empty $fieldName"
)
}
}
4단계. 검증 로직을 확장 함수로 추출하기
- 함수 중첩은 한단계만 권장한다. 중첩된 함수의 깊이가 깊어지면 코드를 읽기가 어려워진다.
class User_4(val id: Int, val name: String, val address: String)
fun User.validateBeforeSave() {
fun validate(value:String, fieldName:String) {
if (value.isEmpty()) {
throw IllegalArgumentException (
// User의 프로퍼티를 직접 사용할 수 있다.
"Can't save user ${id}: empty $fieldName"
)
}
}
validate(name,"Name")
validate(address,"Address")
}
fun saveUser4(user: User) {
// 확장함수를 호출한다.
user.validateBeforeSave()
}
4-1) User의 프로퍼티를 직접 사용한다.
fun User.validateBeforeSave() {
fun validate(value: String, fieldName: String) {
if (value.isEmpty()) {
throw IllegalArgumentException (
// User의 프로퍼티를 직접 사용할 수 있다.
"Can't save user ${id}: empty $fieldName"
)
}
}
...
}
4-2) 확장 함수를 호출한다.
fun saveUser4(user: User) {
// 확장함수를 호출한다.
user.validateBeforeSave()
}
반응형
'Coding > Kotlin' 카테고리의 다른 글
[Kotlin in Action] 14. 코틀린의 가시성 변경자 (open, abstract, internal) (0) | 2022.05.22 |
---|---|
[Kotlin in Action] 13. 코틀린 인터페이스 구현 (0) | 2022.05.21 |
[Kotlin in Action] 11. 문자열과 정규식 (split 메서드, 정규식, 3중 따옴표) (0) | 2022.05.20 |
[Kotlin in Action] 10. 컬렉션 처리 (가변인자, 중위호출) (0) | 2022.05.20 |
[Kotlin in Action] 9. 확장 함수와 확장 프로퍼티 (0) | 2022.05.19 |