生産性のない時間 is プライスレス

当たり前を再認識する・目的の多いシステムにおけるアーキテクチャ

公開日時:

みなさん。開発におけるアーキテクチャに悩んでませんか?私は常に悩んでいます。 (この文脈の「アーキテクチャ」とは、かなりふわっとした意味合いのほうです。 原義とかは気にしないでいただけるとありがたいです。)

というわけで今回は、認知負荷をできるだけ減らして、なおかつまぁそれなりに品質は保てるんじゃねぇの?という妥協案を忘れないうちに整理しておこうと思います。

結論

まずは、今回の妥協案の構造の結論を出します。

- フレームワークルート
  - 機能 1
    - Presentation
      - Controller
    - Application
      - UseCase
    - Domain
      - Entity
      - Repository
    - Infrastructure
      - Repository Implement
  - 機能 2
    - Presentation
      - Controller
    - Application
      - UseCase
    - Domain
      - Entity
      - Repository
    - Infrastructure
      - Repository Implement
  - データベース
    - ORM など

各機能の中で、Presentation 層、Application 層、Domain 層、Infrastructure 層を分けています。 層をディレクトリで分けないという選択肢もありますが、クリーンアーキテクチャなどの設計原則に慣れている人が見たときに、「この構造気持ち悪い」と思われる可能性があるので、ディレクトリで分けています。というより、私がそう思うので。

ちなみに Laravel の構造は大まかにいうと以下のようなものです。

- フレームワークルート
  - app
    - Http
      - Controllers
    - Models
    - Services
    - Repositories

Laravel がどうしてこのような構造を採用しているかを考えてみると、つまるところ一つのアプリケーションで果たすべき目的は一つであるべき、というのが存在しているのだと思います。 もともと複数の目的を同時に果たすようなことを考えていないし、そのような場合は別のアプリケーションを作るべきだという考え方です。適当言ってるので違うかもしれないですが。

でも現実問題として、一つのアプリケーションで複数の目的を果たすことはよくあります。 お客さんありきのシステムだと特にそうですね。

極論そういうときは別のアプリケーションを作ればいいんですけど、そういうわけにもいかない場合もあります。 というよりそれってマイクロサービスなどの考え方だと思うのですが、セッションを含めた認証周りの実装が大変だったり、データベースの管理が大変だったり、という問題があります。

というわけで、色々を考慮して複数の目的を果たすアプリケーションの妥当な構造を考えたとき、結論で提示したような構造になるんじゃないですかね。たぶん。

あとがたり

ここら辺の構造、チーム内で合意が取れていないと普通に仁義なき戦いが始まってしまうの、エンジニアあるあるかもしれませんね。

ところでこのような構造、モジュラモノリスに近い感じだと思うのですが、モジュラモノリスとは微妙に違う気もするのですよね。どういう呼び方をすればいいんでしょうか。ぶっちゃけドメイン層を別パッケージ(名前空間)として分けてしまえばモジュラモノリスになると思うのですが、そうするとドメイン層を人間がぱっと見つけられない問題が発生しそうで、難しいのです…。