Rubyへの型導入、実際にどんな利点がある? 壊さず進める大規模コード改善の実践知

2025年6月9日

株式会社タイミー Rubyコミッター Steep開発者

松本宗太郎

Rubyコミッター。大学院でRubyプログラムの型検査の研究に取り組む。修了後はスタートアップでWebアプリケーション開発に従事。2017年から型検査ツールSteepの開発を開始。2019年からはRubyコミッターとして、Ruby標準の型定義言語RBSの開発を主導。2024年4月、タイミーにフルタイムRubyコミッターとして入社。博士(工学)。

X(@soutaro)
GitHub

株式会社タイミー バックエンドエンジニア

神山大智

2019年にITスタートアップに新卒入社。インフラからフロントエンドまでフルスタックに開発・運用に携わり、エンジニアリングマネージャーとなる。2024年6月に株式会社タイミーに入社、求人のマッチングを改善する機能開発チームにてバックエンドエンジニアとして勤務し、コードベースへの型定義導入を現場で主導

X(@_dak2_)
GitHub

どのような方法で、規模の大きなシステムの品質や保守性を向上させるか――。複数の開発組織が、この課題と日々向き合っています。最近では、解決策として大幅なコードの書き換えやアーキテクチャの刷新を選ぶ事例を目にする機会が増えましたが、一方で「既存のコードを活かしつつ、システムを改善する」取り組みは、あまり表に出てきません。

そんな中、株式会社タイミーでは、Ruby標準の型記述言語RBSの開発を主導してきたフルタイムRubyコミッターの松本宗太郎さんを迎え、社内のRubyプロジェクトへの型検査の導入を推進しています。システム全体を作り直すのではなく、既存のコードベースを保ちながら、段階的かつ合理的に品質を高めているのです。

今回は、そうした型導入に携わる松本宗太郎さんと、普段の開発業務で型を記述しているバックエンドエンジニアの神山大智さんにお話を伺いました。「型を書くとどんな利点があるの?」「どこから始めればいい?」そんな疑問を持つ方に向けて、現場で培われたリアルな知見をご紹介します。

コードの理解がスムーズに。型は“補助線”の役割を果たす

――Rubyは動的型付けの言語であり、型を明示せずにコードを書くスタイルが一般的でした。そこに型定義の仕組みを導入することで、開発の現場ではどのような利点を得られるのでしょうか?

松本:他の人が書いたコードを読むときには、時間をかけて「何をしているか」を読み解く必要があります。型があることで、その理解を助けてくれるんですよね。「このメソッドは引数としてどのような型を期待しているのか」「どんなオブジェクトが返されるのか」といった情報が明確になります。

ビジネスロジックが複雑な部分ほど、その効果は大きくなります。型は、コードの構造を読み解くための“補助線”のような役割を果たしてくれます。特に効果を感じるのは、新しいメンバーがチームに加わったときや、他チームから異動してきたときですね。コードの意図や制約が明示されていることで、オンボーディングが格段にスムーズになります。

――タイミー社では、これまでどのような流れでRubyプロジェクトへの型導入をしてきたのでしょうか?

神山:もともと弊社では、YARDコメントからRBSファイルを自動生成するsord gemを導入し、型情報を補完的に活用していました。しかし、そもそもYARDOCを使っておらずYARDがただのコメントになっていましたし、YARDだとinterfaceなどの型定義ができないため表現力の限界を感じていたんです。こうした背景のもと、RBS::Inlineの導入が検討されました。


RBS::Inlineは、Rubyコード内に型情報をコメントとして直接書けるようにするツール。名前の通り、型記述言語RBSを「インライン(=コード中)」で扱えるようにする仕組み。

# 例:与えられた文字列を指定回数くり返す処理

# 型記述が行われていないコード(従来のRuby)
def repeat_message(message, count)
  message * count
end

# 型記述を行ったコード(RBS::Inlineを使用)
# @rbs message: String
# @rbs count: Integer
# @rbs return: String
def repeat_message(message, count)
  message * count
