![見出し画像](https://assets.st-note.com/production/uploads/images/142438991/rectangle_large_type_2_4fd544eb02cbafb5fe35d95f925aa8dc.png?width=1200)
旬なアーキテクチャって何だろう?
みなさんこんにちは!
SOMPOシステムズのアプリケーションエンジニアです!
今回のお題は「アーキテクチャ」です。「アーキテクチャ」は色々なところでつかわれる言葉ですが、本記事でのお題は伝統的な3層構造とドメイン駆動設計を題材にしたソフトウェア開発の設計手法に関する「アーキテクチャ」について考えてみたいと思います。
先に筆者の答え
先に本記事を書いている筆者自身の答えを言ってしまうと、アーキテクチャを「野菜」に例えるとすれば「旬」はなく、どのお野菜も作る人のレベルや目的の料理に合わせて味付けすれば美味しくなるでしょう!という言葉にすると当たり前のような感じですが、これが「答え」でもあり、ある意味「答え」になってないかなと思っています。
※あくまでも私見です。セロリは味付けしてもニガテ…とかはありますけど。
はじめに
Webシステムにおける旧来のアプリケーション構造は「古い」というイメージはありますが、年を重ねれば昔からあるものは「古い」と感じるのは当たり前なのでまぁそれ自体は良しとして、、、それが「悪」なのか?というとそうではないと思っています。今ではドメイン駆動設計が「絶対正義」なのか?というとそれもまた違うのかなと。良いアーキテクチャパターンの選択は、味付けも含めてそのシステム開発で置かれている状況・その後の保守に適したアーキテクチャにしていくことが、アーキテクトに求められることであり、旧来のアプリケーション構造が「悪」ではないと思う点は、どのアーキテクチャも旧来から大きくかけ離れたものではないと思うからです。
また、今現在(2024年)から見ればドメイン駆動設計自体も10年以上前から存在する考えであり、1つのパターンに当てはめるものでもないです。これをシステム開発の前提にすること自体は良いと思いますが、良い部分と不要部分をきちんと捉えることが必要だと思います。
※以後の文章は「Java」における用語を使ってイメージしています。
伝統的な3層構造
まずは伝統的な3層構造(これが「古い」と聞く旧来の構造)ですが、こちらですね。
![](https://assets.st-note.com/img/1715045968726-eR4QWMmZ92.png)
層間の依存関係は上から下へ矢印のほうへ依存する形です。下から上への依存はNGです。
プレゼンテーション層 : クライアントとの入出力を行う層
ビジネスロジック層 : 対象ビジネスのロジックを実現する層
データアクセス層 : データ・ファイルなど外部と入出力をする層
ドメイン駆動設計(DomainDrivenDesign)
ドメイン駆動設計(DDD)ではよく4つのアーキテクチャの考えが一緒に登場します。
※オブジェクト指向が考えのベース
「ドメイン」というのは「ソフトウェアを使って問題解決しようとしている領域」「プログラムを適用する対象となる業務領域」という言葉で説明されます。具体的には保険システムでいえば「商品」であったり「契約者」であったり、会計システムでは「お金」になりますが、これらを中心に考えて設計をしましょうということになります。
レイヤードアーキテクチャ
ヘキサゴナルアーキテクチャ
オニオンアーキテクチャ
クリーンアーキテクチャ
1つずつ簡単に紹介していきます。
レイヤードアーキテクチャ
伝統的な3層構造と比べて分かりやすく変化してるものが「レイヤードアーキテクチャ」です。※これがドメイン駆動設計の原点と思います。
![](https://assets.st-note.com/img/1716981866368-xlPcyMBxUe.png?width=1200)
3層構造のうちビジネスロジック層が肥大化してくるため、Application層とDomain層に分けましょうという発想かと思います。これだけ見れば「クラス肥大化したらそりゃ分割したくなりますよ」といたって普通の発想にも思えるので、分割する目線をどこに置くか?がポイントになります。
アプリケーション層 :ユースケースを実現する層
ドメイン層 :業務ルールなど対象オブジェクトを実現する層
Domain層がInfrastructure層(つまりは特定のライブラリとかDBとか)に依存することは特定技術・製品に制限されてしまうことを意味するため、この点がアーキテクチャ上の課題になります。(そのシステムにおいてそれを課題と思うかどうかはさておき)
この課題の解決方法として「依存性逆転の法則」が登場してきます。
![](https://assets.st-note.com/img/1715053463620-bh0xYf7dhf.png?width=1200)
「依存性逆転の法則」の具体は、ドメイン層にインタフェースを設け実装をインフラストラクチャ層内に作ることです。インタフェースに依存することでライブラリやDBを隠蔽することができます。
ヘキサゴナルアーキテクチャ
ヘキサゴナルアーキテクチャは2005年に提唱された考えになりますが、六角形をイメージして外部とのインタフェースはアダプタを介しアプリケーション(=ビジネスロジック)との接続を交換可能なアーキテクチャになります。
![](https://assets.st-note.com/img/1716983367327-HpQxm31ZZI.png?width=1200)
分かりやすいところでいえば、アプリケーションとの接点となるDBが物理的なハードなのか、クラウド上にあるサービスなのか、アプリケーションから見れば気にせずアダプタを介在させることで、外の変更がアプリケーションへ波及せず守られることによりアプリケーション影響を最小限にとどめるための設計になります。
「アプリケーション/ドメインレイヤが外部の変更による影響を受けないよう設計する」という点はレイヤードアーキテクチャと比べると形が変わっていますが(「層」だったものが「六角形」になりアダプタを介在)、着眼点は同じかと思います。(ドメイン駆動設計のテクニックなので)
オニオンアーキテクチャ
オニオンアーキテクチャは2008年に提唱されたアーキテクチャパターンです。「オニオン」と名前が付くくらいなので図で示すと以下のような円形の図になります。
![](https://assets.st-note.com/img/1715056767961-e4xdH8BS4J.png?width=1200)
これは外から中へ依存する関係性を示したもので「層」のイメージで描くとこのようになります。
![](https://assets.st-note.com/img/1715056883151-MbpCBzDKAz.png?width=1200)
レイヤードアーキテクチャの説明にあった「依存性逆転の法則」が含まれています。依存性、保守性、テスト容易性の観点で優れた設計になります。外側に位置されるUI、Infrastracture、Testsといった層はヘキサゴナルアーキテクチャと同じく中心に向かって依存する形となっており、外部の変化が内側に影響しないことを思想として持っています。
クリーンアーキテクチャ
クリーンアーキテクチャは2012年に提唱されたドメイン駆動設計における一番新しい考えです。初めてこれを見たときは「言葉の定義」がこれまでと異なるため理解しにくいというのが率直な感想でした。
(例えばEntitiesはDomainのことです)
![](https://assets.st-note.com/img/1715058871785-YJyzANWQKb.png?width=1200)
引用元: The Clean Code Blog - The Clean Architecture
オニオンアーキテクチャをさらに細分化して各レイヤの責務を明確にし、クラスにしたとき「何を」「どこに」ということを細かく示したものになるかと思います。細かければ細かいほどインタフェースクラスがたくさんできます。
で、結局どうなの?
ここまで伝統的な3層構造とドメイン駆動設計のアーキテクチャパターンを簡単に見てきましたが、原点は3層構造(層における責務とその依存関係)であって、ビジネスロジックを大事に保護していくために他の層に依存しないことや、外部からの影響を受けないよう間にインタフェースやアダプタを介在させて「疎」の関係を保つためのいわばテクニックかと思います。だから伝統的な3層構造は今の時代では「悪」なのか?というと、そうじゃないでしょ。と思うわけで、重要な基礎であり、依存関係逆転の法則は言葉にすると難しそうに感じますが、オブジェクト指向の基礎テクニックを活用したものだと思っています。そのためドメイン駆動設計でもレイヤードよりオニオン(円形)さらにはクリーンでしょ!というイメージを持ってしまいがちですが、どれも「層」における責務と依存関係を謳っているものなので、3層構造と同じイメージを持つレイヤードだから「古ッww」ということではないかと思います。
そんなことはドメイン駆動設計を経験してきた人からすれば誰でも知ってるよーとか、説明が不十分じゃない?とかあるかもしれませんが、大事なのは次からの話だと思ってます。
アーキテクチャパターンの選択は「目的」と「規模」と「開発者スキル」を考えましょう
ドメイン駆動設計はオブジェクト指向の設計に基づいたものです。旧来のシステムは構造化プログラム(COBOL)であったり、.NETを扱うけどもTHEオブジェクト指向な設計ではなく手続き型のプログラム構造になっているシステムも多いかと思います。
現行システムのモダナイゼーション
昨今多くの企業で考えられている現行システムのモダナイゼーションにおいては以下の方式(例)があります。
リビルド :現行システムをベースにした新規構築
リライト :現行システムのプログラムをベースとして、新言語へ変換
リホスト :現行システムのプログラムをコンパイルしなおして稼働
リプレイス:ハードウェアのみ変更
その他割愛
構造化プログラム・手続き型プログラムを「リビルド」「リライト」する場合において「ドメイン駆動設計しましょう!」と言っても「どうやって?!」が先に来ます。リビルドのパターンで気合を入れたらもしかしたらできるかもしれませんが、このようなモダナイゼーションのプロジェクトにおいて現行システム有識者・経験者の知見は絶対に外すことはできず、システムによっては複雑回帰している可能性が高いことや旧来構造の考えがベースにあるため「ドメイン中心に物事を新しく考え始める」とプロジェクトリスクにもつながっていきます。現行システムは完全に捨て、システム要件から新しく作り直す場合においてはドメイン駆動設計にしていきましょうという話はアリかと思います。つまりは現行システムを活かすか否かでアーキテクチャの採用パターンは大きく変わってくるのだろうと思います。
大規模開発におけるアーキテクチャの採用
もう一つパターンとして「大規模開発」です。基幹システムの刷新である未来革新プロジェクトを例にすると、新規システム構築であり多くの開発者が参画する大規模開発です。Javaを使ったアプリケーション実装であり「オブジェクト指向」を適切に行える設計者・実装者を集めることも難しくなってきます。オブジェクト指向の設計を誤った形で進めてしまうとかえって複雑回帰にしてしまったり凝集度が極端であったり、変更容易性を求めていたのに難しくなってしまう恐れもあります。オブジェクト指向自体の経験の深さによって出来上がりの品質が変わってくるため、多くの開発者を抱えているプロジェクトにおいては各アプリケーション間で一定の品質を保つために設計難易度を抑えたアーキテクチャのルールを定めることは極めて重要となります。そのため開発PJTに合わせたアーキテクチャを考える必要があると思います。
さいごに
「旬」なアーキテクチャ選択というものは無く「置かれている状況」によって最適なアーキテクチャパターンの選択は必要であり、実際の開発者が迷わないようにしていくこととその後の保守を続けられることが重要だと思います。
オニオン(たまねぎ)が出てくるので「旬」と表現したかっただけですが、「今はこれだー!」という絶対なものは筆者の中にはなかったです。スミマセン
またドメイン駆動設計も層間の依存関係を正しくコントロールすることが大事であり、これは旧来の3層構造と同じで適切な依存関係を保ちましょうということが言えるのかなと思います。
2024年度もGWを過ぎて日中は暑さが出てきました。夏の野菜はキュウリ・トマト・枝豆と自分の中で決まっています。冷蔵庫で冷やして美味しくつまみながら旬の野菜を楽しみたいと思ってます。