yotiky Tech Blog

とあるエンジニアの備忘録

Unityを取り巻くアーキテクチャ 第2部 「DDDのアーキテクチャ」

アーキテクチャは読み手の解釈に委ねられる部分が多かったり、提唱されたあとも進化や変化があったりするので、あくまで現時点でそれぞれどう捉えてるかの覚書と考察を。雑ならくがき、雑がき。

※編集したり更新したりする予定です。

目次

概要

つらつらと書き始めたら思いの外風呂敷が広がってしまったので、「MVxとLayerd Circleについて」、「DDDについて」、「Unityで実装する話」の3部構成くらいに収まるといいなぁと言った所です。
今回の記事は第2部「DDDについて」にあたります。 第1部を読まれていない方は、全体における導入部分もありますのでそちらも読んで頂けると嬉しいです。

DDD

「DDD」は、「Domain Driven Design」。「X Driven "Development"」ではないので注意してほしい。開発プロセスではなく、ドメインを中心に"設計を成熟させる"ための思想、パターン、HowTo。言い換えると「どのように駆動していくと設計が成熟するか」の方法論。アーキテクチャの構成、つまり『アプリケーションの静的側面を図式化して説明する』だけの話ではない。

「DDD」は、2003年にEric Evansが『Domain-driven design』という書籍で提唱した。その後、2013年にVaughn Vernonが『Implementing Domain-Driven Design』という書籍で「DDD」を解説している。前者を「DDD」や「原典」、後者を「IDDD」などと呼ぶ。
アーキテクチャについては、この2つは異なるアーキテクチャを持ち出しているらしい。ここからは原典のお話し。

Domain

ドメイン」とはなんぞや、これがとても分かりづらく厄介。
アプリケーションが対象とする業務領域、業務の関心事なんて言われるが、それって一体何って話。

一部の業務アプリケーションを例に取ると少し想像しやすいと思う。会計なら"会計"を成す一連の処理。
"どこから入力"されようが、入力されたものが正しければ会計処理自体には影響がない。また、データが"どこから取得"できて、"どこに保存"されるのかも、会計処理自体には影響がない。さらに、会計処理を"ソフトウェアとして具現化"するために必要な処理もまた会計処理自体とは切り離される。

ソフトウェアであろうがなかろうが、とにかく正しくインプットされ、必要なデータが取れたり、保存されたりされていれば会計処理自体は論理的に動く、つまりそこが「ドメイン」。

この切り口で行くとゲームも同じように、インプットを分離し、データへのアクセスを分離し、スマホだろうが、紙のボードだろうが、机上だろうが、動くロジカルな部分が「ドメイン」となる。インゲーム/アウトゲームなんて分け方もあるが、どちらも関心事には違いないし、アウトゲームを動かさないとインゲームが動かない事もあるのでどちらも「ドメイン」。ログは「ドメイン」から外れるだろうし、認証はゲームを動かす根底には関係ないものの必要な要素、ということで「サブドメイン」なんてロールも用意されてるらしい。

ドメインを駆動する基盤

で、この「ドメイン」にはエキスパートがいる。いなかったりもするが。
特に業務系で、先に上げた会計や金融などは業務への深い知識が必須となる。
(...ゲームを「ドメイン」として設計してる人はいるんだろうか。)

過去に会計パッケージのプロジェクトに携わった事があるが、50代、60代のおじちゃまがExcel方眼紙に「もしXXがOOだったら」といった日本語プログラミングを書いて、若い人がコードに起こすなんてことを経験したこともあり、一朝一夕で「業務領域」を理解するのは難しいなと思わせることもあった。

DDDでは、このエキスパートと、ユーザー、プログラマ、設計、ソースコードに至るまで、アプリケーションを取り巻く環境において「モデル」を共通言語として透過的に「ドメイン」が扱われる。つまりドメインをモデルで表現する。
エキスパートが話す「ドメインモデル」は、ソースコードレベルで同じ表現として実装される。人および設計、さらにコード間で透過的に同じ意味として扱われることで、相互に関係、関心を維持し、設計を成熟の道へ駆動するための礎となる。

