-
[🏝 이펙티브 코틀린] 1 안정성Book/Effective Kotlin 2023. 6. 6. 00:04반응형
⚽️ item 1 가변성을 제한하라
- var 보다는 val 사용 하기
- mutable 보다는 immutable 사용 (property, 객체, class 등)
- 데이터 클래스를 변경한다면 immutable 로 만들고 copy 하자
- mutable 객체를 외부에 노출하지 말자
1. 읽기 전용 속성 val
- val 을 var로 오버라이드 할 수 있다.
- 읽기 전용 ≠ 가변성
- val은 읽기 전용 속성이지만, 변경할 수 없음을 의미하는 것은 아니다.
- mutable 객체를 담고 있다면, 내부적으로 변할 수 있음
2. 가변 컬렉션과 읽기 전용 컬렉션 구분하기
- 읽고 쓸 수 있는 컬렉션 ≠ 읽기 전용 컬렉션
- 읽기 전용 컬렉션 ≠ 가변성
- 다운캐스팅 X
- 읽기 전용 컬렉션을 mutable 컬렉션으로 다운캐스팅 하지말아라
- 읽기 전용 > mutable 하려면 copy를 이용 (list.toMutableList())
3. 데이터 클래스의 copy
객체를 변경했기 때문에 해시테이블 내부에서 찾을 수 없다.
⚽️ item 2 변수의 스코프를 최소화하라
- 프로퍼티보다는 지역변수 사용하는 것이 좋다.
- 최대한 좁은 스코프를 갖게 변수 사용
- ex) 반복문 내부에서만 변수가 사용되면, 변수를 반복문 내부에 작성
- 람다에서 변수 캡쳐링 주의
⚽️ item3 최대한 플랫폼 타입을 사용하지 말라
- 플랫폼 타입 이란?
- 코틀린은 자바 등의 다른 프로그래밍 언어에서 넘어온 타입들을 플랫폼 타입이라고 부른다.
- 즉, 다른 프로그래밍 언어에서 와서 nullable 여부를 알 수 없는 타입
- 플랫폼 타입은 최대한 빨리 제거해야한다.
⚽️ item4 inferred 타입으로 리턴하지 말라
- 코틀린의 특징 중 하나인 코틀린의 타입 추론(type inference)
- 자료형을 명시하지 않아도 할당된 값으로 타입을 추론한다.
- 할당 할 때 추론 타입은 정확하게 오른쪽에 있는 피연산자에 맞게 설정된다.
- 타입을 확실하게 지정해야 하는 경우에는 명시적으로 타입을 지정해야한다.
- 추론 타입은 제한이 많아지거나 예측하지 못한 결과를 낼 수 있다.!
⚽️ item5 예외를 활용해 코드에 제한을 걸어라
- require : 아규먼트 제한
- 예시
- 숫자가 양의 정수여야 할 때
- 비어 있지 않은 조표 목록이 필요할 때
- 이메일 주소 값이 입력 되었는지, 형식이 올바른지 확인 할 때
- 조건을 만족하지 못하면 무조건 IllegalArgument Exception
- 예시
- check : 상태와 관련된 동작 제한
- 예시
- 객체가 미리 초기화되어 있어야만 처리하게 하고 싶은 함수
- 로그인을 했을 때만 처리하고 싶을 때
- 객체를 사용할 수 있는 시점에 사용하고 싶은 함수
- 조건을 만족하지 못하면 무조건 IllegalState Exception
- 예시
- assert : 어떤 것이 true 인지 확인, 테스트 모드에서만 작동
- 예시
- 함수가 10개의 요소를 리턴하는가?
- 예외를 throw 하지 않음
- 코드를 안정적으로 만들고 싶을 때 양념처럼 사용
- 예시
- Elvis 연산자 (return 또는 thorw와 함께 활용하는)
val email:String = person.email ?: return
- nullable 을 확인할 때 많이 사용되는 관용적인 방법
장점
- 문서를 읽지 않은 개발자도 문제 확인 가능
- 문제가 있을 경우, 예상하지 못한 동작을 하지 않고! 예외를 throw > 문제를 놓치지 않을 수 있고, 코드를 더 안정적으로 지킬 수 있음
- 코드 자체 검사, 단위 테스트를 줄인다.
- 스마트 캐스트 기능
⚽️ item 6 사용자 정의 오류보다는 표준 오류를 사용하라
require, check, assert 함수를 사용하면, 대부분의 코틀린 오류를 처리할 수 있다.
가능하다면 직접 오류를 정의하는 것보다 최대한 표준 라이브러리의 오류를 사용하는 것이 좋다.
⚽️ item 7 결과 부족이 발생할 경우 null과 Failure를 사용하라
함수가 원하는 결과를 만들어 낼 수 없는 경우 예시 3가지
- 서버로부터 데이터를 읽어 들이여 했는데, 인터넨 연결 문제로 읽어들이지 못한 경우
- 조건에 맞는 첫번 째 요소를 찾으려 했는데, 조건에 맞는 요소가 없는 경우
- 텍스트를 파싱해서 객체를 만들려고 했는데, 텍스트의 형식이 맞지 않는 경우
이러한 상황들을 처리하는 메커니즘 2가지
- 충분히 예측할 수 있는 범위의 오류는 Null 과 Failure를 사용
- 예측하기 어려운 예외적인 범위의 오류는 throw 처리
⚽️ item 8 적적하게 null을 처리하라
null is lack of value ( 값이 부족하다. )
1. ?., 스마트캐스팅, Elvis 등으로 null 을 안전하게 처리하기
- safe call 안전 호출
- printer?.print()
- smart casting 스마트 캐스팅
- if (printer != null) printer.print() if (!name.isNullOrBlank()){ }
💡 방어적 프로그래밍과 공격적 프로그래밍
방어적 프로그래밍 - 모든 가능성을 올바른 방식으로 처리하는 것 (ex: null 일 때는 출력하지 않기 등)
공격적 프로그래밍 - 예상하지 못한 상황이 발생했을 때, 개발자에게 문제를 알려 수정하게 하는 것 (ex: item5)
2. 오류를 throw 한다.
위의 코드는 printer가 Null일 때 개발자에게 알리지 못해서 개발자가 오류를 찾기 어렵게 만든다.
오류를 강제로 발생시켜주는 것이 좋다.
💡 throw, !!, requireNotNull, checkNotNull 등을 활용
3. 함수 또는 프로퍼티를 리팩토링 해서 nullable 타입이 나오지 않게 바꾼다.
not null assertion(!!)
nullable 을 처리하는 가장 간단한 방법 > not null assertion(!!)
하지만, 이는 좋은 방법이 아니다. 제네릭 예외(어떤 설명도 없는)이 발생한다.
!! 은 타입은 nullable 인데, null 이 나오지 않는 다는 것이 확실한 상황에서 사용
일반적으로 !! 연산 사용을 피해야한다. !! 연산자가 의미 있는 경우는 굉장히 드물다. 미래에 코드가 어떻게 변화할지 모른다!
의미없는 nullability 피하기
null 은 중요한 메세지를 전달하는데 사용한다.
의미가 없을 때는 Null을 사용하지 마라
⚽️ item 9 use 를 사용하여 리소스를 닫아라.
더 이상 필요하지 않을 때 close 메서드를 사용해 명시적으로 닫아야하는 리소스가 있다.
전통적으로 : 이러한 리소스는 try-finally 블록을 사용해 처리한다. (finally 에서 close) > 하지만 close 하면서 예외가 발생할 수도 있다. 또한 try 블록과 finally 블록 내부에서 오류가 발생하면 둘중 하나만 전파된다.
use : 객체를 사용한 후 close 를 자동으로 호출해서 닫는다.
useLines : 파일을 한 줄 씩 읽어 들임
⚽️ item10 단위 테스트를 만들어라
반응형'Book > Effective Kotlin' 카테고리의 다른 글
[🏝 이펙티브 코틀린] 4 추상화 (0) 2023.07.04 [🏝 이펙티브 코틀린] 3 재사용성 (0) 2023.06.12 [🏝 이펙티브 코틀린] 2 가독성 (0) 2023.06.06