SlideShare a Scribd company logo
1 of 71
Download to read offline
Kotlin DSL
2018 10/12
Kamedon
•
• Kotlin
•
•
• DSL
•
• DSL Kotlin
DSL
DSL
• domain-specific language/ )
• DSL
(wikipedia )
• 

• DSL 

Builder
//Java
Human human= new Human.Builder()
.setName("Kamedon")
.setAge(30)
.build();
//Kotlin
class Human(val name: String, val age: Int)
Human(age = 30, name = "Kamedon")
if(human.isAdult()){
//成人だったらなにかする
}
Build DSL
buildscript {
ext.kotlin_version = '1.2.70'
repositories {
google()
jcenter()
maven {
url 'http://kamedon.github.com/Validation/repository'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:
$kotlin_version"
}
}
•
Layout Anko)
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
•
• LinearLayout
DI DSL(Kodein)
Kodein {
bind<Presenter>() with singleton {
Presenter(instance(), inetance())
}
}
val presenter: Presenter by instance()
•
•
DSL
•
•
• IDE
• Sansan Kotlin DSL
DSL
•
•
• Kotlin 

Java DSL
• DSL Kotlin
DSL
• Validation DSL
• DSL
• Validation 

https://github.com/kamedon/Validation
Step1.
• 

• 

[ ]

5 10 

[ ]

20
•
•
•
•
Step2. DSL
DSL (1)
•
• 5
•
• A be B
DSL (2)
•
• 5 

• A be B 

not
• A be B not Message
DSL
be not
be not
be not
be not
be not
DSL
be not
be not
be not
be not
be not
Validation<User> {
"name"{
be { name.isNotBlank() } not "入力してください"
be { name.length >= 5 } not "5文字以上入力"
be { name.length <= 10 } not "10文字以下で入力"
}
"age"{
be { age >= 0 } not "入力してください"
be { age >= 20 } not "20歳以上で入力"
}
}
•
Step3.
be
be not
be not
•
• Pair Triple 

Build
• 

DSL
• DSL
data class User(val name: String, val age: Int)
class ValidationTest {
@Test
fun dslTest() {
Validation<User> {}
}
}
Validation<User> {}
• operator invoke companion object 

• companion object Java static
•
•
operator invoke
• Kotlin +,-, a..b , a in b, 

• invoke
class K {
operator fun invoke(value: Int) = value * 1000
}
val k = K()
k.invoke(1)
k(1) // invokeは省略可能
fun Int.k() = this * 1000
val kg = 1.k() //1000
public static final int k(int $receiver) {
return $receiver * 1000;
}
}
•
• static
• 

+ operator invoke
• operator invoke
operator fun String.invoke(){}
"name"()

operator fun String.invoke(f: ()->Unit){}
"name"({})
"name"{}
• Lambda)
• Syntax Suger
val kg: (Int) -> Int = fun(value: Int): Int {
return value * 1000
}
val kg = { value: Int -> value * 1000 }
kg.invoke(1) //invokeメソッドが作られる
kg(1) //invokeは省略可能
class Sample {
fun task(f: (String) -> Unit) {
//taskする
f("Hello")
}
fun task2(f: String.() -> Unit) {
//taskする
"Hello".f()
}
}
class Test {
fun task() {
val sample = Sample()
sample.task {
print(this::class.java.name)
print(it.length)
}
sample.task2 {
print(this::class.java.name)
print(length)
}
}
}


// f: String.() -> Unit)
public static final String f(@NotNull String $receiver)
// f: (String) -> Unit)
public static final String f($receiver: Test, @NotNull String it)
•
• {} this
Validation{}
class Validation<T> {
companion object {
operator fun <T>
invoke(init: Validation<T>.() -> Unit): Validation<T> {
return Validation<T>().apply(init)
}
}
}
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
@Test
fun dslTest() {
Validation<User> {
"name"{}
}
}
•
• {}
• +
{}
class Validation<T> {
operator fun String.invoke(init: () -> Unit)
}
• Validation 

Validation
•
{}
•
• ChildValidation
• {} ChildValidation
• ChildValidation
• ChildValidation Validation
be not
be not
be not
be not
{}
class Validation<T> {
val validations = mutableMapOf<String, ChildValidation<T>>()
operator fun String.invoke(
init: ChildValidation<T>.() -> Unit
) {
validations.put(this, ChildValidation<T>().apply(init))
}
}
•
• String.invoke ChildValidation
• ChildValidation Validations 

