Study/이펙티브코틀린

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

주지민 2022. 3. 22. 02:07
반응형

본 포스트는 사내 스터디를 진행하며 정리한 포스트입니다

https://book.interpark.com/product/BookDisplay.do?_method=Detail&sc.shopNo=0000400000&dispNo=&sc.prdNo=354452929&sc.saNo=002001023&bkid1=category&bkid2=ct028023&bkid3=c1&bkid4=001

 

싸니까 믿으니까 인터파크도서

실제 개발 사례를 통해 알려주는 코드 품질 향상 전략 이 책은 더 나은 코틀린 개발자가 될 수 있도록 도움을 주는 안내서입니다. 코틀린에 어떤 기능이 있는지, 어떤 표준 라이브러리가 있는지

book.interpark.com


1. 코틀린의 프로퍼티

  • 코틀린의 프로퍼티와 자바의 필드는 비슷해보이지만 완전히 다른 개념이다
  • var로 정의되는 프로퍼티
    • 기본적으로 사용자 정의 Setter와 Getter를 가질 수 있다
    • field: 프로퍼티의 데이터를 저장해두는 백킹 필드 ( 따로 만들지 않아도 디폴트로 생성됨 )
    • 파생 프로퍼티라고 불린다
var name: String? = null
    get() = field?.toUpperCase()
    set(value) {
        if (!value.isNullOrBlank()) {
            field = value
        }
    }
  • val로 정의되는 프로퍼티
    • 읽기전용이기 때문에 field가 생성되지 않는다
  • 이처럼 코틀린의 모든 프로퍼티는 디폴트로 캡슐화되어있다
  • 프로퍼티는 필드가 필요없고 개념적으로는 접근자(val는 getter, var는 setter, getter)를 나타낸다
  • 따라서 인터페이스에도 정의가능 ( val로 정의하여 getter를 구현해야함 )
interface Person {
    val name: String
}

class A : Person {
    override val name: String
        get() = TODO("Not yet implemented")
}

 

 

2. 유의사항

  • 앞서 말씀드린 내용처럼 프로퍼티를 함수 대신하여 사용할 수도 있지만, 그렇다고 완전히 대체해서 사용하는 것은 좋지 않다
  • 안좋은 예
val Tree<Int>.sum: Int {
    get() = when(this) {
        is Leaf -> value
        is Node -> left.sum + right.sum
    }
}
  • Tree.sum의 getter로 모든 요소를 돌며 합을 구하는 알고리즘을 정의
    • 일단 관습적으로 getter에 어떠한 알고리즘이 있을 것이라고 예상하지 않는다
    • 따라서 이러한 처리는 프로퍼티가 아닌 함수로 처리해야한다
  • 원칙적으로 프로퍼티는 상태를 나타내거나 설정하기 위한 목적으로만 사용하는 것이 좋고, 다른 로직 등을 포함하지 않아야 한다
  • 프로퍼티(상태 집합)로 사용하기 좋은 예
    • 해당 프로퍼티를 함수로 정의할 경우 접두사로 get 혹은 set이 들어가기 적절한 경우
    • 상태를 추출/설정할 때 ( 특별한 이유가 없다면 )
  • 함수(행동)를 사용해야하는 예
    • 연산비용이 높거나 복잡도가 O(1)보다 큰 경우
    • 비즈니스 로직을 포함하는 경우 ( 프로퍼티는 단순한 동작 이상을 할 것이라고 예상되지 않는다 )
    • 같은 동작을 연속적으로 두번 했는데 다른 결과값이 나올 경우 
    • 변환, 컨버터
    • 게터에서 프로퍼티의 상태변화가 일어나는 경우
728x90
반응형