読者です 読者をやめる 読者になる 読者になる

アラタナエンジニアブログ

aratana Engineer's Blog

エリック・エヴァンスのドメイン駆動設計を1週間で読んでみた


はじめに

こんにちは、2015年9月に入社し、開発チームに加わった田中翔太です。
今回は、ドメイン駆動設計(Domain-Driven Design)、略してDDDについての本を読んでみたので、
そのまとめと感想を徒然なるままに書き留めたいと思います。


まず、私が読んだ本の紹介をします。
エリック・エヴァンスのドメイン駆動設計」(2011年4月8日 初版第1版発行 翔泳社)です。


私が配属されたECテクノロジー事業本部では、
DDDを用いた設計手法でScalaを使用したECサイトの構築を行っています。
既にコードをバリバリ書いてる先輩方も、
開発に入る前に1週間で読破(1日100ページ超のペース)されています。
もちろん、1度読んだだけでは理解度は薄いですが、
読みきった事で自信が付き、この本を辞書的に使えれば(どこに何が書いてあるか分かれば)、
迷った時にサッと読み込む事ができます。


本を手に取ってみての感想としては. . .
分厚い!という印象でした。
ですが、概念を学習するにはこれだけのボリュームが必要なのだなと感じました。


さて、本題へ移っていきたいと思います。

そもそも、ソフトウェアを作成するにあたって大事なことがあります。
ソフトウェアの対象となる業務内容の理解と、その課題解決についてです。
課題解決をする為に色々な知識やコミュニケーションが必要になりますが、
その手助けをする方法が書かれています。


その中でも注目したいのが、”モデル”なんです!!!
このモデルというのは、とてもシンプルなもので、
知識の表現形式の1つです。
例えば、知識や概念など形がないもの等を説明する時、
理解度を深める為にホワイトボードに図を書いて説明する事があると思います。

そのようにモデルで表現すると、
ドメインエキスパート(業務を熟知している人=お客様、利用者)と開発者との間で
共通の認識を持つ為の手助けとなり、
プログラミングに落とし込みやすくなります。


この本の概要をざっと説明すると、
ソフトウェアシステム設計で、ユビキタス言語を用いた設計とドメインおよびドメインロジックに
焦点を当てることが重要であるということです。
そのために、以下の3つのモデルの基本的用法により、
システム設計にどのように関わってくるかが重要となります。


1. モデルと設計の核心が相互に形成し合う
2. チームメンバー全員の基盤を整える
3. 蒸留された知識である


それでは、この3つについて詳しく見ていきたいと思います。


1.モデルと設計の核心が相互に形成し合う

ソフトウェアを書き始める時、ドメインエキスパートの業務(ドメイン)がこうだから、
こういう機能が必要なんだなという理解が必要だと思います。
そこで、理解を深めるためには、何回もコミュニケーションを行い、
ユビキタス言語をブラッシュアップして、よりよいモデルを作って、
やっと”知識のかみ砕き”ができると思います。


ここまでに、ユビキタス言語というものが出てきましたが、これは何ぞやと思われるでしょう。
ユビキタス言語とは、システムを開発する際のプロジェクト内での共通言語みたいなものです。
DDDでは実際にどのように関わってくるのかを図にしてみました。

f:id:tanaka_shota:20150915165539j:plain

図を見てみると、従来の手法ではドメインモデルはドメインエキスパートの頭の中にあって、
それを開発者に伝えて実装という流れをイメージしてます。
お客様はお客様の言葉を、開発者は開発者の言葉を使ってコミュニケーションします。

しかし、この手法だと言葉の意味が置かれている立場によって勝手に解釈され、
ズレて伝わるなどの問題が発生しそうですよね?
特に大規模案件になってくると、長期化する上に関係者が増える為、
落としこまれる各種ドキュメントなどにも表現に揺れが出やすくなります。
DDDでは、プロジェクト内でユビキタス言語(共通言語を載せた辞書みたいなものとして図を描いてみました)
を使用してコミュニケーションすることで、共通の認識が生まれると考えられます。
これだけでみると当たり前のようなことを言っていますが、
従来のようにお客様はお客様の言葉、開発者は開発者の言葉を使ってコミュニケーションとることと、
ユビキタス言語でコミュニケーションを前提とするのとでは後々大きな違いが出てくると思います。


ここで、モデルと設計の核心が相互に形成し合うとはどのようなことかと言うと、
開発者が実装する時に当然モデルとコードは親密な関係にあって、
双方に「同じ程度の影響」を与えることが考えられます。
ドメインモデルが大きく変わらないならばコードも小さな変更で済むはずです。