be {}
@Test
fun dslTest() {
Validation<User> {
"name"{
be { name.isNotBlank() }
}
}
}
•
be
• name
"name"{
be { name.isNotBlank() }
this.be { name.isNotBlank() }
this.be({ name.isNotBlank() })
this.be({ this.name.isNotBlank() })
}
• 

ßbe
class Validation<T> {
operator fun String.invoke(init: ChildValidation<T>.() -> Unit)
}
class ChildValidation<T> {
fun be(f: T.() -> Boolean) {}
}
•
• String{} ChildValidation
• be ChildValidation
• User(T)
• T boolean
(infix)
infix fun Int.k(str: String): String {
return "${this * 1000}$str"
}
val kg = 1.k("g") //1000g
val kg = 1 k "g" //1000g
•
• 1 infix
•
be {} not message
@Test
fun dslTest() {
Validation<User> {
"name"{
be { name.isNotBlank() } not "入力してください"
}
}
}
•
be not
not
val validation = be { name.isNotBlank() } not "入力してください"
if(!validation(user)) {
return errorMessage
}
• 

1
• {} not
• be {} /
class ChildValidation<T> {
fun be(f: T.() -> Boolean) = f
infix fun (T.() -> Boolean).not(message: String)
}
•
• be
• not
DSL
Validation<User> {
"name"{
be { name.isNotBlank() } not "入力してください"
be { name.length >= 5 } not "5文字以上入力"
be { name.length <= 10 } not "10文字以下で入力"
}
"age"{
be { age >= 0 } not "入力してください"
be { age >= 20 } not "20歳以上で入力"
}
}
•
class Validation<T>
(val validations: Map<String, ChildValidation<T>>)
class ChildValidation<T> {
val validations: MutableList<Pair<T.() -> Boolean, String>>
= mutableListOf()
}
• ChildValidation Validation
• <Pair<T.() -> Boolean, String> ChildValidation
ChildValidation
"name"{
be { name.isNotBlank() } not "入力してください"
be { name.length >= 0 } not "5文字以上で入力"
}
class ChildValidation<T> {
val validations =
mutableListOf<Pair<T.() -> Boolean, String>>()
infix fun be(f: T.() -> Boolean) = f
infix fun (T.() -> Boolean).not(message: String) {
validations.add(Pair(this, message))
}
}
Validation
ChildValidation
Validation<User> {
"name"{
be { name.isNotBlank() } not "入力してください"
}
}
class Validation<T> {
val validations = mutableMapOf<String, ChildValidation<T>>()
operator fun String.invoke(init: ChildValidation<T>.() -> Unit) {
validations.put(this, ChildValidation<T>().apply(init))
}
}
•
DSL
Validation<User> {
"name"{
}
}
class Validation<T> {
val validations = mutableMapOf<String, ChildValidation<T>>()
operator fun String.invoke(init: ChildValidation<T>.() -> Unit) {
validations.put(this, ChildValidation<T>().apply(init))
}
companion object {
inline operator fun <T> invoke(
init: Validation<T>.() -> Unit): Validation<T> {
return Validation<T>().apply(init)
}
}
}
DSL
be { name.isNotBlank() } not "入力してください"
class ChildValidation<T> {
val validations = mutableListOf<Pair<T.() -> Boolean, String>>()
infix fun be(f: T.() -> Boolean) = f
infix fun (T.() -> Boolean).not(message: String) {
validations.add(Pair(this, message))
}
}
•
DSL
Validation<User> {
"name"{
be { name.isNotBlank() } not "入力してください"
be { name.length >= 5 } not "5文字以上入力"
be { name.length <= 10 } not "10文字以下で入力"
}
"age"{
be { age >= 0 } not "入力してください"
be { age >= 20 } not "20歳以上で入力"
}
}
•
validate
Validate
class Validation<T> {
val validations = mutableMapOf<String, ChildValidation<T>>()
fun validate(value: T): Map<String, List<String>> {
val messages = mutableMapOf<String, List<String>>()
validations.forEach { map ->
val errors = map.value.validations.asSequence()
.filter { !it.first.invoke(value) }
.map { it.second }
.filter { it.isNotEmpty() }
.toList()
if(errors.isNotEmpty()){
messages.put(map.key, errors)
}
}
return messages
}
}
DSL OK
val user = User("kamedon", 30)
val v = Validation<User> {
"name"{
be { name.isNotBlank() } not "入力してください"
be { name.length >= 5 } not "5文字以上入力"
be { name.length <= 10 } not "10文字以下で入力"
}
"age"{
be { age >= 0 } not "入力してください"
be { age >= 20 } not "20歳以上で入力"
}
}
v.validate(user)
•
DSL NG
val user = User("k", 10)
val v = Validation<User> {
"name"{
be { name.isNotBlank() } not "入力してください"
be { name.length >= 5 } not "5文字以上入力"
be { name.length <= 10 } not "10文字以下で入力"
}
"age"{
be { age >= 0 } not "入力してください"
be { age >= 20 } not "20歳以上で入力"
}
}
v.validate(user)
{name=[5文字以上入力], age=[20歳以上で入力]}
•
Step4.
• Pair
• Builder var build val
• mutable immutable
• DSL 

