Ruby on RailsとLaravelの違いをPHPer視点で書いてみる

Laravel,PHP,Ruby,Ruby on Rails,勉強,思想

なぜ書こうと思ったか

面接に進んだ企業にて、コーディングテストを受けた。テストの内容はRailsで作られたAPIの機能改修をするというもの。30分や1時間で疑似コードを書くようなものではなく、一週間ほどの期間を与えられ期間内にその内容を実装するという形だった。

Railsは趣味程度でしか使ったことがない旨を伝えたところ「得意な言語/FWに書き換えてよい、むしろその方が実力が見られるのでよい」とアドバイスを頂いたのでPHP/Laravelで課題コードを再現して改修した。

その際にRailsとLaravelの思想や方向性の違いを認識することがあったので、備忘録としてメモしておきたい。

私がRuby on Railsに関して素人であるのと、言語やFWの優劣を主張したいわけではなく「違いがあって面白いな」という意識で書いていることを注意されたし。

モデルのディレクトリ位置

モデルのディレクトリ位置についても違いがある。

RailsもLaravelもコマンドラインでmodelを作成できるようツールが用意されているが、modelファイルが作られるデフォルトのディレクトリがそれぞれ違う。

Railsの場合

Railsのモデル作成コマンドは以下

rails g model user

作られるmodelはapp/modelsに格納される。

Laravelの場合

モデル作成コマンドは以下

php artisan make:model User

作られるmodelはapp/に格納される。特定のディレクトリに作りたい場合は–pathオプションをつけることで実現できる。

php artisan make:model User --path=your/model/dir

この違いの由来を考えてみる

Railsには、設定より規約(Convention Over Configuration:CoC)という重要な思想がある。Railsはその名の通り、railに沿えば非常に簡単に短い記述でアプリケーションを構築できるように作られている。

一方LaravelはRailsよりはかなり緩い規約しかない。これは公式で明言しているわけではないのだが、使用感で言うと規約より設定という感覚が強い。ちなみにLaravelの由来はナルニア国物語から。

Laravelにも昔はModelディレクトリがあったそうなのだが、MVCのMに対する誤解を解くためにver.5以降からディレクトリが削除されたとのこと。その辺りの経緯は詳しく知らないが、modelというのはORMモデルだけのことを指すのではない、という主張が背景にはあったのではないかと理解している。

そのため、この違いは「明確な違い」と言うよりは「LaravelがMVCに関する誤解を避けた」結果だと言える。果たしてModelディレクトリを削除したことでmodelへの誤解が解けたのかは分からない(むしろapp直下にmodelが大量に作られるようになっただけのような気もする)が、「ここに作ってね!」というRailsと「好きな場所に作りなよ」というLaravel、そのスタンスに違いがあることは読み取れる。

私の意見としては、最近ピュアなMVCディレクトリ構成で作ることは少なくなっているためmodelを置くディレクトリは好きに設定できた方がいいかなあ、と感じている(もちろんRailsでもディレクトリをいじることは可能だが)。最近はクリーンやオニオン,ヘキサゴナル的なアーキテクチャを採用することが多いので、ORMのモデルはInfrastructuresのようなディレクトリに配置することが多い。

MVCをあまり使ったことがない入門者が使うには「なるほどそういうものなのか」とrailが敷いてあった方が馴染みやすく、考えることが減って楽しくプログラミングができる。しかしLaravelが危惧するように、model==ORMモデルだと誤解してしまう可能性は確かに高いと思う。別のソフトウェアアーキテクチャに移行する際や他言語のエンジニアと会話をする際modelの認識がずれてしまうと「???」となってしまい、それはエンジニアにとって損失になりそう。どちらがよいという話ではなく、一長一短なのかなとも思う。

バリデーションの捉え方

当然RailsもLaravelも必要に応じて各クラス/メソッドで必要に応じてバリデーション処理を実装することもあるのだが、基本的にバリデーションを行う層をどこにすべきか、という思想には違いが見られた。

Railsでバリデーションというと、モデル(Active Recordモデル)でのデータ保存時のバリデーションを指すことが多い。対してLaravelでは、httpリクエストの内容に対するバリデーションを指すことが多い。

今回受けたコーディングテストの内容では

  1. httpリクエスト受け取り
  2. ルーティング
  3. コントローラで処理
  4. ORMモデルを使って永続化なり検索なり
  5. 結果をリターン

という一般的な流れのwebアプリケーションを取り扱っていた。

