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)投稿機能: ヘルパー(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