目次
はじめに
私は普段、クラウド(インフラ)関連の仕事を扱うことが多いですが、最近ソフトウェアアーキテクチャを重要視するようになってきました。
ソフトウェアアーキテクチャとはシステムの品質や拡張性を保つために、設計原則を取り入れながら将来の変更に強いソフトウェアを作るための設計アプローチです。
そんなシステム開発で使用するソフトウェアアーキテクチャですが、クラウド・インフラの知識としても非常に重要だと感じております。
それは結局のところクラウド環境の設計・構築もプログラム開発の設計・開発においても目標が同じだからです。
お客様のビジネスをどうシステム化しビジネスの発展に貢献できる仕組みを作るかという目標です。
アプリケーション開発であれ、クラウド・インフラ構築であれ同じ目標のもと設計を進めていくことが重要と感じたためです。
例えば、洗練された秀逸なアプリケーションが出来ても貧弱なインフラだと、その価値が発揮しづらいです。
デプロイ独立性の観点でアプリケーションがコンポーネントごとにレイヤー化されていれば、柔軟性があり、スケーラビリティも確保しやすいです。この処理だけ重たいので単独でスペックの高いサーバーで実行させたい。と言ったことがある場合、デプロイを独立してインフラ側で実行環境を分けるといった変更が可能となってきます。
特にクラウドだと、機能ごとに分離させて必要なスペックで実行させるといったことも可能になっています。
最近のモダンなアーキテクチャを実現しようと思うとアプリケーションもインフラも同じ方向を向いて設計をしていかないといけないなと感じています。
また、「ビジネスは常に変化する」というものも意識しないといけません。システム化にあたってドメインエキスパート(専門領域の知識をお持ちのお客様)と会話し、お客様の業務範囲をドメインとして、ルールやパターンを見つけ出して、どの処理を同じコンテキストにまとめるかを判断していきます。
そしてビジネスの変化の中にも変わるものと変わらないもの(変わりづらいもの)を整理して、未来に備えた変更を考慮しておかなければいけない点もアプリ、インフラ両方に当てはまる設計アプローチだと思います。
システム開発においてその変化を考慮しておかないと変更が容易にできなくなることもあり得ます。
そうなるとビジネスの変化にシステムが応えられないようになってきます。
依存関係を整理する
「変わるもの」と「変わらないもの」という表現の具体例ですが、
ユーザーインターフェース(UI)なんかは、具象的で最も変更が加わる要素の代表者かと思います。
逆に変わらないものというのは、お客様の業務のコア(ドメイン)となる部分です。
ドメイン層には Entities(同一性で識別されるオブジェクト)と Use Case(行動)が含まれています。
例えば、商品配送システムを開発すると仮定した場合、商品を配送する「配送エンティティ」という同一性で識別されるオブジェクトがあるとします。
- ID
- 配送ステータス
- 配送先アドレス
配送エンティティは上記の情報をもっており、そのエンティティを使った商品の注文から決済・配送をする Use Case(行動)がある。といった流れはおそらく変化が少ない部分です。
それらをビジネスルールと呼んでおり、設計の中心に集めて、依存性の方向を中心に向けることで変化に強い設計が可能だとエリック・エヴァンスやロバート・C・マーチンは唱えています。
そのドメイン層にはその他のコンポーネントには依存しないことで、不必要な変更を避けることが可能です。
例えば、データベースのエンジンを MySQL から PostgreSQL へ変更するといったインフラ要件の変更があったときに、注文に関するロジックに変更が加わってしまうのは、おかしいですよね。
はたまた、商品画像を格納しているストレージをファイルシステムからオブジェクトストレージに変えたからといって、仕入れや在庫や注文のビジネスロジックに変更が加わってしまうのもおかしいですよね。
業務規模が拡大してソフトウェアの動作環境がデスクトップアプリケーションからWebアプリケーションに変更をする場合なども、ビジネスロジック自体に変更が加わる必要はないですよね。
何かを変更するために不必要な部分にまで修正を加えなくても良いようにするために、依存関係を管理しながらプログラムを設計していく必要があります。それを実現するための設計思想がソフトウェアアーキテクチャです。
コンポーネント(domain層やInfrastructure層等)の依存関係を一方向にしていく原則と「業務」(ドメイン)を軸に境界づけられたコンテキストを見極めてサブドメインに分離していくドメイン駆動設計。
エリック・エヴァンスのDDDは「何を(What)モデル化し、どう分けるか」という戦略と中身を教えてくれています。
一方で、ロバート・C・マーチン(通称:アンクル・ボブ)のクリーンアーキテクチャでは 「それをどこに(Where)配置し、どう繋ぐか」という具体的な構造とルールを設計原則という具体的なプログラミング手法を交えて教えてくれていると言えるかと思います。
AI時代における人間がプログラム開発に介入する必要性
昨今、AIでコードの生成ができ、ある程度の要件を伝えればプログラム開発も容易に出来る時代になってきています。
実際に本ブログでもコーディングをせずともアプリケーションの開発が出来ている記事もあります。
そうなってくるとシステム開発を行う上でプログラム開発に関してエンジニアの必要性が今後無くなってくるのでは?と疑問を持つこともあります。
AIが苦手とする「0 から 1 を産む」場面に関して人間が介入しないといけないと思っており、その役目を担っているのがエンジニアだとも思っております。
その設計の過程で、エンジニア(人間)は業務についての理解を深めドメイン設計をする必要があるとも思っています。複雑なビジネスルールを分析していくところです。
その手の設計思想についてもAIはかなり得意としており本ブログでも設計パターンを指定してコーディングをAIに依頼することでドメイン駆動設計を物理的に言語仕様に沿ってあてはめたクリーンアーキテクチャでAIがプログラム開発出来てしまう事実もあります。
それでは、さきほどの言っていた「0 から 1を産む」ところに関してもAIがうまいこと作ってしまえるのではないか?とも思いますが、私は半分正解で半分は不正解だと思っています。
そもそもドメイン駆動設計とは
ドメイン駆動設計(DDD)とは、一言で表すとソフトウエアの複雑さの中心にあるドメイン(業務)の正しさを、コードと一致させる設計アプローチです。それには戦略的設計と戦術的設計の2軸があります。戦略的設計アプローチは、ドメイン(業務範囲)の中で低結合・高凝集を見極めます。
例えばアパレル業のお客様でECサイトを立ち上げるときに「商品」というエンティティに対して、立場によって見えかたが変わります。仕入れをする立場からすると商品には、仕入れ単価があり、服であればサイズ、アウターなのかインナーなのかなどの種類や、色など様々な情報を扱います。
一方で、購入後、商品の配送をする立場からするとそれが、どのサイズで何色なのかなどは持たなくて良い情報だったりします。それぞれの立場で境界づけられたコンテキストを見つけます。
- 注文コンテキスト(注文の受付・キャンセル)
- 在庫コンテキスト(在庫数の管理)
- カタログコンテキスト(商品情報)
- 配送コンテキスト(配送手配・追跡)
- 決済コンテキスト(外部決済サービスとの連携)
- ポイント付与コンテキスト(ポイント管理)
これらを並べて、関係性を見極めていく必要があります。
例えば、ECサイトの動作を思い浮かべると注文を受けた時点では、配送はすぐにされないですよね。
注文を受けたら在庫を確保して決済処理をするなど、「商品を購入する」というユースケース(行動)に対して、依存関係が強いもの、弱いものを整理して境界づけていくんですね。
「商品を購入する」というユースケース(行動)で発生する処理を密結合にしてしまうと、決済後にユーザーにポイントを付与する処理で問題が発生した場合、ロールバックやリトライをする場合、決済等もやり直すことになってしまうといった事態になりかねないです。コンテキストを分けることでポイントを付与する処理はキューイングさせて別処理させることで疎結合にすることも可能となります。これが戦略的設計です。