DSL Builder
class Validation<T> {
val validations = mutableMapOf<String, ChildValidation<T>>()
operator fun String.invoke(init: ChildValidation<T>.() -> Unit) {
validations.put(this, ChildValidation<T>().apply(init))
}
companion object {
inline operator fun <T> invoke(
init: Validation<T>.() -> Unit): Validation<T> {
return Validation<T>().apply(init)
}
}
fun validate(value: T): Map<String, List<String>>
}
DSL Builder
class ValidationBuilder<T> {
val validations = mutableMapOf<String, ChildValidation<T>>()
operator fun String.invoke(init: ChildValidation<T>.() -> Unit) {
validations.put(this, ChildValidation<T>().apply(init))
}
fun build(): Validation<T> {
return Validation(validations)
}
}
class Validation<T>(val validations: Map<String, ChildValidation<T>>) {
companion object {
inline operator fun <T> invoke(
init: ValidationBuilder<T>.() -> Unit): Validation<T> {
val builder = ValidationBuilder<T>().apply(init)
return builder.build()
}
}
}
Step5.
• object DSL
• inline GC
•
• interface
Validation<User> {
"name"{
be { name.length >= 5 } not "5文字以下"
be { name.length <= 10 } not "10文字以下"
}
"age"{
be { age >= 20 } not error message { "20歳以上" }
be { age <= 150 } not with callback ("150歳以下"){
print("callback")
}
}
}
•
11/2 

• Java
• DSL
• IDE DSL
• DSL
• var val : Builder
• {} : lambda lambda
• ()
• : operator invoke
• : (Extensions Functions or
Properties)
• : infix)
• DSL
•
• 

Validation GitHub 

11/2
つくってあそぼ Kotlin DSL 第2版

More Related Content

What's hot

Software architecture2008 ejbql-quickref
Software architecture2008 ejbql-quickrefSoftware architecture2008 ejbql-quickref
Software architecture2008 ejbql-quickref
jaiverlh
 

What's hot (18)

JDD 2016 - Pawel Byszewski - Kotlin, why?
JDD 2016 - Pawel Byszewski - Kotlin, why?JDD 2016 - Pawel Byszewski - Kotlin, why?
JDD 2016 - Pawel Byszewski - Kotlin, why?
 
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de pro...
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIO
 
The Ring programming language version 1.5.2 book - Part 33 of 181
The Ring programming language version 1.5.2 book - Part 33 of 181The Ring programming language version 1.5.2 book - Part 33 of 181
The Ring programming language version 1.5.2 book - Part 33 of 181
 
Software architecture2008 ejbql-quickref
Software architecture2008 ejbql-quickrefSoftware architecture2008 ejbql-quickref
Software architecture2008 ejbql-quickref
 
Parsing with Perl6 Grammars
Parsing with Perl6 GrammarsParsing with Perl6 Grammars
Parsing with Perl6 Grammars
 
The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185
 
Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)
 
