코틀린의 DSL (Domain-Specific Language)과 DslMarker
DSL(Domain-Specific Language)은 특정 주제에 특화된 언어를 의미하며,
데이터베이스에 접근하기 위한 SQL이 대표적인 DSL이다.
이 밖에도 화면 레이아웃을 단순화한 DSL이나 웹 접근을 단순화한 DSL 등의 많은 프레임워크가 만들어져 있다.
코틀린에서는 고차함수와 람다식의 특징을 이용하여 읽기 좋고 간략한 코드를 만들수 있다.
우리가 목표로 할 DSL 코드는 다음과 같다
data class Person(
var name: String? = null,
var age: Int? = null,
var job: Job? = null)
data class Job(
var category: String? = null,
var position: String? = null,
var extension: Int? = null)
fun person(block: Person.() -> Unit): Person = Person().apply(block)
fun Person.job(block: Job.() -> Unit) { // 3번
job = Job().apply(block)
}
fun main() {
val person = person { // 1번
name = "KaSha"
age = 27
job { // 2번
category = "IT"
position = "Server Developer"
extension = 4670
}
}
println(person)
}
1번에서 person 함수를 호출하여 코드 블럭을 파라미터로 넘겨주었고 person 함수는 Person()을 통해 인스턴스를 생성하여 코드 블럭을 apply한다.
코드 블럭을 apply하면서 name과 age를 세팅하고, 2번에서 job함수를 실행한다.
3번인 job함수를 살펴보면 Person 클래스의 extension 함수임을 알 수 있다.
job 함수가 실행되면서 Job()을 통해 Job 객체를 인스턴스화 하고 job 함수의 파라미터로 전달된 코드블럭을 apply하여 모든 프로퍼티를 초기화 한다.
DslMarker 애노테이션
@DslMarker 애노테이션은 코틀린 1.1부터 제공되며 사용자 애노테이션 클래스에 적용해 DSL로 사용하기 위한 정의입니다.
우리는 DSL을 사용할때 컨텍스트에서 너무 많은 함수를 호출할수 있다는 문제에 봉착할수 있습니다.
그래서 @DslMarker를 이용하여 하기 예제처럼 클래스의 함수 범위를 제한하여 잘못 구조화된 코드를 작성하려할때 오류를 발생시킬수 있습니다.
html {
body {
body { // 에러 발생
}
}
}
해당 예제는 코틀린 공식문서에서 확인 할 수 있습니다.
참고
서적 : Do it! 코틀린 프로그래밍