Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions EffectiveKotlin/11장/페토.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
## 가독성을 목표로 설계하라

로버트 마틴의 저서 클린 코드에선 개발자가 코드를 작성하는 데는 1분 걸리지만, 이를 읽는 데는 10분이 걸린다는 이야기가 있다.
예를 들어 코드를 작성하다가 오류가 발생한 경우 오류를 찾기 위해 코드를 작성할 때보다 오랜 시간 코드를 읽는 자신을 발견할 수 있다.

실제로 프로젝트를 진행할 때도 코드 한 줄 고치겠다고 몇 주 동안 코드를 살펴보는 상황도 많다.
프로그래밍은 쓰기보다 읽기가 중요하다. 따라서 항상 가독성을 생각하면서 코드를 작성해야 한다.

### 1. 인식 부하 감소
가독성은 사람에 따라 다르게 느낄 수 있다. 하지만 일반적으로 많은 사람의 **경험**과 **인식**에 대한 과학으로 만들어진 어느 정도의 규칙이 있다.
```
// 구현 A
if(person != null && person.isAdult){
view.showPerson(person)
}else{
view.showError()
}

// 구현 B
person?.takeIf { it.isAdult }
?.let(view::showPerson)
?: view.showError()
```

위 예시 코드에서 어떤 것이 더 좋다고 생각하는가 ?
단순히 B가 더 짧다는 이유로 B를 선택했다면 아쉽게도 좋은 대답이 아니다. B는 읽고 이해하기 어렵다.

가독성이란 코드를 읽고 얼마나 빠르게 이해할 수 있는지를 의미한다. 이는 우르의 뇌가 얼마나 많은 관용구(구조, 함수, 패턴)에 익숙해져 있는지에 따라서 다르다.
코틀린 초보자에게는 일반적인 관용구(if-else)를 사용하기 때문에 구현 A가 더 읽고 이해하기 쉽다.
구현 B는 코틀린에서는 꽤 일반적으로 사용되는 관용구를 사용하고 있다. 때문에 경험이 많은 코틀린 개발자라면 쉽게 읽을 수 있을것이다.

하지만 숙련된 개발자만을 위한 코드는 좋은 코드가 아니다. 구현 A와 B는 사실 비교조차 할 수 없을 정도로 A가 훨씬 가독성이 좋은 코드다.
또한 숙련된 개발자도 이런 코드는 익숙하지 않아 이해하는데 시간이 꽤 걸리 수 있다.

> 사용 빈도가 적은 관용구는 코드를 복잡하게 만든다.

또한 구현 A는 수정하기 쉬운 반면 구현 B는 상당히 복잡해진다.
```
// 구현 A
if(person != null && person.isAdult){
view.showPerson(person)
view.hidePrgreassWithSuccess()
}else{
view.showError()
view.hideProgress()
}

// 구현 B
person?.takeIf { it.isAdult }
?.let{
view.showPerson(person)
view.hidePrgreassWithSuccess()
}
?: run {
view.showError()
view.hideProgress()
}
```

이처럼 일반적이지 않은 굉장히 창의적인 구조는 유연하지 않고 지원도 제대로 받지 못한다.
기본적으로 인지 부하를 줄이는 방향으로 코드를 작성하라. 우리의 뇌는 패턴을 인식하고, 패턴을 기반으로 프로그램의 작동 방식을 이해한다.

가독성은 뇌가 프로그램의 작동 방식을 이해하는 과정을 더 짧게 만드는 것 이다.
자주 사용되는 패턴을 활용하면 이와 같은 과정을 더 짧게 만들 수 있다.

### 2. 극단적이 되지 않기
앞서 let으로 인해서 예상하지 못한 결과가 나올 수 있다고 했다. 그렇다고 let은 절대로 쓰면 안 된다로 이해해선 안 된다.
let은 분명 좋은 코드를 만들기 위해서 다양하게 활용되는 관용구다.

```
class Person(val name: String)
var person: Person? = null

fun printName() {
person?.let {
print(it.name)
}
}
```
이런 관용구는 널리 사용되며, 많은 사람이 쉽게 인식한다. 이외에도 다음과 같은 경우에 let을 많이 사용한다.
```
fun printName() {
person?.let {
print(it.name)
}
}
```
위코드처럼 nullable 안전 호출할 수 있으며
```
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
```
데코레이터를 사용해서 객체를 wrap 할 때 같이 let은 많은 용도로 사용된다.

이처럼 관용구를 이해하는데 비용이 발생하더라도, 그만한 가치가 있다면 사용해도 좋다. 또한 두 구조를 조합해서 사용하면 단순하게 개별적인 복잡성의 합보다 커진다.
let과 if문의 구조들을 보면서 사람에 따라 가독성의 관점이 다르다는 것을 알 수 있다. 그래서 우리는 컨벤션 규칙이 필요하다.

### 3. 컨벤션
많은 개발자들이 함수명을 어떻게 지어야 하는지, 어떤 것이 명시적이어야 하는지, 어떤 것이 암묵적이어야 하는지, 어떤 관용구를 사용해야 하는지 등으로 토론한다.
프로그래밍은 표현력의 예술이다. 이를 위해 이해하고 기억해야 하는 몇 가지 규칙이 있다. 이런 내용들을 앞으로 하나하나 자세하게 살펴본다.
Loading