본문 바로가기

안드로이드/Kotlin

(28)
8. Effective Kotlin - 사용하지 않는 객체의 레퍼런스를 제거하라 사용하지 않는 객체의 레퍼런스를 제거하라 Java와 같은 메모리 관리를 자동으로 해주는 프로그래밍 언어를 사용할 경우, 해제(free)를 따로 고려하지 않는다. 하지만, 메모리 관리를 완전히 무시해버리면 메모리 누수가 발생하여 OOM(Out Of Memory)가 발생한다. 따라서, 필요 없는 객체의 레퍼런스는 명시적으로 끊어주어야 한다. 메모리 문제는 굉장히 사소한 곳에서 발생한다. class Stack { private val elements: Array = arrayOfNulls(DEFAULT_CAPACITY) private var size = 0 fun push(e: Any?) { ensureCapacity() elements[size++] = e } fun pop(): Any? { if (size..
7. Effective Kotlin - 인라인 클래스의 사용을 고려하라. inline class 특정 class의 Default 생성자의 프로퍼티가 하나일 경우 inline을 사용하면, 해당 객체를 사용하는 위치가 모두 해당 프로퍼티로 교체된다. inline class Millis(private val time: Int) { // ... } 이러한 inline 클래스는 타입만 일치한다면 값을 바로 넣는 것도 가능하다. val time: Millis = Millis(3000) // 컴파일 시 다음 형태로 변경 val time: Int = 3000 inline 클래스에 존재하는 메서드는 컴파일 시 모두 정적 메서드로 만들어진다. inline class Name(private val value: String) { fun greet() { print() } } // 실제 코드 val..
6. Effective Kotlin - 함수를 파라미터로 갖는 함수에 inline을 사용하라 함수 타입 파라리터를 갖는 함수에 inline 한정자를 붙여라 inline의 역할은 컴파일 시점에 '함수를 호출하는 부분'을 '함수의 본문'으로 대체하는 역할을 한다. inline fun repeat(times: Int, action: (Int) -> Unit) { for (index in 0 until times) { action(index) } } repeat(10) { print (it) } 위의 repeat는 컴파일 시점에 아래와 같이 교체된다. for (index in 0 until times) { print(index) } inline을 사용하면 다음과 같은 장점이 있다. reified를 사용할 수 있다. 더욱 빠르게 동작한다. 비지역(non-local) 리턴을 사..
5. Effective Kotlin - 효율성 효율성 과거에 비해 메모리의 값이 저렴해지고 개발자의 몸 값이 오르면서, 메모리 효율적인 코드를 작성하는 것에 대해 관대함이 생겼다. 하지만, 효율성을 고려한 코드는 대부분의 경우에서 옳다. 그 과정에서 가독성과 효율성의 trade-off도 고려한다면 최적이다. 불필요한 객체 생성을 피하라 객체 생성에는 언제나 비용이 들어간다. 다양한 레벨에서 객체 생성을 피할 수 있다. 예를들어 JVM에서는 하나의 가상 머신에서 동일한 문자열을 처리하는 코드가 여러 개가 존재할 경우, 기존 문자열을 재활용한다. 또한, Integer, Long과 같은 박싱 타입도 작은 수에서는 재활용한다. val str1 = "Kotlin" val str2 = "Kotlin" print(str1 == str2) //true print(..
4. Effective Kotlin - 가독성 가독성을 목표로 설계하라 인지 부하 감소 가독성은 사람에 따라 다르게 느낄 수 있다. // Type:A if (person != null && person.isAdult) { view.showPerson(person) } else { view.showError() } // Type:B person?.takeIf { it.isAdult } ?.let(view::showPerson) ?: view.showError() 가독성은 뇌가 얼마나 많은 관용구에 익숙해졌냐에 따라 다르다. Type:A의 경우 kotlin을 사용해보지 않은 개발자라도 빠르게 이해할 수 있다. 하지만, Type:B의 경우 kotlin에서 일반적으로 사용되는 패턴으로 익숙하지 않아 어려울 수 있다. 그리고, 사실 Kotlin을 오래 하지 ..
3. Effective Kotlin - 결과 부족 시 null & Failure를 사용하라 결과 부족 시 null & Failure를 사용하라 함수가 원하는 결과를 만들지 못하는 경우가 있다. 예를 들면 다음과 같다. 서버로부터 데이터를 읽어들이는 과정에서 네트워크 오류로 읽어들이지 못한 경우 조건에 맞는 첫 번째 요소를 찾으려 했으나 없는 경우 위와 같은 상황을 핸들링하는 방법은 크게 두 가지이다. null 혹은 _Failure_를 나타내는 _sealed class_를 사용하라. 예외를 throw한다. 위는 두 가지 차이점이 있다. 먼저, 예외는 정보를 전달하는 목적이 아니다. 반면에, _null_과 _Failure_는 정보 전달의 역할을 충분히 수행한다. 가능하면 nullable을 리턴하지 않는 것이 좋다. null을 리턴해야되는 경우 개발자에게 getOrNull 등을 사용해서 무엇이 리턴..
2. Effective Kotlin - Inferred, Exception Inferred 타입을 가급적 제한하라. 코틀린은 타입 추론을 지원한다. 타입 추론은 매우 편리하지만, 엄격해야 될 필요성이 있다. 예를 들어 다음과 같은 경우를 고려해야 된다. open class Animal() class Zebra : Animal() var zebra = Zebra() zebra = Animal() // --> Error 발생, zebra의 타입은 Zebra이다. //방지하기 위한 코드 var zebra: Animal = Zebra() zebra = Animal() 예외를 활용해 코드를 제한하라. 확실하게 어떤 형태로 동작해야되는 코드가 있다면, 예외를 활용하여 제한을 걸어두는 것이 좋다. 코틀린은 require, check 등을 지원한다. 제한을 걸면 다음과 같은 이점이 있다. 문..
1. Effective Kotlin - Destructuring declaration Destructuring declaration 직역하면 구조분해 선언이다. Old한 언어에서는 특정 함수나 작업의 결과 값을 하나만 받을 수 있다. 최신 언어의 경우 여러 결과를 동시에 받을 수 있다. 구조분해 선언을 활용하면 변수를 선언과 동시에 초기화할 수 있어 가독성 향상에 도움이 된다. 예시 fun updateWeather(degrees: Int) { val (description, color) = when { degrees "cold" to Color.BLUE degrees "mild" to Color.YELLOW else -> "hot" to Color.RED } }