SlideShare une entreprise Scribd logo
1  sur  41
Télécharger pour lire hors ligne
Production Koltin DSL
Сергей Рыбалкин
@lightdelay@rybalkinsd
Speaker
Principal Engineer @ Alibaba Group

Kotlin & Java Lecturer in MSU

9 years of experience
3 years with Kotlin
2
Agenda
1.[Путь к DSL]
2.DSL в экосистеме Kotlin
3.Строим свой DSL
4.Проблемки и решения
3
Serverless. FaaS
4
Gateways
MQRPCHTTP
Security
Routing
Serverless. FaaS
5
val result = httpPost {
host = "s.alibab-inc.com"
path = "/order"
header {
"version" to 1688
cookie {
"sender" to "alibaba"
}
}
body {
json { ... }
}
}
val result = rpcCall {
group = "alibaba"
method = "OrderService.orders"
args {
"id" to productId
"referrer" to json { ... }
}
}
Agenda
1.Путь к DSL

2.[DSL в экосистеме Kotlin]
3.Строим свой DSL
4.Проблемки и решения
6
Domain Specific Language
7
SQL
HTML
CSS Markdown
Regex
Domain Specific Language
8
DSL =
Problem Context + Syntax =
F(Productivity, Concision, Safety)
Successful DSL
∥FDSL∥ > ∥FGeneral Purpose Language∥
9
Embedded DSL. Kotlin
• Null-safety

• Статическая типизация

• Средства построения DSL

• IDE
10
Embedded DSL. Kotlin
• Gradle

• Bean definition DSL (Spring)

• WebFlux Functional DSL (Spring)

• Spek

• kotlinx.html

