Slide 1

Slide 1 text

Deep Dive into Kotlin DSL Kotlin Fest 2019 @red_fat_daruma

Slide 2

Slide 2 text

Self Introduction Jumpei Matsuda / Daruma / @red_fat_daruma ▸ Software Engineer @DeployGate ▸ GitHub: jmatsu / Twitter: red_fat_daruma ▸ JVM projects : Android apps/SDK, Scala server- side and Gradle plugins ▸ One of Kotlin users since M10 2 M10 Ҏདྷͷ Kotlin Ϣʔβʔ

Slide 3

Slide 3 text

Today's Goal Hopefully, Every Audience Will.... ▸ Know what is DSL and/or Kotlin DSL ▸ Understand what specifications/features of Kotlin support Kotlin DSL ▸ Have a motivation to develop the original Kotlin DSL and/or extend existing libraries through Kotlin DSL. 3 DSL ͱ͸Կ͔ɺKotlin DSL ͱ͸Կ͔Λ஌Δ ͲΜͳ࢓༷/ػೳ͕ Kotlin DSL Λࢧ͍͑ͯΔͷ͔ཧղ͢Δ ಠࣗͷ Kotlin DSL ͷ࡞੒΍طଘϥΠϒϥϦΛ Kotlin DSL Ͱ֦ு͢ΔϞνϕʔγϣϯΛಘΔ ͜ͷൃදΛฉ͍ͨਓ͕ͨͪɺ ͱ͍͍ͳ͊

Slide 4

Slide 4 text

Let me ask questions! 4

Slide 5

Slide 5 text

Who thinks Kotlin DSL is for Gradle? ✋ 5 Kotlin DSL == Gradle ͷ΋ͷͩͱࢥ͍ͬͯΔਓʁ

Slide 6

Slide 6 text

I do not use a word *Kotlin DSL* to represent Kotlin DSL for Gradle Kotlin DSL Is Not Only Kotlin DSL for Gradle ▸ *Kotlin DSL* in this presentation does not mean Gradle's one ▸ Kotlin DSL for Gradle is just a DSL in Kotlin for Gradle ▸ Contracts, coroutines, etc. are also Kotlin DSL 6 Kotlin DSL ͸ Kotlin DSL for Gradle ͷ͜ͱ͚ͩ͡Όͳ͍ ͜ͷൃදͰͷ Kotlin DSL ͸ Gradle ͷ΋ͷ͚ͩΛࢦ͢Θ͚͡Όͳ͍ Kotlin DSL for Gradle ͸ Kotlin Ͱॻ͔Εͨ Gradle ༻ͷ DSL Ͱ͋Δͱ͍͏͚ͩ Contracts, coroutines ͱ͔΋ Kotlin DSL

Slide 7

Slide 7 text

I do not use a word *Kotlin DSL* to represent Kotlin DSL for Gradle Kotlin DSL Is Not Only Kotlin DSL for Gradle ▸ *Kotlin DSL* in this presentation does not mean Gradle's one ▸ Kotlin DSL for Gradle is just a DSL in Kotlin for Gradle 7 Go to Next questions!

Slide 8

Slide 8 text

Who have used and/or are using Kotlin DSL? ✋ 8 ࠓ·Ͱʹ Kotlin DSL ࢖ͬͨΑɺࠓ΋࢖ͬͯΔΑɺͬͯਓʁ

Slide 9

Slide 9 text

Who know what techniques will help Kotlin DSL? ✋ 9 ͲΜͳٕज़͕ Kotlin DSL Λࢧ͑ͯΔ͔஌ͬͯΔਓʁ

Slide 10

Slide 10 text

Who can explain the definition of Kotlin DSL? ✋ 10 Kotlin DSL ͷఆٛΛઆ໌Ͱ͖Δͻͱ?

Slide 11

Slide 11 text

Who can explain the definition of DSL? ✋ 11 DSL ͷఆٛΛઆ໌Ͱ͖Δͻͱʁ

Slide 12

Slide 12 text

If you said YES to all questions, you are already Kotlin DSL deep diver! 12 શ෦ͷ࣭໰ʹʮ͸͍ʯͱճ౴Ͱ͖ͨํ͸΋͏͢Ͱʹ Kotlin DSL Deep diver Ͱ͢ɾɾɾ

Slide 13

Slide 13 text

Today's topics Agenda ▸ The base knowledge of DSL ▸ Specifications/techniques of Kotlin DSL based on levels ▸ Quick tips for DSL development 13 DSL ʹؔ͢Δجૅ஌ࣝ Kotlin DSL ͷ࢓༷΍ٕज़ΛϨϕϧผͰ DSL ։ൃͷͨΊͷͪΐͬͱͨ͠ tips

Slide 14

Slide 14 text

The base knowledges of DSL Domain Specific Language ▸ A computer language specialized to a particular application domain ▸ In contrast: a general purpose language like Kotlin, Java 14 ref: https://en.wikipedia.org/wiki/Domain-specific_language υϝΠϯݻ༗ݴޠ ಛఆͷΞϓϦέʔγϣϯυϝΠϯʹಛԽͨ͠ίϯϐϡʔλݴޠ ରরతͳ΋ͷ͸ Kotlin, Java ͷΑ͏ͳ൚༻ݴޠ

Slide 15

Slide 15 text

Domain Specific Language ▸ A computer language specialized to a particular application domain ▸ In contrast: a general purpose language like Kotlin, Java ▸ What's a motivation to introduce/need DSL? 15 The base knowledges of DSL ref: https://en.wikipedia.org/wiki/Domain-specific_language DSL Λಋೖ͢Δɺඞཁͱ͢ΔϞνϕʔγϣϯ͸ͳʹ͔