The Ring programming language version 1.9 book - Part 42 of 210
The Ring programming language version 1.9 book - Part 42 of 210The Ring programming language version 1.9 book - Part 42 of 210
The Ring programming language version 1.9 book - Part 42 of 210
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
 
Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCode
 
The Ring programming language version 1.10 book - Part 40 of 212
The Ring programming language version 1.10 book - Part 40 of 212The Ring programming language version 1.10 book - Part 40 of 212
The Ring programming language version 1.10 book - Part 40 of 212
 
Specs2
Specs2Specs2
Specs2
 
The Ring programming language version 1.10 book - Part 47 of 212
The Ring programming language version 1.10 book - Part 47 of 212The Ring programming language version 1.10 book - Part 47 of 212
The Ring programming language version 1.10 book - Part 47 of 212
 
Understanding Async/Await in Javascript
Understanding Async/Await in JavascriptUnderstanding Async/Await in Javascript
Understanding Async/Await in Javascript
 

Similar to つくってあそぼ Kotlin DSL 第2版

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
patforna
 

Similar to つくってあそぼ Kotlin DSL 第2版 (20)

Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin WayTDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
 
First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examples
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Introduction kot iin
Introduction kot iinIntroduction kot iin
Introduction kot iin
 
Kotlin
KotlinKotlin
Kotlin
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick Introduction
 
Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Why Scala is the better Java
Why Scala is the better JavaWhy Scala is the better Java
Why Scala is the better Java
 
Functional Scala 2020
Functional Scala 2020Functional Scala 2020
Functional Scala 2020
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
Oop objects_classes
Oop objects_classesOop objects_classes
Oop objects_classes
 
The Future of JVM Languages
The Future of JVM Languages The Future of JVM Languages
The Future of JVM Languages
 
Kotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projects
 
Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016
Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016
Kotlin Developer Starter in Android - STX Next Lightning Talks - Feb 12, 2016
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 

Recently uploaded (20)

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Choreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringChoreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software Engineering
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern Enterprise
 

