さんの「Turbolinksさんと上手く付き合う10の方法」でした。公開期限に間に合わない可能性があるため、まだ途中ですが先に公開してしまいました。サンプルコード等を後ほど追記する予定です。構築したアプリケーションが大規模になり機能が増えていくにつれてモデルが大きくなり、そのうち手がつけられなくなる問題は古くから指摘されています。年になった今でも多くの開発チームを悩ませていると感じています*1。厨、モデリング厨という"プログラマの麻疹”*2を一通り経験した僕がいろいろなドメインロジックの実装方法を模索した結果と感想をまとめてみようと思います。そのものであるというフレームワークのあり方がまさにアンチパターンとして紹介されています。先日、この書籍の読書会でこのアンチパターンについて発表したので、そのときの資料を紹介しておきます。なくフォームとも密結合である点、アンチパターンに陥らないための現実的な落とし所などについて簡単に紹介しています。このエントリではこれらについてもう少し詳細にご説明したいと思います。追記)このエントリではブログシステムのようなアプリケーションで「記事にコメントする」というユースケースを例として扱います。仮にArticleおよびCommentというモデルがあったとすると、特に何も考えなければコントローラに以下のような実装があらわれるでしょう。メソッドをコントローラで利用するとテーブル構造が容易にアプリケーション層まで流出してしまっていてよい実装とは言えません。そこでこの処理をモデルクラスに隠ぺいして実装の詳細をアプリケーション層から見えないようにすると思います。endendしかし、これでは前述したようにシステムの大規模化にともなってモデルクラスがどんどん大きくなっていきます。これをどのように実装するとよくなるか、いろいろな方法を検討していきます。強みを最大限に生かしつつ、現実的な範囲で複雑性を下げていくのは、モデルに実装されたメソッドをモジュールに逃がすことです。ActiveSupport::Concernという便利なモジュールがあるのでこれをextendしたモジュールに責務ごとにメソッドを実装してそれを各モデルにincludeすればアプリケーション全体の見通しはよくなります。これは他の手段に対して比較的安全な手段といえるでしょう。endendこの場合、コントローラの実装は直接モデルにメソッドを実装する場合と変わりません。規約に最も素直に従う実装手法なのでハマりどころが少ない。バージョンアップ等の影響を受けにくい。コントローラの実装は変わらないので既存のアプリケーションのリファクタリング手法としても使える。*3デメリットあくまで見た目の複雑性が下がっているだけであり、実体としては巨大なモデルが出来る上がることに変わりない。本質的には何も解決してない。巨大なオブジェクトができるわけなのでメソッド名の命名にそれなりに気を使う必要がある。異なるコンテキストで同じメソッド名を使うといったことができない。目の方法はサービスオブジェクトを持ち込む方法です。$a_suenami)複数のモデルにまたがる処理をサービスとしてまとめ、専用のクラスを作成します。以下にサンプルを示します。ActiveRecord::Baseendメリットサービスとは手続き的な処理をまとめたものに他ならず設計の難易度が比較的低いため、プログラマのレベルにばらつきがあっても極端にひどいコードになりにくい。サービスは基本的にステートレスであるため状態に依存した不具合は混入されにくい。デメリット設計の難易度が高くないことの裏返しであるが、それほどレベルの高くないプログラマが多くいるとサービスクラスだらけになりドメインモデル貧血症に容易に陥る。このアンチパターンに陥ると単にコントローラにあった処理がサービスクラスに移動するだけになる。おけるドメインサービスがあり、チーム内で認識を合わせておかないとそのレイヤーの役割がまったく違うものになる。用いるという手もあります。何かという説明はここでは割愛しますのでご存知でない方はぐぐってください。言うと、あるエンティティの存在そのものとそのエンティティのあるコンテキストにおける振る舞いを分離し、アプリケーションの設計をドメインエキスパートやプロダクトオーナーのメンタルモデルに近づけようとする設計手法です。サンプルだと以下のような感じです。使う際の妥協ポイントかと個人的には考えています。..略..endコメントを追加する処理をUserのロールとして実装しました。これによりコンテキスト内の実装はユーザのメンタルモデルに近い語彙で表現されており、それらの知識がコントローラからは隠ぺいされました。コントローラは単にコンテキストをexecuteするだけとなります。メリットコンテキストごとにロールが与えるため、異なるロールであれば同名の振る舞い(=メソッド)を持つことが許される。コンテキスト、ロール、ロールに実装されるメソッドの名前はユーザのメンタルモデルにある語彙が選ばれる。それはユビキタス言語を構築していることに等しい。動的に行われるため、性能上の懸念がある。ユーザのメンタルモデルをコードとして表現することが本来の目的であり、ドメインエキスパート/プロダクトオーナーとの対話が必要となる。そのため、設計の難易度は非常に高い。流儀から外れすぎてしまうとどうしてもうまくいかず途中で断念しました。アプリケーションで立ちゆかなくなった際にはいっそ複数のアプリケーションに分割するという方向性もアリかもしれません。日目のエントリであり、「Railsでドメインロジックをモデルに書くのは、果たして良い設計なのだろうか?」へのアンサーエントリでもあります。したときの運用効率などを維持するためのデザインパターンや設計ノウハウが普及し、さらなる発展を遂げることを願います。*1:少なくとも僕のまわりではそういう声がいまだにあります。*2:知らない人はぐぐってください。書かれていればの話ですが。「ビジネスの構造を扱うアーキテクチャとユーザとの接点...タイトルの通り、登壇してきました。見極め方Archiveスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。