今週は第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を実際に動かすのはいつになることやら……!
今週の進捗は以下のプルリクエストにまとまっている。