ç§ã®ååã¯VladislavTankovã§ãã2018幎ãã2020幎ã«ãããŠãITMOã®JetBrainsã³ãŒãã¬ãŒããã¹ã¿ãŒããã°ã©ã ã§åŠã³ã2017幎ããJetBrainsã§åããŠããŸãã
2018幎ã®å€ãJetBrainsããã«ãœã³ã§ãååã®äœäººããšç§ã¯ãã¢ããªã±ãŒã·ã§ã³ã³ãŒããåæããããšã«ããããµãŒããŒã¬ã¹ã¢ããªã±ãŒã·ã§ã³ã®äœæãç°¡çŽ åããKotlinèšèªçšã®ããŒã«ãäœæããããšããŸããã
ããã«ãœã³ã®åŸããã§ã«JetBrainsã®äŒæ¥ãã¹ã¿ãŒããã°ã©ã ã®ç§åŠçç 究ã®æ å ã§ãç§ã¯ãã®ãããžã§ã¯ãã®éçºãç¶ããããšã«ããŸããããã®ããŒã«ã¯2幎éã§æ©èœãå€§å¹ ã«æ¡åŒµããã³ååŸããŸãããããã®ååã¯KotlessãŸãã¯Kotlin ServerlessFrameworkã®ãŸãŸã§ãã
ãµãŒããŒã¬ã¹ãšã¯
ãŸããæãåçŽãªãµãŒããŒã¬ã¹ã³ã³ãã¥ãŒãã£ã³ã°ãã©ãããã©ãŒã ãäœã§æ§æãããŠããããæãåºããŸãããããã®ãããªãã©ãããã©ãŒã ã«ã¯ã次ã®3ã€ã®äž»èŠã³ã³ããŒãã³ããå«ãŸããŸãã
- ãµãŒããŒã¬ã¹æ©èœã®å®è¡ã·ã¹ãã -ç¹å®ã®ã€ãã³ããåŠçããå°ããªã¢ããªã±ãŒã·ã§ã³ã
- å€çïŒãŸãã¯AWSãªã©ã®ã¯ã©ãŠããã©ãããã©ãŒã ïŒãããã©ãããã©ãŒã ã®ã€ãã³ãã·ã¹ãã ïŒHTTPã€ã³ã¿ãŒãã§ã€ã¹ãªã©ïŒãžã®ããŸããŸãªã€ã³ã¿ãŒãã§ã€ã¹ã®ã»ããã
- ã€ãã³ãã·ã¹ãã èªäœãã€ã³ã¿ãŒãã§ã€ã¹ããé¢æ°ãžã®ã€ãã³ãã®è»¢éãšãé¢æ°ããã€ã³ã¿ãŒãã§ã€ã¹ãžã®çµæã®åŠçãæäŸããŸãã
ãããã®3ã€ã®ã³ã³ããŒãã³ãã¯ãããªãè€éãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããã®ã«ååã§ããããšãã°ãWebã¢ããªã±ãŒã·ã§ã³ã¯åãªãå€éšHTTPã€ã³ã¿ãŒãã§ã€ã¹ïŒAWSã®å Žåã¯APIGatewayïŒã§ãããåŠçããããªãœãŒã¹ããšã«ïŒ/ route / myãªã©ïŒç¬èªã®ãµãŒããŒã¬ã¹ãã³ãã©ãŒé¢æ°ã§ããåçã®ããã«ãããŒã¿ããŒã¹ã䜿çšããããèªäœãä»ã®ãµãŒããŒã¬ã¹é¢æ°ãåŒã³åºããããè€éãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã
ããŠãããªãã¯ãã®ãããªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããšãã§ããŸããããããªãã§ããïŒ
ãµãŒããŒã¬ã¹ã¢ããªã±ãŒã·ã§ã³ã«ã¯ãã¢ãŒããã¯ãã£ã¹ã¯ã¯ãããæ£åœåããããã€ãã®èª¬åŸåã®ããå©ç¹ããããŸãã
- ãµãŒããŒã¬ã¹æ©èœã¯ãäžèŠãªå Žåã¯æ©èœããŸãããå®éããã®é¢æ°ã¯ã€ãã³ãã®ã¿ãåŠçããŸããã€ãã³ãããªãã®ã«ããªãã³ã³ãã¥ãŒãã£ã³ã°ãªãœãŒã¹ãæ¶è²»ããå¿ èŠãããã®ã§ããããã
- ãµãŒããŒã¬ã¹é¢æ°ã¯ãåãã¿ã€ãã®ã€ãã³ãã䞊è¡ããŠåŠçã§ããŸããã€ãŸãã/ route / myãéåžžã«äººæ°ã«ãªãã1,000人ã®ãŠãŒã¶ãŒãäžåºŠã«ãªã¯ãšã¹ãããå ŽåããµãŒããŒã¬ã¹ãã©ãããã©ãŒã ã¯ãã€ãã³ãããšã«1ã€ãã€ã1000åã®ãã³ãã©ãŒãèµ·åã§ããŸãã
ãããã®ç¹ãåããããšãããããæãéèŠãªãµãŒããŒã¬ã¹ã®ãã³ãã©ã®1ã€ã«ãªããŸãããµãŒããŒã¬ã¹ã¢ããªã±ãŒã·ã§ã³ã¯ããŒãããç¡é倧ãŸã§æ¡åŒµã§ããŸãããã®ãããªã¢ããªã±ãŒã·ã§ã³ã¯ãéèŠããªããšãã¯ãéãããããå¿ èŠãªãšãã«1ç§ãããæ°åã®èŠæ±ãåŠçã§ããŸãã
åé¡
Kotlinèšèªã®éåžžã«ç°¡åãªäŸãèŠãŠã¿ãŸãããã
@Get("/my/route")
fun handler() = "Hello World"
ãã®ãããªã¢ããªã±ãŒã·ã§ã³ããµãŒããŒã¬ã¹ã¢ãããŒãã䜿çšããŠå®è£ ã§ããããšã¯éåžžã«æçœã§ããäžèŠãããšãããDNSã¢ãã¬ã¹ã䜿çšããŠHTTPã€ã³ã¿ãŒãã§ã€ã¹ãäœæãã/ my / routeãfunãã³ãã©ãŒïŒïŒã«ãããããã ãã§ååã§ãã
å®éããã®ãããªã¢ããªã±ãŒã·ã§ã³ãäœæããã«ã¯ãåäžã®æ³šéãè¿œå ãããããã¯ããã«å€ãã®æéãããããŸããããšãã°ãAWSã®å ŽåïŒ
- ç¹å®ã®ã€ãã³ãïŒãã®å Žåã¯RequestStreamHandlerïŒã®ã€ã³ã¿ãŒãã§ã€ã¹ãã³ãã©ãŒãå®è£ ããå¿ èŠããããŸãã
- ãµãŒããŒã¬ã¹ã¢ããªã±ãŒã·ã§ã³ã®ã€ã³ãã©ã¹ãã©ã¯ãã£ã説æããå¿ èŠããããŸããã¢ããªã±ãŒã·ã§ã³ã®HTTPAPIã説æãããã¹ãŠã®ãã³ãã©ãŒé¢æ°ã説æãããããã®æ©èœãã€ã³ã¿ãŒãã§ã€ã¹ã«é¢é£ä»ããŠãã¢ã¯ã»ã¹èš±å¯ãæ éã«éžæããŸãã
- æåŸã«ããã¹ãŠã®ãã³ãã©ãŒé¢æ°ãåéãããµãŒããŒã¬ã¹ãã©ãããã©ãŒã ã«ããŒãããŠãé©åãªã€ã³ãã©ã¹ãã©ã¯ãã£ãå±éããå¿ èŠããããŸãã
ãã®ãããªåçŽãªã¢ããªã±ãŒã·ã§ã³ã«ã¯ãããã»ã©å€ãã®æé ã¯ãããŸãããïŒ
ã€ã³ãã©ã¹ãã©ã¯ãã£ã®èé€ãã³ãŒããšããŠå§ãã人ã«ãšã£ãŠã¯ããã¡ãããããã»ã¹ã®äžéšãèªååããããšãã§ããŸããããã®èªååèªäœã«ã¯ããŸã£ããæ°ããã¢ãããŒãïŒå®éã«ã¯ã€ã³ãã©ã¹ãã©ã¯ãã£ãã³ãŒããšããŠèšè¿°ããïŒãšæ°ããèšèªã®ç 究ãå¿ èŠã§ããããã¯ãåºæ¬çãªã¢ããªã±ãŒã·ã§ã³ãå±éãããéçºè ã«ãšã£ãŠãäžå¿ èŠã«é£ããäœæ¥ã®ããã«æãããŸãã
ãã£ãšç°¡åãªããšãããããšã¯å¯èœã§ããïŒå Žåã«ãã£ãŠã¯ïŒç¹ã«ããã§ã¯ïŒ-ã¯ãïŒ
ã³ãŒãå ã®ã€ã³ãã©ã¹ãã©ã¯ãã£
å察åŽãèŠãŠã¿ãŸãããããŠãŒã¶ãŒã«ã€ã³ãã©ã¹ãã©ã¯ãã£ã®èª¬æã匷å¶ãã代ããã«ããã§ã«èšè¿°ãããŠãããŠãŒã¶ãŒã³ãŒããããããå°ãåºãããšããŸãã
åãäŸãããäžåºŠèããŠã¿ãŸãããã
@Get("/my/route")
fun handler() = "Hello World"
ãŠãŒã¶ãŒã/ my / routeãžã®ãªã¯ãšã¹ãããã®é¢æ°ã§åŠçããããšãæãã§ããããšã¯ããã£ãŠããã®ã§ã/ my / routeã䜿çšããŠHTTPAPIãäœæããå¿ èŠãªãµãŒããŒã¬ã¹é¢æ°ãäœæããããããæ¥ç¶ããããã«å¿ èŠãªãã¹ãŠã®éæ³ãå®è¡ããã€ã³ãã©ã¹ãã©ã¯ãã£ãåæããŸãããïŒ
Automated Software Engineering 2019ã®ç§ã®èšäºã§ã¯ããã®ã¢ãããŒããã³ãŒãå ã®ã€ã³ãã©ã¹ãã©ã¯ãã£ãšåŒã³ãŸãããå®éãã€ã³ãã©ã¹ãã©ã¯ãã£ã®èª¬æã¯ããããæé»çã«å®çŸ©ããã¢ããªã±ãŒã·ã§ã³ã³ãŒãããæœåºããŸããã€ãŸããå®éã«ã¯ã³ãŒãã®ãå éšãã«å«ãŸããŠããŸãã
以äžãHTTPAPIã¢ããªã±ãŒã·ã§ã³ã®åæã®ã¿ãèæ ®ããŠããããšã«æ³šæããŠãã ãããåæ§ã®ã¢ãããŒããã¯ã©ãŠããã©ãããã©ãŒã ã§ã®ãã¥ãŒã®åŠçãšã€ãã³ãã®åŠçã«äœ¿çšã§ããŸãããããã¯Kotlessã®ãããªãéçºã®åé¡ã§ãã
å®è£
ããŸãããã°ããã®æç¹ã§ã¢ã€ãã¢ãæ確ã«ãªãã3ã€ã®äž»èŠãªè³ªåãæ®ã£ãŠããŸãã
- ã³ãŒãããæ å ±ãæœåºããæ¹æ³ã¯ïŒ
- ãã®æ å ±ã«åºã¥ããŠã€ã³ãã©ã¹ãã©ã¯ãã£ãäœæããã«ã¯ã©ãããã°ããã§ããïŒ
- ã¯ã©ãŠãã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããã«ã¯ã©ãããã°ããã§ããïŒ
åæ
Kotlinã³ã³ãã€ã©åã蟌ã¿å¯èœã¯ãããæ¯æŽããŸãã
äŸã泚éã«é¢ãããã®ã§ãããšããäºå®ã«ãããããããå®éã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã®HTTP APIã¯ã䜿çšãããã©ã€ãã©ãªã«å¿ããŠããŸã£ããç°ãªãæ¹æ³ã§å®çŸ©ã§ããŸããããšãã°ã次ã®ããã«ãªããŸãã
//ktor-like style
get("my-route") {
"Hello World"
}
ä»»æã®ã³ãŒããåæããããã«ãKotlin Compiler Embeddableã¯ããã䜿ããããããã䟿å©ã§ããããšãããããŸããïŒäŸãå€æ°ããããïŒã
çŸæç¹ã§ã¯ãKotlessã¯3ã€ã®äž»èŠãªãã¬ãŒã ã¯ãŒã¯ãåæã§ããŸãã
- KotlessDSL-Kotlessç¬èªã®æ³šéãã¬ãŒã ã¯ãŒã¯
- Spring Bootã¯äººæ°ã®ããWebãã¬ãŒã ã¯ãŒã¯ã§ããã泚éã解æãããŸãã
- Ktorã¯äººæ°ã®ããKotlinWebãã¬ãŒã ã¯ãŒã¯ã§ãããæ¡åŒµæ©èœãåæãããŸãã
ã³ãŒããåæããéçšã§ãKotlessã¹ããŒããåéãããŸããããã¯ããµãŒããŒã¬ã¹ã¢ããªã±ãŒã·ã§ã³ã®ãã©ãããã©ãŒã ã«äŸåããªãè¡šçŸã§ããã€ã³ãã©ã¹ãã©ã¯ãã£ãçµ±åããããã«äœ¿çšãããåæããã»ã¹ãç¹å®ã®ã¯ã©ãŠããã©ãããã©ãŒã ããç¬ç«ãããŸãã
åæ
Terraformã³ãŒããåæããŸãã Terraformã¯ããµããŒããããŠããããŸããŸãªã¯ã©ãŠããã©ãããã©ãŒã ãåããã³ãŒãããŒã«ãšããŠæã人æ°ã®ããã€ã³ãã©ã¹ãã©ã¯ãã£ã®1ã€ãšããŠéžæãããKotlessãæ°ããã¯ã©ãŠããã©ãããã©ãŒã ãšå®å®ããã¢ããªã±ãŒã·ã§ã³å±éããµããŒãã§ããããã«ããŠããŸãã
åæã¯ãã¢ããªã±ãŒã·ã§ã³ã®HTTP APIãšãã®æ©èœã®èª¬æãããã³ããã€ãã®è¿œå ããŒã¿ïŒããšãã°ãç®çã®DNSåïŒãå«ãKotlessã¹ããŒãããè¡ãããŸãã
åæèªäœã«ã¯ãç¹å¥ã«äœæãããTerraformDSLã©ã€ãã©ãªã䜿çšãããŸããåæã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
val resource = api_gateway_rest_api("tf_name") {
name = "aws_name"
binary_media_types = arrayOf(MimeType.PNG)
}
DSLã¯ãç°ãªãTerraformãªãœãŒã¹éã®ãã©ãŒããããšåç §ã®æŽåæ§ãä¿èšŒããåæããããªãœãŒã¹ã®ã»ãããæ¡åŒµããããšãã¯ããã«å®¹æã«ããŸãã
åæãããã³ãŒãã¯ãåçŽãªTerraformã¢ããªã±ãŒã·ã§ã³ã䜿çšããŠã¯ã©ãŠããã©ãããã©ãŒã ã«ãããã€ãããŸãã
ã©ã³ãã³ã°
ãµãŒããŒã¬ã¹ãã©ãããã©ãŒã ã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããããšã¯æ®ã£ãŠããŸãããã§ã«è¿°ã¹ãããã«ããã¹ãŠã®ãµãŒããŒã¬ã¹é¢æ°ã¯åºæ¬çã«äžéšã®ã€ãã³ãïŒãã®å Žåã¯HTTPèŠæ±ïŒã®ãã³ãã©ãŒã§ãã
ã¢ããªã±ãŒã·ã§ã³ãäœæãããã¬ãŒã ã¯ãŒã¯ïŒSpring Bootãªã©ïŒãšãµãŒããŒã¬ã¹ãã©ãããã©ãŒã ãæ¥ç¶ããå¿ èŠããããŸãããããè¡ãããã«ãKotlessã¯ãã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯æã«ãã¢ããªã±ãŒã·ã§ã³ã³ãŒãã«ç¹å¥ãªããã£ã¹ãããã£ãŒããè¿œå ããŸããããã¯ãã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšããããã¬ãŒã ã¯ãŒã¯ãšã¯ã©ãŠããã©ãããã©ãŒã éã®ã¢ããã¿ãŒãšããŠæ©èœãããã©ãããã©ãŒã åºæã®ã€ãã³ããã³ãã©ãŒã§ãã
ããŒã«
ã€ã³ãã©ã¹ãã©ã¯ãã£ãäœæããããã®èª¬æããããã€ãã©ã€ã³å šäœãå«ãããŒã«èªäœã¯ãGradleãã«ãã·ã¹ãã ãžã®ãã©ã°ã€ã³ãšããŠå®è£ ãããŸãããããã«ããã¹ãŠã®ã¡ã€ã³ã¢ãžã¥ãŒã«ã¯åå¥ã®ã©ã€ãã©ãªã§ãããããä»ã®ãã«ãã·ã¹ãã ã®ãµããŒããå€§å¹ ã«ç°¡çŽ åãããŸãã
ãã©ã°ã€ã³ã®äœ¿çšã¯ç°¡åã§ãã-èšå®ããåŸããŠãŒã¶ãŒãäžã€ã ãã®Gradleã®ã¿ã¹ã¯ãããå±éãã¯ã©ãŠããžã®çŸåšã®ã¢ããªã±ãŒã·ã§ã³ããããã€ããããã«å¿ èŠãªãã¹ãŠã®æé ãå®è¡ããŸãã
ãŠãŒã¶ãŒåŽããã®ã«ã¹ã¿ãã€ãºãéåžžã«ç°¡åã§ãããã©ã°ã€ã³èªäœãæåã«é©çšãããŸãã
plugins {
io("io.kotless") version "0.1.5" apply true
}
ãã®åŸããŠãŒã¶ãŒã¯å¿ èŠãªãã¬ãŒã ã¯ãŒã¯ãè¿œå ããŸãã
dependencies {
//Kotless DSL
implementation("io.kotless", "lang", "0.1.5")
}
æåŸã«ãKotlessãå±éã§ããããã«AWSã¢ã¯ã»ã¹ãèšå®ããŸãã
kotless {
config {
bucket = "kotless.s3.example.com"
terraform {
profile = "example"
region = "us-east-1"
}
}
}
ããŒã«ã«ããŒã³ã
æåŸã®ãã€ã³ãã§ã¯ããŠãŒã¶ãŒãAWSã«ç²ŸéããŠããŠãå°ãªããšãAWSã¢ã«ãŠã³ããæã£ãŠããå¿ èŠãããããšã¯å®¹æã«ç解ã§ããŸãããã®ãããªèŠä»¶ã¯ãããŒã«ãèªåã«é©ããŠãããã©ãããæåã«ããŒã«ã«ã§è©ŠããŠã¿ãããŠãŒã¶ãŒãæããããŸããã
ããããKotlessãããŒã«ã«èµ·åã¢ãŒãããµããŒãããçç±ã§ããéžæãããã¬ãŒã ã¯ãŒã¯ã®æšæºæ©èœïŒãã¡ãããKtorãSpring Bootãããã³Kotless DSLã®äž¡æ¹ã§ã¢ããªã±ãŒã·ã§ã³ãããŒã«ã«ã§å®è¡ã§ããŸãïŒã䜿çšããŠãKotlessã¯ã¢ããªã±ãŒã·ã§ã³ããŠãŒã¶ãŒã®ãã·ã³ã«ãããã€ããŸãã
ããã«ãKotlessã¯AWSãšãã¥ã¬ãŒã·ã§ã³ïŒLocalStackã§äœ¿çšïŒãå®è¡ã§ããããããŠãŒã¶ãŒã¯ã¢ããªã±ãŒã·ã§ã³ãæåŸ ã©ããã«åäœããŠããããšãããŒã«ã«ã§ç¢ºèªã§ããŸãã
ãããªãéçº
KotlessãæžããŠããéïŒãããŠãããšãšãã«ç§ã®ãã¹ã¿ãŒã®è«æïŒãç§ã¯ãããASE 2019ãKotlinConf 2019ãããã³TalkingKotlinããããã£ã¹ãã§äœãšãçºè¡šããŸãããäžè¬çã«ããã®ããŒã«ã¯å¥œè©ã§ãããã2019幎ã®çµãããŸã§ã«ã¯ãããã»ã©ç®æ°ãããã®ã§ã¯ãªããªã£ãããã§ãïŒãã®æç¹ã§ãZappaãClaudia.jsãããã³AWS Chaliceã人æ°ãåããŠããŸããïŒã
ããããçŸæç¹ã§ã¯ãã³ããã¬ã¹ã¯ããããã³ããªã³ã®äžçã§ãã®ã¯ã©ã¹ã®æãæåãªããŒã«ã§ãããç§ã¯ç¢ºãã«ãããéçºããäºå®ã§ãã
è¿ãå°æ¥ãæ°ãããŠãŒã¶ãŒãããŒã«ãç°¡åã«åŠç¿ã§ããããã«ãçŸåšã®APIãšæ©èœãå®å®ããããã¥ãŒããªã¢ã«ãšãã¢ãããžã§ã¯ããæºåããäºå®ã§ãã
ããšãã°ãKotlessã䜿çšããŠãã£ããããããäœæããæ¹æ³ã«é¢ããäžé£ã®ãã¥ãŒããªã¢ã«ãæºåããäºå®ã§ãããµãŒããŒã¬ã¹ãã¯ãããžãŒã¯ãã®ãŠãŒã¹ã±ãŒã¹ã«æé©ã§ããããã«æãããŸããïŒKotlessãŠãŒã¶ãŒã¯ãã§ã«TelegramããããäœæããŠããŸãïŒãé©åãªããŒã«ããªããããåºç¯ãªäœ¿çšãå€§å¹ ã«åŠšããããŠããŸãã
æåŸã«ãããŒã«ã®ã¢ãŒããã¯ãã£å šäœã®æãéèŠãªåŽé¢ã®1ã€ã¯ããã©ãããã©ãŒã ã®ç¬ç«æ§ã§ããããã»ã©é ããªãå°æ¥ãç§ã¯Google CloudPlatformãšMicrosoftAzureããµããŒãããã¢ããªã±ãŒã·ã§ã³ãæåéã1ã€ã®ãã¿ã³ã§ã¯ã©ãŠãããã¯ã©ãŠãã«ç§»åã§ããããã«ããããšèããŠããŸãã
Kotlessãåæ§ã®ããŒã«ãããµãŒããŒã¬ã¹ãã¯ãããžãŒã®å€§è¡ãžã®å°å ¥ã«æ¬åœã«åœ¹ç«ã¡ããŸããŸãå€ãã®ã¢ããªã±ãŒã·ã§ã³ãå®è¡äžã«ã®ã¿ãªãœãŒã¹ãæ¶è²»ããå®å®ã®ãšã³ããããŒããããã«æžããããšãé¡ã£ãŠããŸã:)