DDDの読書記録(第3章、モデルと実装を結びつける)

DDDの第3章では、モデルと実装との結びつきについて書かれていますが、この章はこの本の中でも私のもっともお気に入りの内容が書かれている章の一つです。従来、モデルやモデル駆動というと、コーディングとは対極にあるもの、アジャイルの思想と相容れないものというという考えもありましたが、DDDではプログラマーによるコーディング作業をモデリングの最重要の活動の一つと考えていることがこの章にはっきりと記述されています。
コーディング作業と設計の強い結びつきの必要性については以前から自分自身の体験を通して漠然と感じてきたことですし、そのことについては、プログラミングと設計は本来切り離せないものなのでは - 達人プログラマーを目指してでも書いた通りです。このエントリーは今のところ私のブログで最高のブクマ数をいただいたエントリーとなっているのですが、プログラミングと設計との結びつきについては実際に(賛否両論を含めて)多くの人が関心を持っている内容なのだと思います。
実際、デスマーチや大規模障害、開発プロジェクト中断など、SI業界における悲劇の多くは、上流、下流というITゼネコンの構造と結びついた業界構造によってもたらされているということは、もやは疑いようも無い事実です。この悪しき構造により、プログラミングという本来最もスキルと創造性を発揮される作業が苦労のわりにつまらない単純作業とされてしまい(SI業界(日本)のJavaプログラマーにはオブジェクト指向より忍耐力が求められている? - 達人プログラマーを目指して)、その非効率で低い生産性から、業界の技術者全員のQOLを押し下げる原因となっていると考えられます。そして、もちろん最終的にもっとも大きな損害をこうむっているのは低い品質のシステムと必要以上の高い保守費用を払わされているユーザー企業の側です。
とにかく、DDDの本には単にプログラムの設計技法という範疇を超えた重要なアイデアがパターンとして書かれており、こうした状況下に置かれているわれわれにとってはまさに福音となる書物だと思います。この本の翻訳書の出版が、開発の実務担当者のみならず、マネージメント層の方を含めて、現状のSI業界の問題を建設的な方向に向かって見直すきっかけとなってほしいと思います。

第3章とびら(エヴァンス氏が経験した2種類の失敗プロジェクトのエピソード、P43)

第3章の最初の部分では、エヴァンス氏が体験してきた対照的な2つの失敗例について記述されています。まず、最初の例では、実装と切り離された上流モデリングの世界でひたすら分析を行う分析中毒アンチパターンを採用したプロジェクトの例について書かれています。

部屋に入った時にまず目に入ったのは、すべてが書き込まれたクラス図だった。このクラス図は大量の紙に印刷されて、巨大な壁を覆っていた。これは私にとってプロジェクト参加初日のことだったが、このプロジェクトではすでに頭の切れる人々が何ヶ月もの時間を費やして、ドメインについての詳細なモデルを慎重に調査し、開発していた。

しかし、結局この複雑なモデルは実装の段階ではほとんど役に立たなかったとのオチです。

アプリケーションの実装を始めてすぐに、開発者たちはあることに気づいた。関連がもつれているせいで、人間のアナリストなら辿ることができても登録や検索のできる単位に変換してトランザクションの整合性を保ちつつ操作することはできなかったのだ。

そのプロジェクトには、ドメインモデルがあった。しかし、動作するソフトウェアの開発を直接支援しないなら、紙に書かれたモデルが何の役に立つといういうのだろう?

私自身は経験がありませんが、日本の大企業や官公庁向けの何千人月規模の大規模プロジェクトだと、数ヶ月はおろか、数年にもわたってひたすら標準化や業務分析を行っているといった話も同僚から聞いたことがあります。特に、上流、下流という役割が明確に分断された日本の業界では、このようなアンチパターンに陥る例が実際多いと思われます。
一方、まったくドメインモデリングを行わないという逆の極端な例についても記述されています。

そのプロジェクトは既存のC++アプリケーションをJavaで実装される新しい設計に置き換えるというものだった。旧アプリケーションは間に合わせで作成されていて、オブジェクトモデリングは一切考慮されていなかった。旧アプリケーションの設計は、仮に設計と呼べるものがあったとしても、次から次へと機能を融合させて既存のコードの上に積み重ねてきたものだったため、注目に値する一般化も抽象化もなかった。

