Kaigi on Rails 2022 登壇資料
Kaigi on Rails 2022 - 10.22(Sat)入社数ヶ月のnewbieが稼働7年超のプロジェクトに型を導入して見えた世界ふーが@fugakkbn / ESM, Inc
View Slide
Profileふーが @fugakkbn 2022年3月からエンジニアに(at ESM, Inc) Railsを使用したアプリケーション開発 gem_rbs_collectionのコントリビューター プロジェクトへの型導入を進めている Kaigi on Rails Organizer
動機なぜ型に興味を持ったのか?初めての型TypeScriptで静的型に初めて触れ、型があることのメリットを知った。Rubyでも型の恩恵を3.0からRubyでも静的型を扱えるようになったが、プロジェクトには導入されていなかった。後押し1on1でEMに「型に興味がある」話をしたら「プロジェクトに導入してみたら?」
×
コミュニティとの”共生”このワードにピンと来た方は…@fugakkbn or agile.esm.co.jp まで!!
アジェンダnewbieこそ型定義をするべきどのように導入を提案したか導入する上での障壁
今日伝えたいことnewbie の皆さん型情報から得られるフィードバック以外にもたくさんのメリットがあることを知って欲しいもし型に興味を持ってもらえたなら、ぜひプロジェクトへの導入を!先輩の皆さん同僚から型導入の打診があった時は今日紹介するようなメリットを思い出して、ぜひ導入の支援をお願いします!
RBSの文法、書き方導入の具体的な手順
用語の紹介基本的なものだけ紹介RBSRubyの型を書くための言語の名称。Ruby Likeな書き方ができるため理解やすい。SteepRubyの静的型解析機。steep checkコマンドでRubyファイルとrbsファイルの型検査ができる。ジェネレーターこの発表では「プロダクトコードをもとにRBSのコードを自動生成するもの」として話します。
newbieこそ型定義をするべきhttps://unsplash.com/ja/%E5%86%99%E7%9C%9F/ak4hw4r6xio
なぜ?理由はいくつかあります コードを読み解きやすくなる プロジェクトの全容把握の近道になる 実装を読むことへの抵抗がなくなる 無限にコントリビュートチャンスがある
皆さんに質問 プロジェクトに全部でいくつのメソッドが定義されていますか?また、それらの引数にはどんな値が入りますか?
とあるアプリのメソッド数
すべてを覚えておくのはムリ!一度読んで理解してもしばらくしたら忘れてしまう先輩のコードをレビューしているとき、テストコードを読み解くとき、障害発生時に調査するとき…などなど、折に触れてメソッドの構造を理解するべきタイミングがあると思います。
そこで型ですよ型があれば覚えておく必要がないなぜなら型を見ればどんな引数を渡してどんな返り値なのかが一目でわかるから「これってどういうメソッドなんだっけ?」から始まる調査の手間は決して軽いものではないはず。
rbsファイルアプリケーションコード
rbsファイル違う型を引数に渡そうとすると…
rbsファイル型が違うことを教えてくれる!
型をつけたことでたくさんあるメソッドを読み解きやすくなった
型をつけたことでたくさんあるメソッドを読み解きやすくなった型
プロジェクトの全容把握newbieな僕の最初の壁 その1
newbie 心の叫びどこに何が定義されているのかわからない。モデル同士の関連どうなってるの?「簡単な修正」ってissue 振ってもらったけど…どこから手をつければいいの?メソッドの処理が複雑すぎて最終的にどうなるのかわからん!!!コードジャンプ候補に同名メソッドがたくさん出てきてどれが正しいのかわからない。。。
そこで型ですよ型を書くことで理解が深まる型を書くにはメソッドの使い方や使用時の挙動を調査する必要がある。それを繰り返す中でどんどんわかることが増えていき、プロジェクトへの理解が深まっていく。
型定義を進めるために嫌でもプロジェクト内のファイルを横断的に見ることになるモデル同士の関連がどうなっているか理解が進んだり、このモデルにこんなメソッドがあるのか!などの発見があるそれらに型付けする過程でユースケースやどこで使われているのかなどが自然とわかる
別のメリット今後の自分の助けにもなる型付けが進むとIDEの補完の正確度が上がる。正確度が上がると調査も実装も速度が上がるため、相対的に同じ時間内で得られる情報量が増える。
補完候補(型がない場合)
補完候補(型がある場合)
nextメソッドの定義を見たい!
ここでコードジャンプしようとすると…
候補がたくさん表示されてしまう
型をStringだと定義しておくと…
一発で String#next の定義元に飛べる!
型をつけたことでプロジェクトへの理解が進み調査や実装もしやすくなった
型をつけたことでプロジェクトへの理解が進み調査や実装もしやすくなった型
gemの実装を見るのが苦手newbieな僕の最初の壁 その2
苦手な理由思い返してみると…難しいコードがたくさん出てくる印象どこから見ればいいのかわからない「まだ自分には読めない」という先入観
型生成プロセス良いサイクルが生まれます調査メソッドの構造(引数の型、返り値の型)や使われ方を調査する。型定義調査結果をもとに型を定義していく。このときgem の型定義の不足や誤りが判明することも実装の確認起こっているエラーが型定義の誤りなのかそうでないのかは、gem の実装を見る必要がある反復型定義はこれらの繰り返し。繰り返しやっているうちに実装を見るのが日常になる。成果物プロジェクトの型定義はもちろん、場合によっては OSS にコントリビュートできることも。
steep checkで出たエラーに疑義がある場合gemの型定義がなくて追加しようとするとき
steep check 実行時に見つかる
実装元を確認する
Receive block!
gemの実装を見ることが"日常"になった。あの頃の苦手意識はもうない
gemの実装を見ることが"日常"になった。あの頃の苦手意識はもうない型
gemの実装を見ることが"日常"になった。あの頃の苦手意識はもうない型※ただし読めるとは言っていない
OSSってなにから始めればいいの?newbieな僕の最初の壁 その3
OSS
OSS選ばれし人がやること初心者の自分にできるわけがない。技術に秀でたすごい人たちがやること。
OSS選ばれし人がやること初心者の自分にできるわけがない。技術に秀でたすごい人たちがやること。自分にできることがあるはずないすごい技術を持った人たちが作ったものに自分が修正できるところがあるわけない。
OSS選ばれし人がやること初心者の自分にできるわけがない。技術に秀でたすごい人たちがやること。自分にできることがあるはずないすごい技術を持った人たちが作ったものに自分が修正できるところがあるわけない。やってみたい気持ちはあるけれど…どこから手をつけたらいいのか、どこが修正すべきところなのか、どうやってパッチを送ればいいのかナニモワカラナイ。
型定義を始めるまでは…
型定義の誤り
gemの型定義の不足
試行錯誤の中での気づきプロジェクトの型導入をしている中でgemの型定義が足りなかったり間違ってることがあるなぁ
試行錯誤の中での気づきプロジェクトの型導入をしている中でgemの型定義が足りなかったり間違ってることがあるなぁこれってもしや…コントリビュートチャンスってやつ!?
OSSへの初めてのコントリビュート
コントリビュートはすごい人だからするものではない。「使ってる人が気付いた時にするもの」
コントリビュートはすごい人だからするものではない。「使ってる人が気付いた時にするもの」型
興味を持ってもらえたらプロジェクトに型を導入してみてください!newbieの多くの悩みを解決してくれます
とはいえ…
newbieに型を導入する裁量なんてないんですが!?
どのように型導入を提案したかhttps://unsplash.com/ja/%E5%86%99%E7%9C%9F/5Q07sS54D0Q
小さく少しずつ
第1ステップとして、rbs, rbs-rails, gem_rbs_collectionなどで大枠の型定義をそろえる
第1ステップとして、rbs, rbs-rails, gem_rbs_collectionなどで大枠の型定義をそろえる第2ステップとして、生成された rbs ファイルの untyped を正しい型に書き換えていく
第1ステップとして、rbs, rbs-rails, gem_rbs_collectionなどで大枠の型定義をそろえる第2ステップとして、生成された rbs ファイルの untyped を正しい型に書き換えていく並行して、steep check でのエラーから gem の型定義不足や誤りを見つけて修正する
gemもrbsも独立しているので剥がすのは簡単主要なModelやAPIだけでもよい型があってもなくてもプロダクトコードに影響はないLinterで警告が出たりノイズが発生することもない
CIには入れない
エラーの解消が目的ではない目的はあくまで"開発者体験の向上"CIに組み込むと間違いなくエラーが出続けるCIがずっとredだと"オオカミ少年"状態になる…型のエラーを検知したい訳ではないプロジェクト内の型を充実させることに集中する方が建設的
書きたい人だけ
型を書きたい人
型を書きたい
型の恩恵を受けたい型を書きたい
"書かなきゃいけないもの"にすると開発速度の低下ややらされてる感からの生産性低下"書く気力のある人"が少しずつ進めていくしかない。"型のある開発環境"を水面化で進める機能追加のPull Requestに混ぜない。ノイズになる。型は個別のPull Requestで余裕のある人が見る(見なくてもいい)
チームへの説明
newbieの独断では入れられないメンバーの理解と協力が不可欠受け入れてくれたメンバーに感謝ここまで説明したようなスタンス、メリットを伝える「やっぱりダメだね」となった場合もすぐに剥がせる一人でもメンテナンスしていく覚悟
導入の障壁https://unsplash.com/ja/%E5%86%99%E7%9C%9F/sQ5yREHU_fI
gemの型不足
gemの型定義はまだまだ足りていない(2022年10月現在、57個がgem_rbs_collectionにある)gemの型定義が増えるとプロジェクトに導入しやすくなるはずだと考えています興味がある方はぜひgemの型定義をやってみましょう!gemの型定義が増えて導入するプロジェクトが増えれば、型エコシステムの発展も早くなるかも?
RubyKaigi 2022 でそういう発表をしましたhttps://speakerdeck.com/fugakkbn/types-teaches-success-what-will-we-do
変更への追従
コードの変更への追従検知するソリューションがないメソッド追加、構造の変更など自動で検知することができないため人力になる別ファイルであることのデメリット「気づいたときにやればいい」というスタンス
大量のエラー
プロジェクトに型を導入して全体で steep check を実行すると、大量にエラーが出るはず今のプロジェクトでは1万以上のエラーが出る繰り返しになるが、エラーを解消することに心血を注ぐ必要はないと考えている
https://speakerdeck.com/soutaro/ruby-programming-with-types-in-action?slide=13
まとめ
newbieが型を書くメリットはたくさんあります!興味の裾野を広げる一歩目にいかがですか?プロジェクトに型を導入することで得られる恩恵は限定的。でも新しいメンバーがいち早くプロジェクトに馴染む助けにもなりそう。小さく始められてランタイムに影響を与えないので導入しやすい。メンバーから打診があったらぜひ前向きな検討を!
型を通じてできることが増えた取り組む意識が変わった興味の幅が拡がったRubyがもっと楽しくなった
波 紋波 紋https://unsplash.com/ja/%E5%86%99%E7%9C%9F/Tf18kgGiop4
型
誰がメンテしてる?型
誰がメンテしてる?Steepのコマンドは内部的にどう呼ばれてる?型
誰がメンテしてる?どうやってコントリビュートする?Steepのコマンドは内部的にどう呼ばれてる?型
誰がメンテしてる?どうやってコントリビュートする?Steepのコマンドは内部的にどう呼ばれてる?型ASTってなに?ASTってなに?
見える景色が変わった見える景色が変わった知覚できる世界が広がった知覚できる世界が広がったhttps://unsplash.com/ja/%E5%86%99%E7%9C%9F/1lfI7wkGWZ4