Railsの場合

課題のRailsコードだと、例えばPersonモデルがあったとして

class Person < ApplicationRecord
  validates :name, presence: true
end

このようにモデルに制約を書いてあり、コントローラ側では

Person.create(name: "John Doe")

こうした処理が書いてある。この場合、モデルに制約を書いておくことで、実際にデータを操作する際にバリデーションが自動的に走るように作られている。

Laravelの場合

一方Laravelでは、そもそもコントローラ側にバリデート処理が書かれていることが多い。

    $validatedData = $request->validate([
        'name' => 'required'
    ]);

上記の例ではValidatesRequestsトレイトからそのままバリデーションを行っている。それとは別に、バリデーションを責務とするValidatorというクラスもORMとは切り離して用意されている。そのためもちろんモデル側でValidatorを利用すれば同じことができる。とはいえ入力値に関してはコントローラでバリデーションを行うのが一般的という印象。

この違いの由来を考えてみる

これもまた言語の歴史、FWの思想や目的に由来する違いだと感じる。

Rubyは簡単に楽しく記述できる言語であり、Railsもまたそれに準じている。そのためRailsはリクエストを受け取ってDBを操作するごく一般的なアプリケーションを楽しくはやく作ることを得意としている。モデルの設定さえきちんとしておけばDBの操作時に自動でエラーが出るように設計されているし、初心者でもごく簡単に「リクエスト->DB操作」という基本的な動きを実現できるよう考えられている気がする。例えばユーザ作成を行いたければ、コントローラでORMのcreateをパッと呼べば良い。検査や何やらは自動でORMがやってくれる。設定に行数はかかるものの、実処理は1行で実現でき、それを使い回せる仕組みが揃っているというわけで、これはとても簡単に思える。

Laravelもやろうと思えばもちろん同じようなことは実現できるわけだが、モデルでのバリデーションはRailsほど簡単ではない。逆に、コントローラでのバリデーションはRailsよりも楽に実現できる。

PHPもRubyと同じように、習得難易度的には簡単な言語とされる。歴史も古く簡単な言語という特性から、練度の低いエンジニアを大量生産してしまったという負の歴史もあり、その影響や言語自体の品質の問題から、セキュリティに関して緩い言語とされていた。それに対応する形で、CSRF(クロスサイトリクエストフォージェリ)やXSS(クロスサイトスクリプティング)、SQLインジェクション等一般的な攻撃に対し非常に敏感であることが、半ばPHPを扱うものとしての義務とされる風潮がある。そういった経緯で「ユーザの入力値は一切信頼するな、不要なプログラムは動かすな」というエンジニア文化が育まれてきた。「リクエストは受け取ったら即検査、不正リクエストは即処理終了」とするのが一般的になったわけだ。言語をあまり信頼できなかったことから、(一部の)使う側の人間の意識が高まったというなかなか面白い歴史だ。実際、ちゃんとしたPHPのコードを読むと執拗なまでのバリデーションを組んでいることが多い。昔関わったプロダクトで、プロダクションコードの半分がバリデーションに関するコード(テストも含む)だった時は非常に驚いた。

Rubyは簡単に楽しくサービスを作れるし、言語も優秀。PHPは簡単に扱えるが、言語はそれほど優秀ではないので使い方に気をつけましょう。こんな違いがこの文化の差を生み出しているのではないかと結論した。

まとめ

Railsは簡単なものをパッとMVCで作るのに適していて、Laravelは便利な道具を好きに使ってものを作るのに適している。なんとなくそんな印象を受けた。

Railsは趣味程度でしか使ったことがないのでこんなことをいうのは烏滸がましいが、実際使い勝手的にはすごくよかった。最近はバックエンドとフロントエンドでサーバも分かれていることが多いので、バックエンドのAPIをパッと作りたい需要には引き続きRailsは応え続けると思う。

一方でLaravelは本質がコンテナであるということもあり、便利な機能が備わり過ぎていて初心者が扱うには情報量が多いかもしれないなと思う。もちろん簡単なMVCであればそういった複雑な機能を何も気にせずパッと作れるが、こだわろうと思えばいくらでもこだわれるというか、様々な設定すれば使える様々な機能があると後になって気づくことが多いというか。

初めてRailsで書かれた他人のコードを読めて、とても楽しかった。

Laravel,PHP,Ruby,Ruby on Rails,勉強,思想

Posted by shoopon