戦略的設計入門

"Beautiful Development"(2011.04.09 DevLOVE)の講演資料と原稿

はじめに

本日(4/9)、DevLove様と共同で、第2回"Beautiful Development"を開催致しました。これは、日本語版DDDの発売を記念し、DDDに造詣の深い方々に集まって頂き、2枠構成で講演して頂くという豪華なものでした。このカンファレンスでトリを務めさせて頂きましたので、講演資料と原稿を公開致します*1。なお、今回の発表は「ドメイン駆動設計入門」では駆け足でまとめてしまった部分を、改めてクローズアップした続編と考えて頂くこともできるでしょう。


アジェンダはこちら

  • 戦略的設計とは?
  • サンプル業務
  • モデル駆動設計をすると?
  • 戦略的設計


スライドはこちら

戦略的設計とは?

「戦略的設計(Strategic Design)」とは、DDD第4部のタイトルです。DDDは全体で4部構成になっており、第1部が基本概念の導入、第2部が実際の実装方法、第3部がリファクタリングとブレイクスルー、そして第4部が戦略的設計という構成になっています。4部構成と聞くと、分量としては、おおよそ1/4ずつ割り当てられていることを期待するものですが、実際には本全体の大体1/3程度を占めており、また議論の抽象度も上がるため、英語版をがんばって読んでいた方にとっても、第2の挫折ポイントになったケースが少なくないのではないかと思います。今回は、その戦略的設計について、基本となる考え方を説明していきたいと思います。


戦略的設計の対象は、一言で言うと、「個々のオブジェクトレベルでは把握できない、巨大で複雑なシステム」です。いわゆる「大規模」と言えばそうですが、単に「画面数が多い」というだけでなく、エンタープライズ全体を統合するようなシステムを想像して頂ければよいかと思います。システムが巨大になると、全体で1つのまとまりとして理解することが難しくなり、モデルも複数登場してきます。そうした複数のモデルを統一的に扱う手法が、戦略的設計なのです。少し見方を変えると、モデル駆動設計が1人あるいは1つのチームのドメインエキスパートのメンタルモデルを対象とするのに対し、戦略的設計では、経営層のメンタルモデルを対象とする、とも言えるかもしれません*2


この戦略的設計は、3本の柱によって支えられています。それが、コンテキスト蒸留(あるいは抽出)、そして、大規模な構造(あるいは大局的な構造)です。戦略的設計はパターンの数も多く、この時間の中ですべてを網羅することはできませんが、今回はそれぞれの基本的な考え方をお伝えしたいと考えています。


その目的のために、1つ具体的な業務を取りあげ、それがどのようにモデリングされていくのかを見ていくことにします。

サンプル業務

ここで扱うのは、「旅行手配」業務です。*3


さて、みなさん、旅行をしたことはありますか?海外旅行である必要はありませんが、「社内旅行で1泊で温泉」という感じではなく、修学旅行での「京都・奈良」のように、いくつかの都市をまわる旅行をイメージしてください。旅行者の視点からすると、「何を観光する」「何を買う」といったことが重要になると思います。しかし、ドメインエキスパートから見ると、旅行はだいぶ姿を変えます。すなわち、「各移動手段の時刻表」といったものが大切になってくるのです。これは、DDD本の随所で取り上げられている貨物輸送システムと、抽象的なレベルでは似ているかもしれません。貨物輸送システムは、定期的に運行している船なり鉄道なりといった輸送手段を予約し、それらをつないで貨物を目的地まで届けるものでした。旅行手配も、同じようにお客さんの移動手段をつなぎながら目的地まで届けます。少し違うのは、貨物では最終到着地点だけが重要なのに対して、旅行手配の場合、最終目的地は自宅ですから、乗り継ぐ場所が重要になっているということですね。


ここでは海外旅行を題材として、旅行手配の業務について見ていきます:
お客さんの動きを整理すると次のようになります。飛行機を使ってまずは目的とする土地に移動し、夜はホテルに泊まります。空港からホテルに行くために、もしかしたら送迎もつくかもしれません。ある都市から別の都市への移動には鉄道を使います。それぞれの都市では、お客さんは思い思いに観光をしますが、場合によっては事前にチケットを取っておかなければいけないものがあるかもしれません。こうしたパーツを組み合わせて、1つの旅程を組み立てます。そして、その旅行にかかる金額を見積り、成約したら請求書を送ります。

モデル駆動設計をすると?

