Slide 1

Slide 1 text

Kaigi on Rails 2022 - 10.22(Sat) 入社数ヶ月のnewbieが 稼働7年超のプロジェクトに 型を導入して見えた世界 ふーが@fugakkbn / ESM, Inc

Slide 2

Slide 2 text

Profile ふーが @fugakkbn   2022年3月からエンジニアに(at ESM, Inc)   Railsを使用したアプリケーション開発   gem_rbs_collectionのコントリビューター   プロジェクトへの型導入を進めている   Kaigi on Rails Organizer

Slide 3

Slide 3 text

動機 なぜ型に興味を持ったのか? 初めての型 TypeScriptで静的型に初 めて触れ、型があること のメリットを知った。 Rubyでも型の恩恵を 3.0からRubyでも静的型 を扱えるようになった が、プロジェクトには導 入されていなかった。 後押し 1on1でEMに「型に興味 がある」話をしたら「プ ロジェクトに導入してみ たら?」

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

×

Slide 6

Slide 6 text

コミュニティとの ”共生” このワードにピンと来た方は… @fugakkbn or agile.esm.co.jp まで!!

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Kaigi on Rails 2022 - 10.22(Sat) 入社数ヶ月のnewbieが 稼働7年超のプロジェクトに 型を導入して見えた世界 ふーが@fugakkbn / ESM, Inc

Slide 9

Slide 9 text

アジェンダ newbieこそ型定義をするべき どのように導入を提案したか 導入する上での障壁

Slide 10

Slide 10 text

今日伝えたいこと newbie の皆さん 型情報から得られるフィードバック以外にもたくさんのメ リットがあることを知って欲しい もし型に興味を持ってもらえたなら、ぜひプロジェクトへ の導入を! 先輩の皆さん 同僚から型導入の打診があった時は今日紹介するようなメ リットを思い出して、ぜひ導入の支援をお願いします!

Slide 11

Slide 11 text

RBSの文法、書き方 導入の具体的な手順

Slide 12

Slide 12 text

用語の紹介 基本的なものだけ紹介 RBS Rubyの型を書くための言 語の名称。Ruby Likeな 書き方ができるため理解 やすい。 Steep Rubyの静的型解析機。 steep checkコマンドで Rubyファイルとrbsファ イルの型検査ができる。 ジェネレーター この発表では「プロダク トコードをもとにRBSの コードを自動生成するも の」として話します。

Slide 13

Slide 13 text

newbieこそ型定義をするべき https://unsplash.com/ja/%E5%86%99%E7%9C%9F/ak4hw4r6xio

Slide 14

Slide 14 text

なぜ? 理由はいくつかあります   コードを読み解きやすくなる   プロジェクトの全容把握の近道になる   実装を読むことへの抵抗がなくなる   無限にコントリビュートチャンスがある

Slide 15

Slide 15 text

なぜ? 理由はいくつかあります   コードを読み解きやすくなる   プロジェクトの全容把握の近道になる   実装を読むことへの抵抗がなくなる   無限にコントリビュートチャンスがある

Slide 16

Slide 16 text

皆さんに質問 プロジェクトに全部でいく つのメソッドが定義されて いますか? また、それらの引数にはど んな値が入りますか?

Slide 17

Slide 17 text

とあるアプリのメソッド数

Slide 18

Slide 18 text

とあるアプリのメソッド数

Slide 19

Slide 19 text

すべてを覚えておくのはムリ! 一度読んで理解してもしばらくしたら忘れてしまう 先輩のコードをレビューしているとき、テストコードを読み解くとき、障害発生 時に調査するとき…などなど、折に触れてメソッドの構造を理解するべきタイミ ングがあると思います。

Slide 20

Slide 20 text

そこで型ですよ 型があれば覚えておく必要がない なぜなら型を見ればどんな引数を渡してどんな返り値なのかが一目でわかるから 「これってどういうメソッドなんだっけ?」から始まる調査の手間は決して軽い ものではないはず。

Slide 21

Slide 21 text

rbsファイル アプリケーションコード

Slide 22

Slide 22 text

rbsファイル アプリケーションコード

Slide 23

Slide 23 text

rbsファイル 違う型を引数に渡そうとすると…

Slide 24

Slide 24 text

rbsファイル 型が違うことを教えてくれる!

Slide 25

Slide 25 text

型をつけたことで たくさんあるメソッドを 読み解きやすくなった

Slide 26

Slide 26 text

型をつけたことで たくさんあるメソッドを 読み解きやすくなった 型