end

神山:RBS::Inlineを使えば、既存のコードに大きな変更を加えることなく、コメントとして明示的に型を記述できるため、運用負荷が低いです。また、今後はRBS::InlineのgemがRBSに統合される予定であり、Rubyの標準機能になる見込みです。今のうちに乗り換えておいたほうがいいだろうという判断になりました。

そこで、Rubyプロジェクトに対して段階的にRBS::Inlineによる型定義を導入する動きが始まり、私も実際にコードに型を書いていく役割を担いました。

――RBS::Inlineは松本さんが開発しているgemですから、「開発者本人が社内にいる」というのも大きいですね。

神山:そう思います。

松本:私は2024年4月にタイミーへ入社して以来、フルタイムRubyコミッターとしてRBS::InlineやSteepの改善に取り組んできました。現場のエンジニアから挙がってきた声をもとに、それらのgemの改良を続けています。そして2025年からは、本格的にコードベース全体への導入が進み始めたという流れです。

▲松本宗太郎さん

――タイミーでは、どのような体制で松本さんへのフィードバックを行っているのでしょうか?

神山:大きく2つの経路があります。ひとつはSlackの専用チャンネルで、型検査に関する話題を自由に投稿できるようになっています。たとえば「この書き方で合っていますか?」とか「Steepのここを改良してほしい」といった相談が飛び交っています。もうひとつは、隔週で行っているミーティングです。有志が集まり、松本さんと一緒に話し合っています。

このSlackチャンネルでは、内容を精査してからフィードバックするというよりも、気になったことをその場でどんどん投げている感じです。そのカジュアルな空気感があるからこそ、疑問や要望が滞らず、日常的に共有されているのだと思います。

松本:Slackチャンネルで細かな課題がすぐに解決されるため、隔週ミーティングでは、そうした日常的な声を踏まえて、より深い議論や抽象度の高い未来のビジョンについて話し合うことができています。

――この二層構造が、健全なフィードバックループを保つ鍵になっていそうです。

「誰もが恩恵を受けられる状態」を作れば、無関心だった人の心が動く

――どのような手順で型定義を導入していったのでしょうか?

松本:前提として、タイミーはモノリシックなRuby on Railsのシステムを運用しているのですが、それとは別に、独立したペイメント(決済)系のサブシステムがあります。このサブシステムに、最初に型定義を導入しました。本体のシステムとは完全に分離されていたため、導入のとっかかりとして適していたんです。

その後、本体側の巨大なシステムにも型定義を取り入れていったのですが、ここで重要なのは、「型検査を推進したい人」や「どちらかといえば反対の人」以上に、「そもそも型検査に強い意見を持ってない人」が大多数だったということです。そうした人たちは、開発組織全体が「型検査をやっていく」という方針になれば、一緒に取り組んでくれるだろうと考えました。

神山:導入にあたっては、技術的なハードルよりも心理的な壁のほうが大きかったのではないかと思います。最初は社内の全エンジニアを巻き込むのではなく、「書きたい人が書く」というスタンスで始めました。

――型検査に中立的だった方々を動かすうえで、何が有効だったと思われますか?

神山:「普段使っている多くのコードに型が定義がされている」という状態をつくることが、最初の一歩だったと思います。タイミー本体はモノリシックなRuby on Railsアプリなので、あるチームが特定のモジュールに型定義を書けば、型定義を書いていないチームでもその恩恵を受けられるんですよ。IDEの補完が効くようになりますから。    

そうすると、それまで積極的に関与してこなかったメンバーも「確かに便利だ」と意識するようになります。また、一部の有志の方々が型定義のコード記述を推進してくれたおかげで、ほとんどのコードにRBS::Inlineが記述されていきました。そしてテックリードの新谷哲平さんが「型検査を行うこと」という姿勢を明示してくれて、開発組織全体で取り組む流れが生まれました。

▲神山大智さん

