Skip to content

Latest commit

ย 

History

History
168 lines (136 loc) ยท 6.49 KB

Kotlin-DSL.md

File metadata and controls

168 lines (136 loc) ยท 6.49 KB

Android DSL

Present Time: 2018-8-24 FRI

Present Time: 2018-8-24 FRI

1. DSL(Domain-Specific Language)์ด๋ž€?

DSL์ด๋ž€ ํŠน์ • ๋„๋ฉ”์ธ(์„œ๋น„์Šค)์— ํŠนํ™”๋˜์–ด์žˆ๋Š” ์–ธ์–ด๋ฅผ ๋งํ•œ๋‹ค.
์ž์—ฐ์–ด์ฒ˜๋Ÿผ ๋งŒ๋“ค์–ด ๊ธฐ์กด ์ฝ”๋“œ๋ณด๋‹ค ๋” ํ‘œํ˜„์ ์ด๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹๊ฒŒ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•œ๋‹ค.
SQL๋„ DSL ์–ธ์–ด์ค‘ ํ•˜๋‚˜๋‹ค.

1-1. ๋‚ด๋ถ€ DSL, ์™ธ๋ถ€ DSL

DSL์€ ๋‚ด๋ถ€ DSL๊ณผ, ์™ธ๋ถ€ DSL๋กœ ๋‚˜๋ˆ„์–ด์ง„๋‹ค.
๊ทธ์ค‘, ์ด๋ฒˆ์— ์•Œ์•„๋ณผ DSL์€ ๋‚ด๋ถ€ DSL์ด๋‹ค.

๋‚ด๋ถ€ DSL

  • ํ˜ธ์ŠคํŠธ ์–ธ์–ด(๊ธฐ์กด ์–ธ์–ด)์˜ ํ‹€์„ ๋ฒ—์–ด๋‚˜์ง€ ์•Š์œผ๋ฉฐ ๊ตฌ์„ฑํ•˜๋Š”๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
  • ๊ธฐ์กด ์–ธ์–ด์˜ ์ƒˆ๋กœ์šด ๊ตฌ๋ฌธ์œผ๋กœ ๋„์ž…๋˜์–ด ์–ธ์–ด ํ™•์žฅ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ธ๋ผ์ธ ์ฝ”๋“œ ํ˜•ํƒœ๋กœ ํ‘œํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์™ธ๋ถ€ DSL

  • ๊ธฐ์กด ์–ธ์–ด์™€ ๋‹ค๋ฅธ ์–ธ์–ด๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋œ DSL์˜ ์˜๋ฏธํ•œ๋‹ค.
  • XML, CSS ๋“ฑ

์ฝ”ํ‹€๋ฆฐ์—์„œ?

  • ์ฝ”ํ‹€๋ฆฐ์—์„œ Koin, Anko๋“ฑ ์ฝ”ํ‹€๋ฆฐ ์ „์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋„ DSL์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
val values = ContentValues()
values.put("id", 5)
values.put("name", "John Smith")
values.put("email", "[email protected]")
db.insert("User", null, values)
Anko Sqlite ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์„ ๋•Œ
db.insert("User", 
    "id" to 42,
    "name" to "John",
    "email" to "[email protected]"
)
Anko Sqlite ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์˜€์„ ๋•Œ

DSL์„ ์ ์šฉํ–ˆ์„ ๊ฒฝ์šฐ, ๊ฐ€๋…์„ฑ์ด ๋” ๋›ฐ์–ด๋‚˜๋‹ค.

inline fun Activity.verticalLayout(theme: Int = 0, init: (@AnkoViewDslMarker _LinearLayout).() -> Unit)

