技術を愛する者たちが飲み会で交わす会話には、不思議な魅力が宿ります。お酒の力も相まって、「技術の真髄」や「泥臭い本音」がポロリとこぼれ落ちるからです。そんな濃密な時間は、何物にも代えがたい有益な学びの場となります。
そんな思いからスタートした連載企画【言語を肴に一献】。この企画では、特定の技術領域を極めたスペシャリスト同士が、お酒を飲みながらさまざまな観点で議論します。互いの流儀を称え合う、温かな時間になるのでしょうか。それとも、議論が白熱しカオスな展開に?
今回は、Laravelスペシャリストの武田 憲太郎さんと、Ruby on Rails(以下、Rails)スペシャリストの大倉 雅史さんに語り合っていただきました。お二人の熱い会話に、グラスを差し向けます。
【一品目】ORM論。Active RecordとEloquentに通ずる美学
武田: 一緒に議論できるのを楽しみにしていました。Rubyは、Laravelの先輩のようなものですから。
大倉: 私もめちゃくちゃ楽しみにしていました! 昨日は、Laravelの公式ドキュメントを読んで勉強しましたよ。
──それではお酒の席ということで、まずは乾杯から始めましょうか!
武田&大倉: かんぱーーーーい!!!!!

──ぜひ、ラフな雰囲気で語り合ってください! 最初のテーマは、ORMについて。RailsのActive RecordとLaravelのEloquentは、どちらも完成度の高いライブラリですよね。
大倉: 本当にそうですね。私は、Active Recordの設計にCoC(Convention over Configuration:設定より規約)の考えが貫かれているのが素晴らしいなと思っています。InflectorがあるおかげでPersonクラスとpeopleテーブルを紐づけるなどの処理も自動的に行われますし、has_manyやbelongs_toなどテーブル間の関係性を表現するのもすごくシンプルな記述で済むんですよね。
武田: その点はEloquentも同じですね。EloquentはActive Recordに強く影響を受けているので、同様に便利に書ける部分が多いです。
大倉: それから、複数のテーブルを結合して検索する際に、中間テーブルの構造をうまく隠蔽して抽象的に扱えるのも好きです。私は特にmergeがお気に入りなんです。
例えば、users(ユーザー)とfollowings(フォロー関係)の情報を持つテーブルがあるとします。ここで、Followingモデルに「有効なデータのみ」を絞り込むactiveというスコープをつくっておく。すると、user.followings.merge(Following.active)と書くだけで、「アクティブなフォロワー」を取得できます。パッと見ただけで、何をしたいかわかりますよね。
「どうやってデータを取ってくるか」という実装(How)ではなく、「何を取りたいか(What)」にフォーカスした字面になっています。この「自然言語に近い読後感」へのこだわりは、Rubyそのものの思想がRailsの文化圏で純粋培養された結果だと思います。

