목록Kotlin (81)
안드로이드 개발자 노트
함수가 원하는 결과를 만들어 낼 수 없을 때가 있습니다. 서버로부터 데이터를 읽어 들이려고 했는데, 인터넷 연결 문제로 읽어 들이지 못한 경우 조건에 맞는 첫 번째 요소를 찾으려 했는데, 조건에 맞는 요소가 없는 경우 텍스트를 파싱해서 객체를 만들려고 했는데, 텍스트의 형식이 맞지 않는 경우 이러한 상황을 처리하는 메커니즘은 두 가지가 있습니다. null 또는 '실패를 나타내는 sealed 클래스'를 리턴한다. 예외를 throw한다. 여기서 예외는 정보를 전달하는 방법으로 사용해서는 안되며, 이유를 정리하면 다음과 같습니다. 예외가 전파되는 과정을 제대로 추적하지 못한다. 코틀린의 모든 예외는 unchecked(반드시 처리하게 강제되는 예외)이다. 예외는 예외적인 상황을 처리하기 위해서 만들어졌으므로 명..
require, check, assert 함수를 사용하면, 대부분의 코틀린 오류를 처리할 수 있습니다. 하지만 이외에도 예측하지 못한 상황을 나타내야 하는 경우가 있습니다. 예를 들어 JSON 형식을 파싱하는 라이브러리를 구현한다고 가정하고 입력된 JSON 파일의 형식에 문제가 있다면, JSONParsingException 등을 발생시키는 것이 좋을 것입니다. inline fun String.readObject(): T { //... if (incorrectSign) { throw JsonParsingException() } //... return result } 표준 라이브러리에는 이를 나타내는 적절한 오류가 없으므로, 사용자 정의 오류를 사용했습니다. 하지만 가능하다면, 직접 오류를 정의하는 것보다는..
확실한 형태로 동작해야 하는 코드가 있다면, 예외를 활용해 제한을 걸어두는 것이 좋습니다. require 블록: 아규먼트를 제한할 수 있다. check 블록: 상태와 관련된 동작을 제한할 수 있다. assert 블록: 어떤 것이 true인지 확인할 수 있다. assert 블록은 테스트 모드에서만 작동한다. return 또는 throw와 함께 활용하는 Elvis 연산자 제한을 걸어 주면 다양한 장점이 발생합니다. 제한을 걸면 문서를 읽지 않은 개발자도 문제를 확인할 수 있다. 문제가 있을 경우에 함수가 예상하지 못한 동작을 하지 않고 예외를 throw한다. 예상하지 못한 동작을 하는 것은 throw하는 것보다 굉장히 위험하며, 상태를 관리하는 것이 굉장히 힘들다. 코드가 어느 정도 자체적으로 검사된다. 따..
코틀린의 타입 추론(type inference)은 널리 알려진 코틀린의 특징이며 자바도 자바10부터는 타입 추론을 도입했습니다. inferred 타입은 정확하게 오른쪽에 있는 피연산자에 맞게 설정되며 슈퍼클래스 또는 인터페이스로는 설정되지 않습니다. open class Animal class Zebra: Animal() fun main() { var animal = Zebra() animal = Animal() // 오류: Type mismatch } fun main() { var animal: Animal = Zebra() animal = Animal() // 성공 } 직접 라이브러리 또는 모둘을 조작할 수 없는 경우에는 간단하게 해결할 수 없습니다. 이러한 경우에서 inferred 타입을 노출하면 위..
널 안정성(null-safety)은 코틀린의 주요 기능 중 하나입니다. null-safety 메커니즘이 없는 자바, C등의 프로그래밍 언어와 코틀린을 연결해서 사용할 때는 널 포인터 예외(Null-Pointer Exception, NPE)가 발생할 수 있습니다. @Nullable 어노테이션이나 @NotNull 어노테이션이 붙어있다면 코틀린에서 활용할때는 String?과 String으로 변경하면 됩니다. 자바에서 모든 것이 null일 수 있으므로 최대한 안전하게 접근한다면, 이를 nullable로 가정하고 다루어야 합니다. 하지만 메서드가 null을 리턴하지 않을 것이 확실한 경우 not-null 단정을 나타내는 !!를 붙입니다. / 자바 public class UserRepo{ public List ge..
스코프라는 것은 요소를 볼 수 있는 컴퓨터 프로그램 영역으로, 가시성(visible)을 의미합니다. 상태를 정의할 때는 변수와 프로퍼티의 스코프를 최소화하는 것이 좋습니다. 프로퍼티보다는 지역 변수를 사용하는 것이 좋다. 최대한 좁은 스코프를 갖게 변수를 사용한다. 예를 들어 반복문 내부에서만 변수가 사용된다면, 변수를 반복문 내부에 작성하는 것이 좋다. // 나쁜 예 var user: User for (i in users.indices) { user = users[i] print("User at $i is $user") } // 조금 더 좋은 예 for (i in users.indices) { val user = users[i] print("User at $i is $user") } // 제일 좋은 예..
읽기, 쓰기가 가능한 프로퍼티나 mutable 객체는 상태를 가집니다. 상태를 갖게 한다는 것은 변한다는 것이고, 변하는 요소를 관리하는 것은 어렵습니다. 프로그램을 이해하고 디버그하기 힘들어진다. 코드의 실행을 추론하기 어려워진다. 멀티스레드 프로그램일 경우 충돌이 발생할 수 있다. 테스트하기 어렵다. 정렬되어 있는 리스트의 경우 가변 요소를 추가한다면, 요소의 변경이 일어날 때마다 리스트 전체를 다시 정렬해야한다. 가변성을 제한할 수 있는 방법은 immutable 객체를 만들거나, 프로퍼티를 변경할 수 없게(read only) 막는 것이 가장 쉽습니다. 이 중에서 많이 사용되고 중요한 것들을 정리해 보면 다음과 같습니다. 읽기 전용 프로퍼티(val) 가변 컬렉션과 읽기 전용 컬렉션 구분하기(immut..
1. 코테스트 명세 1. 코테스트 시작하기 코테스트 io.kotest:kotest-runner-junit5-jvm:4.5.0 을 사용한다. 2. 명세 스타일 코테스트는 여러 명세 스타일을 지원한다. 프로젝트에서 여러 스타일을 섞어 쓰거나 AbstractSpec 클래스 또는 AbstractSpec 클래스의 하위 클래스 중 하나인 AbstractStringSpec과 같은 클래스를 구현함으로써 명세 스타일을 커스텀할 수 있다. 테스트 케이스를 정의하려면 명세 클래스 중 하나를 상속해야 한다. 그 후 클래스 생성자에 테스트를 추가하거나 상위 클래스 생성자에게 전달하는 람다 안에 테스트를 추가한다. 테스트 자체를 정의하는 방법은 스타일에 따라 달라지며, 대부분의 경우 DSL과 비슷한 API를 통해 테스트를 정의한..
1. 코루틴 1. 코루틴과 일시 중단 함수 코루틴 라이브러리의 기본 요소는 일시 중단 함수(suspend function) 이다. 이 함수는 원하는 지점에서 함수의 실행을 중단하거나 다시 실행을 계속 진행하게 할 수 있다. suspend fun foo() { println("Task started") delay(100) println("Task finished") } delay() 함수는 일시 중단 함수다. 이 함수는 현재 스레드를 블럭시키지 않고 자신을 호출한 함수를 일시 중단시키며 스레드를 다른 작업을 수행할 수 있게 풀어준다. 일시 중단 함수가 아닌 일반 함수에서는 사용할 수 없다. 동시성 코드의 동작을 제어할 때 공통적인 생명 주기와 문맥이 정해진 몇몇 작업이 정의된 구체적인 영역 안에서만 동시성..
1. 연산자 오버로딩 연산자 오버로딩은 +, -, *, / 등 코틀린 내장 연산자에 대해 새로운 의미를 부여할 수 있게 해주는 언어 기능이다. 1. 단항 연산 단항 연산은 피연산자가 한 개인 연산으로 오버로딩할 수 있는 단항 연산자로는 전위+나 -,! 연산자가 있다. 컴파일러는 이런 연산자를 적절한 함수 호출로 펼쳐준다. 식 의미 +e e.unaryPlus() -e e.unaryMinus() !e e.not() 예를 들어 색을 표현하는 이넘 클래스가 있다고 생각해보면, enum class Color { BLACK, RED, GREEN, BLUE, YELLOW, CYAN, MAGENTA, WHITE; operator fun not() = when (this) { BLACK -> WHITE RED -> CY..