Slide 27

Slide 27 text

なぜ? 理由はいくつかあります   コードを読み解きやすくなる   プロジェクトの全容把握の近道になる   実装を読むことへの抵抗がなくなる   無限にコントリビュートチャンスがある

Slide 28

Slide 28 text

プロジェクトの 全容把握 newbieな僕の最初の壁 その1

Slide 29

Slide 29 text

newbie 心の叫び どこに何が定義され ているのかわからな い。モデル同士の関 連どうなってるの? 「簡単な修正」って issue 振ってもらっ たけど…どこから手 をつければいいの? メソッドの処理が複 雑すぎて最終的にど うなるのかわから ん!!! コードジャンプ候補 に同名メソッドがた くさん出てきてどれ が正しいのかわから ない。。。

Slide 30

Slide 30 text

newbie 心の叫び どこに何が定義され ているのかわからな い。モデル同士の関 連どうなってるの? 「簡単な修正」って issue 振ってもらっ たけど…どこから手 をつければいいの? メソッドの処理が複 雑すぎて最終的にど うなるのかわから ん!!! コードジャンプ候補 に同名メソッドがた くさん出てきてどれ が正しいのかわから ない。。。

Slide 31

Slide 31 text

そこで型ですよ 型を書くことで理解が深まる 型を書くにはメソッドの使い方や使用時の挙動を調査する必要がある。 それを繰り返す中でどんどんわかることが増えていき、プロジェクトへの理解が 深まっていく。

Slide 32

Slide 32 text

型定義を進めるために嫌でもプロジェクト内のファイルを横 断的に見ることになる モデル同士の関連がどうなっているか理解が進んだり、この モデルにこんなメソッドがあるのか!などの発見がある それらに型付けする過程でユースケースやどこで使われてい るのかなどが自然とわかる

Slide 33

Slide 33 text

別のメリット 今後の自分の助けにもなる 型付けが進むとIDEの補完の正確度が上がる。正確度が上がると調査 も実装も速度が上がるため、相対的に同じ時間内で得られる情報量 が増える。

Slide 34

Slide 34 text

補完候補(型がない場合)

Slide 35

Slide 35 text

補完候補(型がない場合)

Slide 36

Slide 36 text

補完候補(型がある場合)

Slide 37

Slide 37 text

補完候補(型がある場合)

Slide 38

Slide 38 text

nextメソッドの定義を見たい!

Slide 39

Slide 39 text

ここでコードジャンプしようとすると…

Slide 40

Slide 40 text

候補がたくさん表示されてしまう

Slide 41

Slide 41 text

型をStringだと定義しておくと…

Slide 42

Slide 42 text

一発で String#next の定義元に飛べる!

Slide 43

Slide 43 text

型をつけたことで プロジェクトへの理解が進み 調査や実装もしやすくなった

Slide 44

Slide 44 text

型をつけたことで プロジェクトへの理解が進み 調査や実装もしやすくなった 型

Slide 45

Slide 45 text

なぜ? 理由はいくつかあります   コードを読み解きやすくなる   プロジェクトの全容把握の近道になる   実装を読むことへの抵抗がなくなる   無限にコントリビュートチャンスがある

Slide 46

Slide 46 text

gemの実装を見るのが苦手 newbieな僕の最初の壁 その2

Slide 47

Slide 47 text

苦手な理由 思い返してみると… 難しいコードがたくさん出てくる印象 どこから見ればいいのかわからない 「まだ自分には読めない」という先入観

Slide 48

Slide 48 text

型生成プロセス 良いサイクルが生まれます 調査 メソッドの構造 (引数の型、返 り値の型)や使 われ方を調査す る。 型定義 調査結果をもと に型を定義して いく。このとき gem の型定義 の不足や誤りが 判明することも 実装の確認 起こっているエ ラーが型定義の 誤りなのかそう でないのかは、 gem の実装を 見る必要がある 反復 型定義はこれら の繰り返し。繰 り返しやってい るうちに実装を 見るのが日常に なる。 成果物 プロジェクトの 型定義はもちろ ん、場合によっ ては OSS にコ ントリビュート できることも。

Slide 49

Slide 49 text

steep checkで出たエラーに疑義がある場合 gemの型定義がなくて追加しようとするとき

Slide 50

Slide 50 text

steep check 実行時に見つかる

Slide 51

Slide 51 text

steep check 実行時に見つかる

Slide 52

Slide 52 text

steep check 実行時に見つかる

Slide 53

Slide 53 text

