今週は第39回を開催しました。引き続きKotlin Hands-on編です!
前回の様子はコチラ↓
[第39回の様子]
2020/11/11に第39回を開催した。
参加メンバーは自分をいれて5名。先週までの安定のメンツ3名に加えて、久しぶりに参加してくれたメンバーが2名。ときどきでもこうして戻ってきて、教えてくれるのはありがたい。
勉強会本編の内容としては、前回からはじめたKotlin Hands-onの
Creating HTTP APIs with Ktorを継続中。第3章のCustomer Routesの続きを、Returning a specific customer
から章の終わりまで進めた。最後のところで、動作確認をしたければ第5章へ進んでもよいと書かれていたので、前回の予想は当たっていそうだ。実装したコードを早く実際に動かしてみたい!
今回も、Hands-on編に入って初めてのドライバーが担当してくれた。リポジトリのクローンや、IntelliJのセットアップを済ませておいてくれたので、スムーズに勉強会を始めることができた!
[学んだことや疑問点]
- Creating HTTP APIs with Ktor: 3. Customer Routes
- Returning a specific customer
- パスパラメータでIDを指定したCustomerを取得するルーティングを実装する
- パスパラメータからIDを取得する部分の実装は以下のようになっていた
get("{id}") { val id = call.parameters["id"] ?: return@get call.respondText( "Missing or malformed id", status = HttpStatusCode.BadRequest ) val customer = customerStorage.find { it.id == id } ?: return@get call.respondText( "No customer with id $id", status = HttpStatusCode.NotFound ) call.respond(customer) }
?:
を使っている部分が記述量が少なくて良いなと感じた。Javaだとif (customer == null)
とかが入って長くなりそう。call.parameters["id"]
の部分はktor/Parameters.ktの実装を見ると、String
とList<String>
のMapになっているようだったreturn@get
のラベル付きリターンは、get("{id}")
の外側にある関数のreturn
と区別するために必要っぽかった。本来なら一番最後のcall.respond(customer)
の部分にもラベル付きリターンをつけてもよいが、関数の一番最後の場合はラベル付きリターンを省略できる、と解説してもらった。Kotlinのラベルはこの勉強会で何度か出てきたけど、まだ少し苦手意識が……実装例を見ずに実装しろと言われた場合に、アーリーリターンの部分でラベルをつけ忘れそうな気がする。- 前回も登場していた
respondText
の関数定義は以下のようになっている
public suspend fun ApplicationCall.respondText(text: String, contentType: ContentType? = null, status: HttpStatusCode? = null, configure: OutgoingContent.() -> Unit = {}) { val message = TextContent(text, defaultTextContentType(contentType), status) .apply(configure) respond(message) }
- 型は
HttpStatusCode
と決まっていて同じ型の引数は他にないのだから、わざわざパラメータに名前つきでstatus = 〜
の形で関数を呼び出すのがやや冗長な気がする。関数定義をオーバーロードしておいてくれればいいのに。
delete("{id}") { val id = call.parameters["id"] ?: return@delete call.respond(HttpStatusCode.BadRequest) if (customerStorage.removeIf { it.id == id }) { call.respondText("Customer removed correctly", status = HttpStatusCode.Accepted) } else { call.respondText("Not Found", status = HttpStatusCode.NotFound) } }
- Registering the routes
- ここまでで作成したルーティングを、アプリケーションに登録する必要がある
- CustomerRoutes.kt内でApplicationの拡張関数を定義して、それをApplication.kt側でimportして利用する形式。
// CustomerRoutes.kt fun Application.registerCustomerRoutes() { routing { customerRouting() } } fun Route.customerRouting() { // 省略 } // Application.kt // ここでインポート import com.jetbrains.handson.httpapi.routes.registerCustomerRoutes fun Application.module() { install(ContentNegotiation) { json() } // ここで利用 registerCustomerRoutes() }
Application.registerCustomerRoutes
という拡張関数を作っているのに、インポートするときはApplication
の部分は不要らしい。学びだ……多分IDEのサポートを受けないでKotlinを実装することはないだろうから、そこまで気をつけなくても大丈夫なポイントだろうか。- そういえば前回やったcall.respondのimportも同じく拡張関数の関数名のみのインポートだった。そういうものらしいと覚えておこう。
[まとめ]
モブプログラミング・スタイルで、Kotlin Hands-onを継続している。
APIのルーティングの実装を通して、ラベルつきリターンや拡張関数のimport文などについて復習した。
実装したHTTP APIを実際に動かすのはいつになることやら……!
今週の進捗は以下のプルリクエストにまとまっている。