大規模Rails開発を蝕む5つのアンチパターン

Railsでアプリを作っていると、最初の立ち上がりは速いものの、コードが多くなってくると結構散らかってきますよね。そんな中、5 ARCHIRECTURE ANTI-PATTERNS AND SOLUTIONS FOR LARGE RAILS APPSという記事を見つけたので、ご紹介します。

1. 複数の責務を持つサービスクラスがある

業務別の処理をサービスクラスという形で分割したときの話ですね。ActiveRecordのクラスに直接仕事をさせるのではなく、プレーンなクラスに業務処理をまとめて、そこからだけActiveRecordのクラスのオブジェクトにアクセスするという考え方です。

で、業務別の処理をサービスクラスにまとめたのは良いんだけど、「これもこの業務だよね」という感じで、どんどんサービスクラスに処理を追加していくと、単一責任の原則に違反してしまうし、混沌とするので、良くないよねと。

そんな訳で提案されているのが、ケースクラスを作るという考え方です。もうちょい細かい業務別にネームスペースを切って、サービスに対するケースでクラスを作るという感じ。

僕はこう思うです

ActiveRecordとサービスクラスは、どうも合わない気がしています。あんまり上手く設計できた試しがない。ActiveRecordを使う限りはActiveRecordに寄った方が、規模が大きくなってきても、設計しやすい気がしています。

2. ドメイン層にネームスペースで区切られていないクラスが乱立している

ドメイン層にネームスペースで区切りられていないクラスが236個も転がっていたら、よく分からなくなるよねという話。ケースクラスに分けるのもいいけど、ネームスペースで区切っておきましょうねという話でした。

僕はこう思うです

そりゃそうだな。

3. 機能を共有するためにモジュールをインクルードしている

サービス層を設計しようとする人は、そもそもMix-in嫌いですよね。ここでも綺麗にやらないと死ぬよね、という話をされています。

僕はこう思うです

やたらめったら汎用的なモジュールを作ろうとすると、死ぬかもなと思います。用途を限定したモジュールを、特定のクラスに紐付けるぐらいだと、そんなに辛くなることはない気がしています。

システムのアーキテクチャを考えるときに、疎結合であることは重要なのですが、もっと詳細な実装に限っては、あえて密結合をとるようなバランス感覚も大事なのではないかと考えています。

4. 動的メソッド呼び出しがある

メタプログラミングは便利だけど、保守が大変だよ。うちにはmethod_missingを含むようなコードは一つもないよという話。メタプログラミングは用途を限定するようなDSLを書くときぐらいかなー。

僕はこう思うです

複数人で開発しているときに好き勝手やりだすと、危険なスメルはあります。1人か2人で開発しているなら、メタプログラミング使わないと辛いこともあるので、別に良いんじゃないかと思います。1人か2人で開発する場合は、あえて大規模チックなコードにならないように、メタプログラミングを上手く使うのではないかと思います。

5. Railsのヘルパー

使うなという話。グローバルなメソッドなので、グローバル変数と同じようなスメルがある。特定業務に使うようなヘルパーメソッドを作るなら、Draperを使おう。

僕はこう思うです

Draper良いと思います。ヘルパーメソッドを作る場合は汎用的な用途に限定しておく必要があることもアグリーです。

もう少し考え方を進めて、もっとコンポーネント指向で行こうよという考え方で作られているCellというGemもあります。最近のGemかと思っていたら、最初のコミットは5年前ということで、かなり古いGemなのですね・・・。

Cellはあまり日本語の情報がないように思うのですが、「Cells – Railsの部分テンプレートとそのロジックを分離するコンポーネントフレームワーク」という記事に概要がまとめられているので、気になる方はご参照下さい。

結び

改めて、RailsにDCI的な考え方は合わないような気がするなー・・・と思ったのでした。大規模!と言うとDCI的な考え方に流れがちなのですが、もっとRailsらしいアプローチはないのかな、と思うのでした。