์œ„ ํ•จ์ˆ˜๋Š” Anko Layout์˜ DSL์ธ๋ฐ, ๋ณด๋‹ค์‹œํ”ผ ํ™•์žฅํ•จ์ˆ˜์™€ ๊ณ ์ฐจ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.
๋ฌผ๋ก , ์ด ์˜ˆ์‹œ ์ด์™ธ์—๋„ DSL์€ ๊ณ ์ฐจ ํ•จ์ˆ˜๋‚˜ ํ™•์žฅ ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.
๊ทธ๋Ÿฐ ์˜๋ฏธ์—์„œ ์‹ค์ œ๋กœ ํ•œ๋ฒˆ DSL์„ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ ์ „์—, Higher-order function๊ณผ Extension Fucntion์ด ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด์ž.

2. Extension Function์ด๋ž€?

์ฝ”ํ‹€๋ฆฐ์€ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด์— ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๊ธฐ๋Šฅ์ธ ํ™•์žฅ ํ•จ์ˆ˜๋ฅผ ์ง€์›ํ•œ๋‹ค.

2-1. ํ™•์žฅ ํ•จ์ˆ˜ ๋ง›๋ณด๊ธฐ

์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฌธ์ž์—ด์˜ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๋งŒ ๋ฝ‘์•„๋‚ด๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
ํ˜ธ์ถœํ•  ๋•Œ ๋งˆ๋‹ค str[str.lengthโ€Šโ€”โ€Š1] ์ฒ˜๋Ÿผ ๊ธด ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
ํ™•์žฅ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์กฐ๊ธˆ ๋” ํŽธํ•˜๊ฒŒ ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

fun String.lastIndex() = this[this.length - 1]

ํ™•์žฅ ํ•จ์ˆ˜ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ String ๊ฐ์ฒด์˜ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๊ณ , ์ด์ œ๋Š” str.lastIndex() ๋กœ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๋ฅผ ๋ฝ‘์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

  • ํ™•์žฅ ํ•จ์ˆ˜์—์„œ this๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
  • ๋งŒ์•ฝ ํ™•์žฅ ํ•จ์ˆ˜์˜ ์ด๋ฆ„๊ณผ ์›๋ž˜ ๋ฉค๋ฒ„ ํ•จ์ˆ˜์˜ ์ด๋ฆ„์ด ๊ฐ™๋‹ค๋ฉด, ๋ฌด์กฐ๊ฑด ๋ฉค๋ฒ„ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

3. Higher-order function(๊ณ ์ฐจํ•จ์ˆ˜)

๊ณ ์ฐจ ํ•จ์ˆ˜๋ฅผ ์ถฉ์กฑํ•˜๋ ค๋ฉด ๋‹ค์Œ ์กฐ๊ฑด ์ค‘ ํ•˜๋‚˜๋ฅผ ๋งŒ์กฑํ•ด์•ผํ•œ๋‹ค.

  • ํ•จ์ˆ˜๋ฅผ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค
  • ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์ด ํ•จ์ˆ˜๋‹ค.

์ฝ”ํ‹€๋ฆฐ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” let, run, apply, with๋„ ๋ชจ๋‘ ๊ณ ์ฐจ ํ•จ์ˆ˜๋‹ค.

3-1. apply( )

apply()๋ฅผ ์˜ˆ์‹œ๋กœ ๋“ค์–ด๋ณด๋ฉฐ ๊ณ ์ฐจํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ์ง„ํ–‰๋˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

public inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}
(Kotlin 1.2 ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” apply ์•ˆ์— contract ๋ฉ”์†Œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด์žˆ์œผ๋‚˜, ํŽธํ•œ ์„ค๋ช…์„ ์œ„ํ•ด ์ œ์™ธ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.)
val test = Test(3,5).apply {
        square()
}

data class Test(var x: Int, var y: Int){
    fun square(){
        x *= x
        y *= y
    }
}

T.apply๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด๋ฅผ ๋ธ”๋ก์˜ ๋ฆฌ์‹œ๋ฒ„(this)์— ์ „๋‹ฌํ•˜๊ณ , ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋‹ค.