こうした設計も実際によく目にするものですね。上記のとおりレガシーマイグレーションのプロジェクトはもちろん、納期を極端に削ってアジャイルもどきのプロセスで開発したWeb系のシステムなど、さまざまな事例が考えられます。もっと言えば、現状、どちらかのアンチパターンのいずれかに当てはまるプロジェクトがこの業界ではほとんどなのではないかとさえ思われるくらいです。
実際エヴァンス氏が経験してきた以上のような失敗例、つまり、過剰な設計(オーバーエンジニアリング)や、まったく設計なし(アンダーエンジニアリング)の失敗は、日本だけでなく海外でも昔はごく普通にあったのだと思います。しかし、海外と日本の業界との違いはこうした失敗事例から学び、新しいやり方の採用につなげていくことができたかどうかという点にあるのではないかと思います。DDDの翻訳は原著から8年もたってしまい、その間に大きな差を広げられてしまっているという事実はありますが、今からでも、できるところから改善につなげていくべきではないでしょうか。

モデル駆動設計(MODEL-DRIVEN DESIGN、P45)

45ページからモデル駆動設計パターンについて説明されています。要約すれば、概念的なドメインのモデルは重要だが、それは実装の詳細と切り離されたものではいけないという主張です。分析中毒に陥る先の失敗例のように、実装と切り離された状態で分析を行ったため、プログラムを作成する上で必要になる重要な要素がモデルから抜け落ちてしまうだけでなく、無関係なところが無意味に複雑化されてしまうといったことに陥りがちです。それゆえ、

ソフトウェアシステムの一部を設計する際には、紐づけが明らかになるように、ドメインモデルを文字通りの意味で忠実に反映させること。モデルについて再検討し、より自然にソフトウェアに実装されるように修正すること。これは、ドメインに対するより深い洞察を反映させようとする時にも言える。強固なユビキタス言語を支えることに加えて、ドメインと実装両方の目的に使える単一のモデルを要求すること。
・・・

この考え方は、通常行われているように概念レベルのモデリングを時間をかけて上流工程で行ったけれど、実装コードはがんじがらめの規約で縛り付けて、ロジックをすべてexecute()内部に書けといった通常のSIの開発手法とは真逆の考え方*1であることに注意してください。DDDのモデル駆動設計においては、ドメインモデルがプログラムコードの設計と相互に影響を及ぼしあうということが要求されているのです。

モデリングパラダイムとツールによるサポート(P48)

そして、モデル駆動設計を成功させるためには、その考え方をサポートするモデリングパラダイムやツールのサポートが必要であると書かれています。そして、はっきりと手続き指向のパラダイムを否定し、オブジェクト指向のアプローチを採用すべきと主張しています。*2

オブジェクト指向プログラミングが強力なのは、あるモデリングパラダイムに基づいていて、モデルを構成する概念に実装を提供するからだ。
・・・
しかし、オブジェクト指向設計の真のブレークスルーが訪れるのは、コードがモデルにある概念を表現したときなのだ。Javaや他の多くのツールを使うことで、オブジェクトやそれらの関連性を作成する際に、概念的なオブジェクトモデルと直接的に類似したものにできる。

モデル駆動設計も、Cなどの言語を使った場合には、限定的にしか適用できないが、これは純粋な手続き型言語と対応するモデリングパラダイムがないからだ。こうした言語が手続き型とされるのは、プログラマがコンピュータに対して従うべき、一連のステップを指示することによる。プログラマドメインの概念について考えていたとしても、プログラム自体は、データに対して行われる一連の技術的な操作でしかないのだ。操作による結果は役に立つかもしれないが、プログラムの意味のほとんどをとらえ損ねている。
・・・
結果として、手続き型言語で書かれたソフトウェアにある入り組んだ関数は、想定される実行パスに基づいてつなぎ合わされるだけで、ドメインモデルにおける概念的なつながりを反映することがないのだ。

オブジェクト指向設計は、現在、大掛かりなプロジェクトの多くで採用されているパラダイムであり、本書でも主にこのアプローチを採用する。

例3.1では、PCB設計ツールの手続き的なスクリプトオブジェクト指向のモデルで設計しなおす例について書かれています。この例だけ表面的に読むと、単にエヴァンス氏がOO厨なだけであり、別に手続き型でも何の問題もないように思われてしまう人もいるかもしれません。しかし、重要なことは、バスという重要な概念を明示的にプログラムの設計に取り入れたことでドメインの知識がプログラムの設計に反映されたということがポイントです。そうすることで、多数の同様なプログラムの処理がまとまったり、単体テストや機能拡張が容易になったりしたという点を見落とさないようにすべきかと思います。

骨格を見せる:なぜモデルがユーザにとって重要なのか?(P55)