大倉雅史さん
武田: Active Recordのmergeは、結合するテーブルの数に制限はないんですか?
大倉: ないですね。もちろん、あまりに数が多くなってしまうケースは、そもそも設計に問題があると思いますけれど。
武田: Eloquentでもカラム値で同様のことはできますが、リレーション先のスコープをスマートに合成する機能は、標準では少し弱いです。リレーションを辿りつつ、クロージャ(無名関数)の中でクエリを書いて遅延評価させるのが一般的です。こうして比べると、Active Recordは細かいところの完成度が高いな、と感じますね。
// 参考: Eloquentで同様の処理を書く場合
// ユーザーの過去の注文の中で、現在も販売中の商品だけを取得
$user->orders()
->whereHas('product', function ($query) {
$query->onSale(); // クロージャの中でスコープを適用
})
->get();
──なぜ、リレーション先のスコープをそのまま取り込むような仕組みが、Laravelにはないのでしょうか?
武田: おそらく、作者であるTaylor Otwellの哲学でしょうね。彼は「APIが肥大化しすぎると、かえってユーザーを混乱させる」という考え方を徹底しています。
だからこそ、Laravel本体に採用するAPIは、なるべく機能がミニマルであるよう吟味されているんです。例えばhasManyThrough(中間テーブルを介したリレーション)も、標準のAPIでは1つの中間テーブルを介した「2段階」の結合までを想定したつくりになっています。
LaravelはRuby on Railsと比較して、「プログラマに自由を与えること」を重視する側面があります。きっと、「コアはシンプルに保つので、高度な抽象化が必要な人は自由に拡張してほしい」というスタンスなんでしょう。
例を挙げると「hasManyThroughは2段階まで」という制限も、Eloquent HasManyDeepというLaravel Extensionで拡張できます。このライブラリに限らず「鉄板」なExtensionは多数あり、作者の思惑通りにエコシステムが回っている感じですね。
【二品目】バックエンドを支えるバッチや認証
──バックエンドの実装に欠かせない、バッチ処理や認証周りの話も聞きたいです。
大倉: バッチの話からすると、RailsにはActive Jobというジョブの抽象化レイヤーがあります。そのバックグラウンドジョブの実装であるSidekiqやDelayed Jobなどは、基本的にサードパーティツールなんですよ。最近になってようやく公式のSolid Queueが出てきましたけれど、基本的には「インターフェースだけ決めておくから、実装は好きなものを選んでね」というスタンスでした。
武田: Laravelの場合は真逆ですね。インストールをした時点で、バッチやキューに関する機能が最初から全部入りです。RDBやRedis、Amazon SQS、Amazon DynamoDBなどのアダプターも標準装備されています。しかも、「ジョブAが終わったらB、その後に並列でCとDを走らせる」といったワークフローエンジン的な依存関係の定義まで、クラスの宣言だけで書けるんですよ。並列化のレースコンディション対策も標準で入っています。
// 参考: バッチ処理の依存関係を書く場合
// ECサイトで決済完了した後のワークフローを非同期にディスパッチ
Bus::chain([
new ProcessPayment($order), // A: 決済処理
new UpdateInventory($order), // B: 在庫更新(Aの後に実行)
Bus::batch([
new SendReceipt($order), // C: 領収書送信(B完了後、並列で実行)
new NotifyWarehouse($order), // D: 倉庫への通知(B完了後、並列で実行)
]),
])->catch(function (Throwable $e) use ($order) {
// 途中で失敗した場合、完了済みの処理を巻き戻す
dispatch(new RollbackOrder($order));
})->dispatch();
大倉: えー! めちゃくちゃ便利ですね。
武田: 便利なんですけれど、そこまで多機能だと「使いこなすのが難しい」という面もありますね。私は業務委託としてさまざまな開発現場に行きますが、これらの便利な機能を知らずに自前でワークフローを書いている方がよくいます。そんな方々に「公式機能でできますよ」とアドバイスするのが私の日常です(笑)。
大倉: Railsだと、そうした機能は今でも「手書き」の世界ですね。バッチ周りは正直、Railsの弱い部分だと思っています。
──認証周りはいかがでしょう?
大倉: Laravelって認証ライブラリがめちゃくちゃ多いですよね。昨日調べてみたんですが、OAuth2の認証機能を追加できる機能(Laravel Passport)まで公式で用意されています。「ここまでやってくれるんだ!」と驚きました。
武田: PHPはライトユーザーが多いので、「Laravelを入れれば全部できる」という状態を目指しています。だからこそ、認証の品揃えも多いのかなと。ただ、認証のデファクトって時代ごとに変わるじゃないですか。だから、Taylor Otwellがその時々の最適解をトライ&エラーでつくってきた結果、ライブラリが乱立したという背景もある気がします(笑)。

武田憲太郎さん
大倉: Railsは認証関連の機能も少ないです。一昨年くらいまで、公式にはパスワードを扱うhas_secure_passwordという機能しか用意されていませんでした。より複雑な認証機能を実装したければ、Deviseなどのサードパーティツールを使うのが当たり前でしたね。
武田: 本当にミニマルですね。
大倉: Railsの作者であるDHH(David Heinemeier Hansson)は、自分が本当に良いと思ったものでなければ、導入に消極的なんですよ。だから、サードパーティツールがなかなか本体に取り込まれないという事情があります。
【三品目】DHHとTaylor。偉大なる2人のカリスマ
──それぞれのフレームワークには、DHHとTaylor Otwellという強烈なカリスマがいます。彼らの存在は、開発文化にどう影響しているのでしょうか?
武田: Laravelのコミュニティを見ていて感じるのは、「TaylorがOKを出すかどうか」に最終的な方針の合否がかかっている、ということです。そこはRailsと共通しているかもしれません。ただ、TaylorはDHHと比べると、もう少し現実主義というか、ビジネス的な合理性を持っている気がします。
具体的には「この変更がユーザーにとってどのようなメリットがあるか」を非常に重視します。例えば、Pull Requestのレビューにおいて、Taylorがレビューイーに「この機能はどんなユースケースを想定しているか」「どんなユーザーのどんな課題を解決するのか」について質問している場面がよくありますね。

