2014-11-09

"エリック・エヴァンスのドメイン駆動設計" Eric Evans 著

ドメイン駆動設計(Domain-driven design)とは、モデリングパラダイムを中心に据えたソフトウェア設計手法である。おいらはプログラマではないが、あらゆる分野の研究、開発、設計が、効率化とコスト削減のためにデスクトップ上に展開される御時世。プログラミングをまったくやらなくて済むなんて職場を、おいらは知らない。統計モデルの記述には数値演算言語が、電子回路の実装にはハードウェア記述言語が、データベースの管理にはSQLが、Webの構築にはマークアップ言語が、などなど... 古くから、脳をモデリングするための人工知能言語が研究され、新しいところでは、ゲーム開発用のスクリプト言語が登場する。いわゆる、ドメイン固有言語ってやつだ。こうした言語は、各々の分野で本質を見極めようとする動機から生まれ、おかげで、システムのプリミティブな知識を知らずとも、本来の仕事に集中することができる。本書は、コンポーネント群から分離した本質を抽出するプロセスに、「蒸留(distillation)」という語を当てる。モデルとは、蒸留された知識を言うそうな。今宵は、余計な知識を揮発させるために、熟成された蒸留酒をやらずにはいられない...

ソフトウェアの設計は、対象が目に見えないだけに、メタファ的な発想を要求してくる。いわば、概念と実体を結びつける空想力だ。リファクタリングやリポジトリ、あるいはレイヤ化アーキテクチャといった発想は、システムを理解する上で重要な概念となる。こうした思考法は、ソフトウェアに限らず、多くのシステム開発で参考にできるはずだ。現実に、システムを本当に理解している人は、そういるもんじゃない。技術屋の関心事は特定の技術に向けられ、営業屋は顧客の要求がすべてだと考え、お偉いさんは納期や政治的な事ばかりに気を配る。顧客だって提案に反応するだけで、本当に要求するべきものを知っているわけではあるまい。強烈な責任分解が悪しきシステムを生み出し、複雑なシステムほど手に負えなくなるのも道理である。
「大規模な構造を適用すべきなのは、モデルの開発に不自然な制約を強いることなく、システムを大幅に明確化する構造が見つけられた時だ。うまく合わない構造なら、ない方がましなのだから、包括的なものを目指すのではなく、出てきた問題を解決する最小限のものを見つけることが一番だ。"より少ないことは、より豊かなこと(Less is more)"なのだ。」

本書が提供してくれるものは、ソフトウェアの核心にある複雑さを相手取るための思考法である。それは、設計上の意思決定を行うフレームワークと、ドメイン設計について議論するための技術的な語彙であり、語彙の定義こそが要だ!ということを教えてくれる。つまり、顧客から開発者に至るまで対話できる共通ボキャブラリの構築である。なによりも強調していることは、チームをより効果的に導くこと、ビジネスエキスパートとユーザにとって意味ある設計に集中させること、そして、深いモデルとしなやかな設計を目指して試行錯誤の継続が重要だとしている。
ここには、エリックの経験則が綴られる。むかーしから蓄積されてきた愚痴が、つい爆発してしまうのは、それだけ現場の本音を物語っているからであろう。設計者が顧客を説得できないのは、システムのポリシー、ひいては哲学がないからに違いない。もっと言うなら語彙が乏しい。専門に閉じこもればシステムとしてのドメインが見えなくなる、高度な技術に凝り固まればユーザの気持ちが見えなくなる... とは、実に頭の痛い御指摘!こいつは、実践に概念を結びつけるための哲学書である。そして、ドメイン駆動設計には非常に高度な設計スキルを養う機会が溢れていることを教えてくれる。
尚、対象読者には、オブジェクト指向, UML, Javaなどの基本的な知識が必要としているが、プログラミングを趣味ぐらいにしか考えていないアル中ハイマーでも抵抗感がない。もっとも仕事も趣味の延長ぐらいにしか考えていないが...

