이펙티브 코틀린 1장 안정성

Rm·2022년 2월 24일
0

이펙티브 코틀린

목록 보기
1/8
post-thumbnail

현직자 멘토링 F-Lab에서 멘티 및 수료생을 대상으로 이펙티브 코틀린 온/오프라인 스터디를 참여하였습니다.

1주마다 각자 1장씩을 맡아서 브리핑하고 아젠다를 제시하면 그에 따라 다같이 토론 형태로 스터디를 진행합니다.

먼저 1장에서 다루는 안정성에 대한 아젠다와 개인적으로 느낀점에 대해서 서술하고자 합니다.

Item 정리

Item1 가변성을 제한하라

  • 코틀린은 모듈로 프로그램을 설계한다.
  • 모듈은 클래스 / 객체 / 함수 / 타입 별칭 / 톱레벨 프로퍼티 등 다양한 요소로 구성된다.
  • var를 사용하거나, mutable 객체를 사용하면 상태(state)를 가질 수 있다.

상태를 적절하게 관리하는 것이 힘든 이유

  1. 프로그램을 이해하고 디버그하기 힘들어진다.
  2. 가변성(mutability)이 있으면, 코드의 실행을 추론하기 어려워진다.
  3. 멀티스레드 프로그램일 때는 적절한 동기화가 필요하다.
  4. 모든 상태를 테스트해야 하므로 테스트하기 어렵다.
  5. 상태 변경이 일어날 때, 이러한 변경을 다른 부분에 알려야 하는 경우가 있다.(ex, 정렬되어 있는 리스트에 가변 요소를 추가 -> 변경이 일어날 때마다 리스트 전체를 다시 정렬)

멀티스레드를 활용해서 프로퍼티를 수정할 때, 충돌에 의해 일부 연산이 이루어지지 않는 경우

ps) 코틀린의 코루틴을 활용하면, 더 적은 스레드가 관여되므로 충돌과 관련 된 문제가 줄어듭니다.

가변성은 생각보다 단점이 많아서 이를 완전하게 제한하는 프로그래밍 언어도 있다 => 순수 함수형 언어(하스켈)

하지만 이러한 프로그래밍 언어는 가변성에 너무 많은 제한이 걸려서 프로그램을 작성하기가 굉장히 어렵다.

가변성은 시스템의 상태를 나타내기 위한 중요한 방법이다.

코틀린에서 가변성 제한하기

  • 코틀린은 가변성을 제한할 수 있게 설계되어 있다. 따라서 immutable 객체를 만들거나, 프로퍼티를 변경할 수 없게 막는 것이 굉장히 쉽다.
  1. 읽기 전용 프로퍼티(val)
  2. 가변 컬렉션과 읽기 전용 컬렉션 구분하기
  3. 데이터 클래스의 copy

읽기 전용 프로퍼티(val)

  • val로 선언되는 프로퍼티는 마치 값(value)처럼 동작하며, 일반적인 방법으로는 값이 변하지 않습니다.(읽고 쓸 수 있는 프로퍼티는 var로 만든다.)

코틀린의 프로퍼티는 기본적으로 캡슐화되어 있고, 추가적으로 사용자 정의 접근자(getter와 setter를 가질 수 있습니다.)
추가적으로 var은 게터와 세터를 모두 제공하지만, val은 변경이 불가능하므로 게터만 제공합니다. 그래서 val을 var로 오버라이드할 수 있습니다.

interface Element {
    var active: Boolean
}

class ActualElement: Element {
    override var active: Boolean = false
}

정리 : 읽기 전용 프로퍼티 val의 값은 변경될 수 있기는 하지만, 프로퍼티 레퍼런스 자체를 변경할 수는 없으므로 동기화 문제 등을 줄일 수 있습니다. 그래서 일반적으로 var보다 val을 많이 사용한다.

val은 읽기 전용 프로퍼티지만, 변경할 수 없음(불변)을 의미하는 것은 아니다. 또한, 게터 또는 델리게이트로 정의할 수 있다.
만약, 완전히 변경할 필요가 없다면, final 프로퍼티를 사용하는 것이 좋다.
val은 정의 옆에 상태가 바로 적히므로, 코드의 실행을 예측하는 것이 훨씬 간단하다. 또한, 스마트 캐스트 등의 추가적인 기능을 활용할 수 있습니다.

  • 스마트캐스트 : 코틀린 컴파일러가 똑똑하게 자동으로 변환해주는 기능이다.

가변 컬렉션과 읽기 전용 컬렉션 구분하기

읽기 전용 컬렉션 : Iterable, Collection, Set, List 인터페이스
읽고 쓸 수 있는 컬렉션 : MutableIterable, MutableCollection, MutableSet, MutableList

Immutable 객체를 사용하면 좋은 점

  • 한 번 정의된 상태가 유지되므로, 코드를 이해하기 쉽다.
  • Immutable 객체는 공유했을 때도 충돌이 따로 이루어지지 않으므로, 병렬 처리를 안전하게 할 수 있다.
  • Immutable 객체에 대한 참조는 변경되지 않으므로, 쉽게 캐시할 수 있다.
  • Immutable 객체는 방어적 복사본(defensive copy)을 만들 필요가 없다.
  • Immutable 객체는 다른 객체를 만들 때 활용하기 좋다.
  • Immutable 객체는 세트 또는 맵의 키로 사용할 수 있다.

