Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
型だけでバグを減らそう! Kotlinの型パワーを使った実践タイプセーフエンジニ...
Search
YuitoSato
December 10, 2022
Technology
2
1.7k
型だけでバグを減らそう! Kotlinの型パワーを使った実践タイプセーフエンジニアリング
Kotlin Fest 2022の登壇内容のスライドです。
YuitoSato
December 10, 2022
Tweet
Share
More Decks by YuitoSato
See All by YuitoSato
「規約、知識、オペレーション」から考える中規模以上の開発組織のCursorルールの 考え方・育て方 / Cursor Rules for Coding Styles, Domain Knowledges and Operations
yuitosato
9
5.5k
大AI時代で輝くために今こそドメインにディープダイブしよう / Deep Dive into Domain in AI-Agent-Era
yuitosato
2
2.4k
50人の組織でAIエージェントを使う文化を作るためには / How to Create a Culture of Using AI Agents in a 50-Person Organization
yuitosato
6
6.6k
Railway Oriented Programming を オニオンアーキテクチャに適用する by kotlin-result / Railway Oriented Programming in Onion Architecture by kotlin-result
yuitosato
4
1.3k
リファクタリングへの耐性が高いモデルベースの統合テストの紹介 / Model-Base Integration Test for Refactoring
yuitosato
7
3.5k
Expressing Business Logic with Types: Functional DDD for OOP
yuitosato
1
160
ビジネスロジックを「型」で表現するOOPのための関数型DDD / Functional And Type-Safe DDD for OOP
yuitosato
44
30k
Java21とKotlinの代数的データ型 & パターンマッチの紹介と本当に嬉しい使い方 / Algebraic Data Type in Java and Kotlin: Happy Use of Pattern Match
yuitosato
14
5.4k
ログラスの継続的ライブラリアップデートのWhyとHow / Why and How to Update Libraries Continuously in Loglass
yuitosato
0
500
Other Decks in Technology
See All in Technology
改竄して学ぶコンテナサプライチェーンセキュリティ ~コンテナイメージの完全性を目指して~/tampering-container-supplychain-security
mochizuki875
1
400
2025 DORA Reportから読み解く!AIが映し出す、成果を出し続ける組織の共通点 #開発生産性_findy
takabow
0
410
雲勉LT_Amazon Bedrock AgentCoreを知りAIエージェントに入門しよう!
ymae
2
220
巨大モノリスのリプレイス──機能整理とハイブリッドアーキテクチャで挑んだ再構築戦略
zozotech
PRO
0
360
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.2k
AI時代の戦略的アーキテクチャ 〜Adaptable AI をアーキテクチャで実現する〜 / Enabling Adaptable AI Through Strategic Architecture
bitkey
PRO
15
11k
[続・営業向け 誰でも話せるOCI セールストーク] AWSよりOCIの優位性が分からない編(2025年11月21日開催)
oracle4engineer
PRO
1
130
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.3k
AI エージェントを評価するための温故知新と Spec Driven Evaluation
icoxfog417
PRO
2
770
AWS re:Invent 2025 で頻出の 生成 AI サービスをおさらい
komakichi
3
240
組織の“見えない壁”を越えよ!エンタープライズシフトに必須な3つのPMの「在り方」変革 #pmconf2025
masakazu178
1
990
社内外から"使ってもらえる"データ基盤を支えるアーキテクチャの秘訣/登壇資料(飯塚 大地・高橋 一貴)
hacobu
PRO
0
7.7k
Featured
See All Featured
Building Adaptive Systems
keathley
44
2.8k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
YesSQL, Process and Tooling at Scale
rocio
174
15k
The Pragmatic Product Professional
lauravandoore
36
7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
36
6.1k
KATA
mclloyd
PRO
32
15k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.2k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Transcript
1 ©2022 Loglass Inc. 型だけでバグを減らそう! Kotlinの型パワーを使った実践タイプセーフ エンジニアリング 2022.12.10 佐藤有斗(Yuiiitoto) 株式会社ログラス
2 ©2022 Loglass Inc. 自己紹介 佐藤有斗(Yuiiitoto) ログラス エンジニア # React
# 組織・アジャイル # Kotlin
3 ©2022 Loglass Inc. ログラスについて(5秒) 企業価値を向上する 経営管理クラウド
4 ©2022 Loglass Inc. 目次 • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン 1.
標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
5 ©2022 Loglass Inc. 目次 • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン 1.
標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
6 ©2022 Loglass Inc. なぜ型を使いこなすことでバグが減るのか コンパイル時に実装ミスに気付けるから
7 ©2022 Loglass Inc. コンパイル時に実装ミスに気づくとは?
8 ©2022 Loglass Inc. ミドルネームにnullを渡す
9 ©2022 Loglass Inc. ぬるぽ、ガッ! Λ_Λ \\ ( ・∀・) | | ガッ と )
| | Y /ノ 人 / ) < >_Λ∩ _/し' //. V`Д´)/ (_フ彡 / ←>>1 NullPointerExceptionが起きる
10 ©2022 Loglass Inc. と思いきやKotlinはコンパイルで落ちる
11 ©2022 Loglass Inc. Kotlinではデフォルトで 引数や変数にnullを渡すことができない KotlinのNull Safety
12 ©2022 Loglass Inc. Kotlinではデフォルトで 引数や変数にnullを渡すことができない KotlinのNull Safety
13 ©2022 Loglass Inc. 実装ミスをコンパイル時に気づけると何がいいのか? • 実行時に気付くバグと比較して ... ◦ 全ての分岐を実行しなくてもよく
必ず実装ミスに気づくことができる ◦ テストカバレッジ100%は現実的ではない
14 ©2022 Loglass Inc. では、なぜKotlin? • Kotlinは型に関する機能が豊富 ◦ Generics ◦
型推論 ◦ Smart Cast ◦ 代数的データ型 ◦ 高階関数やラムダ ◦ Delegation などなど
15 ©2022 Loglass Inc. 要するに、、 Kotlinを駆使して、実装ミスをコンパイルで 気付けるようにしよう!!!
16 ©2022 Loglass Inc. 型によってバグが減らせるパターン • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン 1.
標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
17 ©2022 Loglass Inc. 標準の型をラップする • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン 1.
標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
18 ©2022 Loglass Inc. 標準の型をラップする • よくあるミス: 引数のIDを取り間違えてしまった
19 ©2022 Loglass Inc. 標準の型をラップする • よくあるミス: 引数のIDを取り間違えてしまった
20 ©2022 Loglass Inc. Stringをラップする
21 ©2022 Loglass Inc. TaskIdとUserIdを区別することでコンパイル時に実装ミスに気付ける
22 ©2022 Loglass Inc. TaskIdとUserIdを区別することでコンパイル時に実装ミスに気付ける
23 ©2022 Loglass Inc. ちなみに: ラップすることによるオーバーヘッドを避ける • Stringをクラスでラップするとヒープ領域のオーバーヘッドが増える • inline
classesという機能を使うことで String型として扱えてスタック領域だけの割り当てで済む
24 ©2022 Loglass Inc. ここで一つ疑問が 全てのIDに別々の型をつけるの面倒 ではないか?
25 ©2022 Loglass Inc. タイプセーフにしたいが、型の増加を抑制したい => Genericsを使おう! Genericsでさらに汎用的にする
26 ©2022 Loglass Inc. Genericsでさらに汎用的にする
27 ©2022 Loglass Inc. Genericsでさらに汎用的にする
28 ©2022 Loglass Inc. Genericsでさらに汎用的にする • 型を増やさずに、タスク IDとユーザーIDを区別できた!
29 ©2022 Loglass Inc. Genericsでさらに汎用的にする • 型を増やさずに、タスク IDとユーザーIDを区別できた!
30 ©2022 Loglass Inc. Genericsでさらに汎用的にする • 型を増やさずに、タスク IDとユーザーIDを区別できた!
31 ©2022 Loglass Inc. Genericsでさらに汎用的にする • 型を増やさずに、タスク IDとユーザーIDを区別できた!
32 ©2022 Loglass Inc. Genericsでさらに汎用的にする • 型を増やさずに、タスク IDとユーザーIDを区別できた!
33 ©2022 Loglass Inc. 標準の型をラップする : まとめ 標準の型をラップして取り間違いを防ぐ 型の増加をGenericsで抑制する
34 ©2022 Loglass Inc. 認可処理などの特定の処理をパスしたことを型で示す • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン 1.
標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
35 ©2022 Loglass Inc. 認可処理などの特定の処理をパスしたことを型で示す • よくあるミス: 認可されていないIDで参照をしてしまった
36 ©2022 Loglass Inc. 認可処理などの特定の処理をパスしたことを型で示す • よくあるミス: 認可されていないIDで参照をしてしまった
37 ©2022 Loglass Inc. 認可処理などの特定の処理をパスしたことを型で示す • よくあるミス: 認可されていないIDで参照をしてしまった
38 ©2022 Loglass Inc. 「認可された」ID型を導入する • 認可されたID型として AuthorizedTaskId を定義する
39 ©2022 Loglass Inc. 「認可された」ID型を導入する • TaskAuthChecker だけが返す特別な型とする
40 ©2022 Loglass Inc. 「認可された」ID型を導入する • TaskAuthChecker だけが返す特別な型とする
41 ©2022 Loglass Inc. 「認可された」ID型を導入する • findTaskByIdはAuthorizedTaskIdしか受け付けないように修正
42 ©2022 Loglass Inc. 「認可された」ID型を導入する • findTaskByIdはAuthorizedTaskIdしか受け付けないように修正
43 ©2022 Loglass Inc. 「認可された」ID型を導入する • 認可処理を通過していない IDはコンパイル時に落ちるようになる
44 ©2022 Loglass Inc. 「認可された」ID型を導入する • 認可処理を通過していない IDはコンパイル時に落ちるようになる
45 ©2022 Loglass Inc. 「認可された」ID型を導入する • 認可処理を通過していない IDはコンパイル時に落ちるようになる
46 ©2022 Loglass Inc. 「認可された」ID型を導入する • 認可処理を通過していない IDはコンパイル時に落ちるようになる
47 ©2022 Loglass Inc. しかし油断してはいけない • AuthorizedTaskIdのコンストラクタが公開されている! ここに public が潜んでいる
48 ©2022 Loglass Inc. しかし油断してはいけない • AuthorizedTaskIdのコンストラクタが公開されている!
49 ©2022 Loglass Inc. しかし油断してはいけない • 不正に認可されていない AuthorizedTaskIdが作成されてしまう
50 ©2022 Loglass Inc. しかし油断してはいけない • 不正に認可されていない AuthorizedTaskIdが作成されてしまう
51 ©2022 Loglass Inc. 不正にインスタンスを作成されないためには? data classを使ってコンストラクタの可視性を コントロールする
52 ©2022 Loglass Inc. コンストラクタの可視性を data classで制御する
53 ©2022 Loglass Inc. コンストラクタの可視性を data classで制御する • インスタンスを作成できない interface
AuthorizedTaskIdを定義する sealed を使えば同ファイルからしか継承できない
54 ©2022 Loglass Inc. コンストラクタの可視性を data classで制御する • コンストラクタ機能だけの data
classをprivateで定義する private classは同ファイルからしか参照できない
55 ©2022 Loglass Inc. コンストラクタの可視性を data classで制御する • TaskAuthCheckerからのみprivate data
classにアクセスする
56 ©2022 Loglass Inc. コンストラクタの可視性を data classで制御する • 別ファイルから AuthorizedTaskId
インスタンスが生成できなくなった!
57 ©2022 Loglass Inc. コンストラクタの可視性を data classで制御する • 別ファイルから AuthorizedTaskId
インスタンスが生成できなくなった!
58 ©2022 Loglass Inc. コンストラクタの可視性を data classで制御する • 別ファイルから AuthorizedTaskId
インスタンスが生成できなくなった!
59 ©2022 Loglass Inc. コンストラクタをprivateにするのではダメ? • この場合のprivateは同じクラス ファイル のみアクセス可能という意味なので NG
60 ©2022 Loglass Inc. 認可処理などの特定の処理をパスしたことを型で示す : まとめ 処理が通過したことを型で示す コンストラクタを非公開にして不正にインスタンスを作らせない
61 ©2022 Loglass Inc. 型でデータの不整合をなくす • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン 1.
標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
62 ©2022 Loglass Inc. 型でデータの不整合をなくす • よくあるミス: あり得ないデータを作成してしまった
63 ©2022 Loglass Inc. 型でデータの不整合をなくす • タスクには以下のステータスがある • 完了ステータスのときのみ完了時刻を持つ
64 ©2022 Loglass Inc. 型でデータの不整合をなくす • しかし間違えて着手時に完了時刻を入れてしまった • →着手中なのに完了時刻を持つという不整合データが誕生
65 ©2022 Loglass Inc. 型でデータの不整合をなくす • しかし間違えて着手時に完了時刻を入れてしまった • →着手中なのに完了時刻を持つという不整合データが誕生
66 ©2022 Loglass Inc. データ不整合をなくすには? sealed classを使って データの不整合が起こりえない型を定義する
67 ©2022 Loglass Inc. sealed class を導入する • 完了の時のみ完了時刻をもつというデータ構造を sealed
classで定義
68 ©2022 Loglass Inc. sealed class を導入する • sealed class
+ object, data classのパターンはEnumのように扱える
69 ©2022 Loglass Inc. sealed class を導入する • Enumだとこうなる •
objectはEnumとほぼ同じ扱いで、data classはEnum + 構造体というような振る舞い
70 ©2022 Loglass Inc. sealed class を導入する • Task型からnullableなcompletedAtプロパティが消える
71 ©2022 Loglass Inc. sealed class を導入する • 着手中時に完了時刻を渡せなくなった
72 ©2022 Loglass Inc. sealed class を導入する • 着手中時に完了時刻を渡せなくなった
73 ©2022 Loglass Inc. sealed class を導入する • 完了時には完了時刻の入力を強制できる
74 ©2022 Loglass Inc. sealed class を導入する • 完了時には完了時刻の入力を強制できる
75 ©2022 Loglass Inc. OSS: kotlin-resultの事例 • 成功値かエラー値かどちらかの値をとる Result型を提供するOSS kotlin-result
: https://github.com/michaelbull/kotlin-result
76 ©2022 Loglass Inc. OSS: kotlin-resultの事例 • 成功値かエラー値かどちらかの値をとる Result型を提供するOSS kotlin-result
: https://github.com/michaelbull/kotlin-result
77 ©2022 Loglass Inc. OSS: kotlin-resultの事例 • NGパターン: nullableな value
と errorを持っているわけではないことに注意
78 ©2022 Loglass Inc. 型でデータ不整合をなくす : まとめ sealed classを使って データの不整合が起こりえない型を定義する
79 ©2022 Loglass Inc. まとめ • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン 1.
標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
80 ©2022 Loglass Inc. まとめ • なぜ型を使いこなすことでバグが減るのか? ◦ →コンパイル時に実装ミスを検出できるから ◦
→Kotlinの型パワーを使ってコンパイル時により多くのミスを検出する
81 ©2022 Loglass Inc. まとめ • 型によってバグが減らせるパターン 1. 標準の型をラップする →
genericsで型の増加を抑制しよう 2. 認可処理などの特定の処理をパスしたことを型で示す → コンストラクタの可視性を data classを使ってコントロールしよう 3. 型でデータの不整合をなくす → sealed classでデータの不整合をなくそう
82 ©2022 Loglass Inc. 最後に: タイプセーフなポストモーテム • なぜ型を使いこなすことでバグが減るのか? • 型によってバグが減らせるパターン
1. 標準の型をラップする 2. 認可処理などの特定の処理をパスしたことを型で示す 3. 型でデータの不整合をなくす • まとめ • 最後に: タイプセーフなポストモーテム
83 ©2022 Loglass Inc. 最後に: タイプセーフなポストモーテム 情報漏洩が起きました!再発防止策は?
84 ©2022 Loglass Inc. 最後に: タイプセーフなポストモーテム - レビュワーを2人に増やす - 偉い人のチェックを増やす
- GitHubのPRテンプレにチェック項目を足 す - テスト工数を2倍にする etc…
85 ©2022 Loglass Inc. 最後に: タイプセーフなポストモーテム それ、型で解決できませんか?
86 ©2022 Loglass Inc. 最後に: タイプセーフなポストモーテム • 障害のたびにテスト工数を増やしたり、「儀式」を追加するとスピードが落ちる • 最優先で考えるべき再発防止策はコンパイル時に障害のタネを気付けるようにすること
• Kotlinはそのための機能をたくさん有している
87