1. ドメインとユビキタス言語
ところで、ドメインってなんだ?改めて突き付けられると、なかなか手強い用語であることに気づかされる。辞書を引くと、領域、範囲、分野、あるいは、境界や定義域といった意味を見つける。通信業界ではネット―ワックの管理単位とし、ディレクトリサービスでは共有範囲や利用者グループの範囲とする。ソフトウェア工学は仮想的な領域を扱うことが得意なだけに、用語の量や複雑さに圧倒される。活動や関心の範囲を抽象化し、実体を含む領域もあれば、実体を含まない概念だけの領域までも編み出しやがる。モデルは、この重荷と格闘するためのツールであり、シンプルに組み立てられた知識の表現形式である。したがって、ドメインとは、知識が厳密に構成され、効率的に抽象化された定義域とでもしておこうか。
自然言語も、人間のコミュニケーションツールとしてのドメイン固有言語と言えるかもしれない。あらゆる学問で情報交換を効率的に行うために専門用語が編み出されるが、これも同じようなものであろうか。そして、システムは言語である、とでもしておこうか。
それは、技術者に留まらず、ユーザを含めたシステムに携わるすべての連中とコミュニケーションできる手段となるべきもの。本書は「ユビキタス言語」と呼んでいる。ユビキタスとは、チームの至ることころに存在するという意味で使われている。
しかしながら、言語の柔軟性は想像以上に手強い。言語表現は、精神活動の投影でもあるのだから。例えば、「信用」という用語は、経済学のものと心理学のものとでは大きな隔たりがあるし、「客観」という用語は、数学のものと他の学問のものとでは度合いがまったく違う。客観性の強いはずの技術用語ですら微妙なニュアンスの違いを見せる。パッケージ、コンポーネント、インスタンス、エンティティなど、これらの用語は専門によって使い方が違ったり、企業組織や開発グループによっても微妙に解釈が違ったりする。オブジェクト指向を一つとっても捉え方は様々で、美しいモジュール性を励行したり、カプセル化や継承を強調したり、メソッド操作の一貫性を保ったりと。Wikipediaや用語辞典に頼り過ぎると、却って混乱することもある。
チームに浸透する微妙なニュアンスは、実践でしか育まれるものではない。最初の会議で、用語群の定義を大切にするマネージャを見つければ、それだけで信頼に値するだろう。プロジェクトマネージャとは、ある種のシナリオライターだと、おいらは考えている。その一方で、長嶋茂雄ばりの英語まじりで、何を言っているか分からないお偉いさんを見かけるけど...
どんなシステムを設計するにしても、その仕事に適した用語群が形成されるはずだ。言語とは、記号で記述するものだけでなく、構造図、振る舞い図、関連図といった視覚的に訴える手段も含めておこう。言語は、柔軟性こそ味方につけるべきである。プロジェクト内で用いられる言語が、設計の楽しさを醸し出し、我がチームの合言葉となることを願いたい...

2. レイヤ化アーキテクチャとドメイン層
本書は、システムアーキテクチャを四つの層に分けて分析することを推奨している。上位から、ユーザインターフェース層、アプリケーション層、ドメイン層、インフラストラクチャ層である。ユーザインターフェース層はユーザの要求や状態などを管理、アプリケーション層は処理やトランザクションなどの管理、インフラストラクチャ層は上位のレイヤを支える技術を提供する。
注目したいのは、ドメイン層を独立させていることだ。この層では、概念や規定の責務を負うという。いわば、設計思想を担う核心部分というわけだが、これを分離する感覚がとっつきにくい。そもそも思想や哲学というものは概念的なものであって、しかもシステム全体に浸透すべきものであり、すべてのレイヤを含んでいそうなもの。しかし、概念と手段を明確に区別することにも、一理ありそうだ。ドメイン層がアプリケーション層とインフラストラクチャ層の間に位置するのは、思想と実践の架け橋にでもなろうというのか。
ところで、古くから、MVCというデザインパターンがある。モデル、ビュー、コントローラで分離する設計概念である。ビューとコントロ―ラを結合させて、ドキュメント/ビュー構造にも馴染みがある。ドメイン層という発想は、こうした流れから派生しているようである。そうなると、ドメイン層は実装よりもドキュメントとの結びつきが強そうに映る。なるほど、ユビキタス言語との結びつきが鍵というわけか。
実際、多くのエンジニアが手段に目を奪われ、本質的な要因を理解しようとしない。コマンドの叩き方やコードの書き方を工夫すれば、目的に適った動きをしてくれるので、それで理解した気分になれる。コンピュータサイエンスの視点からモノを見るエンジニアは意外と少ない。そんな必要もないのかもしれんが。些細な問題を抱えても目先の対処で誤魔化すために、潜在的に大きな問題を抱えるケースも珍しくない。あるいは逆に、冗長的な方法論や過剰な機能を付加して、自ら墓穴を掘るケースもある。
しかしながら、モデリングパラダイムによく適合した実装技術を身に付けるとなると、かなり骨が折れる。手っ取り早く、オブジェクト指向あたりでええじゃん!と、つい考えてしまう。実際、言語システムを選択することで、設計思想の確立を肩代わりさせることもある。設計グループには文化があり、そこに実装に用いる言語がどっぷりと浸かっている。設計文化が、言語そのものとか、コーディングルールだと主張する人も珍しくない。そのために、どの言語システムを選ぶべきか、という論調になりがちである。
「モデルに貢献する技術的な人はだれでも、一定の時間をコードに触れることに費やさなければならない。プロジェクトで主に果たしている役割が何であれ、そうしなければならないのだ。コードの変更に対して責任を負う人はだれでも、コードを通してモデルを表現することを習得しなければならない。すべての開発者は、モデルに関する議論にいずれかの段階で参加して、ドメインエキスパートと話をしなければならない。その他の方法で寄与する人々は、ユビキタス言語を通じてモデルに対する考え方をダイナミックに交換する際に、コードに触れる人々を意識して巻き込まなければならない。」

