들어가기 앞서
- 
코틀린의 핵심 철학은 '실용주의(pragmatism)' 
- 
실용주의는 다음과 같은 비지니스 요구 사항을 충족한다는 것을 의미 - 
생선성(productivity) 
- 
확장성(scalability) 
- 
유지보수성(maintainability) 
- 
신뢰성(reliability) 
- 
효율성(efficiency) 
 
- 
- 
이 책의 목표 코틀린을 활용해서 더 안전하고, 더 가독성이 좋고, 더 확장성이 있으며, 더 효율적인 코드를 작성하는 방법 설명 
좋은 코드
안정성
1. 가변성을 제한하라
- 
코틀린의 프로퍼티는 상태(state)를 가질 수 있음. read-write property( var) 혹은 mutable object
- 
상태를 가지는 것 - 
프로그램 이해하기 어렵고 디버그 어려워짐 
- 
코드 실행을 추론하기 어려워짐 
- 
멀티스레드일 때 적절한 동기화 필요 
- 
테스트 어려워짐 
- 
변경을 알려야함 (정렬된 리스트일 경우 엘리먼트 변경시 매번 재정렬 필요) 
 
- 
- 
가변성은 생각보다 단점이 많아 이를 제한하는 언어도 있음 → 순수 함수형 언어(Haskell, …) 
- 
일반적으로 var보다val을 많이 사용함
- 
코틀린은 가변성을 제한할 수 있게 설계되어 있음 
읽기 전용 프로퍼티(val)
- 
val로 선언된 프로퍼티는 마치 값(value)처럼 동작
- 
읽기 전용 프로퍼티가 완전히 변경 불가능한 것은 아니라는 것을 주의 val은 읽기 전용 프로퍼티지만, 변경할 수 없음(불변, immutable)을 의미하는 것이 아니라는 것을 기억해야 함
- 
읽기 전용 프로퍼티가 mutable 객체를 담고 있다면, 내부적으로 변경 가능 '프로퍼티를 읽을 수만 있다는 것(읽기 전용) vs. 값이 변할 수 없는 것(가변성)' 구분할 줄 알아야 함 
- 
읽기 전용 프로퍼티는 다른 프로퍼티를 활용하는 사용자 정의 게터로도 정의 가능 var id = "1" var name = "jun" val key get() = "$id:$name" (1) fun main() { println(key) // 1:jun id = 2 println(key) // 2:jun (2) }- 
사용자 정의 게터 
- 
val임에도 불구하고 값이 변경됨
 
- 
- 
코틀린의 프로퍼티는 기본적으로 캡슐화 되어 있고, 사용자 정의 접근자(getter, setter) 가질 수 있음 = 유연함 제공 (아이템 16 참고) 
- 
val을var로 오버라이드 가능interface Element { val active: Boolean } class ActualElement: Element { override var active: Boolean = false } fun main() { with(ActualElement()) { println(active) // false active = true println(active) // true } }
가변 컬렉션과 읽기 전용 컬렉션 구분
- 
읽기 전용 인터페이스: Iterable,Collection,Set,List
- 
읽고 쓸 수 있는 인터페이스: MutableIterable,MutableCollection,MutableSet,MutableList
- 
읽기 전용 컬렉션을 mutable 컬렉션으로 다운캐스팅하면 안됨 (해당 인터페이스의 계약을 위반하고, 추상화를 무시하는 행위. 안전하지 못하고, 예측하지 못한 결과를 초래함) val list = listOf(1, 2, 3) // 하지 말아야 할 행위. 다운캐스팅 if (list is MutableList) { list.add(4) }
- 
복제(copy)를 통해 새로운 mutable 컬렉션을 만드는 list.toMutableList를 활용해야 함
데이터 클래스의 copy
- 
data한정자는copy라는 이름의 메서드를 만들어 줌
- 
String이나Int처음 내부적인 상태를 변경하지 않는 immutable 객체를 많이 사용하는 데에는 이유가 있음- 
변경되지 않으므로(상태가 유지되므로) 코드 이해하기 쉬움 
- 
공유시 충돌 X, 안전하게 병렬 처리 
- 
쉽게 캐싱할 수 있음 
- 
방어적 복사본(defensive copy)을 만들 필요가 없음. 또한 깊은 복사하지 않아도 됨 
- 
실행을 쉽게 예측할 수 있음 
- 
맵, 셋의 키로도 사용 가능 
 
- 
2. 변수의 스코프를 최소화하라
- 
상태를 정의할 떄 변수나 프로퍼티의 스코프를 최소화하라 
- 
프로그램을 추적하고 관리하기 쉬워짐 
- 
다른 개발자에 의해 잘못 사용되는 것을 막음 
- 
코틀린의 if, when, try-catch, Elvis 표현식 활용 가능 
- 
구조분해 선언(destructuring declaration) 활용 가능 
- 
람다에서 변수를 캡쳐하는 것 주의 
3. 최대한 플랫폼 타입을 사용하지 말라
- 
플랫폼 타입(platform type): 다른 프로그래밍 언어에서 전달되어서 nullable인지 아닌지 알 수 없는 타입 - 
String!과 같이 타입 뒤에!기호를 붙혀서 표기
 
- 
- 
자바와 코틀린을 함께 사용할 때, 자바 코드를 직접 조작할 수 있다면 가능한 @Nullable,@NotNull어노테이션을 붙여서 사용- 
JetBrains, JSR-305, ReactiveX, Lombok 등에 관련 어노테이션이 존재함 
 
- 
- 
플랫폼 타입이 전파되는 일은 위험 - 
항상 위험을 내포, 안전한 코드를 원한다면 이런 코드를 제거 
 
- 
public class JavaClass {
    public String getValue() { return null; }
}
fun statedType() {
    val value: String = JavaClass().value // NPE
    println(value.length)
}
fun platformType() {
    val value = JavaClass().value
    println(value.length) // NPE
}4. inferred 타입으로 리턴하지 말라
- 
코틀린의 타입 추론(type inference)은 JVM 세계제어 가장 널리 알려진 코틀린의 특징 
- 
할당 때 inferred 타입은 정확하게 오른쪽에 있는 피 연산자에 맞게 설정됨. 절대 슈퍼클래스 or 인터페이스로 설정되지 않음 open class Animal class Zebra: Animal() fun main() { var animal = Zebra() // (1) animal = Animal() // 오류: Type mismatch }- 
타입을 선언하지 않고 추론을 통해 타입 지정 
 
- 
- 
타입을 확실하게 지정해야 하는 경우 명시적으로 타입을 지정. 
- 
타입은 굉장히 중요한 정보이므로, 숨기지 않는 것이 좋음 
5. 예외를 활용해 코드에 제한을 걸어라
- 
다양한 방법으로 코드에 제한을 걸 수 있음 - 
require블록: 인자를 제한할 수 있음- 
require함수는 조건을 만족하지 못할 때 무조건IllegalArgumentException을 throw 함
 
- 
- 
check블록: 상태와 관련된 동작을 제한할 수 있음- 
이런 경우에 check함수를 하용함- 
어떤 객체가 미리 초기화되어 있어야만 처리를 하게 하고 싶은 함수 
- 
사용자가 로그인 했을 때만 처리하게 하고 싶은 함수 
- 
객체를 사용할 수 있는 시점에 사용하고 싶은 함수 
 
- 
- 
IllegalStateException을 throw함
- 
일반적으로 require블록 뒤에 배치
 
- 
- 
assert블록: 어떤 것이 true인지 확인할 수 있음.assert블록은 테스트 모드에서만 작동.
- 
returnorthrow와 함께 활용하는 Elvis 연산자
 
- 
- 
제한을 걸면 문서를 읽지 않은 개발자도 문제를 확인할 수 있음 
- 
코드가 어느 정도 자체적으로 검사됨 
- 
스마트 캐스트 기능 활용 
6. 사용자 정의 오류보다는 표준 오류를 사용하라
- 
require,check,assert함수를 사용하면 대부분의 코틀린 오류를 처리할 수 있음
- 
최대한 표준 라이브러리의 오류를 사용하는 것이 좋음 - 
많은 개발자가 알고 있으므로 이를 재사용 
 
- 
- 
나타내기 위한 적절한 오류가 없을 경우 사용자 정의 오류 사용 - 
but, 설정보다는 관례 
 
- 
- 
"규칙 60. 표준 예외를 사용하라" - 이펙티브 자바 2판 
7. 결과 부족이 발생할 경우 null과 Failer를 사용하라
코드 설계
재사용성
8. knowledge를 반복하여 사용하지 말라
Appendix A: test
Glossary
- mud
- 
wet, cold dirt 
- rain
- 
water falling from the sky