まずは「自分が修正した部分」から型定義を入れる

――導入の最初の一歩として、ソースコード全体のどの箇所から手を付けるのが現実的でしょうか?

神山:私の所属するチームでは、スクラムで1週間単位のスプリントを回していて、その中で変更があったコードにだけ型定義を書くルールを設けています。

松本:私も、既存コードの中では「自分が手を入れた箇所に型を書く」のがよいと思います。すべてのコードに型を付けようとしても、それは「すでに正常に動いているコード」なので、労力のわりに成果を得にくいんですよね。

神山:sinsokuさんがRubyKaigi2025で発表していたRBS::Traceというgemを使うと、RSpec実行時にRBS::Inlineが自動で定義されます。既存のRuby on Railsプロジェクトに型定義を導入する際には、まずこれを試してみるのもおすすめですね。

――型定義の導入を進めたことで、どんな成果がありましたか?

神山:少なくとも私が感じている恩恵としては、主に2点あります。まず、ドメインロジックに集中しやすくなったこと。メソッドの引数や戻り値の詳細を気にせずに済むので、より本質的な部分に注力できるようになりました。

そしてもうひとつは、メソッドの戻り値を単一にする意識が生まれたことです。その結果として、自然と読みやすいコードを書くようになり、型定義の導入がコードの質の向上に貢献していると実感しています。

コードベースが大きくなるほど、読みやすいコードの価値は上がる

――型検査について、今後のビジョンをお聞かせください。まずは、松本さんの立場から。

松本:まず、RBS::InlineとSteepにはまだ不足している機能があると自覚しているので、それらを実装していきたいと考えています。また、Steepのパフォーマンスが遅い点についても改善が必要です。タイミーくらいのコード量では問題なく動いていますが、より大規模なコードベースに対応できるかどうかが、今後の課題になります。

#参考:取材時点でのタイミーのRubyのソースコード行数

- Total: 355,197
- Models: 57,995
- Controllers: 12,528

また、進捗をうまく計測できるようにもしたいです。Steepには、プログラム全体のうち、どれくらい型が記載されているかをパーセンテージで示す仕組みがあります。この計測機能を活用して、進捗状況を可視化できるようにしたいです。

さらに大きな話をすると、型検査の機能とRubyプログラムの実行とを連携できるようになればと考えています。現時点では型検査は「コードを書く」ステップでのみ使われていますが、将来的にはRubyの実行過程にも型情報を活用できるようになると、より広い用途で価値を発揮できるのではないでしょうか。

――神山さんはいかがでしょうか?

神山:ビジョンというほどではないですが、まずは型検査の対象を着実に広げていくことが、ひとつのチャレンジだと考えています。タイミーのコードベースのほとんどに型が定義されるようになったとき、開発者体験がどのように変わるのかには興味がありますし、その取り組みに貢献できたらうれしいですね。

――では最後に、大規模システムの品質改善や安全性の強化を検討している読者の方々に向けて、今回の事例を踏まえたメッセージをお願いします。

松本:「型検査を導入すれば安全なコードが書ける」という側面はあると思いますが、その効果を過度に期待しすぎると、うまくいかないことも多いです。型を書いたからといって、すぐに劇的に品質が上がるわけではありません。

それよりは、型のことを「コードを読み書きする際に、プログラマーを助けてくれる存在」として捉えるほうが現実的です。「無理のない範囲から始めて、徐々に生産性や品質を高めていく」という考え方のほうが、長期的にはうまくいくと思います。

神山:コードベースが大きくなるほど、読みやすいコードの価値は高まっていきます。型を書くことは、その読みやすさを支えることにつながります。私自身、この取り組みに大きな価値を感じているので、ぜひ読者のみなさんにも関心を持っていただけたらうれしいです。

取材:中薗昴、光松瞳、池田恵実
執筆:中薗昴
編集:光松瞳
撮影:山辺恵美子

関連記事

人気記事

  • コピーしました

RSS
RSS