결론 : immutable 객체는 자신의 일부를 수정한 새로운 객체를 만들어야 한다.

하지만, 모든 프로퍼티를 대상으로 함수를 하나하나 만드는 것은 굉장히 귀찮은 일이기 때문에 data 한정자를 사용해야 한다.

Item2 변수의 스코프를 최소화하라

요약 : var 보다는 val을 사용하는 것이 좋다. 람다에서 변수를 캡처한다는 것, 간단한 규칙만 지켜 주면, 발생할 수 있는 여러 문제를 차단 할 수 있다.

Item3 최대한 플랫폼 타입을 사용하지 말라

  • 코틀린은 자바 등의 다른 프로그래밍 언어에서 넘어온 타입들을 특수하게 다루는데 이를 플랫폼 타입이라고 부른다.

요약 : 플랫폼 타입을 사용하는 코드는 해당 부분만 위험할 뿐 아니라, 이를 활용하는 곳까지 영향을 줄 수 있는 위험한 코드이다.
또한, 연결되어 있는 자바 생성자, 메서드, 필드에 nullable 여부를 지정하는 어노테이션을 활용하는 것도 좋다.

Item4 inferred 타입으로 리턴하지 말라

요약 : 타입을 확실하게 지정해야 하는 경우 명시적으로 타입을 지정해야 한다는 원칙만 갖고 있으면 된다.
또한, 안전을 위해서 외부 API를 만들 때는 반드시 타입을 지정하고, 이렇게 지정한 타입을 특별한 이유와 확실한 확인 없이는 제거하지 말아야 한다.

Item5 예외를 활용해 코드에 제한을 걸어라

요약
require 블록 : 아규먼트와 관련된 예측을 정의할 때 사용하는 범용적인 방법
check 블록 : 상태와 관련된 예측을 정의할 때 사용하는 범용적인 방법
assert 블록 : 테스트 모드에서 테스트를 할 때 사용하는 범용적인 방법
return과 throw와 함께 Elvis 연산자 사용하기

Item6 사용자 정의 오류보다는 표준 오류를 사용하라

Item7 결과 부족이 발생할 경우 null과 Failure를 사용하라

Item8 적절하게 null을 처리하라

Item9 use를 사용하여 리소스를 닫아라

Item10 단위 테스트를 만들어라

주요 아젠다

1. 사용자 정의 오류와 표준 오류

두 오류를 사용하게 되는 상황은 어떤 때인가?

엔지니어링이 강한 회사(또는 스타트업, 신규 사업)은 공격적 코딩이 주가 되어 표준 오류를 사용하게 된다. 서비스 회사의 경우 방어적 코딩을 중시해 사용자 정의 오류를 사용하게 된다.

예외 처리의 경우 되도록 처리가 되지 않는 상황을 만드는 게 좋다. 이유는 top down 구조에서 C언어의 goto 예외 처리와 관련이 있다.

2. 단위 테스트

단위 테스트를 어떻게 사용해야 할까?

단위 테스트는 너무 광범위한 내용을 다루므로 현재는 넘어가는 걸로 결정함 대신 단위 테스트를 작성할 때는 "무엇"을 테스트 해야 하는지 명확하게 인식하고 작성해야 한다. 안 그러면 작성 코드량만 불어나며 비효율적인 작업이 된다.

3. immutable collection

불변 객체에 값을 더할 때 새로 객체를 생성하며 성능 상 불이익이 발생하는가?

copy 대신 플러스로 값을 더해 새로운 객체를 만들 면 불이익은 발생하지 않는다.

4. immutable

객체지향적인 언어는 상태와 행위를 포함한다. 그런데 불변 객체는 상태가 없다. 그렇다면 이 상황에서 불변 객체는 과연 객체지향적인 것인가?

해당 논점은 각자 좀 더 생각해보기로 했음.

5. null의 해석

개발자마다 null의 의미 부여가 달라 생기는 문제점?

null을 아예 안 쓰는 방법 또는 null을 잘 활용하는 방법을 고려할 수 있다. null을 사용하지 않으면 안전하지만 그만큼 코드가 불어나 가독성과 작성 시간이 길어질 수 있다. null을 활용하면 편하긴 하지만 그만큼 남용될 가능성이 있다.

느낀점

F-Lab 멘토링을 받으면서 immutable, mutable에 대해서 인지는 하고 있었지만 실제로 개발할 때 크게 신경쓰지 못한 포인트였었다. 하지만 1장에서부터 Immutable 객체를 사용하면 좋은 점들이 대해서 안내하여 확실하게 인지하는 계기가 되었다. 그 밖에도 코틀린에 한정된 것이 아니라 전체적인 프로그래밍 언어 베이스로 개발을 진행할 때 기본적으로 지키면 좋은 것들에 대한 안내가 나와있다. 잠깐 코루틴에 대한 언급이 있어서 중요한 것 같아 찾아봤더니 동시성 관련 내용이였고 관련해서 추후 더 상세하게 학습할 예정이다.

profile
우당탕 개발자 성장기

0개의 댓글