逆にドメインモデルに紐付いていない場合はどういうことが起きやすいでしょうか。
例えば、業務の成長に合わせてシステム側の拡張を長期間に渡って続けていた案件があったとして、
ある時業務面からみると小さい改修だとおもって要望出された内容が
システム的には大きな変更を伴うものになっていた、というのはよくある話です。
これは、システムがドメインモデルに紐付いておらず、
パッケージ、フレームワーク、データベースの構造などの都合に紐付いている為だと思います。
その場合、その状況を説明して費用や日程の説明するのは非常に難しくなりますし、
リファクタの提案をしようものなら、初めから考慮してつくってくれていれば、という話になり兼ねません。


2.チームメンバー全員の基盤を整える

チームで開発するにあたり、整えたい点が2つあります。

ユビキタス言語
ドメインモデルの表現方法

ユビキタス言語が定義されると何が嬉しいかというと、システムの整合性がとれ、信頼できるシステムの開発につながります。
モデルをリファクタリングする際に、用語が混同したら認識を合わせることを忘れてはいけません。
また、モデルは図だけではないということに注意しなければなりません。

また、レイヤードアーキテクチャによりドメイン層を分離してはじめて、モデル駆動開発が可能となります。
各レイヤと役割を以下の表に示します。

レイヤ 役割
ユーザインターフェース層 ユーザに情報を表示し、ユーザの入力を認識
アプリケーション層 ドメイン層のオブジェクトを協調させ、作業の調整を行う
ドメイン ロジックの表現
インフラ層 上位レイヤを支える


実際のドメイン層がどのような構造になるかの概要(コンテキストマップ)を図に示します。

f:id:tanaka_shota:20150915165529j:plain


コンテキストマップの中には、システムの機能別に集めた括りとして"context"が存在します。
そのcontext内には正確に定義されたインターフェースであるmoduleがあります。
module間は低結合であり、module内は高凝集である必要があります。
高凝集になると機能の純粋度があがり、一貫性の取れた機能を実現できます。
moduleは、いくつかのentityとvalueObjectを持ちますが、変数のスコープに注意する必要があり、
DB(データベース)にアクセスできるのはAggregateRootとなるentityのみとなるので、
module内のvalueObjectにアクセスしたい場合は、AggregateRootを参照しなければなりません。
entityとvalueObjectの定義には、区別できるかできないかという違いを使用します。
また、aggregate(集約)とは、関連するオブジェクトの集まりでありデータを変更するための単位として扱われます。
ここで、ドメインモデルとはどこを指すのかというと、aggegate内のすべてのことを表現しています。
また、serviceとは、モデルにおいて独立したインターフェースとして提供される操作のことで、状態(stateless)を持ちません。

このような、コンテキストの決まりがあるため、プロジェクトの基盤となることができます。


3.蒸留された知識である

モデルはシンプルかつ知識を蒸留したものである必要があります。
蒸留とは、混ざり合ったコンポーネントを分離するプロセスのことであり、価値があって役立つ形式で本質を抽出するためのものです。
ドメインモデルに対する蒸留の方法として以下の5つを行います。

1.システムの全体的設計と、設計同士がどう関係するのかメンバ全員が把握できるようにする
2.ユビキタス言語に入れやすいサイズのコアモデルを識別し、コミュニケーションを促進する
3.リファクタリングの指針となる
4.モデルで最も価値がある領域に作業を集中させる
5.アウトソーシングと既製のコンポーネントの利用、その割り当てについて決定する際の指針となる

難しい言葉が5つ列挙されましたが、まとめるとモデルを作る時にそのつける名前はその機能を表したユビキタス言語を使用して、
それをメンバで認識しリファクタリングするときもスムーズにこなすことが可能となります。


感想

全体を通しての感想としては、設計と実装の間には強力な関係があるという印象を受けました。
その中で、モデルの作成は一貫性および整合性のとれたシステムを作るにあたってDDDがとても有効であり、
かつオブジェクト指向と関数型で書けるのでscalaはDDDと相性のいい言語であると感じました。

図のコミュニケーションとしてUMLがよく用いられると思いますが、
それに加えユビキタス言語も使用するようになれば、
より意思疎通のできたコミュニケーションがとれると思いました。


正直この1週間は苦痛でした(笑)
しかし、無知の知といいますか、自分が「何を知らないのかを知る」というような意味で
有意義な時間となりました。