一方で、エンティティや値オブジェクトはドメイン駆動設計の中での戦術的設計に含まれる設計アプローチです。
「値オブジェクト」というのは同一性を持たなくて良いオブジェクトです。
そもそも同一性という概念ですが、時間を経て変化があっても同じことを保証する必要があるものを指します。
例えば人間だと、年齢は変わるし髪型も変わるし職業も変わるし性別も変わるかもしれない。
でも、その人は数年後、容姿が変わっていても同じ人なんですね。
または、銀行システムで1万円を引き出して、後日1万円を預け入れをした際に、預金残高は変わらず1万円ですが、引き出して預けたという事象は履歴として追跡可能な状態にしなければいけないです。それはエンティティとなります。
こういった連続性のあるものはエンティティと区分けし、逆に連続性のないものプリミティブ型に位置するもの、「金額」といったそれ単体で意味が通るものは値オブジェクトとして分類するようにします。
値オブジェクトはただの値とは異なり、ルールやパターンが存在するものを指します。
上記ので例えると金額オブジェクトには金額と通貨単位(円やUSドル等)が必ず含まれている。や金額はマイナスにならないことなど、ただの「数値」ではなくルールで制限がかけられるものは「値オブジェクト」として分類します。
そうすることでシステム的にはバリデーションとしての機能を持たせることも出来るし、コーディングミス等の引数間違いによるビルドエラーを起こさせることで型安全な設計が可能となる訳です。