Slide 16

Slide 16 text

Why People Want To Use DSL ▸ Simplify complex code ▸ More readable, understandable, fluent ▸ Use smart and/or minimum APIs for the domain ▸ Improve productivity and reduce human errors ▸ Get a power of type system etc. 16 The base knowledges of DSL ͳΜͰ DSL Λ࢖͏ͷ͔ ෳࡶͳίʔυΛγϯϓϧʹ͢ΔͨΊ ಡΈ΍͍͢ɺཧղ͠΍͍͢ɺྲྀெͳ interface ΁ ಛఆυϝΠϯʹର͢ΔεϚʔτͰɺඞཁ࠷௿ݶͳ API ͕ར༻Ͱ͖Δ ੜ࢈ੑͷ޲্΍ώϡʔϚϯΤϥʔͷݮগͷͨΊ ܕγεςϜͷྗΛಘͨΓͩͱ͔

Slide 17

Slide 17 text

Why People Want To Use DSL 17 The base knowledges of DSL NOTE: pseudo code DSL ٖࣅίʔυ

Slide 18

Slide 18 text

Aspects of Domain Specific Language ▸ External DSL and Internal DSL ▸ External: A language that's parsed independently of the host general purpose language ▸ Internal: A particular form of API in the host general purpose language for the domain 18 The base knowledges of DSL ref: https://martinfowler.com/books/dsl.html υϝΠϯݻ༗ݴޠಛੑ ֎෦ DSL ͱ಺෦DSL ϗετͱͳΔ൚༻ݴޠͱ͸ಠཱͯ͠ύʔε͞ΕΔ DSL ϗετͱͳΔ൚༻ݴޠͷதͰɺಛఆͷ API ͷܗࣜΛఏڙ͢Δ DSL

Slide 19

Slide 19 text

Examples in the Real World ▸ External DSL ▸ SQL, CSS, Regular expressions ▸ Internal DSL ▸ HTML, Mock Libraries, DI container 19 The base knowledges of DSL ࣮ྫ SQL, CSS, ਖ਼نදݱ HTML, ϞοΫϥΠϒϥϦɺDI

Slide 20

Slide 20 text

Examples in the Real World ▸ External DSL ▸ SQL, CSS, Regular expressions ▸ Internal DSL ▸ HTML, Mocking Libraries, DI container ▸ Kotlin DSL 20 The base knowledges of DSL

Slide 21

Slide 21 text

Examples in the Real World ▸ External DSL ▸ SQL, CSS, Regular expressions ▸ Internal DSL ▸ HTML, Mocking Libraries, DI container ▸ Kotlin DSL ▸ NOT a special edition of Kotlin 21 The base knowledges of DSL Kotlin ͷಛผͳ೿ੜͱ͔͍͏Θ͚Ͱ͸ͳ͍

Slide 22

Slide 22 text

Techniques for Internal DSL Depends on... ▸ The host general purpose language ▸ Type checking ▸ Syntax ▸ Syntactic extensions ▸ Compiler extensibility and interpolation 22 The base knowledges of DSL ಺෦ DSL Λࢧ͑Δٕज़͸ҎԼʹґଘ ϗετͱͳΔ൚༻ݴޠ ܕݕࠪ جૅߏจ ߏจ֦ு ίϯύΠϥ֦ுੑ΍ิؒࢠ

Slide 23

Slide 23 text

Techniques for Internal Kotlin DSL Depends on... ▸ A general purpose language Kotlin ▸ Type checking Static type checking ▸ Syntax Lambda expressions, etc. ▸ Syntactic extensions Method extension, operator overloading, etc. ▸ Compiler extensibility and/or interpolation Compiler plugins etc. 23 The base knowledges of DSL

Slide 24

Slide 24 text

e.g. kotlinx.html is one of Kotlin DSL ▸ DSL for HTML domain ▸ Generate DOM tree from a Kotlin code 24 The base knowledges of DSL https://github.com/Kotlin/kotlinx.html

Slide 25

Slide 25 text

e.g. kotlinx.html is one of Kotlin DSL ▸ DSL for HTML domain ▸ Generate DOM tree from a Kotlin code 25 Type safe builder pattern, lambda expressions, functions with receiver, higher-order functions, operator overloading, DSLMarker, etc. The base knowledges of DSL

Slide 26

Slide 26 text

Today's topics Agenda ▸ The base knowledge of DSL ▸ Specifications/techniques of Kotlin DSL based on levels ▸ Quick tips for DSL development 26 ▸ NOTE: DSL in following slides means Internal DSL unless specified Kotlin DSL ͷ࢓༷΍ٕज़ΛϨϕϧผͰ DSL ։ൃͷͨΊͷͪΐͬͱͨ͠ tips ͔ͬ͜Β໌هͳ͘ DSL ͱ͍ͬͨΒ಺෦ DSL Ͱ͢

Slide 27

Slide 27 text

Techniques of Kotlin DSL Techniques of Kotlin DSL ▸ Getting started ▸ Language specifications ▸ Intermediate ▸ Features for syntactic extensions ▸ Expertise ▸ Build environment stuff of Kotlin 27 ॳڃ தڃ ্ڃ

Slide 28

Slide 28 text

Techniques of Kotlin DSL ▸ Getting started ▸ Language specifications ▸ Intermediate ▸ Features for syntactic extensions ▸ Expertise ▸ Build environment stuff of Kotlin 28 Techniques of Kotlin DSL - Getting Started ݴޠ࢓༷

Slide 29

Slide 29 text