戦略的設計に入る前に、少し1つのモデルに対して何をするかを整理しておきましょう。モデル駆動設計は、まずは「知識のかみ砕き」から始まります。ドメインエキスパートにとっての旅行のイメージを図示すると、以下のようになることが分かりました。ある都市に飛行機で入り、それぞれの都市(=黒丸)を移動手段で結び、最後は飛行機で帰ってきます。ただ、図には表現されていませんが、各都市で観光したいものに応じて滞在所要時間もかわってくるため、組み立てはもう少し複雑になります。


ドメインエキスパートの考えていることがおおよそ理解できたら、次はそれをモデリングします。その際に使われる言葉は、ドメインエキスパートが理解できるものでなければなりません。また、そこで出来上がるモデルは実装可能なものでなければなりません。こうした考え方が、ユビキタス言語モデル駆動設計です。


DDDではさらに、「すでに確立されている概念体系をモデルに当てはめることができる場合がある」と説明されています。そうすることで、そのモデルに初めて触れる人であっても、その基になっている概念体系を知ってさえいれば、スムーズに理解できるからです。今回であれば、滞在場所をノード、移動手段をエッジと考え、「グラフ」を使うことができるかもしれません*4

戦略的設計

それでは、いよいよ戦略的設計に入っていきましょう。今度は個別のモデルの内部をモデリングするのではなく、システムの全体像の把握するように試みていきます。

コンテキスト

モデリングをする際の武器は「言葉」です。特に、話し言葉のレベルでドメインエキスパートと共有し、その言葉を実装でも用いなければなりません。しかし、言葉はそれ単独で意味を持つわけではありません。言葉の意味を規定するもの、それがコンテキスト(=文脈)です。


戦略的設計の第一歩は、各モデルが位置づけられたコンテキストの境界を明確にするところから始まります。これが境界づけられたコンテキスト(BOUNDED CONTEXT)です。旅行手配ドメインを見ると、境界づけられたコンテキストを3つ見つけることができます。

  • 旅行手配:旅程を組んで代金を見積もる
  • 予約:移動手段や滞在先を予約する
  • 経理:実際に金銭を扱う


こうして境界づけられたコンテキストが確立されたら、次はこのコンテキストの内部を安定させなければいけません。このコンテキスト内で行われるすべての作業に対して一貫性を保つために行われるのが、継続的な統合(CONTINUOUS INTEGRATION)です。この統合には、自動化されたテストに代表されるようないわゆるCIだけではなく、概念上でも、ユビキタス言語を絶えず洗練させ続けることも含まれています。


コンテキストが1つであれば、ここまででよいのですが、境界づけられたコンテキストが複数存在している場合には、コンテキスト間を関係を定める必要があります。ここで登場するのが、コンテキストマップ(CONTEXT MAP)です。ここで重要なのは、コンテキスト間の接点を明示的にするということです。共有しているオブジェクトがあれば強調しなければなりませんし、何らかの変換が必要になるのであれば、それについて説明しなければなりません。


コンテキストマップが出来上がった後は、それぞれのコンテキスト間の関係を明確にしていく必要があります。DDDの第14章では、そのためのパターンがいくつか紹介されています。すべてを紹介することはできませんが、イメージをつかむためにいくつかのパターンを紹介します。


図の中に、予約のための専用端末があるとあります。これは特に航空券の予約に使われるのですが、ここではその端末との関係について考えていきたいと思います。航空券予約端末の場合、この専用端末とやり取りするためのプロトコルは予め定められています。SQLと同じような機能を持っていて、さらにそれが短くなったDSLがあると思って下さい。端末と人間が直接やり取りする場合、ドメインエキスパートは、素人にはまったく解読できないこのDSLを高速でコンソールに打ち込み、これまた素人には理解できない文字列が結果として返ってきます。Unix/Linuxのエキスパートがコマンドラインを叩いているのと、雰囲気的には一緒ですね。ここまでは、人間がインタラクションする前提で書いていますが、こうした機能はプロトコルを定めてまとめることで、たとえば、Webサービスとして公開することもできるようになります。こうしたサービスの集合が、公開ホストサービス(OPEN HOST SERVICE)と呼ばれます*5


こうした公開ホストサービスのクライアントとなる場合、何も手を打たないと、自分たちのモデルがサービス側のモデルに引きずられてしまいます。それでいいケースもありますが、自分たちのモデルの独自性を保ちたい場合には、中間に変換層を設けることが考えられます。これが腐敗防止層(ANTICORRUPTION LAYER)です。大手の旅行会社であれば、こういう仕組みがありそうです。


ただし、こうした変換層を作るためには多大なコストがかかりますし、それが常に利益と見合うわけでもありません。「せっかくCUIがあるのだから、別に人間がやっても構わない」ということであれば、システム的に統合する必要はありません。ある程度までは、Excel秀丸が最強の統合ツールだということですね。これが、別々の道(SEPARATE WAYS)と名付けられている、統合しない統合パターンです。