steep check 実行時に見つかる

Slide 54

Slide 54 text

実装元を確認する

Slide 55

Slide 55 text

Receive block!

Slide 56

Slide 56 text

gemの実装を見ることが "日常"になった。 あの頃の苦手意識はもうない

Slide 57

Slide 57 text

gemの実装を見ることが "日常"になった。 あの頃の苦手意識はもうない 型

Slide 58

Slide 58 text

gemの実装を見ることが "日常"になった。 あの頃の苦手意識はもうない 型 ※ただし読めるとは言っていない

Slide 59

Slide 59 text

なぜ? 理由はいくつかあります   コードを読み解きやすくなる   プロジェクトの全容把握の近道になる   実装を読むことへの抵抗がなくなる   無限にコントリビュートチャンスがある

Slide 60

Slide 60 text

OSSって なにから始めればいいの? newbieな僕の最初の壁 その3

Slide 61

Slide 61 text

OSS

Slide 62

Slide 62 text

OSS 選ばれし人がやること 初心者の自分にできるわけがない。技術に秀でたすごい人 たちがやること。

Slide 63

Slide 63 text

OSS 選ばれし人がやること 初心者の自分にできるわけがない。技術に秀でたすごい人 たちがやること。 自分にできることがあるはずない すごい技術を持った人たちが作ったものに自分が修正でき るところがあるわけない。

Slide 64

Slide 64 text

OSS 選ばれし人がやること 初心者の自分にできるわけがない。技術に秀でたすごい人 たちがやること。 自分にできることがあるはずない すごい技術を持った人たちが作ったものに自分が修正でき るところがあるわけない。 やってみたい気持ちはあるけれど… どこから手をつけたらいいのか、どこが修正すべきところ なのか、どうやってパッチを送ればいいのかナニモワカラ ナイ。

Slide 65

Slide 65 text

型定義を始めるまでは…

Slide 66

Slide 66 text

型定義の誤り

Slide 67

Slide 67 text

gemの型定義の不足

Slide 68

Slide 68 text

試行錯誤の中での気づき プロジェクトの型導入をしている中で gemの型定義が足りなかったり間違ってることがあるなぁ

Slide 69

Slide 69 text

試行錯誤の中での気づき プロジェクトの型導入をしている中で gemの型定義が足りなかったり間違ってることがあるなぁ これってもしや…コントリビュートチャンスってやつ!?

Slide 70

Slide 70 text

OSSへの初めてのコントリビュート

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

コントリビュートは すごい人だから するものではない。 「使ってる人が 気付いた時にするもの」

Slide 73

Slide 73 text

コントリビュートは すごい人だから するものではない。 「使ってる人が 気付いた時にするもの」 型

Slide 74

Slide 74 text

なぜ? 理由はいくつかあります   コードを読み解きやすくなる   プロジェクトの全容把握の近道になる   実装を読むことへの抵抗がなくなる   無限にコントリビュートチャンスがある

Slide 75

Slide 75 text

興味を持ってもらえたら プロジェクトに型を 導入してみてください! newbieの多くの悩みを解決してくれます

Slide 76

Slide 76 text

とはいえ…

Slide 77

Slide 77 text

newbieに型を導入する 裁量なんてないんですが!?

Slide 78

Slide 78 text

どのように 型導入を提案したか https://unsplash.com/ja/%E5%86%99%E7%9C%9F/5Q07sS54D0Q

Slide 79

Slide 79 text

小さく少しずつ

Slide 80

Slide 80 text

第1ステップとして、rbs, rbs-rails, gem_rbs_collection などで大枠の型定義をそろえる

Slide 81

Slide 81 text

第1ステップとして、rbs, rbs-rails, gem_rbs_collection などで大枠の型定義をそろえる 第2ステップとして、生成された rbs ファイルの untyped を 正しい型に書き換えていく

Slide 82

Slide 82 text

第1ステップとして、rbs, rbs-rails, gem_rbs_collection などで大枠の型定義をそろえる 第2ステップとして、生成された rbs ファイルの untyped を 正しい型に書き換えていく 並行して、steep check でのエラーから gem の型定義不足 や誤りを見つけて修正する

Slide 83

Slide 83 text

gemもrbsも独立しているので剥がすのは簡単 主要なModelやAPIだけでもよい 型があってもなくてもプロダクトコードに影響はない Linterで警告が出たりノイズが発生することもない

Slide 84

Slide 84 text

CIには入れない

Slide 85

Slide 85 text

