Slide 1

Slide 1 text

1 ©2023 Loglass Inc. Kotlinにおける型の世界と エラーハンドリング 2023.3.07 Makoto Kobayashi

Slide 2

Slide 2 text

2 2 ©2023 Loglass Inc. 小林 允(Makoto Kobayashi) 自己紹介 @mako_makok mako-makok 所属: 株式会社ログラス 好きな言語: Java, Kotlin, TypeScript 普段はSpringBootをKotlinで書いています AndroidをJavaで書いてた Luceneのパッチを書いてSolrに組み込む JavaでSpringBootやSeasar2を書いていた ログラスでSpringBootとKotlinを書いている 2017〜2018 2018〜2019 2019〜2021 2022〜

Slide 3

Slide 3 text

3 ©2023 Loglass Inc. ログラスについて Loglassは経営データを正確かつ迅速に可視化/分析す ることで、柔軟/高精度な事業推進を実現する経営管理 クラウドサービス です。 企業価値を向上する経営管理クラウド

Slide 4

Slide 4 text

4 ©2023 Loglass Inc. ログラスについて

Slide 5

Slide 5 text

5 5 ©2023 Loglass Inc. 目次 1. Javaにおけるエラーハンドリング 2. Kotlinにおける例外処理 3. Kotlinでのエラーハンドリング 4. よりメンテナブルなエラーハンドリングに

Slide 6

Slide 6 text

6 ©2023 Loglass Inc. Javaにおけるエラーハンドリング

Slide 7

Slide 7 text

7 ©2023 Loglass Inc. 7 例外のtry-catch Javaにおけるエラーハンドリング

Slide 8

Slide 8 text

8 ©2023 Loglass Inc. Kotlinの例外処理

Slide 9

Slide 9 text

9 ©2023 Loglass Inc. Kotlinにおける例外 Kotlinの例外処理 Javaの検査例外をthrowしてもコンパイルエラーにならない

Slide 10

Slide 10 text

10 ©2023 Loglass Inc. Kotlinにおける例外 Kotlinの例外処理 try-catch式 runCatching

Slide 11

Slide 11 text

11 ©2023 Loglass Inc. Kotlinにおける例外 Kotlinの例外処理 ● 検査例外がないので例外を無視してもコンパイルエラーにならない ● throwsも無いので例外のチェックを強制するような設計は 絶対できないようになっている ● 呼び出し階層の中で例外を投げる処理を書くと ハンドリング忘れで意図しないエラーが発生する可能性がある

Slide 12

Slide 12 text

12 ©2023 Loglass Inc. Kotlinにおける例外 Kotlinの例外処理 設計レベルでなんとかできないかな? ● 設計標準に例外ハンドリングについて定義する? ● ArchUnitでアーキテクチャテストを書く?

Slide 13

Slide 13 text

13 ©2023 Loglass Inc. Kotlinでのエラーハンドリング

Slide 14

Slide 14 text

14 ©2023 Loglass Inc. 例外のtry-catchに代わるハンドリング Kotlinでのエラーハンドリング ● 代数的データ構造で Result型を設計する ● パターンマッチでokとerrorをハンドルして値を安全に取り出す

Slide 15

Slide 15 text

15 ©2023 Loglass Inc. 代数的データ構造とは Kotlinでのエラーハンドリング 代数的データ型(だいすうてきデータがた、英 : algebraic data type)とは プログラミング、特に関数型プログラミングや型システムにおいて使われ るデータ型である。それぞれの代数的データ型の値には、 1個以上のコ ンストラクタがあり、各コンストラクタには 0個以上の引数がある。 代数的 データ型の値(データ)の感覚的な説明としては、引数で与えられた他の データ型の値を、コンストラクタで包んだようなもの、である。コンストラク タに引数がある代数データ型は複合型(他のデータ型を組み合わせて形 成する型)である。 Wikipediaより引用: https://ja.wikipedia.org/wiki/代数的データ型

Slide 16

Slide 16 text

16 ©2023 Loglass Inc. 代数的データ構造とは Kotlinでのエラーハンドリング ● パラメータの組み合わせが和や積など、 代数的に表現できるためそう呼ばれている ? ● 厳密的な定義はなさそう ?

Slide 17

Slide 17 text

17 ©2023 Loglass Inc. 直積型 Kotlinでのエラーハンドリング

Slide 18

Slide 18 text

18 ©2023 Loglass Inc. 直積型 Kotlinでのエラーハンドリング data error String null null String null null String String 2 * 2の直積でパターンが表される

Slide 19

Slide 19 text

19 ©2023 Loglass Inc. 直和型 Kotlinでのエラーハンドリング Resultの型はOkかErrorなので、直和のパターン数で表される

Slide 20

Slide 20 text

20 ©2023 Loglass Inc. 直和型 Kotlinでのエラーハンドリング

Slide 21

Slide 21 text

21 ©2023 Loglass Inc. 余談: こういうのも直和 Kotlinでのエラーハンドリング

Slide 22

Slide 22 text

22 ©2023 Loglass Inc. 余談: こういうのも直和 Kotlinでのエラーハンドリング

Slide 23

Slide 23 text

23 ©2023 Loglass Inc. 直和型によるエラーハンドリング Kotlinでのエラーハンドリング ::doSomethingはinterfaceを返却する

Slide 24

Slide 24 text

24 ©2023 Loglass Inc. 直和型によるエラーハンドリング Kotlinでのエラーハンドリング パターンマッチによるデータの取り出し

