ソフトウェアアーキテクチャのおさらい

Webシステムでよく議論されるソフトウェアアーキテクチャについて記憶が曖昧になってきたので改めて整理してみました。

レイヤードアーキテクチャ

レイヤードアーキテクチャの図

関心事にレイヤーを分けたアーキテクチャで、リクエストは全てのレイヤーを上から下に向かって通過します。
データベースを変更した際はDatabaseレイヤを変更するだけで済むなどのメリットがあります。

陥没穴アンチパターン(sinkhole anti-pattern)

全てのリクエストが全てのレイヤーを通るので、リクエストによっては何もしないレイヤーが発生することを陥没穴アンチパターンと呼びます。

参考資料: https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.html

オニオンアーキテクチャ

オニオンアーキテクチャの図

関心毎にレイヤーを分けるのはレイヤードアーキテクチャと同じです。
レイヤードアーキテクチャと異なるのは、依存性逆転の原則を適応し、データベースが外部化され、ビジネスロジックがデータベースに依存しなくなった点です。(図中のInfrastructureの部分)

オニオンアーキテクチャのルール

より内側にあるレイヤーにのみ依存できます。
レイヤーをまたいで依存するのも可。
外側のレイヤーにアクセスする場合は依存性逆転の原則を用います。

依存性逆転の原則とは

  • クラスではなくインターフェースに依存する
  • 実体を外から注入する(Dependency Injection)
  • 呼び出し元により実体を差し替えられるようになる
    • 例)テストの場合はモックに差し替えるなど

参考資料: https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/

ヘキサゴナルアーキテクチャ

ヘキサゴナルアーキテクチャの図

アプリケーションと外界との境界に「ポート」と「アダプター」という概念を導入したのがヘキサゴナルアーキテクチャです。

アプリケーションをユーザー、プログラム、自動テスト、バッチスクリプトのいずれからでも等しく動作し、永続化層(データベースやファイルなど)から分離して開発、テストできるようにする狙いがあります。

どのようなポートが必要かは「ソフトウェアによる」との事です。

参考資料: https://alistair.cockburn.us/hexagonal-architecture/

クリーンアーキテクチャ

まずは原本の図を示します。

クリーンアーキテクチャの図(原本)

上記の図をレイヤーの関心の名称で置き換えると以下の様になります。
ヘキサゴナルアーキテクチャの特徴を引き継ぎアダプター層ポートがあります。

クリーンアーキテクチャの図(レイヤーの関心の名称で置き換えた物)

元図の右下の図を見ると、Use Case Input PortUse Case Output Portを通してアプリケーションを操作することが分かります。
ヘキサゴナルアーキテクチャに比べてポートの実装がより具体的に示されています。

アダプター層とアプリケーション層の間の関係

クリーンアーキテクチャはヘキサゴナルアーキテクチャのアダプターポートをより具体的に示したものと言えそうです。

参考資料: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

個人的な見解

個人的には、ソフトウェアを破綻させないために費用対効果の高い施策が「ユニットテストを書く」だと思っているので、最低限、ユニットテストを書ける状態であるオニオンアーキテクチャになっていればOKだと思ってます。

ユニットテストさえあれば後から、レイヤーを増やす、アダプターやポートの概念を導入するというリファクタリングも比較的容易かと思います。

逆にヘキサゴナルアーキテクチャやクリーンアーキテクチャを採用してもテストを書かなければあまり意味がないとも思ってます。

コメントする