Language Specifications ▸ Type system ▸ Static type checking ▸ Syntax related specifications ▸ Lambdas, Functions literals with receiver 29 Techniques of Kotlin DSL - Getting Started ܕγεςϜ ੩తܕݕࠪ ߏจʹؔ͢Δ࢓༷ ϥϜμࣜɺϨγʔό͖ͭؔ਺Ϧςϥϧ

Slide 30

Slide 30 text

Static Type Checking ▸ Code analysis based type safety verification ▸ In contrast: Dynamic type checking ▸ Allow know type violations before executing 30 Techniques of Kotlin DSL - Getting Started - 1/3 ίʔυղੳϕʔεͷܕ҆શੑݕࠪ ରর : ಈతܕݕࠪ ࣮ߦલʹܕҧ൓Λ஌Δ͜ͱ͕Ͱ͖Δ

Slide 31

Slide 31 text

Static Type Checking ▸ Code analysis based type safety verification ▸ In contrast: Dynamic type checking ▸ Allow know type violations before executing 31 Groovy : no error but fail at runtime Techniques of Kotlin DSL - Getting Started - 1/3 Τϥʔ͸ͳ͍͕ɺ࣮ߦ࣌ʹམͪΔ ίʔυղੳϕʔεͷܕ҆શੑݕࠪ ରর : ಈతܕݕࠪ ࣮ߦલʹܕҧ൓Λ஌Δ͜ͱ͕Ͱ͖Δ

Slide 32

Slide 32 text

Static Type Checking ▸ Code analysis based type safety verification ▸ In contrast: Dynamic type checking ▸ Allow know type violations before executing 32 Groovy : no error but fail at runtime Kotlin : a compilation error Techniques of Kotlin DSL - Getting Started - 1/3 ίϯύΠϧΤϥʔ Τϥʔ͸ͳ͍͕ɺ࣮ߦ࣌ʹམͪΔ ίʔυղੳϕʔεͷܕ҆શੑݕࠪ ରর : ಈతܕݕࠪ ࣮ߦલʹܕҧ൓Λ஌Δ͜ͱ͕Ͱ͖Δ

Slide 33

Slide 33 text

Syntax-Related Specifications ▸ Lambda expressions ▸ Function literals with receiver 33 Techniques of Kotlin DSL - Getting Started - 1.5/3 ϥϜμࣜ Ϩγʔό͖ͭؔ਺Ϧςϥϧ

Slide 34

Slide 34 text

Lambda Expressions ▸ Syntax sugar for function type variables and SAM ▸ Represent a function by braces 34 Techniques of Kotlin DSL - Getting Started - 2/3 ؔ਺ܕม਺΍ SAM (Single abstract method) ͷ౶ҥߏจ தׅހͰؔ਺ΛදݱͰ͖Δ

Slide 35

Slide 35 text

Lambda Expressions - Example 35 Techniques of Kotlin DSL - Getting Started - 2/3

Slide 36

Slide 36 text

Lambda Expressions - Example 36 Techniques of Kotlin DSL - Getting Started - 2/3

Slide 37

Slide 37 text

Lambda Expressions - Example 37 Techniques of Kotlin DSL - Getting Started - 2/3

Slide 38

Slide 38 text

Lambda Expressions - Example 38 Techniques of Kotlin DSL - Getting Started - 2/3

Slide 39

Slide 39 text

Lambda Expressions - Example 39 Techniques of Kotlin DSL - Getting Started - 2/3

Slide 40

Slide 40 text

Function Literals With Receiver ▸ Kotlin allows specify what is this scope of a function ▸ Groovy also can do this but Java cannot. ▸ Function Type : Receiver.(Argument) -> Return ▸ Great help for block-code and fluent style coding 40 Techniques of Kotlin DSL - Getting Started - 3/3 ؔ਺ͷ this είʔϓ(receiver)Λࢦఆ͢Δ͜ͱ͕Ͱ͖Δ e.g. Groovy ͸Ͱ͖Δ͚ͲɺJava ͸Ͱ͖ͳ͍ ؔ਺ܕදه ϒϩοΫίʔυදݱ΍ྲྀெͳදݱʹศར

Slide 41

Slide 41 text

Function Literals With Receiver 41 Techniques of Kotlin DSL - Getting Started - 3/3

Slide 42

Slide 42 text

A Primitive Kotlin DSL ▸ Techniques described before allow create a simple DSL 42 Techniques of Kotlin DSL - Getting Started - Closing ͜͜·ͰͷςΫχοΫͰγϯϓϧͳ DSL ͸࡞Δ͜ͱ͕Ͱ͖Δ ݪ࢝తͳ Kotlin DSL

Slide 43

Slide 43 text

A Primitive Kotlin DSL - Is It Enough for Your Better Development? ▸ Only techniques described before allow create a simple DSL 43 Techniques of Kotlin DSL - Getting Started - Closing ྑ͍։ൃͷͨΊʹ͸͜ΕͰे෼ͩΖ͏͔

Slide 44

Slide 44 text

Break ▸ We can build DSLs easily from scratch with knowledges I have explained ▸ It's enough if you want type-safe and/or lambda's elegant style. ▸ Let's check what techniques can improve usability of Kotlin DSL and how we can create Kotlin DSL for existing libraries/APIs. 44 Techniques of Kotlin DSL - Getting Started - Closing ࠓ·Ͱͷ஌ࣝͰɺεΫϥον͔Β؆୯ʹ DSL ͸࡞ΕΔ ܕ҆શͰ͋ͬͨΓɺϥϜμࣜʹΑΔελΠϧͰॻ͖͍͚ͨͩͳΒे෼

Slide 45

Slide 45 text

