本記事はREADYFOR Advent Calendar 2024の10日目の記事です。
Railsを開発している会社が、実際にどのようなRailsアプリケーションのコードを書いているのかを知ることができる、という噂を耳にしました。日頃のRailsへの感謝の気持ちも込めて、思い切って身銭を切り、$299でCampfireを購入し、読み解いてみました。(※オープンソースではないため、コードそのものはこの記事に掲載していません)
興味はビジネスロジックをどこに書いているか?
出た...この話題...何周目よと言われそうだが、わたしの興味はこの1点のみです。
- ビジネスロジックをどこに書いているか?
-
app/models
のみで見通しの良いコードになるのか?
-
経験上、この3パターン
実務でよく見る3つのパターン、それぞれ一長一短があると考えています。
モデル (app/models) 派
- メリット:
- 伝統的なRailsの「Fat Model, Skinny Controller」のアプローチを踏襲し、ActiveRecordモデルにビジネスロジックを持たせることで、Railsの標準的な構成を維持できます。初学者や小規模なプロジェクトには理解しやすく、Rails Wayに忠実。
- デメリット:
- モデルが肥大化しやすく、特に複雑なビジネスロジックを持つ場合は、テストが難しくなることがある。また、ActiveRecordに依存する形でロジックを記述するため、インフラ層(データベース)との結合が強くなりがち。
サービスクラス (app/services) 派
- メリット:
- ビジネスロジックをサービスクラスに分離することで、モデルやコントローラがシンプルになり、コードの責任範囲が明確になります。また、サービスクラスはテストがしやすく、再利用性が高い
- デメリット:
- サービスクラスが増えすぎると管理が複雑になり、結局どこに何があるのかが分かりにくくなることも。特に大規模プロジェクトでは、明確な命名規約や依存関係の管理が重要。
DDD (app/contexts, app/contexts/domain, app/contexts/infra...) 派
- メリット:
- ドメイン駆動設計(DDD)の考え方に基づいて構成を設計するため、ドメインごとに分割されたコードがビジネスロジックを自然に反映するようになる。複雑なビジネスロジックを整理しやすく、特に大規模なシステムでの拡張性に優れる。
- デメリット:
- 学習コストが高く、全てのチームメンバーがその設計方針を理解し、遵守する必要がある。また、Railsの標準的な構成から離れるため、既存のRails開発者にとっては馴染みにくい。
本題のコードリーディング
正直なところ、もっとボリュームのあるコードを期待していましたが、実際のコード量はそれほど多くなく、感想をまとめるのが難しい部分もありますが...
-
app/models/concerns
に切り出して、見通しのよいコードを保っている- concernsディレクトリを活用し、共通の処理をモジュールとして切り出すことで、コードの見通しをよくしていました。このアプローチは、たとえばマストドンのコード構造にも見られます。
-
複数のモデルにまたがる処理についての実装
- こちらの参考記事の通りの実装でした
- 主となるモデルに処理を実装
app/models
配下に何も継承していないただのクラスで実装
- こちらの参考記事の通りの実装でした
が、感想になります。
で、あなたの意見は?
最終的には、プロジェクトとしての一貫性が重要だとは思います。ただ、現実にはやり切れずに複数の手法が混ざり合い、結果的にコードが混沌としてしまうこともよくあります。そのため、どのアプローチを採用するにせよ、徹底的にやり切ることが鍵だと感じます。
個人的には、あまり大きな声では言えませんが、下記の参考例からapp/services
は肯定派です。
-
マストドンのコードベース
- マジカルなコードもなく、読みやすく整理されていると感じます。
-
「Sustainable Web Development with Ruby on Rails」
- この書籍には、次のような興味深い指摘があります。
これが美しいコードだとは言いません。これがオブジェクト指向の設計原則に準拠しているとは言いません。 。 。それらが何であれ。また、これがDHHのやり方であるとは主張しません。
私が主張するのは、このアプローチにより、Railsから大量の価値を引き出すと同時に、ビジネスロジックを好きなように統合および整理できるということです。そしてこれにより、そのロジックがHTTPリクエスト、メール、データベース、およびRailsによって提供されるその他のものと絡み合うのを防ぐことができます。そして、これは持続可能性に大いに役立ちます。
- Service Layerに関する考察
明日は、 yuji_developer さんによる記事です。