- 코틀린의 안정성(safety)입니다. 코틀린은 다양한 설계 지원을 통해서 애플리케이션의 잠재적인 오류를 줄여 줍니다.
- 크래시(crash)가 적으면 사용자와 개발자 모두 에게 좋고, 상당한 비즈니스 가치를 제공합니다.
- 코틀린은 정말 안전한 언어지만, 정말로 안전 하게 사용하려면 개발자가 뒷받침을 해야 합니다.
- 코틀린이 안전을 위해 제공하는 기능들을 알아보고, 이를 올바르게 사용하는 방법을 알아볼 것입니 다. ‘오류가 덜 발생하는 코드를 만드는 것’입니다.
- 모듈은 클래스, 객체, 함수, 타입 별칭(type alias), 톱레벨(top-level) 프로퍼티 등 다양한 요소로 구성됩니다.
- 가변성(mutability)이 있으면, 코드의 실행을 추론하기 어려워집니다.
- 멀티스레드 프로그램일 때는 적절한 동기화가 필요합니다.
- 변경 가능한 부분에 의한 일관성(consistency) 문제, 복잡성(complexity) 증가와 관련된 문제에 익숙할 것입니다.
- 코틀린의 코루틴을 활용하면 하지만 문제가 사라지는 것은 아닙니다.
- 동기화를 잘 구현하는 것은 굉장히 어려운 일입니다. 또한 변할수 있는 지점이 많다면 훨씬 더 어려워집니다. 따라서 변할 수 있는 지점은 줄일수록 좋습니다.
- 가변성은 시스템의 상태를 나타내기 위한 중요한 방법입니다. 하지만 변경이 일어나야 하는 부분을 신중하고 확실하게 결정 하고 사용하기 바랍니다.
코틀린은 가변성을 제한할 수 있게 설계되어 있습니다. 그래서 immutable(불 변) 객체 2 를 만들거나, 프로퍼티를 변경할 수 없게 막는 것이 굉장히 쉽습니다.
- 읽기 전용 프로퍼티( val )
- 값(value)처럼 동작하며, 일반적인 방법으로는 값이 변하지 않습니다(읽고 쓸 수 있는 프로퍼티는 var 로 만듭니다).
- 읽기 전용 프로퍼티가 mutable 객체를 담고 있다면, 내부적으로 변할수 있습니다.
- 읽기 전용 프로퍼티는 다른 프로퍼티를 활용하는 사용자 정의 게터로도 정의할 수 있습니다. 이렇게 var 프로퍼티를 사용하는 val 프로퍼티는 var 프로퍼 티가 변할 때 변할 수 있습니다.
- 읽기 전용 프로퍼티는 다른 프로퍼티를 활용하는 사용자 정의 게터로도 정의할 수 있습니다. 이렇게 var 프로퍼티를 사용하는 val 프로퍼티는 var 프로퍼 티가 변할 때 변할 수 있습니다.
- val 은 읽기 전용 프로퍼티지만, 변경할 수 없음(불변, immutable)을 의미하는 것은 아니라는 것을 기억하기 바랍니다. 또한 이는 게터 또는 델리게이트 (delegate)로 정의할 수 있습니다.
- 가변 컬렉션과 읽기 전용 컬렉션 구분하기
- Iterable, Collection , Set , List 인터페이스는 읽기 전용
- MutableIterable , MutableCollection , MutableSet , MutableList 인터페이스는 읽고 쓸 수 있는 컬렉션
- mutable이 붙은 인터페이스는 대응되는 읽기 전용 인터페 이스를 상속 받아서, 변경을 위한 메서드를 추가한 것
- 이러한 컬렉션을 진짜로 불변(immutable)하게 만들지 않고, 읽기 전용으로 설계한 것은 굉장히 중요한 부분입니다. 이로 인해서 더 많은 자유를 얻을 수 있습니다. 내부적으로 인터페이스를 사용하고 있으므로, 실제 컬렉션을 리턴할수 있습니다. 따라서 플랫폼 고유의 컬렉션을 사용할 수 있습니다.
- 컬렉션 다운캐스팅은 이러한 계약을 위반하고, 추상화를 무시하는 행위입니 다.
- 코틀린에서 읽기 전용 컬렉션을 mutable 컬렉션으로 다운캐스팅하면 안 됩니다. 읽기 전용에서 mutable로 변경해야 한다면, 복제(copy)를 통해서 새로운 mutable 컬렉션을 만드는 list.toMutableList 를 활용해야 합니다.
- 데이터 클래스의 copy
- 한 번 정의된 상태가 유지되므로, 코드를 이해하기 쉽습니다.
- immutable 객체는 공유했을 때도 충돌이 따로 이루어지지 않으므로, 병렬 처리를 안전하게 할 수 있습니다.
- immutable 객체에 대한 참조는 변경되지 않으므로, 쉽게 캐시할 수 있습 니다.
- immutable 객체는 방어적 복사본(defensive copy)을 만들 필요가 없습니다. 또한 객체를 복사할 때 깊은 복사를 따로 하지 않아도 됩니다.
- immutable 객체는 다른 객체(mutable 또는 immutable 객체)를 만들 때 활용하기 좋습니다. 또한 immutable 객체는 실행을 더 쉽게 예측할 수 있습 니다.
- immutable 객체는 ‘세트(set)’ 또는 ‘맵(map)의 키’로 사용할 수 있습니다. 참고로 mutable 객체는 이러한 것으로 사용할 수 없습니다.
- 모든 프로퍼티를 대상으로 이런 함수를 하나하나 만드는 것은 굉장히 귀찮은 일입니다. 그럴 때는 data 한정자를 사용하면 됩니다. data 한정자는 copy 라는 이름의 메서드를 만들어 줍니다. copy 메서드를 활용하면, 모든 기본 생성자 프로퍼티가 같은 새로운 객체를 만들어 낼 수 있습니다.
- 첫 번째 코드는 구체 적인 리스트 구현 내부에 변경 가능 지점이 있습니다. 멀티스레드 처리가 이루 어질 경우, 내부적으로 적절한 동기화가 되어 있는지 확실하게 알 수 없으므로 위험합니다.
- 두 번째 코드는 프로퍼티 자체가 변경 가능 지점입니다. 따라서 멀티스레드 처리의 안정성이 더 좋다고 할 수 있습니다
- 상태를 변경할 수 있는 불필요한 방법은 만들지 않아야 합니다. 상태를 변경하는 모든 방법은 코드를 이해하고 유지해야 하므로 비용이 발생합니다. 따라서 가변성을 제한하는 것이 좋습니다.
- 리턴되는 mutable 객체를 복제하는 것입 니다. 이를 방어적 복제(defensive copying)라고 부릅니다. 이때 data 한정자로 만들어지는 copy 메서드를 활용하면 좋습니다.
- 컬렉션은 객체를 읽기 전용 슈퍼타입으로 업캐스트하여 가변성을 제한할 수도 있습니다.
- var 보다는 val 을 사용하는 것이 좋습니다.
- mutable 프로퍼티보다는 immutable 프로퍼티를 사용하는 것이 좋습니다.
- mutable 객체와 클래스보다는 immutable 객체와 클래스를 사용하는 것이 좋습니다.
- 변경이 필요한 대상을 만들어야 한다면, immutable 데이터 클래스로 만들고 copy 를 활용하는 것이 좋습니다.
- 컬렉션에 상태를 저장해야 한다면, mutable 컬렉션보다는 읽기 전용 컬렉션을 사용하는 것이 좋습니다.
- 변이 지점을 적절하게 설계하고, 불필요한 변이 지점은 만들지 않는 것이 좋습니다.
- mutable 객체를 외부에 노출하지 않는 것이 좋습니다.