Break ▸ We can build DSLs easily from scratch with knowledges I have explained ▸ It's enough if you want type-safe and/or lambda's elegant style. ▸ Let's check what techniques can improve usability of Kotlin DSL and how we can create Kotlin DSL for existing libraries/APIs. 45 Techniques of Kotlin DSL - Getting Started - Closing Ͱ͸ͲΜͳςΫχοΫ͕ Kotlin DSL ͷརศੑ΍දݱྗΛ͋͛Δ͔ɺͲ͏΍ͬͯ Kotlin DSL Λ࡞͍͚ͬͯΔͷ͔ΛݟͯΈ·͠ΐ͏

Slide 46

Slide 46 text

Techniques of Kotlin DSL ▸ Getting started ▸ Language specifications ▸ Intermediate ▸ Features for syntactic extensions ▸ Expertise ▸ Build environment stuff of Kotlin 46 Techniques of Kotlin DSL - Intermediate தڃ ߏจ֦ுͷػೳ

Slide 47

Slide 47 text

Syntactic Extension ▸ Extension method ▸ Operator overloading ▸ Infix notation ▸ Method convention ▸ Delegation 47 Techniques of Kotlin DSL - Intermediate - 0/5 ֦ுؔ਺ ԋࢉࢠΦʔόʔϩʔυ தஔه๏ ϝιουن໿ ҕৡ

Slide 48

Slide 48 text

Syntactic Extension ▸ Extension method ▸ Operator overloading ▸ Infix notation ▸ Method convention ▸ Delegations 48 Techniques of Kotlin DSL - Intermediate - 1/5 ֦ுؔ਺

Slide 49

Slide 49 text

Extension Method ▸ Define new member methods w/o inheritances ▸ However, we cannot avoid member visibility restrictions ▸ The benefits of Extension Method for DSL ▸ Can apply the techniques which I will explain later ▸ Can create DSLs without modifying 3rd party libraries 49 Techniques of Kotlin DSL - Intermediate - 1/5 ܧঝͳ͠ʹ৽͍͠ϝϯόʔϝιουΛఆٛͰ͖Δ ͨͩ͠ϝϯόʔՄࢹੑ͸ӽ͑ΒΕͳ͍ ར఺ for DSL ͜ͷ͋ͱઆ໌͢ΔςΫχοΫΛ͋ͱ͔Βద༻͢Δ͜ͱ͕Ͱ͖Δ 3rd party ϥΠϒϥϦΛमਖ਼ͤͣʹ DSL ΛߏஙͰ͖Δ

Slide 50

Slide 50 text

Syntactic Extension ▸ Extension method ▸ Operator overloading ▸ Infix notation ▸ Method convention ▸ Delegations 50 Techniques of Kotlin DSL - Intermediate - 2/5 ԋࢉࢠΦʔόʔϩʔυ

Slide 51

Slide 51 text

Example - kotlinx.html - DOM tree generator in Kotlin ▸ + would become a text node 51 Techniques of Kotlin DSL - Intermediate - 2/5 https://github.com/Kotlin/kotlinx.html + ͷه๏ͰςΩετϊʔυΛ࡞੒Ͱ͖Δ

Slide 52

Slide 52 text

Example - kotlinx.html - DOM tree generator in Kotlin ▸ +"any text" means appending text to the node ▸ + is shorter than *text* 52 Techniques of Kotlin DSL - Intermediate - 2/5 https://github.com/Kotlin/kotlinx.html +<೚ҙͷςΩετ> ͱ͍͏ه๏ͦͷ΋ͷ͕ϊʔυ΁ͷςΩετ௥Ճͱ͍͏ૢ࡞Λද͍ͤͯΔ + ͸ text ΑΓ type ਺͕গͳ͍

Slide 53

Slide 53 text

Operator Overloading ▸ Kotlin allow overload operators for developers ▸ We can assign a logic to several operators like +, -... ▸ The benefits of Operator Overloading for DSL ▸ Basically, operators are shorter than method names ▸ A meaning of an operation is clear 53 Techniques of Kotlin DSL - Intermediate - 2/5 ։ൃऀ͸ԋࢉࢠΛΦʔόʔϩʔυ͢Δ͜ͱ͕Ͱ͖Δ ͭ·ΓɺಠࣗͷϩδοΫΛطଘͷԋࢉࢠʹ͕͋ͯ͑Δ རӹ for DSL ͍͍ͩͨͷέʔεͰԋࢉࢠͷํ͕ϝιου໊ΑΓ୹ͯ͘ࡁΉ ԋࢉࢠ͔Β͘Δૢ࡞ͷҙຯ͕໌ྎ

Slide 54

Slide 54 text

Syntactic Extension ▸ Extension method ▸ Operator overloading ▸ Infix notation ▸ Method convention ▸ Delegations 54 Techniques of Kotlin DSL - Intermediate - 3/5 தஔه๏

Slide 55

Slide 55 text

Example - DSL for Hamcrest API ▸ Not fluent ▸ It might be unclear for non-hamcrest users 55 Techniques of Kotlin DSL - Intermediate - 3/5 ྲྀெͰͳ͍ɺ͗ͪ͜ͳ͍ Hamcrest ͷϢʔβʔҎ֎ʹ͸΍΍ෆ໌ྎ

Slide 56

Slide 56 text

Example - DSL for Hamcrest API ▸ Looks fluent ▸ Hamcrest's knowledge is not required 56 Techniques of Kotlin DSL - Intermediate - 3/5 ࣗવݴޠʹ͍ۙɺྲྀெ Hamcrest ͷυϝΠϯ஌͕͍ࣝΒͳ͍

Slide 57

Slide 57 text

