Item 2 : 스코프가 좁을 수록 코드 분석과 관리가 쉽다 _변수의 스코프를 최소화하라
코드 분석할 때 스코프 범위가 좁을수록 추적과 관리가 쉬워진다
- 프로퍼티보다 지역변수 사용하기
- 스코프는 최대한 좁게 사용하기
- 반복문 내부에서만 사용되는 변수는 반복문 내부에 작성하기
- 여러 프로퍼티를 한번에 설정할 경우 구조분해 선언 활용하기
반복문 내부에서만 사용되는 변수를 반복문 내부에 작성한 예시
for((i, user) in users.withIndex()) {
print("User at $i is $user")
}
Item 3 : 플랫폼 타입은 위험하다 _최대한 플랫폼 타입을 사용하지 말라
플랫폼 타입의 위험성
플랫폼 타입 : 다른 언어에서 넘어온 타입
코틀린은 null-safety 매커니즘이 있어 타입이 null인지 아닌지 알 수 있지만,
플랫폼 타입의 경우 null 인지 아닌지 확신할 수 없다. -> 타입 검사기에서 오류가 검출되지 않음
때문에 null 가능성을 열어두고 코드를 작성해야 한다
- 플랫폼 타입은 위험하니 가급적 제거한다
- 자바 코드에 접근할 수 있다면 nullable 여부를 지정하는 어노테이션을 활용하자
Item 4 : 타입을 명확하게 하자 _inferred 타입으로 리턴하지 말자
타입추론의 위험성
inferred 타입은 오른쪽에 있는 피연사자에 의존하여 설정된다
open class Animal
class Zebra: Animal()
fun main() {
var animal = Zebra()
animal = Animal() // Error : type mismatch
}
인터페이스를 만들 때 리턴타입의 경우 inferred 타입 대신 명시적으로 지정해 주는 것이 좋다
외부에서 확인할 때 리턴타입이 없다면 어려움이 생길 수도 있기 때문이다.
interface CarFactory {
fun produce(): Car
}
val DEFAULT_CAR: Car = Ferari()
interface CarFactory {
fun produce() = DEFAULT_CAR
}
// 타입을 명시하지 않음으로 인해 CarFactory는 Ferari만 생성할 수 있게됨
Item 5: 예외를 활용해 코드에 제한을 걸어라
코틀린에서 코드 동작에 제한을 걸 때 예외를 활용할 수 있는 방법
- require 블록
- check 블록
- assert 함수
- Elvis 연산자
-> 문제가 발생할 경우 빠르게 수정할 수 있고 스마트 캐스트 기능을 활용할 수 있다는 장점
require 블록
argument에 제한을 거는 코드 : 유효성 검사, notnull 등
- 조건을 만족하지 못할 경우 IllegalArgumentException 발생
- 코드 제일 상단에 배치
Check 블록
상태에 관련된 제한을 거는 코드 : 초기화 여부, 로그인 상태 등
- 지정된 예측을 만족하지 못할 경우 IllegalArgumentException 발생
- require 블록 뒤에 배치
Assert 계열 함수
테스트코드 작성 시 사용
- 예외를 throw 하지 않음
- 모든 상황에 대해 테스트 가능
Elvis 연산자
nullablility를 염두해두고 오류를 회피할 수 있음