蒸留

さて、戦略的設計の2つめの柱が蒸留(抽出)です。専用端末との統合と聞いて、心が踊った方も多いのではないでしょうか。それが、エンジニアの基本的な習性ですよね。しかし、ドメイン駆動設計が重視するのは、技術ではなく、ビジネスです。したがって、フレームワークチームにエースを投入するというのは、ドメイン駆動設計にとってはアンチパターンとなります。そのビジネスにとって、最も重要な場所に注力しなさい、という命題が蒸留では語られています。この最も重要な場所がコアドメイン(CORE DOMAIN)と呼ばれます。


それでは、今回の旅行手配業務におけるコアドメインはどこでしょう?コンテキストで言えば旅程作成ですが、さらに細かく言えば、実際に旅程を組み立てるところだと言えるでしょう。商品の価格を集計して見積りする部分に対しては、旅行手配に限らず、もう少し汎用的に考えることができるはずです。こうしたコアドメインを補佐する汎用的な領域が汎用サブドメイン(GENERIC SUBDOMAIN)と呼ばれています。戦力をコアドメインに集中させることが重要で、汎用サブドメインであれば、実は既製品を当てはめても構わないかもしれないのです。

大規模な構造

さて、ここまでで、登場するコンテキストの地図とそれに対する重みづけはできるようになりました。しかし、まだ1つ欠けているものがあります。それが全体をとらえるための構造です。「木を見て、森を見ず」にならないよう、全体をとらえるパターンを見出すこと、それが大規模な構造(大局的構造)です。ここで言う大規模とは、単純に数が多いという意味での規模ではなく、全体をとらえるという意味であるということに注意してください。


こうした構造をとらえるパターンの1つが、責務のレイヤ(RESPONSIBILITY LAYERS)です。モデルの中で概念上の依存関係を明確化し、階層化された責務に対して、抽象的な責務を割り当てます。ここではDDDで取り上げられている例のうち、いくつかを当てはめてみました:

  • 能力:何ができるのか。このシステムで扱うリソース。
  • 業務:能力を利用して、何ができるのか。その時の状況を反映する。
  • 意思決定支援:どのように活動するべきなのか


もし、システムの目的が、引き継ぎなどのためにお客さんに提示した旅程を保存するためだけであれば、あるいは、登録した旅程を帳票出力したり、商品の金額計算を自動的に行ったりするためだけであれば、意思決定支援層は必要ないでしょう。そうではなく、たとえば、特定の航空会社を優先的に使いたいというバイアスをかける必要があるのであれば、そうした情報を保持する意思決定支援層あるいはポリシー層が必要になるでしょう。


さらに、重要なことですが、こうした概念上の大規模な構造は、アップフロントに設計し、詳細な設計を制約しすぎてしまってはいけません。アプリケーションと共に成長させ、必要があればまったく別のものに置き換えなければならないとされます。この命題には、進化する秩序(EVOLVING ORDER)という名前が与えられています。

最後に

戦略的設計にしても、モデル駆動設計にしても、DDDに一貫して流れている1つのテーマがあります。それが「有機的秩序(organic order)」と呼ばれているものです。1つのオブジェクトから、それが集まってエンタープライズ全体を統合するに至るまで、それぞれの抽象度でモデルとしての統一性を失わない点にあると言えるでしょう。一定の凝集度を持ったそれぞれの単位が、環境に対して柔軟に適応しながら成長し、1つの有機的な全体として変化し続ける。DDDは、そういった、ビジネスに寄り添って成長していくシステムを作るための方法論なのです。

*1:事前に準備していたもののため、内容については一部相違がある可能性がありますが、ご了承ください

*2:この辺りについては、「スクラムによるドメイン駆動設計 - Digital Romanticism」をご参照ください

*3:実はこれは、日本語版DDDのレビューとして全章を読破し、今や強力なドメインエキスパートになった妻の本業でもあります。ちなみに、妻はDDDに対するコメントとして、「大切なところにできる人を入れて、知識をかみ砕いて、リファクタリングするんでしょ?」と言っておりました。だいたいあっているかと。

*4:【2011.04.11 追記】私自身は汎用化とは別のこうした抽象化は、ビジネスモデルをとらえる上での重要な武器になると考えていたのですが、Ericと話していて間違っていたことに気がつきました。こうした「確立された形式」でとらえることができない特殊なものこそが、実はビジネスの核心だということのようです。こうした視点は、安易なシステム開発が早々にシステム化をあきらめる場所に向かっていく力を生み出しえるものです。

*5:実際にそういうサービスが存在するかどうかは問題にしていません。あるかもしれませんし、ないかもしれません。