Infix Notation ▸ Allow call a function like *Receiver infix-function argument* ▸ Can omit a dot and parentheses from a method call ▸ The benefits of Infix Notation for DSL ▸ Would be more fluent style ▸ Can reduce domain knowledge 57 Techniques of Kotlin DSL - Intermediate - 3/5 Recever infix-function argument ͷܗͰݺͼग़͕͠Մೳ υοτ΍ׅހΛলུͯ͠ϝιουίʔϧͰ͖Δ རӹ for DSL ΋ͬͱྲྀெͳදݱΛ௥ٻͰ͖Δ υϝΠϯ஌ࣝΛinterface͔ΒݮΒ͢͜ͱ͕Ͱ͖Δ

Slide 58

Slide 58 text

Syntactic Extension ▸ Extension method ▸ Operator overloading ▸ Infix notation ▸ Method convention ▸ Delegations 58 Techniques of Kotlin DSL - Intermediate - 4/5 ϝιουن໿

Slide 59

Slide 59 text

Example - Kotlin DSL for Gradle ▸ debug is not an existing function which accepts closure ▸ It's dynamically generated and be configured by a passed closure 59 Techniques of Kotlin DSL - Intermediate - 4/5 Groovy code https://github.com/gradle/gradle debug ͸ΫϩʔδϟΛड͚औΔΑ͏ͳطଘͷؔ਺Ͱ͸ͳ͍ ಈతʹੜ੒͞Εɺ౉͞ΕͨΫϩʔδϟΛݩʹઃఆ͞ΕΔ

Slide 60

Slide 60 text

Example - Kotlin DSL for Gradle ▸ NOTE: create(String) creates a configurable object for SigningConfig ▸ Prob.: configure is domain knowledge but hidden in Groovy DSL 60 Techniques of Kotlin DSL - Intermediate - 4/5 Groovy code Raw Kotlin code https://github.com/gradle/gradle NOTE: create(String) ͸ ߏ੒ՄೳͳΦϒδΣΫτΛฦ͢ configure ؔ਺͸υϝΠϯ஌͕ࣝͩɺGroovy DSL Ͱ͸Ӆ͞Ε͍ͯΔͱ͍͏໰୊఺

Slide 61

Slide 61 text

Example - Kotlin DSL for Gradle ▸ Implement an invoke function which accepts a lambda ▸ Could hide configure from Kotlin DSL users 61 Techniques of Kotlin DSL - Intermediate - 4/5 https://github.com/gradle/gradle/blob/90974be832395cd5eabff97c18842791d7bee3a8/subprojects/kotlin-dsl/src/main/kotlin/org/gradle/kotlin/dsl/ NamedDomainObjectContainerExtensions.kt#L36 https://github.com/gradle/gradle ϥϜμΛड͚औΕΔ invoke ؔ਺Λఆٛ͢Δ configure Λ Kotlin DSL users ͔ΒӅͤΔ

Slide 62

Slide 62 text

Method Convention ▸ This is a kind of operator overloading ▸ Operators/syntax which Java does not implement manually will be available if a method satisfies a convention ▸ Index-access, invoke, range operator... ▸ The benefits of Method Convention for DSL ▸ Easy to create lambda expressions-based builder by overloading invoke ▸ Can hide domain knowledge bypass a common operator/syntax in Kotlin 62 Techniques of Kotlin DSL - Intermediate - 4/5 ԋࢉࢠΦʔόʔϩʔυͷҰछ ϝιου͕ن໿Λຬͨ͢͜ͱͰɺJava ͕ಠࣗͰ͸ఆٛͰ͖ͳ͍Α͏ͳԋࢉࢠ΍ߏจ͕࢖͑ΔΑ͏ʹͳΔ IndexϕʔεͷΞΫηεɺinvokeɺൣғԋࢉࢠ རӹ for DSL invoke Λఆٛ͢Δ͜ͱͰɺϥϜμࣜϕʔε(ϒϩοΫίʔυ)ͷϏϧμʔͳͲ͕࡞Γ΍͍͢ Kotlin Ͱ͸Α͘࢖ΘΕΔԋࢉࢠ΍ߏจͷதʹɺυϝΠϯ஌ࣝΛӅṭ͢Δ͜ͱ͕Ͱ͖Δ

Slide 63

Slide 63 text

Syntactic Extension ▸ Extension method ▸ Operator overloading ▸ Infix notation ▸ Method convention ▸ Delegation 63 Techniques of Kotlin DSL - Intermediate - 5/5 ҕৡ

Slide 64

Slide 64 text

Example - Kotpref - Android SharedPreferences DSL ▸ SharedPreferences API is low-level ▸ A simple command-query API sequence is required 64 Techniques of Kotlin DSL - Intermediate - 5/5 https://github.com/chibatching/Kotpref SharedPreferences API ͸௿ڃ ୯७ͳίϚϯυΫΤϦAPI Λॱ൪ʹୟ͘ඞཁ͕͋Δ

Slide 65

Slide 65 text

Example - Kotpref - Android SharedPreferences DSL ▸ Hide low-level API and domain knowledge ▸ Writing a value to a property will save it to the preferences but it's hidden 65 Techniques of Kotlin DSL - Intermediate - 5/5 https://github.com/chibatching/Kotpref https://github.com/chibatching/Kotpref ௿ڃ API ΍υϝΠϯ஌ࣝΛӅͤΔ ྫ͑͹propertyʹ஋Λ୅ೖ͢Δͱ SharedPreferences ʹॻ͖ࠐΉ͕ɺͦͷϩδοΫ͸׬શʹӅṭ͞Ε͍ͯΔ

Slide 66

Slide 66 text

