item 11 : 가독성을 목표로 설계하라
짧은 것보다 익숙한게 읽기 좋다
A는 범용적인 관용구, B는 코틀린 문법의 관용구를 사용하고 있다.
/* Style A */
if (person != null && person.isAdult) {
view.showPerson(person)
} else {
view.showError()
}
/* Style B */
person?.takeIf { it.isAdult }
?.let(::view.showPerson)
?: view.showError()
- B가 cool 해보일 수 있지만 쉽게 읽을 수 있는 코드가 아니므로 A가 더 가독성이 좋다고 할 수 있다.
- B와 같은 코드는 수정에도 불리하다.
- B에서 만약
showError
가 null을 리턴한다면 else 에 해당하는view.showError()
문도 실행 될 수 있다.
뇌는 기본적으로 짧은 코드를 빠르게 읽을 수 있겠지만, 익숙한 코드는 더 빠르게 읽는다!
그렇다고 해서 let 같은걸 아예 쓰지말라는건 아니고요
- 연산을 인자 처리 후로 이동 시킬 때
- 데코레이터를 사용해서 객체를 wrap할때
students.filter { it.result >= 50 }
.joinToString("\n") { "${it.name} ${it.surname}, ${it.result}" }
.let(::print)
적절히 쓰면 좋다. 뭐든 적당히..
item 13 : Unit?
을 리턴하지 말라
반환 값이 없는 함수의 return 값을 보통 Unit
으로 주는데 Boolean
리턴하는 거면 Unit
/ Unit?
주면 대체 가능하지 않나요?
No! 오해의 소지가 있으며 예측하기 어려운 오류를 만든다.
EX) getData()?.let { view.showData() } ?: view.showError()
기본적으로 Unit?
을 리턴하거나, 이를 기반으로 연산하지 않는 것이 좋다
item 14 : 변수 타입이 명확하지 않은 경우 확실하게 지정하라
val data = getData()
타입이 getData()
함수 반환 값에 의해 정해지며 숨겨져있다. 이는 가독성이 떨어뜨리는 행위이며, github 같은 곳에서 코드를 본다면 알기 더 힘들다.
또한 1장에서 플랫폼 타입(item3) + 예측 하기 힘듦(item4) 문제로 안정성에도 문제가 있다.
item 15 : 리시버를 명확하게 참조하라
- 짧게 적을 수 있다는 이유만으로 리시버를 제거하지 말라
- 여러 개의 리시버가 있는 상황 등에는 리시버를 명시적으로 적어 주는 것이 좋다.
- 명시하면 어떤 리시버의 함수인지를 명확하게 알 수 있으므로, 가독성이 향상된다.
item 16 : 프로퍼티는 동작이 아니라 상태를 나타내야 한다
필드가 아니라 접근자다
- 자바의 field와는 다르다
getter
와setter
를 가질 수 있다. (접근자)- 다른
var
프로퍼티로 부터 정의되면 파생 프로퍼티(drived property)가 존재한다. - 기본적으로 캡슐화 되어 있다. (get/set을 통한 unwrap/wrap)
// interface도 property를 가질 수 있다.
interface Person { val name: String }
open class Supercomputer {
open val theAnswer: Long = 42
}
// super class의 property를 override 할 수 있다.
class AppleComputer: Supercomputer() {
override val theAnswer: Long = 1_800_275_2273
}
// delation 가능하다.
val db: Database by lazy { connectToDb() }
그렇기 때문에
- 인터페이스에도 프로퍼티를 정의할 수 있다.
- getter를 가지므로 override 가 가능하다.
- delegation도 가능하다.
그렇다고 프로퍼티를 함수처럼 쓰지는 말라
- 프로퍼티는 함수 대신 사용할 수 있지만 완전히 대체해서는 안된다.
- 상태를 나타내거나 설정하기 위한 목적으로 사용되어야 한다.
- 이 프로퍼티를 함수로 정의한다면 get/set을 붙일건가?
- 아니라면 프로퍼티로 쓰지마라...
- 이럴때는 프로퍼티 말고 함수를 쓰자
- 연산 비용 또는 복잡도가 높은 경우
- 비즈니스 로직을 포함한 경우
- 결정적이지 않은 경우 (실행할 때마다 값이 바뀌는 등)
- getter에서 상태변경이 있는 경우
item 17 : 이름 있는 아규먼트를 사용하라
argument에 이름을 붙이면 이럴때 좋다
- default 아규먼트의 겨웅
- 같은 타입의 파라미터가 많은 경우
- 함수 타입의 파라미터가 있는 경우
마지막에 위치한 함수 하나는 lambda로 처리하곤 한다. 근데 경험 상 compose의 경우 compose builder 제외하고는 그냥 모두 이름을 붙이는 게 가독성 측면에서 좋은 경우가 많은 것 같다고 생각합니다.
'Kotlin' 카테고리의 다른 글
[이펙티드 코틀린] 4장 🖼️ 추상화 설계 Abstraction Design (item 26..32) (0) | 2023.06.28 |
---|---|
[이펙티드 코틀린] 3장 ♻️ 재사용성 Reusability (item 19..25) (0) | 2023.06.28 |
[이펙티트 코틀린] 1장 🏰 안정성 Safety (item 01..10) (0) | 2023.06.18 |