Rubyの2500万行のフォーマット: Stripeにおける `rubyfmt` の物語

Stripeは最近、rubyfmt を使って25百万行に及ぶRubyコードベース全体を一晩でフォーマットした経験を共有しました。この野心的なプロジェクトは、膨大な規模でコード品質と開発者の生産性を維持する際に直面する複雑さと考慮事項を浮き彫りにしています。この取り組みは、一貫したコードスタイルへの大きなコミットメントを示し、開発ワークフローを効率化し、エンジニアの認知負荷を軽減する自動化ツールの活用を実証しています。

このような広大なコードベースを段階的ではなく、単一の原子的な操作で再フォーマットする決断は、リスクとリターンを計算した評価に基づくものです。たとえGitHubが表示に苦労するほど巨大なdiffが生じても、大規模なエンジニアリング組織にとって統一されたコードスタイルが最重要であるという信念を強調しています。

課題の規模: 2500万行

StripeのRubyコードベースの規模—25百万行—は、かなりの議論を呼びました。多くの人がこの数字に驚き、システムの性質やアーキテクチャについて質問しました。

"25M行という部分に衝撃を受けました! それは1つのコードベースとしては全く想像を超える量です。もっと詳しく知りたいです。" — @varun_ch

主要な金融処理会社がRubyで資金処理システムを書いていることにも眉をひそめる声がありました。

"大手金融処理会社がRubyでお金の取り扱いシステムを書いている。恐ろしい。" — @andrewstuart

しかし、この規模はツール開発にとってユニークな機会も提供します。あるコメント者が指摘したように、処理するデータに比べてコード自体は非常に小さく、大規模な操作が実現可能です。

"コードに関する洞察として、我々がデータ上で操作する規模と比べるとコードは極小です。トークンがストリームで戻ってくるのを待つ間でも、瞬時のgit操作や『すべてのコードに対してこのツールを走らせる』が常態です。その洞察は自明に思えるかもしれませんが、作業中に意識し続ければ、個人やチームのためにかなり驚くべきツールを発明できます。" — @cadamsdotcom

rubyfmt アプローチ: 一括 vs. 増分

Stripeが週末に「一括」再フォーマットを実施した選択は、マージコンフリクトを回避するための意図的な戦略でした。チームはテストスイートに大きく依存して自信を持ちましたが、これほど大規模な変更の困難さも認識していました。

このアプローチは、いくつかの開発者が好む増分戦略とは対照的です。増分方式では、PRで触れられたファイルだけを再フォーマットしたり、より小さなバッチで実行したりします。

"一括再フォーマットを選んだことに驚きました。週末に実施したとしても、規模の大きい環境では多数のオープンPRに影響を与えるはずです。過去に数十万から数百万LOCのコードベースにフォーマッタを導入した際は、常にスクリプトでオープンPRに触れられていないファイルだけを段階的に再フォーマットしていました。最初の実行で全ファイルの95%を再フォーマットしました。" — @hobofan

ビッグバンアプローチの利点は、コードベース全体で即座に一貫性が得られ、ファイルごとにフォーマット状態がばらばらになる過渡期がなくなることです。rubyfmt ツール自体はRustで書かれており、パフォーマンス重視の開発者ツールとして一般的な選択です。

正確性の確保: サニティチェック

自動フォーマッタにとって重要なのは、空白文字だけを変更し、コードの意味論を決して変えないことです。Stripeチームの rubyfmt への自信は、堅牢なテストによって支えられました。例えば、Dartのフォーマッタは厳格な内部サニティチェックを実装しています。

"Dartフォーマッタには内部サニティチェックがあります。未フォーマット文字列とフォーマット済み文字列を平行して走査し、空白以外の文字が一致しなければ即座に中止します。これにより、フォーマッタが変更するのは空白だけであることが保証され、巨大なコードベースに盲目的に適用しても怖くなくなります。" — @munificent

この種の安全策は、複雑な言語機能や新しい構文に対処する際に特に価値があります。フォーマットエラーによる微妙なバグがコードベースに混入するのを防ぐからです。

コードフォーマットの哲学

フォーマットに費やした労力は、特にAIがコード生成にますます関与する時代において、その価値についての議論を呼び起こしました。

"コードをフォーマットする意味はもう何ですか。" — @throwatdem12311

"確かに、人が読む必要はなくなり、AIが食事チケットを書き出す時代に、書くだけのコードがやっと現れました。25百万行のスラップをフォーマットする意味は何ですか、そしてAIがコードを人が読めるようにするのにトークンを浪費する必要があるのでしょうか。" — @CrzyLngPwd

しかし、コードの可読性という人間的要素は、協働や保守にとって依然として重要です。個人の好みとチーム標準の間の緊張感を示すユーモラスな逸話があります。

"リード開発者はコードのフォーマットを面倒だと思っていたので、私は makenice というツールを書いて彼の乱雑なスパゲッティごみをインデントとレイアウトが整ったものに変換しました。彼は激怒しました… そこで makenasty を書いて、彼が好むようにコードをフォーマットしました。私は makenasty/makenice をチームの数人にだけ共有しましたが、彼らはそれが好きでした。なぜなら、可読なものとリードが好むものの間を簡単に変換できたからです。" — @CrzyLngPwd

この例は、フォーマットが些細なディテールに思えても、開発者体験やチームの結束に大きく影響することを示しています。将来的には、テキストベースのフォーマットから完全に離れ、コードを構文木として保存・操作する方向へシフトする可能性すらあります。

"実は、原則的に構文木を保存し、gitのような仕組みで公開すれば、フォーマット自体が不要になるだけでなく、フォーマットに起因するマージコンフリクト全体を回避できると考えさせられます。フォーマットはデータ—つまりコード—上のテーマに過ぎません。" — @eigenblake

戦略的ツールと生産性

rubyfmt の物語は、開発者生産性ツールへの投資価値を示す証です。最も複雑な構文から取り組むことで、rubyfmt チームは堅牢なフォーマッタ構築のための健全な戦略を採用しました。

"その複雑さを考えると、仮説はシンプルでした: 最も難しい構文から取り組めば残りは自然に追いつく。常に嬉しいことです。多くの人が一般的なケースだけを設計し、実はコードの大半が稀なケースに対処する必要があることに気付いていません。" — @nitwit005

このアプローチにより、ツールは遭遇するすべてのコードスペクトルを処理でき、信頼性と一貫性のある出力が保証されます。何百万行ものコードに対して自動的に一貫したスタイルを適用できることで、開発者は手動のフォーマット作業から解放され、ロジックや機能実装に集中できます。

Stripeが rubyfmt を用いて巨大なRubyコードベースを一晩で成功裏に再フォーマットしたことは、開発者ツールと大規模コード管理における重要な成果です。これは、一貫したコードスタイルの重要性、堅牢な自動ツールの威力、そして広大なエンジニアリング環境で高い生産性とコード品質を維持するために必要な戦略的決定を強調しています。

Sources