通常の複雑なソフトウェアはレイヤ化されていて、エンドユーザーは画面などを通してプログラムを操作するため、結局ユーザーにとってはプログラムレベルの設計は関係ないという反論もあるかもしれません。このセクションではIEのお気に入りの実装の例により、プログラムの心臓部であるドメインのモデルがユーザーとプログラマーとの間で共有できていることの重要性を説明しています。つまり、プログラマーの実装都合で勝手にドメインモデルを構築してしまうと、ユーザーにとってよいソフトになるとは限らないということでしょうか。

実践的モデラ(HANDS ON MODELERS、P57)

製造業はソフトウェア開発を表すのによく使われるたとえだ。このメタファから推測できるのは、次のようなことである。すなわち、高度なスキルを持つ技術者が設計し、それほどスキルのない労働者が製品を組み立てる。このメタファは数多くのプロジェクトを台無しにしてきたが、理由は1つ、単純なことである。すなわち、ソフトウェア開発は、すべてが設計なのだ。どんなチームでも、メンバに対して専門の役割が与えられるものだが、分析、モデリング、設計、プログラミングのように責任を過剰に分離することは、モデル駆動設計の妨げになる。

なるほど、という感じです。(もちろん、実際の製造業のライン工のスキルが不要ということは必ずしも正しくない理解であると思いますが。)以前に原書を読んでいたということもあり、この考え方が私の頭の潜在意識に深く浸透していたのだと思いますが、プログラミングと設計は本来切り離せないものなのでは - 達人プログラマーを目指してで書いたことはまさにこのパターンの説明に書かれていることと同じでした。そして、エヴァンス氏も私が感じたのと同じような境遇で仕事をしたエピソードを語っています。このセクションに書かれている内容に、あらためて、心から共感してしまいました。

あるプロジェクトにおいて、私は、いろいろなアプリケーションチームを調整して、設計を推進するドメインモデルの開発を助けるという仕事を任された。しかし、経営陣の考えでは、モデラはモデリングを行うべきで、コーディングはそうしたスキルの無駄遣いとされたため、私がプログラミングしたり、プログラマと詳細を検討したりすることは、事実上許されなかった。

エヴァンス氏もいろいろ苦労されてきたのですね。このセクションで説明されていますが、結局モデラーがコードから切り離された環境でモデルを作っても、それが最終的に実装レベルで役に立つようなモデルを作成することは困難ということですね。しかも、実装がモデルと切り離されることで、後々モデルを発展させることもできなくなってしまいます。それゆえ、

モデルに貢献する技術的な人はだれでも、一定の時間をコードに触れることに費やさなければならない。プロジェクトで主に果たしている役割が何であれ、そうしなければならないのだ。コードの変更に対して責任を負う人はだれでも、コードを通してモデルを表現することを習得しなければならない。すべての開発者は、モデルに関する議論にいずれかの段階で参加して、ドメインエキスパートと話をしなければならない。その他の方法で寄与する人々は、ユビキタス言語を通してモデルに対する考え方をダイナミックに交換する際に、コードに触れる人々を意識して巻き込まなければならない。

個人的にはこのパターンはDDDを行う上での前提条件を提示する最も大切なパターンの一つではないかと考えています。レポジトリやエンティティなど、後から様々な設計のパターンが出てくるのですが、結局、設計者がプログラムを理解しないという前提であれば、DDDが本来目指すモデル駆動設計や、ドメインエキスパートとプログラマーとの間での単一のモデルの共有と言ったことは決して不可能だと思います。
結局、このパターンは言い換えれば、設計者はプログラマーでなくてはならない、また、逆にプログラマードメインのモデルを意識してプログラムを作成しなくてはならないということになります。少なくとも、ゼネコン構造により上流、下流と分断されているようなやり方では、決してDDDが目指すような深いモデルに到達することはできないということです。
この点について、予測される反論は、そのような奇麗なモデルというのはDDDを信奉するプログラマーの自己満足に過ぎないのではないか、DDDが目標になっているだけなのではないかというものです。しかし、本書を最後まで読み進めていけばわかるように、この本の主張は一貫して業務側と技術側双方にメリットのある実践的なモデルの作成というところにあるのですし、実際、すでに海外では多くの実績がある(原書が出版されて8年たった今でも有用性が薄れていない)という事実に支えられたものなのであるという点を忘れてはならないと思います。

*1:侵略的なフレームワーク - 達人プログラマーを目指して

*2:ただし、Prologによるルールの推論モデルについてはモデルとして有用な可能性があるとしている。