이 글은 Effective Java 를 완독하고, Kotlin 을 상용으로 사용하는 개발자 입장에서
Effective Kotlin 글 중 새로운 내용, remind 할 필요 있는 부분, 핵심 내용 등만 추려 정리한 내용입니다.
#
HTML, View hierarchy, config 등등 많은 케이스에 적용될 수 있다.
돼왕 : 선언적인 느낌을 주기 좋은 것 같다.
#
만들기 복잡한 계층구조를 이루는 data 구조의 경우 DSL 로 하면 간단할 수 있다.
DSL 로 하면 Groovy 와 다르게 type safe 를 이룩할 수 있다.
Defining your own DSL
#
function type with receiver 의 개념을 이해해야 DSL 을 만들 수 있다.
#
function type 을 만드는 방법은 아래와 같다.
- lambda expression
val plus1: (Int, Int) -> Int = { a, b -> a + b }
- anonymous function.
val plus2: (Int, Int) -> Int = fun(a, b) = a + b
- function reference.
fun plus(a:Int, b: Int) = a + b val plus3 : (Int, Int) -> Int = ::plus
type inference 를 이용해서 아래와 같이 정의도 가능하다.
val plus4 = { a: Int, b : Int -> a + b }
val plus5 = fun(a: Int, b:Int) = a + b
#
function type with receiver 는 아래와 같이 정의된다.
fun Type.name(args){ /* ... */ }
val myPlus: Int.(Int) -> Int = fun Int.(other:Int) = this + other
이 경우 lambda 함수의 this 는 Type 객체가 된다. 이게 가장 큰 포인트이다.
#
function type with receiver 는 아래 3가지 형태로 invoke 될 수 있다.
- 일반 object 처럼 invoke 함수를 사용할 수 있음.
myPlus.invoke(1, 2)
- non-extension function 처럼 사용할 수 있음.
myPlus(1, 2)
- normal extension function 처럼 사용할 수 있음.
1.myPlus(2)
#
fun createTable(): TableDsl = table{
tr{
for(i in 1..2){
td{
+"This is column $i"
}
}
}
}
위의 DSL 을 만들기 위해서는 아래 함수정의들이 필요하다.
fun table(init: TableBuilder.()->Unit): TableBuilder{
return TableBuilder().apply(init)
// val tableBuilder = TableBuilder()
// init.invoke(tableBuilder)
// return tableBuilder
}
class TableBuilder{
var trs = listOf<TrBuilder>()
fun tr(init: TrBuilder.() -> Unit) {
trs = trs + TrBuilder().apply(init)
}
}
class TrBuilder{
var tds = listOf<TdBuilder>()
fun td(init: TdBuilder.()->Unit) {
tds = tds + TdBuilder().apply(init)
}
}
class TdBuilder {
var text = ""
operator fun String.unaryPlus() {
text += this
}
}
When should we use it?
#
DSL 은 정보를 정의하는 좋은 방법을 제공한다.
그러나 사용자 입장에서 DSL 에 전달된 정보가 어떻게 활용되는지는 알기 어렵고, 상황에 따라서 사용법이 복잡할 수 도 있다.
제작자 입장에서 코드 유지보수도 복잡하다. 퍼포먼스 이슈가 없는지 체크도 까다롭다.
더 쉬운 방법으로 대체할 수 있는 경우에 DSL 은 오버이다.
그러나 다음과 같은 경우에는 유용할 수 있다.
- 복잡한 데이터 구조
- 계층화된 구조
- 엄청난 양의 데이터
DSL 은 위와 같은 구조에서 발생하는 boilerplate 를 제거하기에 좋다.
Summary
끝
댓글