Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Hanamiフレームワークに寄せる私の想い(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。


leanpub.com/ddrより


追記: HanamiについてはRubyist Magazineで詳しく紹介されています。

Hanamiフレームワークに寄せる私の想い(翻訳)

本記事は元々Redditへのコメントとして投稿されました

この数週間Hanamiでいろいろ遊んでみました。そして今、個人的にはRailsよりよさげに感じています。文章よりコードが見たいぜ!という方は、私がHanamiで構築したささやかなサンプルアプリをどうぞ。

以下は、私がHanamiについて気に入っている点トップスリー(訳注: 実際には4つです)について少し詳しく書いたものです。

1. ActiveRecordではなくRepositoryパターンを採用

Active Recordパターン(訳注: 実装ではなくPofEAAの用語です)では、あらゆるものをモデルに投げることを促します。コールバック、バリデーション、永続性、データベースロジック(クエリ)、そしてビジネスロジックを思い浮かべてください。

(ROMを経由する)Repositoryパターンは対照的に、データベースとアプリの分離を明確にする方向に導きます。私がとりわけ気に入っているのは、バリデーションをdry-validation(ROMと完全に別のライブラリ)で扱う手法です。これによってモデル同士や永続性/バリデーションの層が強制的に分離され、使いたい機能を自由に拾い上げて選べるようになります。

Repositoryパターンで私が最も愛して止まない部分は、ビューでデータベースクエリを作成するという行為が非常に難しくなる点です。このおかげでN+1クエリなどを防止しやすくなります。

さらに、ROMにコールバックなどがないのも私にとって非常に嬉しい点です。コールバックという手法は(DHHの言う)マジックが強すぎ、開発者にとって切れ味が必要以上に良すぎます。明示的に書かれたコードは、理解を大きく助けてくれます。

2. アクションクラス

あらゆるアクションを同じコントローラに投げるのではなく、アクションを独自のクラスに隔離します。これによってアクション間の分離が保たれ、アプリ全体のアーキテクチャがさらに明確になります。

アクション間で何らかの機能を共有したい場合、その機能のためのモジュールを作成してアクションクラスにincludeするだけで簡単に実現できます。たとえば、find_postメソッドをshow/edit/update/destroyアクションで使いたい場合、モジュールでこのメソッドを定義して、使いたいアクションでincludeするだけで完了します。

Railsで上のようなメソッドをヘルパーメソッドとして追加すると、大抵の場合コントローラがとっ散らかってしまいます。アクションやヘルパーメソッドが複雑なため、Railsではコントローラのコードが数百行にもなることは珍しくありません。各アクションが独自のクラスに分離されることで、はるかに作業しやすくなります。

Hanamiのアクションはシンプルなクラスなので、テストをルーティング層から完全に分離することもできます。Railsのcontroller specは元々これを目指していたと私は考えていますが、これが私にはどうしても正しく思えないので、最近はもっぱらrequest specでやっています。Hanamiでは再びアクションを簡単にテストできるようになります。こういうのは大好きです。

3. アクションparamsのバリデーション

一部は前述の内容と関連しています。

Hanamiのアクションではパラメータのバリデーションも用います(dry-validationを援用しているのだろうと考えています)。つまり、アクションごとにパラメータを一意にバリデーションできるということです。皆さんがおそらくRailsでやっているであろう、コントローラでcreate_project_paramsupdate_project_paramsを定義する方法とは異なり、有効なパラメータの構成をまさにアクションクラス内で定義できるのです。

私がHanamiで試してみた範囲ではこれを使う機会はまだ見当たりませんでしたが、Railsアプリでこのようなものが必要になった部分ならいくつも思い当たります。

4. ビュークラス

アクションクラスと同様、Hanamiには「ビュークラス」という概念もあります。ビュークラスは、ビューの「ヘルパーメソッド」のロジックをテンプレートから極めて明確に分離してくれるので、大好きです。

Railsアプリの場合、コントローラ名に沿った名前を持つモジュールの中でヘルパーを定義します。私は次の2つの理由から、このアプローチがどうしても好きになれません。1つ目は、私は普段からヘルパーを1つのビューでしか使っていないこと、2つ目はヘルパーがアプリのビュー全体でグローバルにアクセスできてしまうことです。つまり、別のヘルパーモジュールに同じような名前のヘルパーメソッドを置けないということです。このような設計方針が決定されたのはかなり恐ろしいことです。

Hanamiのビュークラスは、このような小粒のヘルパーメソッドたちを置くのにうってつけの場所ですし、しかもビュークラスは分離された小さなクラスなので、ルーティングやコントローラやモデルと一切関わりを持たないテストを書けます。

訳注: Railsでは、config/application.rbファイルでconfig.action_controller.include_all_helpers = falseを記述することで、ヘルパーメソッドをビュー全体でグローバルにしないようにできます。
参考: ActionController::HelpersおよびRails中級チュートリアル: ヘルパー

まとめ

最初に申し上げたとおり、私にはHanamiが正しいと感じられます。Hanamiは、私たちがRailsですっかり慣れ親しんでいるMVC(Model-View-Controller)アーキテクチャに従っている部分もあるので、親しみやすさも十分ですし、使っていて実に快適です。いくつかの考え方については「Hanami Way」に切り替えなければなりませんが、ひとたび発想を改めてしまえばHanamiの方が優れていることに気がつくことでしょう。

Hanamiは、大規模Railsアプリの開発から学んだ厳しい教訓を実証した、頑丈かつ開発の行き届いたもうひとつのRuby向けWebフレームワークです。

実際、「頑丈かつ開発の行き届いた」という点は本当にうまくいっているので、もし私がproduction向けのWebアプリをスクラッチからRubyで開発することがあれば、私はRailsよりHanamiを使うでしょう。Railsでの開発経験が10年にもおよんでいるにもかかわらず、です。

追記:本記事へのご感想

関連記事

Railsの`CurrentAttributes`は有害である(翻訳)

Rails5「中級」チュートリアル(3-2)投稿機能: ヘルパー(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。