Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

디지안의 개발일지

[TIL] Effective Kotlin을 읽어보자 - 2 장 본문

Kotlin

[TIL] Effective Kotlin을 읽어보자 - 2 장

안덕기 2022. 3. 7. 11:06

이 글은 이펙티브 코틀린 2장을 보면서 배운 것에 대해서 요약합니다. 코드 예제, 자세한 설명은 생략되어 있기 때문에 이펙티브 코틀린을 구입해서 보시는 것을 적극적으로 추천합니다.

 

코틀린에서 코드의 가독성이 좋다는 것은 코드가 간결하다는 것을 의미하는 것이 아니다. 사람이 이해할 수 있는 간결한 코드를 작성하는 것을 의미한다. 2장에서는 코틀린에서 프로그래머가 숨기거나 강조할 수 있는 기능에 대해 어떻게 활용하는지 소개한다.

 

item 11 - 가독성을 목표로 설계하라.

코드는 작성할 때보다 읽을 때 더 많은 시간을 쓴다. 그렇기 때문에 다음과 같은 특징들을 고려해야한다.

  • 인식 부하 감소
    • 사람이 쉽게 이해할 수 있는 문법으로 작성하는 것이 좋다.
    • 코틀린이 제공하는 간결한 문법보다 비 숙련자도 쉽게 이해할 수 있는 코드로 작성하는 것이 더 좋을 수도 있다.
    • 우리의 뇌는 짧은 코드를 빠르게 읽을 수 있지만 익숙한 코드를 더 빠르게 읽을 수 있다.
  • 극단적이 되지 않기
    • 코틀린에서 제공하는 함수들이 간결하게 해주지만 초보 코틀린 개발자가 이해하기 어려울 수 있다.
    • 이 때문에 무조건 코틀린에서 제공되는 함수를 사용하지 않을 수는 없다.
    • 항상 trade off 이기 때문에 간결한 함수를 쓸지 가독성 및 디버깅의 편리성을 찾을지는 고민해야한다.
  • 컨벤션
    • 코드에 대한 인식을 위해서 일반적인 관용을 따라야 한다.
    • 연산자는 의미에 맞게 사용해야 한다.
    • 람다를 마지막 아규먼트로 사용한다.
    • 등등..

 

item 12 - 연산자 오버로드를 할 때는 의미에 맞게 사용하라 .

코틀린에서 제공하는 연산자 오버로드의 함수명에 알맞게 코드를 정의해야한다.

  • 분명하지 않은 경우
    • 관례에 해당하지 않는 경우를 말한다.
    • 연산자 로버로드를 하지 말고 infixtop-level function으로 정의하는 것이 좋을 수 있다.
  • 규칙을 무시해도 되는 경우
    • DSL를 만들 때는 어차피 해당 도메인에 맞춰 작성해야되기 때문에 이를 무시해도 된다.
  • 정리
    • 연산자 오버로딩은 그 이름에 맞게 사용해야한다. 의미가 맞지 않는데 비슷한 형태로 사용하고 싶으면 infix 또는 top-level 함수로 사용하자.

 

 

item 13 - Unit?을 리턴하지 말라.

Unit?을 리턴하는 경우 코드를 읽기가 어렵다. 그러므로 대신 Boolean을 리턴하도록 하자.

 

item 14 - 변수 타입이 명확하지 않은 경우 확실하게 지정하라.

코틀린은 굉장한 수준의 타입 추론을 제공해준다. 하지만 함수명을 보고 함수의 정의를 보지 않고는 타입을 추측할 수 없다면 코드를 읽는 시간을 줄여주기 위해서 타입을 지정해주는 것이 좋다.

 

item 15 - 리시버를 명시적으로 참조하라

  • 여러 개의 리시버
    • 스코프 내부에 둘 이상의 리시버가 있으면 코드를 오해할 수 있다.
    • 외부에 있는 리시버를 사용할 때는 레이블을 활용하면 된다.
  • DSL 마커
    • 기본적으로 모든 스코프에서 외부 스코프에 있는 리시버 메소드를 사용할 수 있다.
    • 외부 리시버를 사용하는 것을 막으려면 @DslMarker라는 메타 애노테이션을 활용하면 된다.
    • @DslMarker를 통해 외부 리시버를 자동으로 사용하는 것을 막으면 레이블을 통해서 외부 리시버를 사용할 수도 있다.
  • 정리
    • 짧게 적을 수 있다는 이유로 리시버를 제거하지 말자.
    • DSL에서 외부 스코프에 있는 리시버를 명시적으로 작성하게 하려면 @DslMarker 애노테이션을 활용하자.

item 16 - 프로퍼티는 동작이 아니라 상태를 나타내야 한다.

  • 코틀린 프로퍼티의 특징
    • 사용자 정의 getter와 setter를 가질 수 있다.
    • 자유롭게 정의 내릴 수 있다.
  • 그로 인한 생기는 문제
    • 프로퍼티를 알고리즘 동작을 나타내게 함
    • 알고리즘은 계산량이 많을 수도 있는데 프로퍼티는 계산량이 많다고 예상하지 않음
    • 알고리즘 동작이 많이 들어가는 로직은 프로퍼티가 아니라 함수로 구현해야됨
  • 언제 함수로 사용할 것인가?
    • 프로퍼티를 함수로 정의할 때 접두사로 get 또는 set를 붙일 것인가를 물어보면 된다.
    • 복잡도 O(1)보다 큰 경우
    • 비즈니스 로직을 포함하는 경우
    • 반환 값이 계속 변하는 경우
    • 게터에서 프로퍼티의 상태 변경이 일어나는 경우
  • 왜 그렇게 해야되는데?
    • 일반적으로 사람들은 프로퍼티는 상태 집합, 함수는 행동을 한다고 생각하기 때문에

 

item 17 - 이름 있는 아규먼트를 사용하라

파라미터로 넣는 값에 대해 오해가 생길 수 있다. 그 때는 named parameter를 활용하면 된다.

  • 이름 있는 아규먼트는 언제 사용해야 할까?
    • 장점
      • 파라미터 이름으로 값이 무엇인지 명확히 알 수 있다.
      • 파라미터 입력 순서가 상관이 없다.
    • 디폴트 아규먼트
    • 같은 타입의 파라미터가 많은 경우
    • 함수 타입의 파라미터가 있는 경우(마지막 파라미터는 제외)
  • 정리
    • 코드의 안정성, 가독성을 위해서 사용하자.

 

item 18 - 코딩 컨벤션을 지켜라

코딩 컨벤션을 지키면 여러가지 장점이 있는데 결국 코드를 읽기 쉬워진다. 이건 도구를 통해서 지키면 된다.