エラーの解消が目的ではない 目的はあくまで"開発者体験の向上" CIに組み込むと間違いなくエラーが出続ける CIがずっとredだと"オオカミ少年"状態になる… 型のエラーを検知したい訳ではない プロジェクト内の型を充実させることに集中する方が建設的

Slide 86

Slide 86 text

書きたい人だけ

Slide 87

Slide 87 text

型を書きたい人

Slide 88

Slide 88 text

型を書きたい人

Slide 89

Slide 89 text

型を書きたい

Slide 90

Slide 90 text

型を書きたい

Slide 91

Slide 91 text

型の恩恵を受けたい 型を書きたい

Slide 92

Slide 92 text

"書かなきゃいけないもの"にすると開発速度の低下ややらされ てる感からの生産性低下 "書く気力のある人"が少しずつ進めていくしかない。"型のあ る開発環境"を水面化で進める 機能追加のPull Requestに混ぜない。ノイズになる。型は個 別のPull Requestで余裕のある人が見る(見なくてもいい)

Slide 93

Slide 93 text

チームへの説明

Slide 94

Slide 94 text

newbieの独断では入れられない メンバーの理解と協力が不可欠 受け入れてくれたメンバーに感謝 ここまで説明したようなスタンス、メリットを伝える 「やっぱりダメだね」となった場合もすぐに剥がせる 一人でもメンテナンスしていく覚悟

Slide 95

Slide 95 text

導入の障壁 https://unsplash.com/ja/%E5%86%99%E7%9C%9F/sQ5yREHU_fI

Slide 96

Slide 96 text

gemの型不足

Slide 97

Slide 97 text

gemの型定義はまだまだ足りていない(2022年10月現在、 57個がgem_rbs_collectionにある) gemの型定義が増えるとプロジェクトに導入しやすくなるは ずだと考えています 興味がある方はぜひgemの型定義をやってみましょう!gem の型定義が増えて導入するプロジェクトが増えれば、型エコ システムの発展も早くなるかも?

Slide 98

Slide 98 text

RubyKaigi 2022 でそういう発表をしました https://speakerdeck.com/fugakkbn/types-teaches-success-what-will-we-do

Slide 99

Slide 99 text

変更への追従

Slide 100

Slide 100 text

コードの変更への追従 検知するソリューションがない メソッド追加、構造の変更など 自動で検知することができないため人力になる 別ファイルであることのデメリット 「気づいたときにやればいい」というスタンス

Slide 101

Slide 101 text

大量のエラー

Slide 102

Slide 102 text

プロジェクトに型を導入して全体で steep check を実行する と、大量にエラーが出るはず 今のプロジェクトでは1万以上のエラーが出る 繰り返しになるが、エラーを解消することに心血を注ぐ必要 はないと考えている

Slide 103

Slide 103 text

https://speakerdeck.com/soutaro/ruby-programming-with-types-in-action?slide=13

Slide 104

Slide 104 text

まとめ

Slide 105

Slide 105 text

newbieが型を書くメリットはたくさんあります!興味の裾野 を広げる一歩目にいかがですか? プロジェクトに型を導入することで得られる恩恵は限定的。 でも新しいメンバーがいち早くプロジェクトに馴染む助けに もなりそう。 小さく始められてランタイムに影響を与えないので導入しや すい。メンバーから打診があったらぜひ前向きな検討を!

Slide 106

Slide 106 text

型を通じて できることが増えた 取り組む意識が変わった 興味の幅が拡がった Rubyがもっと楽しくなった

Slide 107

Slide 107 text

波 紋 波 紋 https://unsplash.com/ja/%E5%86%99%E7%9C%9F/Tf18kgGiop4

Slide 108

Slide 108 text

No content

Slide 109

Slide 109 text

Slide 110

Slide 110 text

誰がメンテしてる? 型

Slide 111

Slide 111 text

誰がメンテしてる? Steepのコマンドは内部 的にどう呼ばれてる? 型

Slide 112

Slide 112 text

誰がメンテしてる? どうやってコントリ ビュートする? Steepのコマンドは内部 的にどう呼ばれてる? 型

Slide 113

Slide 113 text

誰がメンテしてる? どうやってコントリ ビュートする? Steepのコマンドは内部 的にどう呼ばれてる? 型 ASTってなに? ASTってなに?

Slide 114

Slide 114 text

見える景色が変わった 見える景色が変わった 知覚できる世界が広がった 知覚できる世界が広がった https://unsplash.com/ja/%E5%86%99%E7%9C%9F/1lfI7wkGWZ4