3-2. apply() ํ•จ์ˆ˜ ์ง„ํ–‰๋„

  1. apply()๋Š” block: T.() -> Unit ๋ผ๋Š” T์˜ ํ™•์žฅ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค.
  2. ๊ณ ๋กœ Test(3, 5).apply{}๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ T์˜ ํ™•์žฅ ํ•จ์ˆ˜์ธ ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  3. ์ต๋ช… ํ•จ์ˆ˜ ๋ธ”๋ก ์•ˆ์—์„œ ๋ฆฌ์‹œ๋ฒ„์˜ ํ•จ์ˆ˜๋‚˜ ๋ฉค๋ฒ„๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  4. apply() ์—์„œ ๋ฐฉ๊ธˆ ์„ ์–ธํ•œ ์ต๋ช… ํ•จ์ˆ˜์ธ block()์„ ํ˜ธ์ถœํ•˜๊ณ , ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๊ฒฐ๋ก 

๋‹ค๋ฅธ ๊ณ ์ฐจ ํ•จ์ˆ˜๋„ apply() ์ฒ˜๋Ÿผ ์ธ์ž๋กœ ๋ฐ›์€ ํ•จ์ˆ˜๋ฅผ ๋™์ž‘๋˜๊ฒŒ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋œ๋‹ค.

4. ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๊ธฐ (์ถ”ํ›„ ์ˆ˜์ • ์˜ˆ์ •)

ํ™•์žฅ ํ•จ์ˆ˜์™€ ๊ณ ์ฐจ ํ•จ์ˆ˜๋ฅผ ์•Œ์•˜์œผ๋‹ˆ ์ด์ œ ์šฐ๋ฆฌ๋„ DSL์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
์ด ๊ธ€์„ ์ฐธ๊ณ ํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” DSL์„ ๋งŒ๋“ค์–ด๋ณด์ž!

data class Person(var name: String = "", var age: Int = 0)

๊ฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

4-1. ํ™•์žฅํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋งŒ๋“ค๊ธฐ

Person์„ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค.

fun person(block: (Person) -> Unit): Person {
    val person = Person()
    block(person)
    return person
}
  1. person ๊ฐ์ฒด๋ฅผ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ƒ์„ฑํ•œ๋‹ค.
  2. block(person)์„ ํ˜ธ์ถœํ•ด person ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค
  3. ์ˆ˜์ •๋œ person ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋Š” ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

val person = person { 
        it.age = 3
        it.name = "Person"
    }

๊ทธ๋Ÿฌ๋ฉด ๊ฐ์ฒด๋ฅผ ์ด๋ ‡๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ฉค๋ฒ„๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๋งˆ๋‹ค it์„ ๋ถ™์—ฌ์•ผํ•œ๋‹ค๋Š”๊ฒŒ ๋„ˆ๋ฌด ๊ท€์ฐฎ๋‹ค. it์„ ์—†์• ๋ณด์ž!

4-2. block ํ•จ์ˆ˜๋ฅผ Person์˜ ํ™•์žฅ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค๊ธฐ

it์„ ์—†์• ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ์ •๋ง ๊ฐ„๋‹จํ•˜๋‹ค. blockํ•จ์ˆ˜๋ฅผ Person๊ฐ์ฒด์˜ ํ™•์žฅ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค!

fun person(block: Person.() -> Unit) = Person().apply(block)

block์„ Person ๊ฐ์ฒด์˜ ํ™•์žฅ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค๊ณ , Person ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ๋’ค block ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ๊ทธ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค.

val person = person {
        age = 3
        name = "Person"
    }

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด it์„ ์—†์• ์„œ ๊ฐ€๋…์„ฑ ์ข‹๊ณ  ํŽธํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค!

5. ์ฐธ๊ณ  ๋ฌธ์„œ

5-1. ๊ณต์‹ ๋ฌธ์„œ

5-2. ์ฐธ๊ณ  ๋ฌธ์„œ