Delegation ▸ A property delegates to another object when accessed ▸ The benefits of Delegations for DSL ▸ Can hide domain knowledge ▸ Effective for DRY when using read and write operations to properties 66 Techniques of Kotlin DSL - Intermediate - 5/5 ϓϩϖςΟ͸ΞΫηε͞ΕͨΒଞͷΦϒδΣΫτʹॲཧΛҕৡ͢Δ རӹ for DSL υϝΠϯ஌ࣝΛӅͤΔ ϓϩύςΟʹର͢ΔಡΈॻ͖ૢ࡞ʹؔ͢Δ DRY ʹศར

Slide 67

Slide 67 text

Techniques of Kotlin DSL ▸ Getting started ▸ Language specifications ▸ Intermediate ▸ Features for syntactic extensions ▸ Expertise ▸ Build environment stuff of Kotlin 67 Techniques of Kotlin DSL - Expertise ্ڃ Ϗϧυ؀ڥͱ͔

Slide 68

Slide 68 text

Build Environment Stuff of Kotlin ▸ The plugin system for the compiler ▸ SAM with receiver compiler plugin ▸ Interpolators ▸ DslMarker 68 Techniques of Kotlin DSL - Expertise - 0/2 ίϯύΠϥͷͨΊͷϓϥάΠϯγεςϜ SAM-with-receiver ίϯύΠϥϓϥάΠϯ ิؒࢠ

Slide 69

Slide 69 text

Build Environment Stuff of Kotlin ▸ The plugin system for the compiler ▸ SAM with receiver compiler plugin ▸ Interpolators ▸ DslMarker 69 Techniques of Kotlin DSL - Expertise - 1/2

Slide 70

Slide 70 text

Example - Kotlin DSL for Java Code ▸ Java cannot specify a receiver of SAM so Kotlin cannot use functions with receiver without extension methods 70 Java code Call Container#execute from Kotlin Techniques of Kotlin DSL - Expertise - 1/2 Java ͸ SAM ͷϨγʔόΛࢦఆͰ͖ͳ͍ɻͦͷͨΊ Kotlin ͸Ϩγʔό͖ͭؔ਺Λͦͷ··(֦ுؔ਺ͳ͠)Ͱ͸ѻ͏͜ͱ͕Ͱ͖ͳ͍ɻ

Slide 71

Slide 71 text

▸ Just annotate SAM interfaces and register the annotation to the plugin ▸ An argument of SAM will be a receiver in Kotlin! 71 Techniques of Kotlin DSL - Expertise - 1/2 Example - Kotlin DSL for Java Code SAM interface ʹΞϊςʔγϣϯ͚ͭͯɺϓϥάΠϯʹ͓஌Βͤ͢Δ͚ͩ SAM ͷҾ਺͕ Kotlin Ͱ͸Ϩγʔόʔʹ

Slide 72

Slide 72 text

SAM With Receiver ▸ Control a receiver in SAM conversions ▸ For Kotlin code, but need to modify Java code ▸ The benefits of SAM-with-receiver ▸ Useful when non-Kotlin libraries assume usability of Kotlin DSL ▸ Avoid a bit awkward API in Kotlin 72 Techniques of Kotlin DSL - Expertise - 1/2 https://github.com/JetBrains/kotlin/tree/master/plugins/sam-with-receiver SAM ม׵࣌ͷϨγʔόʔΛ͍͡ΕΔ Kotlin code ͷͨΊͷػೳ͚ͩͲɺJava ଆΛमਖ਼͢Δඞཁ͕͋Δ རӹ for DSL Kotlin ͡Όͳ͍ϥΠϒϥϦ͕ Kotlin DSL ͷͨΊͷརศੑΛߟ͑Δͱ͖ʹ༗༻ Kotlin Ͱͪΐͬͱ͗ͪ͜ͳ͍ײ͡ͷ API ʹͳΔͷΛճආͰ͖Δ

Slide 73

Slide 73 text

SAM With Receiver - Example - Kotlin DSL for Gradle ▸ Action API is widely used so SAM-with-receiver is better than extensions 73 https://github.com/gradle/gradle/commit/18aebdba33cd9e1be966cc286a11d3ce86a28e4f Techniques of Kotlin DSL - Expertise - 1/2 https://github.com/gradle/gradle Action API ͸ΊͬͪΌ࢖ΘΕͯΔͷͰɺSAM-with-receiver ͷํ͕֦ுؔ਺ΑΓྑ͍

Slide 74

Slide 74 text

Build Environment Stuff of Kotlin ▸ The plugin system for the compiler ▸ SAM with receiver compiler plugin ▸ Interpolators ▸ DslMarker 74 Techniques of Kotlin DSL - Expertise - 1/2

Slide 75

Slide 75 text

Example - Pseudo Dom Tree Builder ▸ head tag in head tag should be forbidden! 75 Techniques of Kotlin DSL - Expertise - 2/2 head tag ͷதʹ head tag ͸ஔ͍ͪΌ͍͚ͳ͍

Slide 76

Slide 76 text

▸ Add an annotation of @DslMarker to receiver classes or superclasses (and functions if necessary) 76 Techniques of Kotlin DSL - Expertise - 2/2 Example - Pseudo Dom Tree Builder DslMarker ͷΞϊςʔγϣϯΛϨγʔόʔͷΫϥε΍εʔύʔΫϥεʹ͚ͭΔ

Slide 77

Slide 77 text

▸ Show an error because of implicit receiver violation! 77 Techniques of Kotlin DSL - Expertise - 2/2 Example - Pseudo Dom Tree Builder ͢Δͱɺ҉໧తʹղܾ͞ΕͨϨγʔόʔ͕ҧ൓ѻ͍ͱͳͬͯΤϥʔ͕දࣔ͞ΕΔ

Slide 78

Slide 78 text