「モデル」を共通言語として扱うには、"関心事をモノとして捉え、人に分かりやすいモノとして設計する"オブジェクト指向設計が馴染むのはよく分かる。人同士がイメージして捉えづらいものを共通言語として使用するのは無理がある。

ここまでが導入にあたって、で導入が済んだら漸くアーキテクチャの話。

モデル構成要素(アーキテクチャ

DDDとは別軸に、「モデル」を元に開発を進める技法 MDD(Model Driven Development)というものが存在する。オブジェクト指向UML界隈で、モデリングを中心に据えた開発手法となる。(モデリングを極めるとコードへと自動変換されるという崇高な手法を手に入れられるらしいが。。)

ドメイン駆動は「ドメイン」をすべての中心に置く壮大な思想である。故に実現するための手段すべてがオリジナルで準備されているわけではなく、一段階噛み砕いた先で使えるツールを必要とする。ここで先程のMDD(のうち主に設計手法)をツールとして利用する。前の項でも書いたようにMDDの「モデル」や元となるオブジェクト指向がよく馴染むのだろう。

ドメインを駆動するには、モデルを駆動させるのである。

さて、DDDのアーキテクチャの話に戻る。

世界の中心であるドメイン層を他から分離すると、UI層、アプリケーション層、ドメイン層、インフラ層となる。左から右へ依存関係を持つ。これ自体は単なるレイヤードアーキテクチャだ。
アプリケーション層は、ソフトウェアとして具現化するために必要な処理を受け持つ。UseCaseやFacade的なやつだ。

f:id:yotiky:20181030034913p:plain

ドメイン層に含まれるドメインモデルは「エンティティ」、「値オブジェクト」、「サービス」に分類される。更にこれらを束ねる「モジュール」(パッケージや名前空間)の4つが重要な構成要素となる。
ドメインモデルのオブジェクトはライフサイクルを管理するため、「ファクトリ」や「リポジトリ」が登場する。これらはドメインとして重要な意味は持たないが必要になるであろう機能ということでドメイン層に持つ。
インフラ層は技術的な関心事を集約する。例えばドメイン層に持つ「リポジトリ」はInterfaceのみを持ち、その中身がどこで永続化されようと同じように操作することができるようにし、永続化するための実処理は特定技術(DBなど)に依存するためインフラ層で担当する。
DBを始め、FileI/Oやその他ストレージ、O/Rマッパー、DIコンテナ、メッセージング、Webサービスなどがある。また、UI周りでもレンダリング機能、Toolkit、ウィジェットなんて記述もありこのあたりは具体的なイメージがあまりついていない。

このあたりはレイヤードアーキテクチャを構成、繋ぎ合わせるために必要となるであろう基本要素であり骨子である。これをベースに「モデル」のリファクタリングを重ねて、Deep Modelへと誘う。
が、この先になってくると継続的に改善して成熟させる話になるのでここまでとする。

IDDDに思いを馳せる

一方で、IDDDにおいては Hexagonal Architecture とそれに関係のありそうないくつかの方針を持ち出しているよう。
Hexagonal Architecture 自体は前回の記事にまとめているのでそちらを参照されたし。
DDD自体はアーキテクチャに依存しない方法論としてレイヤードアーキテクチャを例に提唱されはしたものの、「ドメイン」を隔離するにはそれじゃ足りないんじゃねってとこだろうか。

Layered Circleを持ち出すとどうしてもDIに依存せざるを得ない。した方が楽だし、都合がいい。
DDDとDIの関係については、参考サイトより以下の記述が載っていた。1
2008年と古い記事ではあるが、Eric Evansの解釈が含まれる貴重な内容だ。

DDDのフィロソフィとそれを実現するさせることを助ける技術的なツールボックスOOP、DI、そしておそらくAOP)との線引きを明確にすることが重要だ

と強調した上で、

最近になってDIはとても広く行われるテクニックとなり、それを上手く行えばDDD実践者がデザインを改善する手助けになっています。私からみて一番重要なのは、DIがドメインの分離において役立つということです。

としている。DIばんざい!

Clean Architectureの外周にあるFrameworksに、Application基盤となるDIコンテナは含めないのが頭痛を和らげる解釈になるのかな。

参考にさせて頂いたサイト