つくってあそぼ Kotlin DSL 第2版

  • 4. DSL
  • 5. DSL • domain-specific language/ ) • DSL (wikipedia ) • 

  • 7. Builder //Java Human human= new Human.Builder() .setName("Kamedon") .setAge(30) .build(); //Kotlin class Human(val name: String, val age: Int) Human(age = 30, name = "Kamedon") if(human.isAdult()){ //成人だったらなにかする }
  • 8. Build DSL buildscript { ext.kotlin_version = '1.2.70' repositories { google() jcenter() maven { url 'http://kamedon.github.com/Validation/repository' } } dependencies { classpath 'com.android.tools.build:gradle:3.1.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin: $kotlin_version" } } •
  • 9. Layout Anko) verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } } • • LinearLayout
  • 10. DI DSL(Kodein) Kodein { bind<Presenter>() with singleton { Presenter(instance(), inetance()) } } val presenter: Presenter by instance() • •
  • 12. DSL • • • Kotlin 
 Java DSL • DSL Kotlin
  • 13. DSL
  • 14. • Validation DSL • DSL • Validation 
 https://github.com/kamedon/Validation
  • 16. • 
 • 
 [ ]
 5 10 
 [ ]
 20
  • 17.
  • 21. DSL (2) • • 5 
 • A be B 
 not • A be B not Message
  • 22. DSL be not be not be not be not be not
  • 23. DSL be not be not be not be not be not
  • 24. Validation<User> { "name"{ be { name.isNotBlank() } not "入力してください" be { name.length >= 5 } not "5文字以上入力" be { name.length <= 10 } not "10文字以下で入力" } "age"{ be { age >= 0 } not "入力してください" be { age >= 20 } not "20歳以上で入力" } } •
  • 27. • • Pair Triple 
 Build • 
 DSL • DSL
  • 28. data class User(val name: String, val age: Int) class ValidationTest { @Test fun dslTest() { Validation<User> {} } }
  • 29. Validation<User> {} • operator invoke companion object 
 • companion object Java static • •
  • 30. operator invoke • Kotlin +,-, a..b , a in b, 
 • invoke class K { operator fun invoke(value: Int) = value * 1000 } val k = K() k.invoke(1) k(1) // invokeは省略可能
  • 31. fun Int.k() = this * 1000 val kg = 1.k() //1000 public static final int k(int $receiver) { return $receiver * 1000; } } • • static • 

  • 32. + operator invoke • operator invoke operator fun String.invoke(){} "name"()
 operator fun String.invoke(f: ()->Unit){} "name"({}) "name"{}
  • 33. • Lambda) • Syntax Suger val kg: (Int) -> Int = fun(value: Int): Int { return value * 1000 } val kg = { value: Int -> value * 1000 } kg.invoke(1) //invokeメソッドが作られる kg(1) //invokeは省略可能
  • 34. class Sample { fun task(f: (String) -> Unit) { //taskする f("Hello") } fun task2(f: String.() -> Unit) { //taskする "Hello".f() } }
  • 35. class Test { fun task() { val sample = Sample() sample.task { print(this::class.java.name) print(it.length) } sample.task2 { print(this::class.java.name) print(length) } } }
  • 36. 
 // f: String.() -> Unit) public static final String f(@NotNull String $receiver) // f: (String) -> Unit) public static final String f($receiver: Test, @NotNull String it) • • {} this
  • 37. Validation{} class Validation<T> { companion object { operator fun <T> invoke(init: Validation<T>.() -> Unit): Validation<T> { return Validation<T>().apply(init) } } } public inline fun <T> T.apply(block: T.() -> Unit): T { block() return this }
  • 38. @Test fun dslTest() { Validation<User> { "name"{} } } • • {} • +
  • 39. {} class Validation<T> { operator fun String.invoke(init: () -> Unit) } • Validation 
 Validation •
  • 40. {} • • ChildValidation • {} ChildValidation • ChildValidation • ChildValidation Validation
  • 41. be not be not be not be not
  • 42. {} class Validation<T> { val validations = mutableMapOf<String, ChildValidation<T>>() operator fun String.invoke( init: ChildValidation<T>.() -> Unit ) { validations.put(this, ChildValidation<T>().apply(init)) } } • • String.invoke ChildValidation • ChildValidation Validations 

  • 43. be {} @Test fun dslTest() { Validation<User> { "name"{ be { name.isNotBlank() } } } } • be • name
  • 44. "name"{ be { name.isNotBlank() } this.be { name.isNotBlank() } this.be({ name.isNotBlank() }) this.be({ this.name.isNotBlank() }) } • 
 ßbe
  • 45. class Validation<T> { operator fun String.invoke(init: ChildValidation<T>.() -> Unit) } class ChildValidation<T> { fun be(f: T.() -> Boolean) {} } • • String{} ChildValidation • be ChildValidation • User(T) • T boolean
  • 46. (infix) infix fun Int.k(str: String): String { return "${this * 1000}$str" } val kg = 1.k("g") //1000g val kg = 1 k "g" //1000g • • 1 infix •
  • 47. be {} not message @Test fun dslTest() { Validation<User> { "name"{ be { name.isNotBlank() } not "入力してください" } } } • be not not
  • 48. val validation = be { name.isNotBlank() } not "入力してください" if(!validation(user)) { return errorMessage } • 
 1 • {} not • be {} /
  • 49. class ChildValidation<T> { fun be(f: T.() -> Boolean) = f infix fun (T.() -> Boolean).not(message: String) } • • be • not DSL
  • 50. Validation<User> { "name"{ be { name.isNotBlank() } not "入力してください" be { name.length >= 5 } not "5文字以上入力" be { name.length <= 10 } not "10文字以下で入力" } "age"{ be { age >= 0 } not "入力してください" be { age >= 20 } not "20歳以上で入力" } } •
  • 51. class Validation<T> (val validations: Map<String, ChildValidation<T>>) class ChildValidation<T> { val validations: MutableList<Pair<T.() -> Boolean, String>> = mutableListOf() } • ChildValidation Validation • <Pair<T.() -> Boolean, String> ChildValidation
  • 52. ChildValidation "name"{ be { name.isNotBlank() } not "入力してください" be { name.length >= 0 } not "5文字以上で入力" } class ChildValidation<T> { val validations = mutableListOf<Pair<T.() -> Boolean, String>>() infix fun be(f: T.() -> Boolean) = f infix fun (T.() -> Boolean).not(message: String) { validations.add(Pair(this, message)) } }
  • 53. Validation ChildValidation Validation<User> { "name"{ be { name.isNotBlank() } not "入力してください" } } class Validation<T> { val validations = mutableMapOf<String, ChildValidation<T>>() operator fun String.invoke(init: ChildValidation<T>.() -> Unit) { validations.put(this, ChildValidation<T>().apply(init)) } } •
  • 54. DSL Validation<User> { "name"{ } } class Validation<T> { val validations = mutableMapOf<String, ChildValidation<T>>() operator fun String.invoke(init: ChildValidation<T>.() -> Unit) { validations.put(this, ChildValidation<T>().apply(init)) } companion object { inline operator fun <T> invoke( init: Validation<T>.() -> Unit): Validation<T> { return Validation<T>().apply(init) } } }
  • 55. DSL be { name.isNotBlank() } not "入力してください" class ChildValidation<T> { val validations = mutableListOf<Pair<T.() -> Boolean, String>>() infix fun be(f: T.() -> Boolean) = f infix fun (T.() -> Boolean).not(message: String) { validations.add(Pair(this, message)) } } •
  • 56. DSL Validation<User> { "name"{ be { name.isNotBlank() } not "入力してください" be { name.length >= 5 } not "5文字以上入力" be { name.length <= 10 } not "10文字以下で入力" } "age"{ be { age >= 0 } not "入力してください" be { age >= 20 } not "20歳以上で入力" } } • validate
  • 57. Validate class Validation<T> { val validations = mutableMapOf<String, ChildValidation<T>>() fun validate(value: T): Map<String, List<String>> { val messages = mutableMapOf<String, List<String>>() validations.forEach { map -> val errors = map.value.validations.asSequence() .filter { !it.first.invoke(value) } .map { it.second } .filter { it.isNotEmpty() } .toList() if(errors.isNotEmpty()){ messages.put(map.key, errors) } } return messages } }
  • 58. DSL OK val user = User("kamedon", 30) val v = Validation<User> { "name"{ be { name.isNotBlank() } not "入力してください" be { name.length >= 5 } not "5文字以上入力" be { name.length <= 10 } not "10文字以下で入力" } "age"{ be { age >= 0 } not "入力してください" be { age >= 20 } not "20歳以上で入力" } } v.validate(user) •
  • 59. DSL NG val user = User("k", 10) val v = Validation<User> { "name"{ be { name.isNotBlank() } not "入力してください" be { name.length >= 5 } not "5文字以上入力" be { name.length <= 10 } not "10文字以下で入力" } "age"{ be { age >= 0 } not "入力してください" be { age >= 20 } not "20歳以上で入力" } } v.validate(user) {name=[5文字以上入力], age=[20歳以上で入力]} •
  • 61. • Pair • Builder var build val • mutable immutable • DSL 

  • 62. DSL Builder class Validation<T> { val validations = mutableMapOf<String, ChildValidation<T>>() operator fun String.invoke(init: ChildValidation<T>.() -> Unit) { validations.put(this, ChildValidation<T>().apply(init)) } companion object { inline operator fun <T> invoke( init: Validation<T>.() -> Unit): Validation<T> { return Validation<T>().apply(init) } } fun validate(value: T): Map<String, List<String>> }
  • 63. DSL Builder class ValidationBuilder<T> { val validations = mutableMapOf<String, ChildValidation<T>>() operator fun String.invoke(init: ChildValidation<T>.() -> Unit) { validations.put(this, ChildValidation<T>().apply(init)) } fun build(): Validation<T> { return Validation(validations) } } class Validation<T>(val validations: Map<String, ChildValidation<T>>) { companion object { inline operator fun <T> invoke( init: ValidationBuilder<T>.() -> Unit): Validation<T> { val builder = ValidationBuilder<T>().apply(init) return builder.build() } } }
  • 65. • object DSL • inline GC • • interface
  • 66. Validation<User> { "name"{ be { name.length >= 5 } not "5文字以下" be { name.length <= 10 } not "10文字以下" } "age"{ be { age >= 20 } not error message { "20歳以上" } be { age <= 150 } not with callback ("150歳以下"){ print("callback") } } } •
  • 68. • Java • DSL • IDE DSL • DSL
  • 69. • var val : Builder • {} : lambda lambda • () • : operator invoke • : (Extensions Functions or Properties) • : infix)