DslMarker ▸ Kotlin's only DSL specific feature as far as I know ▸ Add a constraint of a caller scope and can raise errors if invalid ▸ The benefits of DslMarker for DSL ▸ This is required to make your DSL safe ▸ Be developers' help because IntelliJ highlight marked functions 78 Techniques of Kotlin DSL - Expertise - 2/2 ஌ΔݶΓɺKotlin ʹ͓͚Δ DSLಛԽͨ͠།Ұͷػೳ ݺͼग़͠ͷείʔϓʹ੍໿Λ͚ͭΔ͜ͱ͕Ͱ͖ͯɺҧ൓ͯͨ͠ΒΤϥʔͱͰ͖Δ རӹ for DSL DSL ͷ҆શੑΛߴΊΔͨΊʹ͸ඞਢ ։ൃऀͷॿ͚ʹͳΔɻIntelliJ ͸ϚʔΫ͞Εͨؔ਺ʹରͯ͠ಠࣗͷϋΠϥΠτΛ͔͚ͯ͘ΕΔ

Slide 79

Slide 79 text

DslMarker - Example - kotlinx.html ▸ Of course, kotlinx.html uses DslMarker to build DOM tree correctly ▸ html, head, body are marked functions so highlighted 79 Techniques of Kotlin DSL - Expertise - 2/2 kotlinx.html ͸΋ͪΖΜར༻͍ͯͯ͠ɺ͜ΕͰਖ਼͘͠ DOM tree Λ࡞ΕΔΑ͏ʹ͍ͯ͠Δ html, head ͱ͔͕ϋΠϥΠτ͞ΕͯΔΑͶ

Slide 80

Slide 80 text

Build Environment Stuff of Kotlin - Limitations ▸ Compiler plugin stuff is undocumented ▸ Complex logic is hard to be implemented ▸ Maintainability... ▸ DslMarker needs be annotated to classes, so it's unavailable for existing libraries 80 Techniques of Kotlin DSL - Expertise - Closing ίϯύΠϥʔϓϥάΠϯ͸υΩϡϝϯτ͞Εͯͳ͍ ੍ݶ ෳࡶͳϩδοΫ͸ݫ͍͠ อकੑΣɾɾɾ DslMarker ͸ΫϥεʹΞϊςʔγϣϯΛ͚ͭΔඞཁ͕͋ͬͯɺͭ·ΓطଘϥΠϒϥϦͰ͸࢖͑ͳ͍

Slide 81

Slide 81 text

Quick tips for DSL development 81 DSL ։ൃͷͨΊͷͪΐͬͱͨ͠ tips

Slide 82

Slide 82 text

Differences Between API and DSL ▸ Technically, nothing special but... ▸ The concepts of the interface design are different ▸ DSL is focusing on the domain ▸ DSL is well-designed API set for the domain but also limited ▸ We should not assume DSL can work as general APIs 82 Quick Tips 1/4 ٕज़తʹͳΜ͔ҧ͍ͱ͔͸ͳ͍ API ͱ DSL ͷҧ͍ interface ͷઃܭίϯηϓτ͕ҟͳΔ DSL ͸υϝΠϯʹॏ͖Λஔ͍ͯΔ DSL ͸υϝΠϯʹରͯ͠Α͘࿅ΒΕͨ API ηοτ͚ͩͲɺͦͷ෼੍ݶ΋͋Δ DSL ͕൚༻తͳ API ͱͯ͠ಈ͘ͱ૝ఆ͢Δ΂͖Ͱ͸ͳ͍

Slide 83

Slide 83 text

Quick Tips 2/4 Adapt Kotlin DSL to Existing Libraries ▸ Aggregate existing APIs by extension method ▸ Use Operator overloading, Infix operators, Method conventions ▸ Create DTOs if you would like to use DslMarker 83 ֦ுؔ਺Ͱطଘ API Λू໿͢Δͱ͜Ζ͔Βߟ͑Δ طଘϥΠϒϥϦ΁ͷ Kotlin DSL ͷద༻ ԋࢉࢠΦʔόʔϩʔυɺதஔه๏ɺϝιουن໿Λ࢖͍͖ͬͯ·͠ΐ͏ DslMarker Λ࢖͍͍ͨͳΒࣗલͰ Data transfer object Λ࡞ͬͯରԠ͠·͠ΐ͏

Slide 84

Slide 84 text

Quick Tips 3/4 How To Keep Both Usabilities of Kotlin DSL and Other JVM Languages ▸ Java -> Kotlin DSL ▸ Use SAM with receiver ▸ Kotlin DSL -> Other JVM languages ▸ Provide method chaining interface because of functions with receiver issue ▸ Provide alternative non-inline APIs because of inline features' availability ▸ Split API for other JVM languages and Kotlin DSL 84 Kotlin DSL ΛJava ϥΠϒϥϦʹద༻͢Δέʔε Ͳ͏΍ͬͯ Kotlin DSL ͱଞJVMݴޠͱͰརศੑΛҡ࣋͢Δ͔ ͪΌΜͱ sam-with-receiver Λ࢖͍·͠ΐ͏ Kotlin DSL ͷ interface ΛଞJVMݴޠ͔Β࢖͏έʔε Ϩγʔόʔ͖ͭؔ਺Ϧςϥϧ໰୊͕͋ΔͷͰɺϝιουνΣʔϯࣜͷ interface ͳͲΛผ్༻ҙ͢Δ inline ܥػೳͷՄࢹੑ໰୊͕͋ΔͷͰɺinline ͡Όͳ͍ API Λผ్ఏڙ͢Δ ଞJVMݴޠ༻్ͷ API ͱ Kotlin DSL ͸෼͚࣮ͯ૷͢Δ

Slide 85

Slide 85 text

