Eric Evans氏のDDD本は、サブタイトルが、「ソフトウェアの核心にある複雑さに立ち向かう」となっています。複雑さとは何か、それを管理する技術とは何か、古くて新しい問題です。Jim Coplien氏の著作「マルチパラダイムデザイン」では、ドメインとは何か、どのように設計を行うべきかについて書かれています(残念ながら絶版です。)
後半のセッションでは、「What the system is(共通性や可変性を分析する)」を説明しつつも、「What the system does」とは別のものとして切り分けることはできないという主張から、 DDD とリーンアーキテクチャとの比較、そしてパターンに関する議論が展開されました。 @remore が前半部分をまとめてくださっていまして、そこで出て来るいくつかの用語(Form, Structure, What the system is, What the system does)を前提として私のできる範囲で行いました。
しかし、What system is と What system does は別々に考えられるものではない。それは、構造と時間やアルゴリズムを全く別のものとして、分けることは不可能だからである。
リーンアーキテクチャ本では、 What system is も What system does も説明しており、夫婦で共著で書いている。
リーンアーキテクチャ本では分けることができると書いたが、実際は簡単に構造とユースケースを分けることができるわけではない。
それは、歴史が物語っている。
1960年から1970年では、ノイマンコンピュータでは、データ構造は全く注目せずに、 What system does に注力され、 CPU が大事でこの性能を良くするということが重要だった。
1970年後半にデータベースが登場し、ボトルネックはデータへのアクセス速度が重要となった。CPU のことは忘れ去れられ、What system is が注意の関心の的になり、データモデルが重要になった。
1980年にコンピューターネットワーキングが登場し、オブジェクト同士のコミュニケーションが重要になった。こちらは What system does がまた注目された。
このように、歴史を見ると、 What system is と What system does のサイクルができている。
アーキテクチャ全般に言えることだが、例えば部屋の構造では、どこにライトがあって、どこドアがあって、それが何か(What system is)を説明することができるが、どうしてそこにある(What system does)のか、とか、部屋の中をどうやって歩くかなどのプロセスにも影響している。つまり、これらは簡単に分けることはできずに互いに関係しあっている。
共通性と可変性は対称性を持っているが、あるとき対称性が壊れることがある。プログラム言語では対称性を表そうとするが、実際の要件では、対称性のない複雑なものを作り上げる必要がある。リーンアーキテクチャは対称性を扱っており、負の可変性(Negative Variation)は扱っていない。ここが複雑な場所である。パターンは、What system is と what system does の両方を考える必要があり、また、空間と時間を考える必要がある。
パターンに関する議論に関しては、私(ganchiku)の中で消化しきれていない場所があり、まとめることができませんでしたので、今後の課題としてアレグザンダーや Jim Coplien さんの議論を追いかけて、自分の言葉で説明できるようになっていこうと思います。
会場を提供していただいた UUUM 株式会社、また、オーガナイズしていただきました DCI Tokyo メンバーの皆様ありがとうございました。
具体的な例を用いて検討しましょう。バージョン管理システム(Version Control System: VCS)です。現在私たちは束にできるほどたくさんのVCSを持っていて、そのいずれもが他といくらか異なるモデルを提供しています。例えば、Subversionでは「コミット」は中央の(かつ単独の)リポジトリへのソースコードの変更の登録を意味するのに対して、Gitでは同じ言葉が分散された一群のリポジトリの特定のメンバーへのソースコードの変更の登録を意味します。「コミット」はそれぞれのVCSのユビキタス言語の語彙に含まれます。そして、そうであるなら、この語の意味のこうした違いは、その2つのVCSの基礎を成すドメインモデルの違いを反映しているのに他ならないでしょう。
当時は C++ の他に、テレコム業界向け言語である CHILL や、軍需産業向け言語である Ada などの言語があり、それらの言語がオブジェクト指向なのかという議論がされていました。
最終的に C++ が残ることになりますが、C++ の作者である Stroustrup 氏は、そもそも C++ をオブジェクト指向言語ではなく、マルチパラダイム言語と定義していたことに注意する必要があります。
当時考えられていたオブジェクト指向の構成要素は次の3項目でした。
inheritance / 継承
polymorphism / ポリモーフィズム
instantiation / インスタンス化
1994年に Coplien さんは David Weiss 氏と Robert Chi Tao Lai 氏とともに仕事をしますが、その時、共通性/可変性分析を通じて、ソフトウェアファミリの振る舞いなどを特徴づけ、当時取り組んでいたソフトウェアのための DSL(Domain Specific Language) を開発しました。開発言語は C でした。
Domain-Driven Design (DDD) intersects with a broad range of the intellectual heritage in the software design discipline including object-orientation, design patterns and refactoring. And as such, it can be viewed as a synthesis of these knowledge assets tailored towards domain-oriented application software development.
Although this view is valid and productive, there could be another way of viewing accomplishment of DDD. It is the theme of this short discussion.
In this context, DDD could be thought as a quiet departure from “software design” to something we may call “information design” with a special emotional attachment.
What is a Domain Model?
But first thing first. We must have a rethink on one basic question. What is a domain model?
It sounds ridiculous. A domain model is a model of a domain. Isn’t it?
Let us discuss about this on a concrete example: version control systems (VCSs). We now have a bunch of VCSs, each of which offers a somewhat different model than another. For instance, with Subversion, “commit” means a registration of source code changes to the central (and solitary) repository, whereas, with Git, the same word means a registration of source code changes to a particular member of a set of distributed repositories. “Commit” is in the vocabulary of ubiquitous language of each VCS. And if so, this difference in the meaning should be the reflection of a difference of the underlying domain models of the two VCSs.
From this example, we can see that the difference between these two models comes from the difference in approach to solve problems in the same domain. A domain model is not a model of a domain itself. Instead, it actually is a model of a solution for the domain. It was not before each VCS was given birth that each model was recognized.
This idea is quite simple and straightforward. Let us take spreadsheet software as another example. They share a unique domain model consisting of sheets, cells, formula and so on. This domain model did not exist before the birth of VisiCalc and evolved after that. Although we may use spreadsheets for our accounting calculation, it is not that accounting domain had the spreadsheet concept in its history, but the concept and model were engineered to solve problems in a broad domain, which incidentally includes a part of accounting.
Two Domain Models
Traditionally, domain models tend to be seen as “analysis models”, which are subjects of analysis, not design. However, our new vision that a domain model is a model of a solution challenges this view. A solution is something we design, even if we analyze designs of the existing solutions from time to time.
“Analysis” is rather a passive word in that it treats things which already exist, while a design creates something that did not exist before. In traditional OO approaches, an analysis model tend to be viewed as an abstraction of the real world, which already exists and naturally is not a subject of design, while a design governs the functionalities and the structures of software we (as engineers) build. From the engineering perspective, this separation looks very natural.
The point here is that from a domain-driven designer’s perspective, a “real world” would consist of two subcomponents - physical and informational.
In the physical world, people work, things move, and money is earned. They are what we imagine by the word “business”. To let businesses move on, we record and exchange information - orders, invoices, inventory records, financial statements, and so on. This is another component of the real world - information processing.
Accordingly, a domain model is divided into two distinct models: physical world models and informational models.
With such a world view, we would consider the physical world models as usually just given and uncontrollable for us, while we can design most parts of the informational models.
Two Domain Models and OOA
In his DDD book, Evans repeatedly speaks about initial superficial models and deep models. In his example from a container shipping application, the superficial model contains physical entities like Ships and Containers, while the deep model contains such abstract concepts as Vessel Voyages and Bills of Lading (e.g. p.189 “Deep Models”). The distinction between these models is at least partially not of the “depth” but of the “subject” of each model - physical and informational.
Evans tells a story which is suggestive on how traditional OOA ignores this distinction:
Whenever new object modelers showed up on the project, what was their first suggestion? The missing classes: ship and container. They were smart people. They just hadn’t gone through the processes of discovery. (p.190)
With the idea of two domain models, we understand this would not have been only because “they just hadn’t gone through the processes of discovery”, but also because the body of knowledge of OOA (or at least its generally accepted understanding) has lacked the distinction of physical world models and informational models.
However, this ignorance is not surprising, because the distinction between the two models is not always apparent. It is because information has infiltrated into every corner of our world and passes as if they were physical. Are bank checks physical or informational? How do we distinguish them from truly physical objects? Or, do we have to do so at all? I have no definitive answer here. In many cases you can safely omit checks from your informational models (as if they were physical), while you might have to include “cash in hand” in your models (which refers to bank bills, coins, and checks, collectively) instead. But it is not a dogma. We have to use our judgment. Nevertheless, drawing a line between physical and informational models could still bring insights in modeling, because in the end what we have to represent with our software are informational models, not physical business models.
An Implication of DDD
Ubiquitous language and model-driven design are two practices at the heart of DDD. In the light of two domain models, ubiquitous language could be understood as a device to separate an informational model from a physical world model and make it subject of design, not analysis. It extends the realm of us, developers. And model-driven design urges us to keep software structure to be exact reflection of the informational model. It prevents our profession from dissolving into analysts and developers.
Thus, design of informational models is in our hands. Informational models had been designed even before our information technology age. Double-entry book-keeping system is a remarkable instance of those models. Train operation diagrams and music scores are other examples. These models had been designed by people on the “business-side” (because there was no IT-side). By contrast, the responsibility to design informational models seems to be floating in our IT age. Our IT has been too awkward for business people. Therefore they often have felt uncomfortable designing informational models which are to be implemented with IT. Analysts might be the people in charge. But they analyze, do not design. Furthermore, it is difficult to design if you are disconnected from feedbacks that implementation would provide (this is also what model-driven design cares). We, developers are in the best position to accept this responsibility, off course with a tight cooperation with business-side people.
Now an essential act of our profession is the information design underpinned by the software design.
This is what DDD implies.
ここで言うフレームワークは一般的に知られる、SymfonyやRuby on RailsのようなWebアプリケーションフレームワークだけではなく(もちろん、それらもある特定のドメインを対象としたフレームワークです)、様々な問題領域のドメインに対して適用されるフレームワークのことを指しているのだと思います。
それらのフレームワーク開発を通してドメインについて日常的に考え指向することで、プログラマー自身が設計者となって、実装の中でドメインモデルを洗練させていくモデラーとなるというのが久保さんから一番大きく受け取ったメッセージです。最後の「Code the Domain! You are a Domain Coder!」、ドメインをコードにせよ、あなたがドメインコーダーなのだという言葉は、ドメイン駆動設計を超えて、さらにマルチパラダイムデザインを超えて、その先にあるものとしてとても希望の持てるものだと思いました。
ドメインレイヤーはピュアに保つ。これがドメイン駆動設計における基本ポリシーです。しかし、外部とのやり取りを責務として持つオブジェクトについては、根本的に外部への依存を無くすことはできません。次の図のように、何らかのORMコンポーネントを利用した実装になるのは必然で、つまり依存が持ち込まれます。例えばSymfony Standard Editionの構成であれば、ORMコンポーネントにDoctrineが使われます。リポジトリは、Doctrineの提供するリポジトリ用の基底クラスであるEntityRepositoryを継承した実装になります。ドメインレイヤーの実装をドメインパッケージ、ORMはORMパッケージとしてまとめられていることを想定しています。