こういったお客様の業務を分析してコードに落とし込む際の分析の部分については、AIだけの力では難しいと思っています。
AIはドメイン駆動設計・クリーンアーキテクチャを理解している
AI自身は勉強熱心でドメイン駆動設計・クリーンアーキテクチャを理解しています。
(私なんかよりよっぽど詳しい… 悔しい)
なので、AI駆動でプログラム開発時にドメインモデルについて情報を与えることで、適切にコーディングをしてもらえると思っています。「クリーンアーキテクチャ」という設計アプローチが指定されていることで、AIはソフトウェアアーキテクチャを考慮し適切な変更を加えてくれます。
逆に、設計アプローチに関する情報を与えないと破壊的な変更をバリバリ行う可能性もあるのかなとも思います。
AIも人間も同じで設計アプローチに軸があることで、適切にシステムを拡張していけると思いました。
そしてその軸は身内が作ったニッチなルールではなく、世の中の著名なエンジニアが提唱したものに従うことで、AIも人間も同じ軸の上でシステム開発できるとも思いました。
まとめ
プログラム開発をする際に「DDD、クリーンアーキで作って」とAIに投げれば、それらしい構造のプログラムにはなりますが、境界づけられたコンテキストの分析や、業務への深い理解をしていくのは人間が行っていく必要があると感じました。
クリーンアーキテクチャは、依存性逆転の原則(DIP)など、ソースコードを見たときに設計原則の神髄を理解していないと直感的に見づらかったり、開発時のコーディング量が増えオーバーエンジニアリングという意見も実際にあります。しかしコーディング量が増える部分についてはAIを使えば、苦労が減っているかと思います。
プログラム開発、拡張を品質高く行うためにドメイン駆動設計、クリーンアーキテクチャは必要です。
更にはソフトウェアアーキテクチャは人間とAIの開発コラボレーションの鍵となっているとも感じました。
最後に筆者が本記事でお伝えしたかったことを一言にてまとめさせていただき結びの言葉とさせていただきます。
ドメイン駆動設計、クリーンアーキテクチャはシステム開発において人間とAIを繋ぐ
ハーネスエンジニアリングを取り組むきっかけになれば幸いです。
最後まで見てくださり誠にありがとうございました。良いDDDライフをお過ごしください。