Quick Tips 3/4 How To Keep Both Usabilities of Kotlin DSL and Other JVM Languages ▸ Java -> Kotlin DSL ▸ Use SAM with receiver ▸ Kotlin DSL -> Other JVM languages ▸ Provide method chaining interface because of receiver issue ▸ Provide alternative non-inline APIs because of inline vibisility ▸ Split API for other jvm languages and Kotlin DSL ▸ Other JVM languages -> Kotlin DSL : I don't know, sorry 85 JavaҎ֎ͷJVMݴޠʹ Kotlin DSL ΛషΔͱ͖ : ͢Έ·ͤΜɺܦݧෆ଍ͰΘ͔Μͳ͍Ͱ͢

Slide 86

Slide 86 text

Quick Tips 4/4 For Advanced Steps ▸ Read Martin Fowler's DSL Patterns if you want to know DSL interfaces ▸ Good examples of Kotlin DSL ▸ See appendix! 86 ͦͷ·ͨઌ΁ DSL ͷΠϯλʔϑΣʔεʹ͍ͭͯ஌Γ͍ͨ৔߹͸Martin Fowler ͷ DSL ύλʔϯ͸ಡΈ·͠ΐ͏ Kotlin DSL ͷྑ͍ྫ ༨ന͕ͳ͔ͬͨͷͰ Appendix Λݟ͍ͯͩ͘͞

Slide 87

Slide 87 text

Closing 87

Slide 88

Slide 88 text

Closing Summary 1/3 ▸ Kotlin DSL is ▸ A pure Kotlin code ▸ Not only for Kotlin libraries ▸ Built on several techniques 88 ७ਮͳ Kotlin ίʔυ Kotlin Ͱॻ͔ΕͨϥΠϒϥϦͷͨΊ͚ͩ͡Όͳ͍Α ͍͔ͭ͘ͷٕज़ͷ্ʹ੒ΓཱͬͯΔΑ

Slide 89

Slide 89 text

Summary 2/3 ▸ Language specs ▸ Static type ▸ Lambda expressions w/ receiver control ▸ Language features ▸ Extension method, operator overloading, infix notation, method convention, delegation ▸ Build environment features ▸ SAM-with-receiver, DslMarker 89 Closing ੩తܕ෇͚ ϥϜμࣜͱϨγʔόʔͷ؅ཧ ݴޠ࢓༷ ݴޠػೳ ֦ுؔ਺ɺԋࢉࢠΦʔόʔϩʔυɺதஔه๏ɺϝιουن໿ɺҕৡ Ϗϧυ؀ڥܥ

Slide 90

Slide 90 text

Summary 3/3 ▸ DslMarker is the only DSL specific feature but improves safety! ▸ Kotlin DSL can extend existing libraries with only a few constraints ▸ We can co-exist usability for the both of Kotlin and other JVM languages ▸ If you work hard 90 Closing DslMarker ͚͕ͩ Kotlin DSL ༻ͷಛԽػೳɻ҆શੑΛ޲্Ͱ͖Δ(࢖͍·͠ΐ͏) Kotlin DSL ͸طଘϥΠϒϥϦΛͪΐͬͱ੍ͨ͠໿͖͚ͭͩͲ֦ுͰ͖Δ Kotlin DSL ͱଞJVMݴޠͰͷརศੑ͸ڞଘՄೳ(ͨͩ͠ؤுΕ͹)

Slide 91

Slide 91 text

Appendix 1/2 ▸ Books ▸ Domain Specific Languages by M. Fowler with R. Parsons ▸ DSLs in Action by D. Ghosh ▸ Dsl Engineering: Designing, Implementing and Using Domain-specific Languages by M. Voelter ▸ Kotlin in Action by D. Jemerrov and S. Isakova ▸ Web/Blog ▸ Catalog of DSL Patterns https://martinfowler.com/dslCatalog/ ▸ Kotlin DSL: From Theory to Practice https://dzone.com/articles/kotlin-dsl-from-theory-to-practice ▸ Writing a Kotlin DSL (series) https://proandroiddev.com/writing-dsls-in-kotlin-part-1-7f5d2193f277 ▸ Idiomatic Kotlin. Best Practices. https://phauer.com/2017/idiomatic-kotlin-best-practices/ ▸ and more... 91 Closing

Slide 92

Slide 92 text

Appendix 2/2 ▸ Libraries ▸ Build system : gradle/gradle/tree/master/subprojects/kotlin-dsl ▸ Android : android-ktx, Jetpack Compose, Kotlin/anko, JakeWharton/kotterknife, chibatching/Kotpref, infotech-group/ android-drawable-dsl, agoda-com/Kakao ▸ Web : Kotlin/kotlinx.html, perwendel/spark-kotlin, spring-projects/spring-fu, ktorio/ktor ▸ Testing libraries : MarkusAmshove/Kluent, winterbe/expekt, npryce/hamkrest, nhaarman/mockito-kotlin, kotlintest/ kotlintest, spekframework/spek ▸ DI containers : Kodein-Framework/Kodein-DI, Ekito/koin, authzee/kotlin-guice ▸ Otherwise: skrapeit/skrape.it, JetBrains/Exposed, x2bool/kuery, ruslanys/telegraff, ▸ Words ▸ Kotlin DSL, DSL, kotlish, type builder, kotlinize, idiomatic Kotlin 92 Closing

Slide 93

Slide 93 text

Fin. Thank You for Listening! ▸ Jumpei Matsuda / daruma ▸ Software Engineer @DeployGate ▸ GitHub: jmatsu ▸ Twitter: red_fat_daruma ▸ Please feel free to ask questions ▸ ೔ຊޠŧŔŕŪũƄŝſ (Ӊ౎ٶҭͪͷ७೔ຊਓͰ͢) 93