3. リファクタリングとリポジトリ
ドメインモデルを習得するためには、リファクタリングが鍵になるという。戦略的設計には、より深い洞察へ向かうリファクタリングが必要だというわけだ。政治的に言えば、ビジョンってやつか。最初からシステムを理解している者など、そういるものではない。すべては試行錯誤によって導かれるであろう。システムってやつは、機能追加や修正にともなうバージョンアップを繰り返すうちに、いつのまにか設計思想を見失って硬直化し、やがて過去の遺物と化す。
リファクタリングの対象は、モジュールそのものに向かいやすく、設計思想といった上流工程に向かうことはあまりない。インターフェースを保持しながら、構成要素の中身を再検討することはよくやるが、一度決定した全体構成を見直すことをあまりやらない。変更リスクが大きいからだ。
しかし、ドメインレベルで思考することによって、システムそのものが生き物のように進化するという。それは、構成の分離と統合、用語の定義といった様々な境界を明確にしながら、さらに再定義すること、そして、システムに柔軟性を持たせると同時に、異質な設計の紛れ込む余地を許さないことを目的とする。ひとことで言えば、アジャイルに、PDCA(Plan - Do - Check - Act)を回転させるといったところであろうか。
また、リポジトリのテクニックが重要だとしている。データベースへの問い合わせは、過去を遡る手段となる。そして、データベースの構造、すなわちデータ構造そのものが、ドメイン設計にとって根幹となるはずだ。各メソッドのデータ構造へのアクセス方法が、一貫性を保つルールを自然に育むだろう。リファクタリングの意義は、完璧な設計などありえないというコア思想を見直す習慣を身に付けることになる。その習慣が、技術と品質の妥協を許さない技術者魂を呼び起こすであろう。最終的にシステムは、ユーザにとって役立つものでなければ意味がないが、その前にエンジニアにとっても役立つものとしたい。コードの保守は、後々重要な知識の蓄積となって返ってくる。モデルとは、システムの物語を伝えるためのものなのかもしれん。
「深いモデルは、ドメインエキスパートの主要な関心事と、それに最も深く関連した知識に関する明快な表現を提供するが、一方で、ドメインの表面的な側面は捨て去るのだ。」

4. 副作用の宿命
モジュール化によって、様々な副作用の余地を残すのは危険であろう。関数の設計であれば、副作用のないことを期待するが、完全に副作用を排除することも難しいので、どのような作用が生じるか明示しておく必要がある。ライブラリの揃える関数群の引数や戻り値の一貫性や、操作性の一貫性が、他のモジュールへの影響を小さくする。あるモジュールを使用する場合、その実装について悩まされ、コードを確認しなければならないとすれば、カプセル化の価値は失われる。設計思想の違うモジュールの結合によって構成されたブラックボックスは、深刻な問題を抱えている可能性が高い。強烈なものになると、「解析済みの問題」と称して、これらを仕様書に羅列したものを見たことがある。10項目ほどの。これを使えば開発期間が短縮できると、意気込んだお偉いさんとセットで。解析済みってどういう意味かは知らんが、問題を修正してから持ってこいよ!それとも修正できないほど深刻ってか?幸か不幸か、この手の直感は外れたことがない。意図を明確にしておけば、インターフェース仕様が適さないことは明白になるはず。にもかかわらず、政治的な意図で工程が短縮できるとすれば、設計とはなんなんだ?技術とはなんなんだ?おっと、愚痴が加速する!
設計思想の一貫性を保つことは、システムが複雑になるほど不可能なほど難しい。クックブックのようなルールで対処できるものではない。やむを得ず矛盾を許す箇所も生じるだろう。どんな規則にも、例外が生じることは覚悟しておいた方がいい。それでもなお一貫性を保とうとする努力を怠ることはできない。それが、エンジニアの宿命なのかもしれん。物理学者が不確定性原理に、数学者が不完全性定理に、哲学者が二律背反に立ち向かうように...

5. 腐敗防止層と例外処理
ドメイン層とは、ちと違うが、概念を独立させるという意味でイメージしやすい事例を紹介してくれる。「腐敗防止層」とは、なかなか興味深いネーミングだ。究極の例外処理と解するのは、大袈裟であろうか...
どんなに優れたシステムでも、数年後には腐敗する。これは自然法則と思うぐらいで丁度いい。そこで、腐敗の傾向をモデリングできるとありがたい。腐敗防止層のインターフェースとは、どのようなものであろうか?もしかすると、政治色の強いお偉いさんの思考にも、なんらかの傾向があるのだろう。整合性のための自動チェック機構のようなものがモデリングできれば、政治屋を黙らせることができるだろうか。
古代中国は、近隣の遊牧騎馬民族の襲撃から国境を守るために万里の長城を築いた。だが、誰も通れない防壁だったわけではなく、規制しながらも交易は認めたという。大軍の侵略に対して頑強な障害物であればよかったのだ。なるほど、きちんと境界条件が定義されていることが重要だ!という教訓か...

0 コメント:

コメントを投稿