Study/이펙티브코틀린
Item 11. 가독성을 목표로 설계하라
주지민
2022. 3. 15. 01:53
반응형
본 포스트는 사내 스터디를 진행하며 정리한 포스트입니다
1. 코드 예시
- 개발자는 어떤 코드를 작성하는데 보다 읽는데 시간을 많이 소모한다
- 따라서 프로그래밍은 가독성을 생각하면서 코드를 작성해야한다
// A
if (person != null && person.isAdult) {
view.showPerson(person)
} else {
view.showError()
}
// B
person?.takeIf { it.isAdult }
?.let(view.showPerson)
?: view.showError()
- 가독성이란 코드를 얼마큼 빠르게 이해할 수 있는지를 의미
- A 코드는 일반적으로 널리 쓰는 관용구 (if, else...)
- B 코드는 코틀린에서 널리 쓰이는 관용구 ( 안전호출?. , takeIf, let 등 ), 숙달된 코틀린 개발자에게만 쉬운 코드
2. A 코드를 사용해야하는 이유
- 사용 빈도가 적은 관용구는 코드를 복잡하게 만든다
- 그런 관용구들을 한 문장 내부에 조합해서 사용하면 복잡성은 훨씬 더 빠르게 증가
- 수정사항이 있을 때
- A코드에서는 if 블록에 코드만 추가하면 끝
- B코드에서는 함수참조를 사용할 수 없으므로 함수를 추가로 사용하여 수정해야한다 ( 좀 더 어려움 )
- 디버깅
- 일반적으로 디버깅 도구조차 기본적인 구조를 더 잘 분석해 준다
- 가독성은 '뇌가 프로그램의 작동 방식을 이해하는 과정'을 더 짧게 만드는 것
3. 극단적이 되지 않기
- let으로 인해 예상치 못한 결과를 발생할 수 있다
- 안전호출 let
class Person(private val name: String) {
private var person: Person? = null
fun printName() {
person?.let { println(it.name) }
}
}
val person = Person("주지민")
person.printName()
- 주로 사용하는 시기
- 지정된 값이 null이 아닌 경우 코드를 실행해야 할때 사용
- 연산을 아규먼트 처리후 이동시킬 때
- 데코레이터를 통해 객체를 랩할 때
print(students.filter{}.joinToString{})
=>
students.filter{}.joinToString{}.let(::print)
- 이해하기 어려운 코드지만 충분히 지불할만한 가치를 지닌 코드
students
.filter { it.result >= 50 }
.joinToString(separator = "\n") {
"${it.name) ${it.surname}, ${it.result}"
}
.let(::print)
var obj = FileInputStream("/file.gz")
.let(::BufferedInputStream)
.let(::ZipInputStream)
.let(::ObjectInputStream)
.readObject() as SomeObject
4. 컨벤션
val abc = "A" { "B" } and "C"
print(abc) // ABC
operator fun String.invoke(f: ()->String): String = this + f()
infix fun String.and(s: String) = this + s
- 연산자는 의미에 맞게 사용해야한다. invoke는 이렇게 사용하면 안된다
- invoke: 이름없이 간편하게 호출될 수 있는 함수 ( 람다는 내부에 invoke )
- '람다를 마지막 아규먼트로 사용한다'라는 컨벤션을 여기에 적용하면, 코드가 복잡해진다. invoke 연산자와 함께 이러한 컨벤션을 적용하는 것은 신중해야합니다
- 현재 and라는 함수 이름이 실제 함수 내부에서 이루어지는 처리와 맞지 않습니다
- 문자열 결합하는 함수는 이미 있음, 다시만들필요가 없다
728x90
반응형