Slide 25

Slide 25 text

25 ©2023 Loglass Inc. 直和型によるエラーハンドリング Kotlinでのエラーハンドリング パターンの欠損はコンパイルエラーになる

Slide 26

Slide 26 text

26 ©2023 Loglass Inc. Javaでの直和型の実装 Kotlinでのエラーハンドリング instanceof によるパターンマッチ

Slide 27

Slide 27 text

27 ©2023 Loglass Inc. Javaでの直和型の実装 Kotlinでのエラーハンドリング Java 19 third preview(Record Patterns, pattern matching for switch)

Slide 28

Slide 28 text

28 ©2023 Loglass Inc. よりメンテナブルな エラーハンドリングに

Slide 29

Slide 29 text

29 ©2023 Loglass Inc. 言語機能の限界 よりメンテナブルなエラーハンドリングに

Slide 30

Slide 30 text

30 ©2023 Loglass Inc. 言語機能の限界 よりメンテナブルなエラーハンドリングに Resultがネストするとかなり可読性が下がる

Slide 31

Slide 31 text

31 ©2023 Loglass Inc. 言語機能の限界 よりメンテナブルなエラーハンドリングに ● 直和型とパターンマッチは特に関数型言語にしばしば見られる概念である ● Kotlinは関数型ではない ● もう一歩関数型に踏み込む必要がある

Slide 32

Slide 32 text

32 ©2023 Loglass Inc. 他の言語のパラダイムを確認する : Rust よりメンテナブルなエラーハンドリングに

Slide 33

Slide 33 text

33 ©2023 Loglass Inc. 他の言語のパラダイムを確認する : Scala よりメンテナブルなエラーハンドリングに

Slide 34

Slide 34 text

34 ©2023 Loglass Inc. and_thenの実装 よりメンテナブルなエラーハンドリングに ● 関数の合成はシンタックス的に難しそう ● Rustではand_then, ScalaではflatMapがある ● どちらも同じ動きをしている ● これらを模倣してみると良さそう

Slide 35

Slide 35 text

35 ©2023 Loglass Inc. and_thenの実装(1/3) よりメンテナブルなエラーハンドリングに ● out: Kotlinにおける共変を表す ● Nothing: 存在しない値を表す型

Slide 36

Slide 36 text

36 ©2023 Loglass Inc. and_thenの実装(2/3) よりメンテナブルなエラーハンドリングに ● 拡張関数: fun Result.funName() {} と宣言することで、 クラスにメソッドが生えているかのような書き方ができる ● 引数部分は関数渡し 図の場合、引数は Function>と同等

Slide 37

Slide 37 text

37 ©2023 Loglass Inc. and_thenの実装(3/3) よりメンテナブルなエラーハンドリングに

Slide 38

Slide 38 text

38 38 ©2023 Loglass Inc. Nothing型 よりメンテナブルなエラーハンドリングに ● Any型の反対 ● 全てのクラスを継承したクラス ● Nothingはインスタンスを生成することができない ● ex) 必ず例外を送出するようなメソッド ● ex) 型引数が省略できないとき Nothingを指定する

Slide 39

Slide 39 text

39 39 ©2023 Loglass Inc. 必ず例外を送出するメソッド よりメンテナブルなエラーハンドリングに ● fail() とかも適していそう ● ロギング + 例外送出 ● etc…

Slide 40

Slide 40 text

40 ©2023 Loglass Inc. 型引数が省略できないとき よりメンテナブルなエラーハンドリングに ● Resultの型引数はTとEを取る ● OkはTだけでいいし、ErrorはEだけでいい ● しかし型引数は省略できないので Nothingを使う

Slide 41

Slide 41 text

41 ©2023 Loglass Inc. kotlin-resultの紹介 よりメンテナブルなエラーハンドリングに ● サンプルコードをいくつかご紹介しました ● kotlin-resultというライブラリを利用すると、 これまでのことが一瞬でできるようになります ○ https://github.com/michaelbull/kotlin-result implementation("com.michael-bull.kotlin-result:kotlin-result:1.1.16" )

Slide 42

Slide 42 text

42 ©2023 Loglass Inc. kotlin-resultの紹介 よりメンテナブルなエラーハンドリングに kotlin-resultのGitHubページより引用

Slide 43

Slide 43 text

43 ©2023 Loglass Inc. kotlin-resultの紹介 よりメンテナブルなエラーハンドリングに

Slide 44

Slide 44 text

44 ©2023 Loglass Inc. まとめ

Slide 45

Slide 45 text

45 ©2023 Loglass Inc. 今回のサマリ まとめ 1. Kotlinに検査例外は無い 2. エラーハンドリングをする際は直和型 + パターンマッチで Result型を設計すべし 3. kotlin-resultを導入すると、Result型をすぐに使い始められる

Slide 46

Slide 46 text

46 46 ©2023 Loglass Inc. 参考文献 まとめ ● 代数的データ型 ○ https://ja.wikipedia.org/wiki/代数的データ型 ● kotlin-result ○ https://github.com/michaelbull/kotlin-result ● KotlinでResult型使うならkotlin-resultを使おう ○ https://note.com/yasukotelin/n/n6d9e352c344c ● Rust By Example ○ https://doc.rust-jp.rs/rust-by-example-ja/error/opti on_unwrap/and_then.html ● Scala の Option, Either とエラー処理 ○ https://engineering.mobalab.net/2020/09/24/scala -error-handling-option-either

Slide 47

Slide 47 text

47