大倉: DHHはもっと極端で「自分が本当に好きなものだけをRailsに入れる」という方針ですね。例えば、Rails 8から標準になったRuboCopの設定ライブラリrubocop-rails-omakaseは、非常にDHHのカラーが出ています。これは、Rubyコミュニティの標準というより、「DHHがどんなコードを良いと判断するか」に基づいて決められています。
これに関連する余談として、Rails開発の基本方針「The Rails Doctrine」には、Railsは「おまかせ」であるとはっきり書いてあります。つまり、飲食店でおまかせを頼むのと同じで「料理長が一番美味いものをつくって出すから、黙って食え」というスタンスです(笑)。だからrubocop-rails-omakaseという名称なんですね。一方で、標準外のツールを使う、いわば「アラカルト」でもよい、という懐の深さもありますね。
何人かがDHHの方針に逆らおうとするのを見てきましたけれど、基本的には誰もうまくやれていません。それくらい、DHHのセンスが良すぎるんです。
【締め】LaravelとRailsは「ビジネスの課題解決」にフォーカスする
武田: いま話していただいたように、「おまかせに従う」というのはとても重要ですよね。多くの場合、「そのフレームワークをそのフレームワークらしく使う」のが最適解になるケースがほとんどですから。
大倉: 最近、海外のRails界隈では「Boring Rails(退屈なRails)※1」という言葉がある種の褒め言葉として使われたりもします。
エンジニアはどうしても、最新技術の導入とか、複雑なアーキテクチャの構築に取り組みたくなるじゃないですか。でも、技術基盤の構築にどれだけ時間とお金をかけたところで、ユーザーは幸せになりません。
そうではなく、シンプルなアーキテクチャとデフォルトの設定(退屈な技術)を使い、浮いたエネルギーをビジネス改善やユーザー体験の向上に注ぎ込むという思想が「Boring Rails」です。
武田: それはLaravelも全く同じですね。私も開発組織のメンバーに「むやみに複雑な設計にせず、フレームワークが用意してくれたレールに乗って、さっさと顧客の課題を解決しよう」とよく言っています。DHHもTaylorも、手法は違えど「エンジニアをビジネスに集中させる」という考えは通じているように思います。
──LaravelとRailsが提供する「おまかせ」や「なんでも入り」などの手厚さは、フレームワーク開発者からの「より本質的な仕事に時間を使おう」というメッセージなのかもしれませんね。
武田: そうだ。今日、伝えたいと思っていたことがあったので、最後に話してもいいですか。
大倉: なんでしょう?
武田: 私はLaravel以外にも、さまざまな技術を導入している現場に参画することがあります。あるとき、Railsを採用しているチームに放り込まれたんです。すると、驚くような出来事が起きました。
新しく参画したRailsエンジニアが、難易度の高いタスクをすぐにこなしてしまうんです。プロジェクトごとのコードベースの規約や癖をキャッチアップする前にタスクをこなせるなんて、私の常識ではあり得ませんでした。
何が要因なんだろうと思って「Ruby on Rails チュートリアル」を実践してみたところ、すぐに理由がわかりました。Rails開発の「型」のようなものが明確に示されていたんです。この体験を通じて、私はLaravelを真の意味で理解できました。
つまり、Railsを通じて「Laravelってこうあるべきなんだ」と気づくことができ、視界がパーッと開けたんです。その気づきや学びが、PHPerKaigi 2023で発表した「Laravelへの異常な愛情 または私は如何にして心配するのを止めてEloquentを愛するようになったか」というセッションにもつながっています。
大倉: そう言ってもらえると嬉しいです。私も今回Laravelについて調べてみて「Railsよりもずっと歴史が短いのに、すごい数のライブラリやAPIが用意されている!」と、その便利さに驚きました。Laravelもまた、素晴らしいフレームワークだと思います。
武田: うれしいですね。今回はとても美味しいお酒を飲めました。ありがとうございました!

※1:【参考リンク】
執筆:中薗昴
撮影:山辺恵美子