• kohttp
11
Gradle DSL
12
plugins {
kotlin("jvm") version "1.3.40"
`maven-publish`
}
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
implementation(kotlinx("coroutines-core")
}
publishing {
publications {
create<MavenPublication>("artifact") {
...
Spek
13
object SetFeature: Spek({
Feature("Set addition") {
val set by memoized { mutableSetOf<String>() }
Scenario("getting the first item") {
val item = "foo"
Given("a non-empty set") {
set.add(item)
}
lateinit var result: String
When("getting the first item") {
result = set.first()
}
Then("it should return the first item") {
assertEquals(item, result)
}
}
}
WebFlux router
14
router {
accept(TEXT_HTML).nest {
GET("/") { ok().render("index") }
GET("/users", userHandler::findAllView)
}
"/api".nest {
accept(APPLICATION_JSON).nest {
GET("/users", userHandler::findAll)
}
}
resources("/**", ClassPathResource("static/"))
}
HTTP. BC
15
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----
WebKitFormBoundary7MA4YWxkTrZu0gW");
RequestBody body = RequestBody.create(mediaType, "------
WebKitFormBoundary7MA4YWxkTrZu0gWrnContent-Disposition: form-data;
name="key"rnrnxxxxxrn------WebKitFormBoundary7MA4YWxkTrZu0gWrnContent-Disposition: form-
data; name="b"; filename="Screen Shot 2019-06-07 at 10.22.21.png"rnContent-Type: image/
pngrnrnrn------WebKitFormBoundary7MA4YWxkTrZu0gW--");
Request request = new Request.Builder()
.url("https://github.com/search")
.get()
.addHeader("content-type", "multipart/form-data; boundary=----
WebKitFormBoundary7MA4YWxkTrZu0gW")
.addHeader("username", "rybalkinsd")
.addHeader("security-policy", "{ "max-age": 2592000 }")
.addHeader("script-src", ""github.com", "github.io"")
.addHeader("cookie", "{ "user_session" : "toFycNV", "expires" : "Fri, 31 Jul 2019
20:30:00 -0000" }")
.build();
Response response = client.newCall(request).execute();
HTTP. AD
16
httpGet {
url("https://github.com/search")
header {
"username" to "rybalkinsd"
"security-policy" to json {
"max-age" to 2592000
}
"script-src" to listOf("github.com", "github.io")
cookie {
"user_session" to "toFycNV"
"expires" to "Fri, 31 Jul 2019 20:30:00 -0000"
}
}
param { ... }
}
kohttp. Kotlin DSL http client
17
https://github.com/rybalkinsd/kohttp
‣ Asnyc/sync DSL for http methods

‣ Coroutines support

‣ Built-in Interceptors
Agenda
1.Путь к DSL

2.DSL в экосистеме Koltin

3.[Строим свой DSL]
4.Platform
18
Building Kotlin DSL. Tools
19
Tools. Lambda as last argument
20
fun measureTimeMillis(block: () -> Unit): Long {
val start = System.currentTimeMillis()
block()
return System.currentTimeMillis() - start
}
val time = measureTimeMillis {
task()
}
Tools. Extension functions
21
val response: Deferred<Response> =
“https://google.com/search/?q=iphone”.httpGetAsync()
fun String.httpGetAsync(
client: Call.Factory = defaultHttpClient
): Deferred<Response> =
GlobalScope.async(context = Dispatchers.Unconfined) {
...
}
Tools. Lambda with receiver
22
httpGet {
url("https://github.com/search")
header {
"username" to "rybalkinsd"
"security-policy" to json {
"max-age" to 2592000
}
cookie {
"user_session" to "toFycNV"
"expires" to "Fri, 31 Jul 2019 20:30:00 -0000"
}
}
}
Tools. Lambda with receiver
23
fun httpGet(
client: Call.Factory = defaultHttpClient,
init: HttpGetContext.() -> Unit): Response {
val context = HttpGetContext().apply(init)
return client.newCall(
context.makeRequest()
).execute()
}
Lambda with receiver. HttpContext
24
class HttpContext(private val method: Method = GET) {
private val paramContext = ParamContext()
private val headerContext = HeaderContext()
var scheme: String = "http"
var host: String = ""
var port: Int? = null
var path: String? = null
...
}
Tools. Infix function
25
httpGet {
param {
"id" to Id("42")
"sender" to "localhost"
}
}
class ParamContext {
private val params = mutableMapOf<>()
infix fun String.to(v: Any?) { params[this] = v }
}
Tools. Type alias
26
typealias Header = Pair<String, String>
fun Request.headers(): Sequence<Header> = Sequence { ... }
httpRequest.headers().forEach {
(name, value) -> log("$name: $value")
}
Tools. Inline classes
27
inline class Token(val v: String)
infix fun String.to(token: Token) {
specific action
}
val response = httpPost {
url("https://googleapis.com/upload/drive/v3/files")
header {
"Authorization" to Token(“secret-token”)
}
https://kotlinlang.org/docs/reference/inline-classes.html
Inline classes are available only since Kotlin 1.3 and currently are experimental
Tools. Operator overloading
28
+item
-item
++item
--item
!importantAction
jsonArray[1, 2, 3, null]
Tools. Operator overloading
29
+item .unaryPlus()
-item .unaryMinus()
++item .inc()
--item .dec()
!importantAction .not()
jsonArray[1, 2, 3, null] .get(vararg content: Any?)
Tools. Operator overloading
30
val client = client {
interceptors {
+RetryInterceptor(failureThreshold = 5)
+LoggingInterceptor()
}
}
class Interceptors(val interceptors = Storage()) {
operator fun Interceptor.unaryPlus() {
interceptors += this
}
}
Agenda
1.Путь к DSL

2.DSL в экосистеме Koltin

3.Строим свой DSL

4.[Проблемки и решения]
31
Problem 1. Public setter, private getter
32
val client = client {
interceptors = listOf(
RetryInterceptor(failureThreshold = 5),
LoggingInterceptor()
)
interceptors.forEach { ... }
}
https://youtrack.jetbrains.com/issue/KT-3110
33
Problem 1. Public setter, private getter
34
interface ClientBuilder {
@get:Deprecated(
level = DeprecationLevel.ERROR,
message = "Write only field")
var interceptors: List<Interceptor>
}
override var interceptors: List<Interceptor>
set(value) { ... }
get() = throw UnsupportedOperationException()
Problem 1. Public setter, private getter
35
val client = client {
interceptors = listOf(
RetryInterceptor(failureThreshold = 5),
LoggingInterceptor()
)
interceptors.forEach { ... } <— COMPILATION ERROR
}
https://youtrack.jetbrains.com/issue/KT-3110
Problem 2. Java 11 & dokka
36
val dokkaJar = task<Jar>("dokkaJar") {
group = JavaBasePlugin.DOCUMENTATION_GROUP
classifier = "javadoc"
}
publishing {
publications {
create<MavenPublication>("kohttp") {
from(components["java"])
artifacts {
artifact(sourcesJar)
artifact(dokkaJar)
}
}
}
}
https://youtrack.jetbrains.com/issue/KT-31710
37
Problem 3. Context control
38
httpGet {
param {
"text" to "iphone"
param {
"lr" to 213
}
}
}
Problem 3. Context control
39
@DslMarker
annotation class HttpDslMarker
@HttpDslMarker
class ParamContext
httpGet {
param {
param { } <— COMPILATION ERROR
}
}
Outline
‣ DSL это круто, если и только если
помогает вашим пользователям
‣ Работайте над DevX. Пользовательский
фидбек - это единственное что важно при
построении DSL
‣ Уже наступило время делать async-first DSL
40
THANK YOU!
Q/A
@lightdelay@rybalkinsd

Contenu connexe

Tendances

Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察
Tsuyoshi Yamamoto
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
Kiyotaka Oku
 

Tendances (20)

ClojureScript for the web
ClojureScript for the webClojureScript for the web
ClojureScript for the web
 
Coroutines talk ppt
Coroutines talk pptCoroutines talk ppt
Coroutines talk ppt
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180
 
All you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopAll you need to know about the JavaScript event loop
All you need to know about the JavaScript event loop
 
Retrofit
RetrofitRetrofit
Retrofit
 
Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察
 
Introduction to rx java for android
Introduction to rx java for androidIntroduction to rx java for android
Introduction to rx java for android
 
Akka streams - Umeå java usergroup
Akka streams - Umeå java usergroupAkka streams - Umeå java usergroup
Akka streams - Umeå java usergroup
 
Streaming all the things with akka streams
Streaming all the things with akka streams   Streaming all the things with akka streams
Streaming all the things with akka streams
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
 
Luis Atencio on RxJS
Luis Atencio on RxJSLuis Atencio on RxJS
Luis Atencio on RxJS
 
Streaming Dataflow with Apache Flink
Streaming Dataflow with Apache Flink Streaming Dataflow with Apache Flink
Streaming Dataflow with Apache Flink
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
JavaScript ∩ WebAssembly
JavaScript ∩ WebAssemblyJavaScript ∩ WebAssembly
JavaScript ∩ WebAssembly
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
 
多治見IT勉強会 Groovy Grails
多治見IT勉強会 Groovy Grails多治見IT勉強会 Groovy Grails
多治見IT勉強会 Groovy Grails
 

Similaire à «Продакшн в Kotlin DSL» Сергей Рыбалкин

What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...
What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...
What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...
mfrancis
 

Similaire à «Продакшн в Kotlin DSL» Сергей Рыбалкин (20)

Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 
Function as a Service in private cloud
Function as a Service in private cloud Function as a Service in private cloud
Function as a Service in private cloud
 
Rapid Web API development with Kotlin and Ktor
Rapid Web API development with Kotlin and KtorRapid Web API development with Kotlin and Ktor
Rapid Web API development with Kotlin and Ktor
 
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem novaKotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
Kotlin+MicroProfile: Ensinando 20 anos para uma linguagem nova
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기
 
From Java to Kotlin - The first month in practice
From Java to Kotlin - The first month in practiceFrom Java to Kotlin - The first month in practice
From Java to Kotlin - The first month in practice
 
What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...
What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...
What’s cool in the new and updated OSGi specs (DS, Cloud and more) - C Ziegel...
 
A New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDKA New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDK
 
Designing REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDesigning REST API automation tests in Kotlin
Designing REST API automation tests in Kotlin
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Spicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QASpicy javascript: Create your first Chrome extension for web analytics QA
Spicy javascript: Create your first Chrome extension for web analytics QA
 
Why Spring <3 Kotlin
Why Spring <3 KotlinWhy Spring <3 Kotlin
Why Spring <3 Kotlin
 
Let's play with adf 3.0
Let's play with adf 3.0Let's play with adf 3.0
Let's play with adf 3.0
 
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
 
Cloud nativeworkshop
Cloud nativeworkshopCloud nativeworkshop
Cloud nativeworkshop
 
Kotlin. One language to dominate them all.
Kotlin. One language to dominate them all.Kotlin. One language to dominate them all.
Kotlin. One language to dominate them all.
 
Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​ Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​
 
A TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS AdventuresA TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS Adventures
 
Big Data Tools in AWS
Big Data Tools in AWSBig Data Tools in AWS
Big Data Tools in AWS
 

Plus de Mail.ru Group

AMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей ПешковAMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей Пешков
Mail.ru Group
 

Plus de Mail.ru Group (20)

Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
 
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
 
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир ДубровинДругая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
 
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
 
Управление инцидентами в Почте Mail.ru, Антон Викторов
Управление инцидентами в Почте Mail.ru, Антон ВикторовУправление инцидентами в Почте Mail.ru, Антон Викторов
Управление инцидентами в Почте Mail.ru, Антон Викторов
 
DAST в CI/CD, Ольга Свиридова
DAST в CI/CD, Ольга СвиридоваDAST в CI/CD, Ольга Свиридова
DAST в CI/CD, Ольга Свиридова
 
Почему вам стоит использовать свой велосипед и почему не стоит Александр Бел...
Почему вам стоит использовать свой велосипед и почему не стоит  Александр Бел...Почему вам стоит использовать свой велосипед и почему не стоит  Александр Бел...
Почему вам стоит использовать свой велосипед и почему не стоит Александр Бел...
 
CV в пайплайне распознавания ценников товаров: трюки и хитрости Николай Масл...
CV в пайплайне распознавания ценников товаров: трюки и хитрости  Николай Масл...CV в пайплайне распознавания ценников товаров: трюки и хитрости  Николай Масл...
CV в пайплайне распознавания ценников товаров: трюки и хитрости Николай Масл...
 
RAPIDS: ускоряем Pandas и scikit-learn на GPU Павел Клеменков, NVidia
RAPIDS: ускоряем Pandas и scikit-learn на GPU  Павел Клеменков, NVidiaRAPIDS: ускоряем Pandas и scikit-learn на GPU  Павел Клеменков, NVidia
RAPIDS: ускоряем Pandas и scikit-learn на GPU Павел Клеменков, NVidia
 
WebAuthn в реальной жизни, Анатолий Остапенко
WebAuthn в реальной жизни, Анатолий ОстапенкоWebAuthn в реальной жизни, Анатолий Остапенко
WebAuthn в реальной жизни, Анатолий Остапенко
 
AMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей ПешковAMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей Пешков
 
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила СтрелковКак мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
 
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
 
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.ТаксиМетапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
 
Этика искусственного интеллекта, Александр Кармаев (AI Journey)
Этика искусственного интеллекта, Александр Кармаев (AI Journey)Этика искусственного интеллекта, Александр Кармаев (AI Journey)
Этика искусственного интеллекта, Александр Кармаев (AI Journey)
 
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
 
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
 
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
 
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
 

Dernier

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Dernier (20)

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
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
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
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
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 

«Продакшн в Kotlin DSL» Сергей Рыбалкин

  • 1. Production Koltin DSL Сергей Рыбалкин @lightdelay@rybalkinsd
  • 2. Speaker Principal Engineer @ Alibaba Group Kotlin & Java Lecturer in MSU 9 years of experience 3 years with Kotlin 2
  • 3. Agenda 1.[Путь к DSL] 2.DSL в экосистеме Kotlin 3.Строим свой DSL 4.Проблемки и решения 3
  • 5. Serverless. FaaS 5 val result = httpPost { host = "s.alibab-inc.com" path = "/order" header { "version" to 1688 cookie { "sender" to "alibaba" } } body { json { ... } } } val result = rpcCall { group = "alibaba" method = "OrderService.orders" args { "id" to productId "referrer" to json { ... } } }
  • 6. Agenda 1.Путь к DSL 2.[DSL в экосистеме Kotlin] 3.Строим свой DSL 4.Проблемки и решения 6
  • 8. Domain Specific Language 8 DSL = Problem Context + Syntax = F(Productivity, Concision, Safety)
  • 9. Successful DSL ∥FDSL∥ > ∥FGeneral Purpose Language∥ 9
  • 10. Embedded DSL. Kotlin • Null-safety • Статическая типизация • Средства построения DSL • IDE 10
  • 11. Embedded DSL. Kotlin • Gradle • Bean definition DSL (Spring) • WebFlux Functional DSL (Spring) • Spek • kotlinx.html • kohttp 11
  • 12. Gradle DSL 12 plugins { kotlin("jvm") version "1.3.40" `maven-publish` } repositories { mavenCentral() } dependencies { implementation(kotlin("stdlib-jdk8")) implementation(kotlin("reflect")) implementation(kotlinx("coroutines-core") } publishing { publications { create<MavenPublication>("artifact") { ...
  • 13. Spek 13 object SetFeature: Spek({ Feature("Set addition") { val set by memoized { mutableSetOf<String>() } Scenario("getting the first item") { val item = "foo" Given("a non-empty set") { set.add(item) } lateinit var result: String When("getting the first item") { result = set.first() } Then("it should return the first item") { assertEquals(item, result) } } }
  • 14. WebFlux router 14 router { accept(TEXT_HTML).nest { GET("/") { ok().render("index") } GET("/users", userHandler::findAllView) } "/api".nest { accept(APPLICATION_JSON).nest { GET("/users", userHandler::findAll) } } resources("/**", ClassPathResource("static/")) }
  • 15. HTTP. BC 15 OkHttpClient client = new OkHttpClient(); MediaType mediaType = MediaType.parse("multipart/form-data; boundary=---- WebKitFormBoundary7MA4YWxkTrZu0gW"); RequestBody body = RequestBody.create(mediaType, "------ WebKitFormBoundary7MA4YWxkTrZu0gWrnContent-Disposition: form-data; name="key"rnrnxxxxxrn------WebKitFormBoundary7MA4YWxkTrZu0gWrnContent-Disposition: form- data; name="b"; filename="Screen Shot 2019-06-07 at 10.22.21.png"rnContent-Type: image/ pngrnrnrn------WebKitFormBoundary7MA4YWxkTrZu0gW--"); Request request = new Request.Builder() .url("https://github.com/search") .get() .addHeader("content-type", "multipart/form-data; boundary=---- WebKitFormBoundary7MA4YWxkTrZu0gW") .addHeader("username", "rybalkinsd") .addHeader("security-policy", "{ "max-age": 2592000 }") .addHeader("script-src", ""github.com", "github.io"") .addHeader("cookie", "{ "user_session" : "toFycNV", "expires" : "Fri, 31 Jul 2019 20:30:00 -0000" }") .build(); Response response = client.newCall(request).execute();
  • 16. HTTP. AD 16 httpGet { url("https://github.com/search") header { "username" to "rybalkinsd" "security-policy" to json { "max-age" to 2592000 } "script-src" to listOf("github.com", "github.io") cookie { "user_session" to "toFycNV" "expires" to "Fri, 31 Jul 2019 20:30:00 -0000" } } param { ... } }
  • 17. kohttp. Kotlin DSL http client 17 https://github.com/rybalkinsd/kohttp ‣ Asnyc/sync DSL for http methods ‣ Coroutines support ‣ Built-in Interceptors
  • 18. Agenda 1.Путь к DSL 2.DSL в экосистеме Koltin 3.[Строим свой DSL] 4.Platform 18
  • 20. Tools. Lambda as last argument 20 fun measureTimeMillis(block: () -> Unit): Long { val start = System.currentTimeMillis() block() return System.currentTimeMillis() - start } val time = measureTimeMillis { task() }
  • 21. Tools. Extension functions 21 val response: Deferred<Response> = “https://google.com/search/?q=iphone”.httpGetAsync() fun String.httpGetAsync( client: Call.Factory = defaultHttpClient ): Deferred<Response> = GlobalScope.async(context = Dispatchers.Unconfined) { ... }
  • 22. Tools. Lambda with receiver 22 httpGet { url("https://github.com/search") header { "username" to "rybalkinsd" "security-policy" to json { "max-age" to 2592000 } cookie { "user_session" to "toFycNV" "expires" to "Fri, 31 Jul 2019 20:30:00 -0000" } } }
  • 23. Tools. Lambda with receiver 23 fun httpGet( client: Call.Factory = defaultHttpClient, init: HttpGetContext.() -> Unit): Response { val context = HttpGetContext().apply(init) return client.newCall( context.makeRequest() ).execute() }
  • 24. Lambda with receiver. HttpContext 24 class HttpContext(private val method: Method = GET) { private val paramContext = ParamContext() private val headerContext = HeaderContext() var scheme: String = "http" var host: String = "" var port: Int? = null var path: String? = null ... }
  • 25. Tools. Infix function 25 httpGet { param { "id" to Id("42") "sender" to "localhost" } } class ParamContext { private val params = mutableMapOf<>() infix fun String.to(v: Any?) { params[this] = v } }
  • 26. Tools. Type alias 26 typealias Header = Pair<String, String> fun Request.headers(): Sequence<Header> = Sequence { ... } httpRequest.headers().forEach { (name, value) -> log("$name: $value") }
  • 27. Tools. Inline classes 27 inline class Token(val v: String) infix fun String.to(token: Token) { specific action } val response = httpPost { url("https://googleapis.com/upload/drive/v3/files") header { "Authorization" to Token(“secret-token”) } https://kotlinlang.org/docs/reference/inline-classes.html Inline classes are available only since Kotlin 1.3 and currently are experimental
  • 29. Tools. Operator overloading 29 +item .unaryPlus() -item .unaryMinus() ++item .inc() --item .dec() !importantAction .not() jsonArray[1, 2, 3, null] .get(vararg content: Any?)
  • 30. Tools. Operator overloading 30 val client = client { interceptors { +RetryInterceptor(failureThreshold = 5) +LoggingInterceptor() } } class Interceptors(val interceptors = Storage()) { operator fun Interceptor.unaryPlus() { interceptors += this } }
  • 31. Agenda 1.Путь к DSL 2.DSL в экосистеме Koltin 3.Строим свой DSL 4.[Проблемки и решения] 31
  • 32. Problem 1. Public setter, private getter 32 val client = client { interceptors = listOf( RetryInterceptor(failureThreshold = 5), LoggingInterceptor() ) interceptors.forEach { ... } } https://youtrack.jetbrains.com/issue/KT-3110
  • 33. 33
  • 34. Problem 1. Public setter, private getter 34 interface ClientBuilder { @get:Deprecated( level = DeprecationLevel.ERROR, message = "Write only field") var interceptors: List<Interceptor> } override var interceptors: List<Interceptor> set(value) { ... } get() = throw UnsupportedOperationException()
  • 35. Problem 1. Public setter, private getter 35 val client = client { interceptors = listOf( RetryInterceptor(failureThreshold = 5), LoggingInterceptor() ) interceptors.forEach { ... } <— COMPILATION ERROR } https://youtrack.jetbrains.com/issue/KT-3110
  • 36. Problem 2. Java 11 & dokka 36 val dokkaJar = task<Jar>("dokkaJar") { group = JavaBasePlugin.DOCUMENTATION_GROUP classifier = "javadoc" } publishing { publications { create<MavenPublication>("kohttp") { from(components["java"]) artifacts { artifact(sourcesJar) artifact(dokkaJar) } } } } https://youtrack.jetbrains.com/issue/KT-31710
  • 37. 37
  • 38. Problem 3. Context control 38 httpGet { param { "text" to "iphone" param { "lr" to 213 } } }
  • 39. Problem 3. Context control 39 @DslMarker annotation class HttpDslMarker @HttpDslMarker class ParamContext httpGet { param { param { } <— COMPILATION ERROR } }
  • 40. Outline ‣ DSL это круто, если и только если помогает вашим пользователям ‣ Работайте над DevX. Пользовательский фидбек - это единственное что важно при построении DSL ‣ Уже наступило время делать async-first DSL 40