システムのデッサン:光源と陰影

初期のドメインモデリングは、システムの全体像のデッサンに不可欠な実践のひとつ。

「どんな情報を扱うシステムか」という「情報の視点」を中心にして、機能と並行性を視野に入れて、システムの全体像を、A4一枚のクラス図にまとめていく。

「概念モデリング」とか、「業務の用語集作成」とほぼ同じ。

業務で扱う情報名や業務上の処理(機能)名を、クラス図として描いていく。

光源はドメイン


UMLツールでクラス図を書くと、それぞれのクラスは、線の太さや色が同じになる。
これだと、かなり平坦なデッサンになり、あまり役に立たない。

ドメイン、つまり、業務の視点、業務から見た重要度や、関心の強さを光源にして、強く光る部分、弱く光る部分、陰影などを描きこめば、モデルが、立体的に、生き生きとしてくる。

ドメインという光源から、陰影や強弱をつけた絵は、関係者の認識合わせに、とても役にたつ。

線の色も太さも同じ四角がならんだクラス図だと、業務の言葉さえ並んでいれば、なんとなく、そんなもんだろうで終わってしまう。

「重要な関心事オブジェクト」「注意すべきオブジェクト」という色分け、描き分けをしてみると、人によって、捉え方が違っているのが一目瞭然になる。

開発者は、プロジェクトの初期では、どのドメインオブジェクト(どの業務の用語)も同じに見えている。
どこから手を付けてもいっしょに見えるし、どのオブジェクトの分析・設計に、時間とエネルギーを使うべきか判断できない。

ドメイン(業務)という光源からあてた光で、めりはりをつけたクラス図を描けば、業務のエキスパートの重要な関心事、業務のややこしい部分を、プロジェクトの初期で、関係者で共有できる。
共有できれば、開発全体の軸や方向感がでてくる。チームが良い成果を達成するための羅針盤になる。

ドメイン駆動設計(DDD)の Highlighted Core パターンですね。

クラス図に光の強弱と陰影をつける


ドメインから光をあてた結果の、光の強弱は、クラスアイコンの背景色、線の太さ、色などで、描く。
あまり、凝らないほうが良い。
背景色だと、白、黄色、グリーンくらいで十分。
線の色や太さはこらないほうが良い。描きわける労力に比べ、情報の伝達効果はいまひとつ。

もちろん、約束事を決めて、同じ色は同じ意味にする。
Enterprise Architect のような UML ツールだと、ステレオタイプを色で視覚化できるので、core とか、subject とか、主題であることを宣言するステレオタイプを定義して、色設定するといいかもしれない。

陰影のつけ方は、アイコンに影をつけるわけではない。
ドメインから光をあてたとき、そのクラス図で影になる部分とは、クラス図の表面ではなく、裏側に何かある、ということ。

「何かある」ということを、明示するために、便利なのが「ノート」。ようするに、注釈ですね。
注釈がついた、クラスには、何かあるぞ、ということになる。
初期の段階では、「ここはなにかあるかも?」という程度のメモでもよい。

関心事の重要性で色分けし、注意すべきクラスには、ノートがついているクラス図で、関係者で、ドメインの概念、構造を、共有できると、あとあと、つまらない、手戻りが激減します。

業務で重要な部分、注意すべき部分を、ソフトウェアの開発者が最初から、きちんと理解して、開発を進めているのだから、大きなブレは起きない道理です。

逆に、ここらへんの認識合わせが、ずれたままだと、ソフトウェアは動くかもしれないが、中身は、かなり、業務モデルとはずれた、ねじれた実装になっている可能性が高い。

ドメイン(業務)の概念モデルと、ソフトウェア実装の構造がねじれていると、変更に弱く、わけのわからない副作用が発生しやすいソフトウェアになる。

業務の構造と概念を丁寧に反映したソフトウエアだと、変更要求も、合理的だし、コードの変更も局所的に、安全にできるようになる。

初期の概念モデリング(ドメインモデリング)で、ドメイン(業務)を光源に、クラス図に色分けとノートで注釈したものを意識して作成し、共有することが、役に立つソフトウェアを作る、基本テクニックの一つ。

重要度と分析・設計の難易度


業務の光で、クラス図を照らして、強弱・陰影をつけた場合、重要なクラスは、技術者から見たら、単純で、退屈なクラスに見えることが多い。

うまくいっているビジネスほど、ほんとうに重要なことは、精査され、磨き上げられているので、初期のモデルをみる限りは、その中核オブジェクトは、単純に見えることがある。

で、単純に作ると、大失敗。

重要なドメインオブジェクト、業務の関心事であるオブジェクトの分析・設計には、細心の注意が必要。

そのオブジェクトが表現している、業務の関心事は、実際の業務の中で、さまざまなルールや手順が、なかば無意識に適用されている。また、重要な関心事であるだけに、たまにしか起きないような例外的な状況の時は、どうするかとかのノウハウが、業務のエキスパートの頭の中に、しっかり入っている。

ところが、これらのルール、手順、例外対処ノウハウなどは、業務のエキスパートが、事前に、明示的に語ることはまずない。 彼らにとっては、ある意味、前提知識みたいな話だし、あまり意識せずに、それをやっているからこそ、エキスパートなわけで、いちいちそんなことを意識して考えていたのでは仕事にならない。

業務に役に立つ道具を作るためには、そいういうエキスパートの知識をなんとか引っ張り出して、コードに実装しなくちゃいけない。
そのためのテクニックが、ドメインモデリング。概念クラス図。

業務で重要な関心事クラスは、実装は単純なクラスかもしれません。
でも、その背景にある、ビジネスルール、業務知識を、適切にキャッチするのは、かなり難易度が高い。

初期の概念モデリングで、ドメインの中核オブジェクト、業務の重要な関心事オブジェクトを特定できたら、そこが出発点。

楽勝に見えても、細心の注意を払って、分析・設計を進めること。
エキスパートとのやり取りで、ちょっとでも違和感を感じたら、がんばって掘り下げること。

ハイライトされた重要オブジェクトのまわりには、大切な業務知識が山のように埋まっている。
それを、丁寧に掘り出すことで、業務の役に立つソフトウェアを作ることができる。

重要な業務知識のありかの嗅ぎ付け方、掘り出し方が、よいソフトウェアづくりに、必須のスキル。

クラス図に色やノートを使って、強弱・陰影をつけて、業務のエキスパートや、開発者どうしで、認識合わせを丁寧にやれば、重要な業務知識のありかは、容易に見つけることができる。

ただし、そのまわりに埋まっている業務知識の掘り出しは、そう、簡単ではない。

ここに、いろいろ埋まっているんだ、という革新を持って、分析・設計を進めれば、ある日、突然、価値のある業務知識を見つけることができる。 ドメイン駆動設計(DDD)の、ブレークスルーパターンですね。

Evans も書いているように、いつ、どんなブレークスルーが起きるかは、予測不能。地道に、基本的な分析・設計を繰り返すのみ。

でも、あちこちを、手当り次第にほっていたのでは、いかにも効率が悪い。

システム全体のデッサンで、初期の概念モデルに、業務の光をあてて、強弱・陰影をつけることで、どこを掘ればよさそうかのあたりが、つけば、ソフトウェアの価値をもっとも高めることができるポイントに、時間とエネルギーを投入できる。

それが、良いシステムのデッサンのコツであり、やるべきこと。
ブレークスルーが起きるタイミングは予測できないが、ブレークスルーが起きる場所は、分析モデリングの初期からある程度、確信をもって、予想できる。 業務の重要な関心事を表現する、中核クラス。そこに、ブレークスルーのネタはころがっている。

ドメインモデル駆動開発の実践

今のプロジェクト「ドメインモデル駆動開発」に、こだわって、やっている。

ドメインモデル駆動開発(DMDD:Domain Model Driven Development) は、モデリングや設計よりも、実際のコードの書き方が、主要な関心事。

やり方


具体的、かつ、簡単。
基本のアイデアは、Eclipse プロジェクトを、レイヤごとに、別々に作成すること。

(1)まず、ドメイン層のプロジェクトを作って、ドメインのクラス群を作る
(2)次に、データベースを定義する
(3)次に、データアクセス層の プロジェクトを別に作って、ドメイン層プロジェクトを参照する。
   O-R マッピング ( SQL Map ) の仕組みを使って、ドメイン層で宣言した、
   Repository インタフェースを、実装する。
(4)次に、サービス層のプロジェクトを、さらに別に作る。
   このプロジェクトも、ドメイン層プロジェクトを参照する。
   データアクセス層プロジェクトも参照するけど、Spring フレームワークで隠ぺいしてやる。
(5)最後に、Web MVC 用のプロジェクトを作る。
   ここは、ドメイン層とサービス層を参照する。

階層構造と参照関係


こんな感じ。
コンポーネントモデル.png

狙い(1) 構造が明確で、安定する


プロジェクトに分けているので、参照関係が、一方向に、限定される。
レイヤ構造の概念を、コードの構造として、具体化している。

Java のパッケージは、パッケージ間の参照関係を、明示的に宣言する方法がない。
Eclipse のプロジェクトと、プロジェクトの参照の仕組みを使うことで、構造を、具体的な形にできる。

狙い(2)開発が、ドメイン駆動になる


ドメイン層のモデリングと、設計・実装が、全体を駆動することになる。
概念としての「ドメイン重視」ではなく、作業の順番として、「まずは、ドメイン層」というやり方に、自然になる。

実践の結果


そろそろ開発の中盤から終盤にさしかかっているが、期待どおり、ソフトウェア全体の構造が安定している実感がある。
ドメイン駆動も、概念的な話ではなく、「ドメイン層のクラスから作り始める」という、コードレベル、作業レベルの習慣になっている。発想が、自然にドメイン駆動になる。

ビルディングブロックを作って、それを組み立てていく、というやり方の心地よさを感じている。

コードの全体量が少なかった、開発初期には、オーバーヘッドが目立った感じだが、コードの量が膨らんだ今は、全体の見通しのよさ、安定性、仕様変更への対応のしやすさなど、メリットがいろいろ実感できている。

次の機会でも、まちがいなく、このやり方でやりたいと思う。( keep )

補足:アーキテクチャ


このやり方ができたのは、アーキテクチャを、事前によく検討して、固めておいた効果も大きい。

基本方式は、Spring 3 フレームワーク を全面採用。
「アプリケーション開発者は、ドメイン層に集中してください。それ以外の層は、我々がベストプラクティスをコードで提供しまっせ」という Spring フレームワークの思想が、「ドメインモデル駆動開発」には、ぴったり。

Spring フレームワークのコア以外に使っている、主な仕組み

◎データアクセス層は、iBatis の SQL Map
◎Web MVC は、Spring 3 MVC と Spring Web Flow
◎ビューテクノロジーは、 velocity
◎Validation は、アノテーション式の Bean Validation ( JSR-303 )を全面採用

どの仕組みも、アプリケーション開発者は、ドメインオブジェクトの設計・実装に専念すれば良いようになってきている。

補足:ドメイン層とドメインモデル


ドメイン層の実装スタイルは、ドメインモデル以外にも、トランザクション・スクリプトやテーブルモジュールがある。( by Martin Fowler PoEAA )

私たちは、いちおう、「ドメインモデル」でやっていると思っているが、この三つの違いは、あまり本質ではないと思っている。

本質は、「ドメイン層」を分離して、実装するか、どうか、という視点。

永続化や、UIの実装と、ドメイン層の実装を、分離したほうが、コードが整理できて、扱いやすくなる。
重要なのは、「ドメイン層」を独立させて、実装する、ということ。

あとは、ドメイン層の中の、関心事の分離や、リファクタリング作業の方向や程度の問題なんじゃないかと思っている。

私自身は、DOA 経由の ドメインモデル派 なので、

トランザクションスクリプト風に書いても、コードの重複が目立ってきて、リファクタリングを始めれば、わりと、ドメインモデルっぽい感じになるんじゃないの?

テーブルモジュールから、データベースアクセスの実装部分を分離すれば、これも、ある意味、ドメインモデルっぽいものになるんじゃないの?

というような、勝手解釈をして、済ませている。
つきつめて考えて、よく比較してドメインモデルを選択したわけではないんですよね。

補足:モデリングと設計手法、ツール


要件定義は、リレーションシップ駆動分析(RDRA) 、設計は、ICONIX を参考にやっている。ツールは、Enterprise Architect を愛用している。

ICONIX 手法は、ドメインクラスのモデリングと設計・実装で、駆動していくやり方なので、「ドメインモデル駆動開発」そのもの。

RDRA は、上流工程で、ドメインをコンテキストモデルから初めて、モデリングしていくやり方。
必ずしも、ドメインモデル駆動開発ではなく、それぞれの現場のやり方に合わせて使える、わりと、懐の広い手法。

私たちは、初期の段階から、概念クラスモデルを作成し、それを、ドメインクラスの設計・実装まで、成長させつづける、という「ドメインモデル駆動開発」流にアレンジして、使っている。

ツールは、Enterprise Architect を愛用している。

RDRA, ICONIX のテンプレートやマクロが用意されているのが便利。
モデル駆動でやろうと思ったら、Enterprise Architect のように、ダイヤグラムとモデルを明確に区別し、ダイヤグラムは、モデルのビューである、という思想のこのツールは、ほんと使いやすい。

最近は、ステートマシン図と、状態遷移表が、ワンタッチで、表示を切り替えられるのが、ちょっとしたマイブーム。

業務のアプリの場合、結構、状態管理機能の要求が多く、また設計・実装が、いろいろ面倒になりやすい箇所なので、その分析・モデリングツールとして、重宝している。

補足:アプリケーション・アーキテクチャのスタイル


ドメインモデルは、今回は、Martin Fowler が書いている、 Event Sourcing のスタイルを重視している。

簡単にいえば、「起きたこと(事象)」をソースデータとして、「状態」は、そこから派生させる、というスタイル。

なんてことはない、伝票でまず、事象を記録し、それを、台帳に転記する、という業務の基本シナリオにもっともらしい名前をつけただけ(なんちゃって)。

概念は、単純だけど、設計・実装面では、いろいろ興味深いテーマがたくさんある。
今回も、 Event タイプごとに、異なる処理を、どうやって、整理して記述するかを、いろいろ検討してみた。
結果としては、 Enum の Abstract メソッドの仕組みを使って、タイプごとに、異なる処理を switch 文とか使わずに、うまく表現できたように思う。

あとは、REST スタイルにもこだわった。
単純にいえば、 query 文字列は使わずに、いかに、静的な URI らしく設計するかということ。
Spring 3 MVC が、かなり、 REST スタイルのリクエストマッピングをサポートしているので、こちらも、結構、いい感じになってきている。
( 詳細な検索機能の実装はこれからなので、まだ、紆余曲折があるかもしれない )

補足:実行環境と運用


今回は、開発環境も本番環境も、全面的にクラウドのインフラを使っている。
これは、技術トレンドというより、

・初期コストを抑えたい
・ビジネスが順調に拡大すれば、ビジネスの成長(収入増)も合わせて、システムも増強していきたい
・もし、ビジネスが振るわなければ、縮小したい。あるいは、徹底もありえる。

という、事業のニーズを素直にインフラに反映するには、クラウドが適切だったということ。

新規事業なので、初期のキャッシュアウトが抑えられて、インフラコストも変動費用として伸縮性があるのは、ほんとうにありがたい。

これも、ドメインモデル(事業モデル)駆動開発の一部だと思っている。

クラウドのインフラにしたことで、「想定障害」「障害時の対処方法」「キャパシティの計画と管理」なども、いろいろ、新しい発想が必要なことを、実感しはじめたところ。

例えば、ディスク障害のためのスタンバイデータベース、というやり方は、意味がなくなってしまった。
DISK は、インフラ側で、冗長構成で、かつ複製して保護してくれているので、データ保護のために、別のハードにスタンバイデータベースを構築して、データを複製しておく、という考え方は、必要ない、ということ。

久しぶりに書き始めたら、いろいろなネタがまざってしました。
いかんなあ、関心事の分離(SoC)に、もっとこだわらないと。

Domain-Driven Design を読み終えて

去年の11月くらいに DDD を読み直しながら、自分の頭を整理するために、ブログで、DDD ネタをいろいろ書いてきた。

500ページ、17章を、ようやく読み終わった。お疲れさまでした、という感じだな。

何度も読み返してきたけど、ちゃんと通読したのは、今回がはじめて。
今までの読み方が甘かったのが、とてもよくわかった。

まあ、新鮮な発見がいっぱいあって、何か、新しい本を読んだような気分でもある。

自分たちが実践していること、できていること、できていないことも含めて振りかえってみて、改めて、Domain-Driven Design について、思ったことを、書き留めておきたい。

モデル駆動設計


DDD 前と後で、自分にとって、一番の発想の転換は「モデル駆動設計 ( Model-Driven Design )」に目覚めたことだった。

この本に出会うまでは、自分は、徹底的にコード命。エディタだけが、唯一の設計・実装ツール、という感覚だった。
UML とか、デザインツールとか、手はだしてはいたが、ただのお試し。
実際の、開発の仕事では、一切使わず、暇なときに、絵を描いて遊んでいた、という感じ。

DDD を最初に読んでからも、数年は、DDD が、なぜいきなり「モデル駆動設計」が重要なパターンとして登場するのか、ぴんときていなかった。

発想の転換のきっかけは、Domain-Driven Design ではなかった。

ユースケース駆動開発実践ガイド で解説されていた ICONIX プロセスを、現場で、やりはじめてから。

ロバストネス図を、若手に描かせてみて、自分と発想がまるで違うことを発見したとき。
そして、オレだったら、こんな感じにするよ、というポイントを、ちょっと手書きしたら、相手が「なるほど」と一発で、こちらの設計を理解した。

3年くらい前のできごとだったけど、今でも、その小さな会議室で起きたことが、まざまざとよみがえるくらい、強烈な印象だった。

それまで、ずーと「コイツは、なんでこういうコード書きたがるかなあ」と理解できなかったこと。
ここは、こういう書き方でしょう、といっても、相手に全然伝わらず、若手に設計スキルを伝える方法がわからず苦しんでいた。

それが、一枚の絵で、あっというまに解決した。なるほど、そう考えていたか、がこっちもぱっとわかったし、相手も、ぱっとわかってくれた。

一枚の絵が、設計意図の伝達に、手軽で便利な手段という、この事件(?)の印象は、ほんとうに強烈だった。

ICONIX プロセスは、ドメインモデリング(概念クラス図)を中心にした方法論だったこともあって、DDD の実践方法として ICONIX を現場で実践する、ということに、急激にのめりこんでいった。

ICONIX は、最小限の絵だけは、ちゃんと描こう、という軽量なやり方なのも、良い感じだった。

コードを書く前に、手書きでいいから、絵にして、話しをしてみよう、というのが、「モデル駆動設計」ということなんだと思った。

今でも、メンバーのマインドは、「コード中心」から完全に抜け出せたとはいえないかもしれない。

でも、「絵を描くことで設計意図が伝わる、ありがたさ」を体験しながら、そういうやり方が、だんだん、自分たちのやり方になってきた手ごたえがある。

最近になって、それなりの技術者たちと仕事をして、ロバストネス図の作成とレビューをちょっと、やってみただけで、相手の設計の考え方がすぎ理解できたし、こちらの設計意図も、簡単に伝わった。

こういうのが当たり前になってきちゃうと、DDD 前の、コードとエディタにどっぷりとつかっていた自分がいたのが、信じられないくらい。

この感じは、実際にやってみると、すぐ、伝わるんだけど、本を読んでいるだけでは、(私もそうだったけど)ぴんとこないんですよね。

ユビキタス言語


やっぱり、DDD の基本中の基本はこれでしょうね。

チーム内での会話、コンテキスト図やロバストネス図、パッケージ・クラス・メソッド・変数の名前、スキーマ・テーブル・カラムの名前、...

開発の現場の、ありとあらゆる場面に、ドメインの用語・概念が、頻繁に登場すること。できれば、それ一色になること。

それが、ドメイン駆動設計を実践する、ということなんだと思う。

これは、私自身は、Domain-Driven Design に出会う前から実践していたし、こだわっていた。

まあ、DDD に出会ってから、さらに過激になったとは思うけど、良いソフトウェアは、わかりやすい名前から、というのは永遠の真実だと思う。

そして、わかりやすい名前というのは、アプリケーションのドメインで使われる言葉なんです。

ここらへんは、20数年前に、C 言語で格闘していた時に、師匠にうるさくいわれたこと、15年くらい前の,
Oracle 時代に、設計ハンドブックで、業務用語を積極的にテーブル名、カラム名に使う設計・実装の流儀にであったこと、などの影響が大きい。

技術者だけが理解できる命名は、基本的に、よくない、わかりにくい名前。
業務の関係者が理解できる用語を使ったソースコードが良い設計。

ドメイン駆動設計の根底にあるもの


モデル駆動設計とユビキタス言語は、テクニックや方法論として、チームに浸透させることができる。
実際に、現場で取り組んできて、やってみれば、開発メンバーが、その良さを具体的に実感できることは実証できた。

自分たちは、ドメインロジックは、ドメインモデルパターンを重視するし、実装のフレームワークは、Spring 中心にやっている。

でも、モデル駆動設計やユビキタス言語は、トランザクションスクリプトやテーブルモジュールパターンでも効果的なはず。もちろん、実装フレームワークや開発言語に何を選ぶかとは、関係なく、有効。

モデル駆動設計と、ユビキタス言語が、DDD の基本テクニック。

そして、その根底にあるのは、「ドメインの知識への興味」「ドメインの構造やルールを、発見する面白さ」なんだと思う。

そういう興味や面白さが動機になって開発したソフトウェアは、利用者の役にたつ、喜ばれるソフトウェアになる。

また、ドメインの構造をうまく表現したソフトウェアは、要求の追加も、簡単に、安全にできるようになる。
要求は、ドメインから生まれる。だから、ドメインの構造をうまく表現しておけば、追加の要求も、すんなり、そこに収まる、ということ。

こういう、知的好奇心というか、「わかる面白さ」を、チームのメンバーで共有しながら、仕事をするのは、楽しいものです。

その興味の対象が、技術テーマか、ドメインの課題か、というちょっとした(?)問題はありますが....

良いアーキテクトとは? (ドメイン駆動設計的アーキテクト論)

Domain-Driven Design(DDD)の17章に、ドメイン駆動設計的な、アーキテクトと、アーキテクチャ策定の要点(エッセンス)が6つ載っている。

だめなアーキテクト(個人/チーム)


ドメイン駆動設計に限らないと思うけど、まずは、だめなアーキテクトの特徴

× 最初に、がちがちにアーキテクチャを決め、プロジェクト全体の技術を制約
× アプリケーション開発をやっているチームに説明もしないし、声も聞かない
× ネットや本から拾ってきた、実証されていない、アーキテクチャを使いたがる

現場のことを何も考えず(知らず?)、自分の技術興味だけで調査し、サンドボックスで動けば、すべてOK、現場で問題が起きてもわれ関せず、...

こんな、アーキテクトやアーキテクチャチームが幅を利かすプロジェクトでは、良い仕事はできませんねえ。

こんなアーキテクトチームが良い


エバンスは、2つの成功パターンをあげている。

現場の技術リーダーが集まった非公式のアーキテクチャチーム


現場で、アプリケーションそのものを開発しているチームの中の、技術リーダーたちが、非公式に集まって、アーキテクチャの決め事や、改善を継続する。

公式には、概要的な決め事だけがあって、あとは、現場の技術リーダーたちが責任をもって、アーキテクチャを具体的に決め、プロジェクトを進めながら、アーキテクチャを改善し、発展させていく。

プロジェクト全体の目的や背景が、関係者で具体的に共有できていて、技術リーダーたちが、ビジネスの視点、プロジェクト管理の視点、システムのライフサイクルの視点などで、まともな議論ができる程度のマインド、経験、知識があることが、成功条件。

理想的なスーパー技術者、ということではなく、業務アプリケーションの開発プロジェクトで、まじめにリーダーがやっている人たちであれば、ほとんど、有資格者だと思う。

そういうメンバーが集まって、いろいろ話しをして、みんなが納得するものが、ベストのアーキテクチャ、だということ。

プロジェクト全体を仕切る、公式の技術チームがいない場合、自然発生的に、こういう非公式なアーキテクチャ策定チームがうまれることもある。

逆に、公式の技術チームがある場合は、この「現場技術リーダたちの非公式チーム」パターンは、いろいろ難しいだろうなあ。

公式のアーキテクチャチームが現場主義で取り組む


公式のアーキテクチャチームがうまくいくのは、

◎ アプリケーションの開発の現場に精通している
◎ プロジェクトの目的や背景。Context Map から、アーキテクチャを検討していく。
◎ 利害関係者(ビジネスパーソン、技術者、運用担当、...)と継続的にコミュニケーション
◎ 現場の声を元に、アーキテクチャを改善しつづける

という行動ができるチーム。

どんなアーキテクチャが望ましいかを、さまざまな利害関係者とのコミュニケーションを通して、模索しつづけるチーム、という感じかな。

アンチパターンのチームの裏返し。

現場主義のアーキテクト( Hands-on Architect ) が、良いアーキテクト。

アーキテクチャ策定の6つの要点


エバンスがあげている、6つの要点。

決定事項は、チーム全体に周知されること


アーキテクチャとか、大きな設計は、考え方であり、実体がない、といえば、ない存在。

アーキテクチャが実体を持つのは、現場の開発者がその考え方を理解し、日々の実装の中に、その考え方を、具体的に記述していくこと。

「周知する」と「強制する」は同じではない。

「強制」は、おそらく、相手が理解したり、納得することを軽視して、「ルール化」と「ルール違反チェック」という行動になる。

「周知する」というのは、相手が理解できるように努力し、納得して、実践してもらうことにこだわる行動になる。

「周知」するためには、相手が現場で困っていることを、いっしょに手を動かしながら、話しをするのがいちばん伝わりやすいと思う。

それを、時間のムダとか、非効率と思うなら、たぶん、ろくでもないアーキテクトの仲間入り。

決定の過程で現場の声を受けとめる


アーキテクチャは、アプリケーションの開発をしているチームが良い成果を出せるように支援するためにある。
自分の技術興味や、技術力の誇示のためにあるのではない。

主体は、常に、ドメインの概念を、ソフトウェアとして表現しようと奮闘しているチーム。
アーキテクチャチームは、そいういう現場でがんばっているアプリケーション開発チームの声にいつも耳をかたむけ、彼らの声を、アーキテクチャに反映し、アプリケーション開発者が喜んでくれることに、達成感を持つのが良いアーキテクト。

現場が喜ばないのは、選択した技術方式そのものに問題があるか、現場への周知の仕方に、大きな欠陥があるに違いない。

よいアーキテクチャは、アプリケーション開発チームに、喜ばれるもののはず。

エバンスは、「アプリケーション開発チーム」と「アーキテクチャチーム」で、技術者のローテーションを必ず行っていたチームを、うまいやり方の例としてあげている。

「計画」も発展させる


実装コードも、アーキテクチャも、マスタープランも、最初からベストの正解が、ぱっとできあがるものではない。

コードのレベルでは、リファクタリングとかのマインド、知識、経験を持った技術者やチームが増えている気はする。(楽観的すぎる?)

アーキテクチャやマスタープランになると、「最初に格闘して全体を決め、決めたら一切変更しない」という、「大きな前払い」かつ「思考停止」かつ「ソフトウェアと技術者の成長の抑圧」というのアンチパターンが、まだまだ多い気がする。

アーキテクチャや、マスタープランも、プロジェクトの中で、発展させていくのが、基本原則。

アーキテクチャチームに人材を集中させない


もっとも、技術力があるメンバー、マインド・知識・経験がしっかりしたメンバーは、アプリケーション開発チームに投入すべき。特に、コアドメインを担当しているチーム。

アーキテクチャチームは、ナンバー2に、まかせる。

他のメンバーも、アプリケーション開発チームに、まんべんなく、優秀な技術者を配置することをこころがける。

アーキテクチャチームは、技術の指導チームではなく、現場の優秀な技術リーダーたちの声を取りまとめ、実証し、絵やガイドやサンプルや部品として、その成果を現場に供給するためのチーム、という感じかな。

ドメイン駆動的には、アプリケーションのモデリング・設計・実装をするチームにこそ、第一人者を配置すべき。

アーキテクチャチームは、第一人者候補を育成する場にする。

minimalism と謙虚さ


アーキテクチャチームは、技術方式の決め事にあたって、「必要最小限」の決定をすること、他のチームの声に謙虚に耳を傾けることが必要。

これも、アンチパターンの裏返しですね。

「なんでもかんでも、決めたがって」「人の意見を聞かない」のが、最悪のアーキテクト(個人/チーム)ということです。

「オブジェクト」はスペシャリスト、「開発者」はジェネラリスト


大きな設計の最後の要点がこれ。

個人的には、これが一番気にっているし、心がけるべきだと思っている。

オブジェクト(ソフトウェアの部品)は、役割が単純明快な「スペシャリスト」であるべき。

いろいろな役割を兼任しているオブジェクトは、ろくでもない設計なんだ。

「開発者」は、正反対であるべき。

モデリング、設計、実装、データベース、メッセージング、インフラ、運用・監視、ビジネスパーソン、...

いろいろな顔(役割)を同時に持つべきだし、システム全体、プロジェクト全体で、どこでも、それなりの仕事ができる、ジェネラリストであるべき。

実際、「スペシャリスト」を自負する技術者は、アプリケーション開発の現場では、いつでも二流以下です。

得意分野をもつべきだし、磨くべき。

そして、その結果、一芸に秀でる主は、多芸に通じるに決まっている。

多芸ができない技術者は、一芸に秀でているわけがない。(つまり二流以下)

通信プロトコルが分かっているから、そのドメインのビジネスプロトコルの理解も早い、というのが、一流の技術者なんだと思う。

一流になれるかどうかは、能力というより、こころがけしだい。

Responsibility Layers と関連するモデリング手法

企業全体の情報システム、あるいは、他企業との連係を含めた、企業の活動全体のモデリングには、昔から、いろいろな方法が提案されていますよね。

たとえば、組織・部門の機能や役割体系を整理の軸にすえた方法論。(業務アプリでは、伝統的なモデリング手法かな)
あるいは、マイケルポーターの Value Chain モデルとかも有名。

これは、Responsibility Layers と似ていたり、重なる部分がある。

組織・部門の役割体系


部門ごとの役割、つまり「責任 Responsibility」に注目しているのは、基本は、DDD の Responsibility Layers といっしょ。

大きな違いは、「実際にある部門」で考えるか「Responsibility のタイプ」という概念で考えるかの違い。
昔は、企業の組織・部門は、長期的に安定した entity (実在)、というのが大手企業が素朴にもっていた感覚。
役所や大手銀行、大手企業は、いまでも、基本の感覚はそうかもしれない。

コンピュータ導入は、最初は、そういう大きな組織中心だったこともあって、部門・組織に注目するモデリング、というのが、ある意味、主流だった。

世の中は、流れ、企業や組織の流動性は高まっている。今の組織体系が、来年も固定的に存在するかは、かなり怪しい。

組織・部門に、注目するより、「 Responsibility 」に注目してモデリングしたほうが、組織変更があっても、対応しやすいシステムをモデリング・設計できる。

Responsibility Layers の視点のほうが、現代的だし、将来有望でしょうね。

Value Chain


競争優位論で有名なマイケルポーターの企業活動のモデル。

主活動は、仕入れ物流・加工・出荷物流・販売/マーケティング・サービス という価値生産の連鎖が、モデルの中核。

Responsibility Layers の Operations 層は、まさに、この主活動を記録し表現するためのレイヤ。

Value Chain の主活動の要素は、Responsibility Layers の Operations 層の Bounded Context と対応する可能性が高い。

もちろん、Bounded Context 間の関係は、まさに、Value Chain の「連鎖」の関係になる。

Value Chain モデルの支援活動のための情報システムは、一枚の Responsibility Layers に無理矢理押し込めると、話しが入り組んできて、わかがわからなくなる。

・Value Chain モデルの主活動に注目した Responsibility Layers と Context Map
・Value Chain モデルの支援活動に注目した Responsibility Layers と Context Map
・両者の主要な接点を絵にした、大きな視点の Context Map

という感じで、全体のモデリングをするのが良いと思う。

Value Chain モデルは、必ずしも、一企業のモデルではない点が重要。複数企業のコラボレーション、企業をまたがるシステム間連係のモデルとして使うことができる。

あと、Core Domain パターンの議論には、ポーターの競争優位、差別化戦略論は、とっても役にたつ。

競争優位の源泉は、どこにあるか、どこにもとめるか、というのは、 Value Chain モデルと使った、事業戦略論と、Core Domain パターンのモデリングと直接、結びついていると思う。

ドメイン駆動設計やるためのチェックリスト

Domain-Driven Design(DDD)17章に、ドメイン駆動設計を、やるための、6つのチェック項目が載っている。

□ Context Map を描いてみる: Q. ちゃんと描ける?
□ プロジェクトチームの「言語」: Q. コードもドメインの用語が中心?
□ 重要事項の理解度: Q. Core Domain を発見した? Domain Vision Statement ある?
□ プロジェクトの技術基盤: Q. 「モデル駆動設計(MDD)」向き? or MDD の障害 ?
□ メンバーのスキル: Q. 「必要」なスキルセットを持っている?
□ 知的興味: Q. メンバーは、ドメインを知ることに興味を持っている?

このチェックリストで、自分たちの5年前(出発点)、現在、今後の見通し(?)を、書いてみる。

Context Map をちゃんと描ける?



■5年前
言葉すら知らなかった。膨大な数の関心事を「ひとつ」のシステムとして格闘していた。

■現在
ホワイトボードで、時々、関連システムとのマッピングとかはやっている。

RDRA(リレーションシップ駆動要件分析) のコンテキストモデリングをやるようになってから、全体ではないけど、関連するシステム間のマップは、プロジェクトの最初から意識するようになってきた。

60点かな。それなりのレベルまでこれた気がする。

■今後
Responsibility Layers と Context Map を組み合わせた図を、リポジトリーにチェックインして、リファクタリングしながら、成長させていく、対象にしようと思う。

プロジェクトチームの言語



■5年前
コードの中身は、ドメインの用語とは、完全に別の世界。

・意味の分からない省略形
・プログラミングの世界だけの特殊な命名 ( i, val, s, ... )
・一度つけた名前は、別の概念であることが発覚しても、そのまま
...

■現在
ドメイン層は、ドメインの用語で命名する。
概念の違いを発見したら、即、名前変更のリファクタリング。

80点かな。
これは、かなり良いレベルだと思う。
5年間、ソースコード、会議、日報など、うるさく「業務の言葉」を言い続けた成果が実感できる、今日、このごろ。

■今後
インフラ層も、ドメイン駆動設計で、ユビキタス言語を浸透させる。

基盤技術の選択、サーバーの設定とかも、目的・背景を、「ドメインの言葉」で説明し、設計するように変えていきたい。

手始めに、Apache → HTTP サーバー、cisco → ルーター というように、まず、実装と概念を区別して、使い分けよう運動を開始中。

httpd.conf の timeout ディレクティブを 300 に設定、という会話ではなく、「ブラウザからのリクエストに5分間応答できなかった場合、ブラウザがエラー表示するようにする」、というように、技術者以外の関係者にも、理解できる言葉を使うように、ということ。

地道な活動だけど、見返りも大きい。この「利用者の言葉で駆動する」運動の効果は、5年間の経験から確信を持っている。

重要事項の理解度



■5年前
0点。
すべての要求を、まったく同列に、戦線を拡大し、全員、討ち死に状態。

■現在
コアドメインという「言葉」はでてくるようになった。
でも、気がつくと、目先の要求中心で、設計・実装している。

40点。落第点ですね。

これも RDRA(リレーションシップ駆動要件分析) の、システム価値のモデリングを、コンテキスト図や、要求モデル図を使うようになって、徐々に改善はしてきた。

概念クラス図でも、「コア」の概念クラスを中心に組み立てる、ということも、メンバーによってはできはじめている。

ユースケースの実装を、「コアドメイン」のユースケースから手をつけて実装していく、ということを、自分たちで判断できるレベルまではきていない。

■今後
概念クラス図/パッケージ図、ユースケースモデル/パッケージ図で、コアとそれ以外を色分けしたり、コアを中心に、コアとの関係で、配置を工夫する、とか、パッケージ図レベルでコアを検討することを、やらせてみようと思っている。

まあ、先は長そうです。
Core Domain パターンを普通に実践できるチームまで成長したいとは思っていますが...

Domain Vision Statement をさらっと書けるようになる、なんていうのは、妄想だな。
ただ、プロジェクトの初期に Domain Vision Statement を描き、それをリファクタリング(推敲)しながら成長させていく、というのはぜひ、実践していきたい。

やり方はとしては、プロジェクトの初期に作成する「コンテキスト図」に、システムの「目的」「背景」を簡潔に、ノートとして記入することを、ルールとしようと思う。

このノートを改良していけば、それが、Domain Vision Statement になっていく、という目論見です。

プロジェクトの技術基盤 vs. モデル駆動設計



■5年前
0点
Visual Studio で、お絵かきツール使って、Web アプリケーションを半ば、ちょこちょこっと作る。
人を集めて、このパターンで、量産すれば、大きなシステムが作れちゃう。

そんなわけない。完全に破綻プロジェクト。

XP, Agile , Ruby on Rails とか、モデル駆動設計というより、自動生成してでも、とにかく動くものを早くつくる、ということを重視するやり方がある。

XP でも、Agile でも、ちゃんとした技術者は、ここぞというところは手書きで使い捨てかもしれないけど、モデル駆動設計をしているはずだけど、中途半端な、XP/Agile 信者(?)は、絵を描くことが、Agile 精神に反するとか思っているらしい。

まあ、ドメイン駆動設計やるなら、「モデル駆動設計」は「ユビキタス言語」と並ぶ、二本の柱だと思う。

■途中経過 (デザインツール、導入)
数年前に、Enterprise Architect というツールを導入したが、その時点では、完全に失敗。
UML らしき図は描くけど、UML 図を描くことの意味や効果を誰も実感できず、あいかわらず、設計も、エディタで、コードでやる、というスタイルのままだった。

■転換点 ( Spring )
モデル駆動設計の大きな転換点になったのが、Spring フレームワークを、技術方式の中心に置いたこと。

なぜ、Spring フレームワークに注目したのか、正確には覚えていないけど、ジュニアの技術者たちに、データベースアクセスとか、Web MVC とかを低レベルで書かせると、生産性も品質も大問題だったことの改善策を模索していた中で出会った技術だった。

コードの自動生成とか、ブラックボックス化指向のツール/フレームワークは、カスタムアプリケーション開発には、向かないという判断があった。

Spring フレームワークのように Java2 EE ラッピング(?)して、簡単に使えるようにしてくれる技術はほんと、ありがたかった。

「EJBは存在自体がまちがいだった」と言い切っちゃう Rod Johnson の発言は、新鮮だったなあ。
Java のチェック例外批判も多いに共感した。

そして、「ドメイン層以外は、ベストプラクティスを、Spring が提供する」「開発者は、ドメイン層に専念すべき」という発言にも大いに共感。

てなわけで、Spring フレームワークで、 MVC, WebFlow, Security を順次、採用し、O-R マッピングに iBatis, テンプレートエンジンに、velocity, 最近になって、非同期メッセージングに Mule ESB という感じの技術基盤に投資をしてきた。

Spring も、Mule も、「ドメイン層のオブジェクト」をコンポーネントとして使うことを前提としたフレームワーク。

実際、Spring MVC + Web Flow から呼び出すアプリケーションサービスクラスを、Mule ESB で、メッセージ処理のコンポーネントとして、そのまま組み込んで使っている。

基盤技術は整った。あとは、「ドメイン層の実装」、そのためのドメインのモデリング、ドメインオブジェクトの設計をどうするかが課題。

■転換点 (ICONIX)
そして、ICONIX との出会い。きっかけは、単純に、Amazon とかで、Spring 関連の書籍とかを漁っていたときに見つけた本。

昔、Rational 統一プロセスとかでも、ちょっと見かけた、ロバストネス分析とかも、ちょっと、気になった。

そして「ユースケース駆動開発実践ガイド」に取り組み始めてから、世界が変わった。
ICONIX方法論は「必要最小限の図だけ描く」という、minimalism が徹底している。

また、「抽象モデル」「論理モデル」「物理モデル」とかを、教科書的に段階を踏むことも完全否定。
実践的なモデル駆動設計とは、何かを教えてくれた方法論です。

ICONIX の提唱者のダグローゼンバーグ本人が来日してセミナーやった時に、話す機会があったんだけど、まあ、とっても実践的な人。

彼らは、教育を商売にしていて、技術者が陥りがちな点とか、技術者の発想を変えるコツみたいなものを熟知していて、ほんと、得るところが大きかった。

この本が、技術方式は、Spring を使っていて、モデリングツールが、Enterprise Architect を使っていたので、私たちの既存技術とぴったりだったのも大きい。

ICONIX は、最初から、ドメインモデルを作って、成長させていくことが、中心のプロセス。

概念クラス図が、そのまま、ドメインオブジェクトに発展して、実装できちゃうよ、というやり方。
モデル駆動設計、ドメインモデルの設計・実装には、ほんとぴったりの方法論だった。

方法論といっても、よく言えば、超・実践的、悪く言えば、ちょっといいかげん。

■転換点( RDRA )
ICONIX はすごかったけど、カバーしているのは、ユースケース記述以降の設計・実装だけ。

プロジェクトの初期に、どうやって、あいまいで不安定な要件を固めていくかに悩んでいたときに、出会ったのが、神崎さんの RDRA ( リレーションシップ駆動要件分析 )

これも、UML 風の図を使う、上流工程のモデリング技法。
とても、実践的で、上流工程、要件定義の現場で実際に起きること、担当者の悩みを熟知した、これまた、超・実践的、現場主義の方法論。

システム価値、システム環境、システム境界、システムそのもの、という4段階で、システムの要件を定義していくアプローチに、とても共感した。

特に、システム価値(コンテキストモデル、要求モデル)から、システム環境(業務モデル、概念モデル)を関係者で、明らかにしながら、システム境界(画面・帳票、システム間連係インタフェース)を定義していく、というやり方が、具体的・実践的で、私たちの現場に課題にぴったりだった。

最初、本を読んでいるときは、ちょっと、重い方法論に感じて、若干、引き気味だったんだけど、神崎さんのセミナーに行ってみて、いろいろお話しを聞いたら、評価がいっぺん。

めちゃくちゃ実践的で、現場主義。
これだ、と確信し、さっそく、現場に導入開始。
上流から、設計・実装まで、「ドメイン駆動」「モデル駆動」「ユビキタス言語」で、やる、一連の流れが、見えてきた。


■現在
ICONIX は、特に、ドメインモデリングとロバストネス分析が、現場に浸透して、効果をあげている。
ロバストネス図が、そのまま、Spring Web Flow や、Mule ESB の実装設計になっちゃうところがすごい。

現場の技術者も、ロバストネス図を描いてみんなで設計を確認してから、コードを書き始めたほうが、手戻りが減って、仕事が楽になることを、何度も経験したので、今は、自然にロバストネス図を描くようになっている。

しかも、Spring/Mule ESB は、この設計を、そのまま XML 定義ファイルとか、アノテーションで宣言すれば、実装できちゃうという、「モデル」「設計」「コード」の距離の近さが、とっても、仕事を楽にしている。

モデル駆動設計用の技術基盤を使っている、という意味では、100点に近いと思っている。

もっとも、RDRA での実践度合いは、まだ30点くらい。
やれせれば、効果があることは、はっきりしているけど、自分たちだけで、うまくできない。
あと、ほったらかしにすると、RDRA レベルの作業をしないこともあるので、ここはまだまだ。

■今後
テストの自動化、テストデータの設計・実装、インフラ構築、運用、...

ここらへんが、ぜんぜん、モデル駆動設計になっていない。
最近、テストの自動化を、コンポーネント図を使って設計したり、インフラ構築やサーバーのネットワーク設定を、配置図を使って設計してから、実装するというやり方に挑戦中。

モデルを描きながら設計するのは、自分のためというより、関係者での理解を早く・簡単にできるというのが一番の効果。

これは、RDRA/ICONIX を実践しながら、ほんと、痛切に感じている。

絵を使ったコミュニケーションは、ほんとうに、開発プロジェクト全体の仕事を楽にしてくる、ある意味、魔法の道具です。

ソフトウェア開発に銀の弾丸はない、ということはよく言われる。
もちろん、私もそう思う。

でも、モデル駆動設計、絵を描きながら、設計する習慣は、「銀の弾丸」とは言わないが、スーパーバズーカ砲くらいの破壊力はある、強力な武器だと思っている。

メンバーのスキル



■5年前
10数名で、半分が、新人、半分はあちこちから引っこ抜いた混戦チームで、悪しき(?)習慣にどっぷりつかった、曲者ぞろい、てな感じ。

ドメイン駆動設計で、モデル駆動、ユビキタス言語なんて、どこにもない世界。0点からの出発。

■現在
モデリング・設計・実装のバランスがよいスキルは身についてきたように思う。

60点はあげたい。(ぎりぎり合格)

ドメイン駆動設計とか、ビジネスパターンの理解と応用、RDRA/ICONIX の実践スキルとかは、それなりになってきた感じ。

■今後
技術基盤の選定や調整、インフラの構築とかのスキルがまだ弱い。
ここは、外部の技術支援を受けながら、社内の技術メンバーは、ドメイン層の設計・実装に注力できるようにしたいと思っている。

当面は、Mule ESB をドメイン駆動設計的に活用する技術の導入、活用ノウハウの蓄積が目標。

動くソフトウェアを作る技術は、いつでも重要な技術。
昔に比べ、データ構造とアルゴリズムみたいな技術は、フレームワークやツールを活用することで、必要なスキルセットとしては、重要度は低下してきた。
(もちろん、論理思考能力とかは重要)

IT技術も、全体的に、手続き型から、宣言型に変わってきている感じなので、プログラミング=アルゴリズムとか、システムコールAPIというスキルセットではなくなってきていると思う。

知的興味


これがいちばんの難関?

■5年前
寄せ集めた腕自慢たちの知的興味は、当然(?)、技術的なことばかり。
仕事だから、顧客と仕様の話しはするけど、興味は、「どうやって実装するか」ということだけ。

新人君たちは、そもそも、技術への興味も弱く、ドメインなんて、まったく別の世界。あんたら、何が楽しくて、ここにいるの?という感じ。
新人が、何も知らない、配属命令があって、とんでもないプロジェクトに放り込まれ、それが、社会だと思ってくれる、素直な子達だった。

まあ、0点かな。

■現在
ちょっぴり、ドメイン、会社の事業や業務に知的好奇心が芽生えた感じ。
でも、期待値から考えると、30点くらいかなあ。
まだまだ興味も弱いし、理解する力もそれほど強くない。

でも、こういうメンバーで、ドメイン駆動設計ぽいことができはじめていることには、なんか、達成感も感じることがある。

メンバーにまかせる部分が増えてきて、それなりに、ドメイン駆動設計やっている感じはある。

でも、「興味」とか「エネルギー」の出方がいまいちなんだよなあ。

■今後
ドメインへの興味なんて、強制して生まれるものじゃない。

技術者の目線や知的好奇心、達成感を刺激できる「ドメインの理解と実装は面白い」と実感できるネタや機会をいろいろ考えたいと思っている。

私自身は、実装技術で、わかった、動いた、という面白さと、ドメインの仕組みをソフトウェアする面白さが一体になっていたところがある。

人のその面白さを伝えられるかどうかは、あまり自信がない。

でも、そうか、こういう業務ニーズは、こうやって実装すれば、すごくすっきりする、という、感覚、そして、それが面白いという感覚は、多くの技術者と共有できると思っている。

動けば楽しいし、人に注目され、喜んでもらえれば、うれしいに決まっている。

「ドメイン駆動設計」というのは、「人に喜んでもらえる」ソフトを作るテクニックやノウハウだと思っている。

そこに、自然に目覚める、ということは少ないんだろうけど。

DDD 第 IV部「おおきな設計」のまとめ

17章は、第 IV 部 Strategic Design の総集編。

複数のシステム、複数の開発チームが登場する開発シーンでの設計の要点みたいな話し。

数十人規模の会社でも、結構、いろいろなシステムが動いていて、それを、複数のチームが担当する、というのは、よくある話し。

チームは一つでも、数年の視野で見れば、異なるチームが担当しているのと、基本的にはいっしょ。

こういう状況では、

・サブシステム分割
・アプリケーションのパーティショニング
・システム間連携

というような課題をいつも抱えている。

Domain-Driven Design(DDD)の第IV部 Strategic Design は、こういう課題に取り組むパターンをいろいろ解説している。

17章 Bringing the Strategy Together では、第 IV 部の3つの章(14章から16章)を、総括して、エッセンスをまとめている。

第IV部では、20余りのパターンを取り上げているけど、

・Context Map パターン
・Core Domain パターン
・Responsibility Layers パターン

の三つを特に、基本的なパターンとして位置づけ、この三つを組み合わせることを、全体の構造を明確にしていく、基本テクニックとして紹介している。

Context Map を、Responsibility Layers 上で描く


企業のさまざまな情報システムは、それぞれ、異なる目的と背景があり、利害関係者も異なる。

Context Map (14章)


それぞれのシステムを、ひとつひとつの独立した文脈(コンテキスト)として、明確に定義してみようというのが、Context Map パターン。

「Map」なので、それぞれの文脈(Bounded Context) 間の、現在の関係も、絵にしてみる。

Context Map は、あるべき姿ではなく、「現在の実情」を書き出して、関係者で共有するためのパターン。

Responsibility Layers (16章)


それぞれの Bounded Context を、Responsibility Layers パターンの絵の上で位置づけて、Context Map を描いてみる、というのが、大きな設計の基本テクニック。

これ、企業システムとか考えるときは、みんな多かれ少なかれやっていることですね。

一番わかりやすのが、Decision Support レイヤ。

Operations レイヤで発生し、記録されたデータを、収集・分析して、レポートを作ったり、リコメンデーションのリストを作るようなアプリケーション。
「情報系」とか呼ぶこともあるかな。

Operations レイヤとか、Commitments レイヤは、日々の業務(トランザクション)を、サポートするためのシステム。「勘定系」。

ビジネスイベントが発生して、それを記録し、残高や状態を更新し、必要なところに、通知する。
約束した業務、予定した業務を、きちんと履行しているか、追跡する。必要ならアラートを発行する。
Potential レイヤは、マスター管理。 Policy レイヤは、ビジネスルールの記述と実行、という感じ。
こういう5つの Responsibility Layers は、絵にすると、水平にスライスする階層構造。

Context Map と Responsibility Layers を組み合わせる


Context Map で描く、個々の既存システム(既存のBounded Context)は、一つのレイヤの一部だけを担当していることもある。横の幅は狭いが、最下層の Potential 層から、最上層の Decision Support 層まで、ひととおりカバーしるシステムもある。

もちろん、重複もあるし、空白地帯もたくさんある。

Context Map だけで考えるときは、とりあえず、既存のシステム単位を洗い出して、平面にマッピングするだけ。

これと、Responsibility Layers の階層構造を組み合わせると、全体像が、立体的に見えてくる、というわけだ。

この「立体感」は、実際に、描いてみると、全体のわかりやすさが実感できる。

描くのはたいへん


ただし、描くのは、かなりたいへん。
既存のシステム全てをカバーする、それなりの知見を持っているメンバーが集まってやる作業。

ただ、開発当時の担当者が誰もいないシステムとか、ソースすらまともに残っていないないシステムとかあるのが現実。

実際にやってみると、分かっている箇所は、細部まで描きすぎ。わかっていないところは、あやふや、ひどいときには、システムごと見落とし、なんていうことがあった。

この「見落とし」は、Context Map だけで描いたときにおきて、Responsibility Layers 上に、Context Map を描きなおしたことで、「空白地帯」を発見し、そこに「システムがあるはず」という所から、発見できた。(もちろん利用者は存在をしっていたけど、システムの管理部門が見落としていた)

それぞれのシステムの名前、キーとなる情報やロジック(ビジネス知識)、システム間のキーとなる連係箇所、などを、関係者で、絵にしながら、情報を集約することは、大きな成果があった。

◎「わかっていない」ところが明確になった。
◎ システム間の重複とか、空白部分とか、全体のシステム間連携の構成の改善点を関係者で共有できた

でも、「わかった」だけで、何も改善できたわけではない。
DDD 14章の、システム間の7つの連係パターンとその実践ガイドを参考にしながら、少しずつ、手をつけていくつもり。

既存の一枚岩になっちゃって、かつ、構造疲労がめだってきた、販売管理システムを、受注・出荷・売上・請求という4つのサブシステムに分割しなおした、新システムへの移行を、9月までには、完成して、旧システムのクローズをしたいと思っている。

サービス提供側のシステムもいろいろ問題を抱えているけど、こちらは、根本には手をつけにくい。

新サービス、新機能などの案件のたびに、外付けしながら、新システムへの移行を少しずつ進める、という方針で取り組みはじめたところ。

Core Domain パターンと組み合わせる


Responsibility Layers 上で、Context Map を描くことができたら、次は、Core Domain の特定作業。
アプローチは「抽象」ではなく「捨象」が中心。

抽象化アプローチは、たくさんの候補の中から、重要そうな候補を選んで拾い上げていくアプローチ。
捨象化アプローチは、たくさんの候補の中から、重要でなさそうな(アンチ)候補を、取り除いていくアプローチ。

Responsibility Layers + Context Map の絵があれば、候補は揃っていて、整理もできているので、あとは、色分けをしていく作業の繰り返し。

同業他社と同じレベルでよさそうなところが、取り除く候補。

たとえば、請求書発行して、入金管理する債権管理システムは、重要だけど、今の事業では、他社との差別化要因や独自性を発揮する場所ではない。

こうやって、Generic Subdomains とか、Cohesive Mechanism とかに該当する部分を Core Domain 候補から除外していく。

残ったのが、サービス提供の開始・終了の管理とか、使用期間や使用量で課金する、サービス提供管理システム。

ここは、サービスの追加や構成変更、提供ルールや課金ルールを頻繁に変えるし、また、その変更を、サービスの差別化、ビジネスの競争力の源泉にしよう、というのが会社の基本戦略。

だから、サービス提供管理に関わる Operations 層、Policy 層、Potential 層のパッケージは、Core Domain 候補。

Responsibility Layers + Context Map で見えてきた全体像で、「Core」をマーキングして色づけしてみると、システムの全体構造が、さらに、はっきりと見え出す。

今まで、結構、開発投資を続けてきた現行の販売管理システムは、実は、コアドメインのシステムが業務の概念・構造から、かなりねじれて歪んだ箇所を、なんとか、つじつまを合わせるための機能追加/変更だったことが明らかになった。

コアドメイン側の「サービス提供管理」さえ、素直な構造になっていれば、販売管理業務自体は、パッケージソフトでも、どうやら対応可能、という方向が見えてきた。

全体像とコアドメインがはっきりしてきたことで、全体のシステム間の連係関係、ほんらいのあるべき姿とかが、関係者の間で共有できてきた。

こうなると、今までの手当たり次第、そのばしのぎの増築・改築モードから、少しずつ抜け出せそうな光が見えてきた気がする。

もちろん、予算も時間も技術能力も、制限だらけ。
あいかわらず、かなりの業務は、その場しのぎの増築・改築というのが実情。

でも、地図が手に入って、方向とか、到達の筋道や距離感がわかってくると、日々の業務も、その場しのぎというより、最終目標への通過点に見えてくるから、不思議なものです。

全体マップや、コアの色づけは、ときどき見直すことを続けたいと思っている。
でも、形式的に四半期に一回とかやるのは、形骸化しそうだなあ。

ある程度の資源を投入する開発案件の検討時には、全体マップとコアドメインモデルを使って、その開発の目的・期待成果を説明すること、というようなルールがよさそうかな。

まあ、これもやりながら、改善していきましょう。
正しい答え、いつも結果論。やった後しかわからないもの。
だったら、ある程度の仮説をもったら、実際にやってみて、事実からフィードバックを受け取りながら改善したほうが、結局は、早く答えにたどり着けるはず。

構造設計の良し悪し

Domain-Driven Design(DDD)の16章の最後の数ページは、パターンとして定義してないけど、構造設計について、興味深い内容が書かれている。

構造設計の良し悪しの判断?


ソフトウェアは、バグがあったり、性能問題が発覚すれば、開発チームのメンバーは、みんな問題だと思うし、修正しようと思う。
そして、直ったか直らないかは、いちおう確認できる。

構造設計になると、そうはいかない。

ソフトウェアがちゃんと動いていて、ソースの中身も、まあまあ、追いかけることができれば、全体の構造なんて、あまり気にしない技術者、チームが多いのかもしれない。

クラスが肥大化して、参照関係が入り組んできて、コードが読みにくくなり、修正の副作用が恐くなってくると、さすがに、これじゃまずい、という「感覚」はでてくる。

ファウラーが「リファクタリング」で書いているように「コードのいやな臭い」を感じる度合い、感じる人が増えてくる。

でも、臭いは、しょせん、感覚の世界。

●個人や体調によって、感じ方が違う
●いつもその臭いがしていると、なれて(麻痺して)臭いを感じなくなる
●臭いが解消したかどうか、事実として確認しにくい
...

これでは、設計の良し悪しの評価、改善手段の議論、改善の費用対効果、リスク判断、など、チームで意識統一するのは、至難のわざ。

スキルや経験の違いによって、視点、価値観、意見はばらばら。

こういう状態では、構造設計のスキルや実践レベルが向上するのは、なかなか難しそう。

最初にちゃんと設計して規則化して、構造を強制する?


プロジェクトによっては、パッケージの分割ルール、命名規則、クラスのサイズやメソッドのサイズの制限、アクセス修飾のガイドライン、...とか、構造にかかわる事項を、プロジェククトの初期に細かく決めて、ルールとして強制することもある。

私たちも、ドメイン層以外は、暗黙の習慣も含めて、結構、いろいろなルールを強制している。

UI層, サービス層、ドメイン層、インフラ層のレイヤ構造などは、かなり厳格に規則をつくって、分離構造を徹底している。
(フレームワークの使い方の約束ごと、という感じで強制している)

でも、ドメイン層の内部の構造は、分析しながら、見つけていくもんだと思っているので、特に、ルールは決めていない。

エバンスも書いているように、ドメイン層の内部の構造を、最初から、予見して、ルール化して強制する、というのは、弊害はあるけど、メリットはないと思う。

ガイドがないのも困ったもの


でも、ドメイン層の構造について、なんのガイドラインもないと、さすがに、無秩序すぎて、ソフトウェアがわかりにくく、扱いにくくなる問題がはっきりしてきた。

ドメイン層の構造も、ある程度のガイドライン、ゆるやかな決め事はプロジェクトの最初から用意したほうが良いと思うようになってきた。

ひとつひとつのオブジェクトの粒度


構造設計の前に、粒度設計というか、ドメインのオブジェクトをどういう単位で、作るか、という大まかな約束ごとを決めた。

基本は、小さいほうが良い、ということ。

そういうルールを言葉にすると、なんでもかんでもみじん切りにしちゃうやつがでてくる。
まあ、チームでちょっと話しをすれば、それなりのところに収まることは収まる。

もうちょっと、具体的な指針(考え方のヒント)としては、以下のようなことをやった。

◎ Primitive な Value Object (日付、金額、数量、識別番号、メールアドレス、... )を作る

ドメイン層のいちばん下、つまり、参照されるだけのスタンドアローンの Value Object を作ることを奨励した。

String, Date, BigInteger/BigDecimal フィールドと、それを操作するロジックを見つけたら、それを、Value Object として抽出する、というリファクタリングを地道に続ける。

◎ 発生や変更の同時性、一意性

ドメインオブジェクトは、発生時点で、専用のコンストラクタで、全ての初期値をセットするのが良い習慣、という方針。

デフォルタのコンストラクタと、setter を使って、 new, set,set,set, ... は、アンチパターンという発想に転換を進めている。(この達成度は、まだまだ)

オブジェクトの状態(ステート)の変更も、複数のステートを個別に変更するのではなく、一括して変更するメソッドを用意する。

もし、個別の変更が必要なら、それは、別のオブジェクトに分離することを、検討する。

オブジェクトの状態が、異なる理由で、異なるタイミングでいろいろ変化するのは、どこかおかしいぞ、ということ。

これは、状態(ステート)だけではなく、ソースコードの変更にも当てはまる原理。

クラスのソースコードが、異なる理由で、異なるタイミングで変更が起きるのであれば、それは、たぶん、クラスを分割したほうが良い。

電話番号のバリデーションルールを変更するときに、顧客 クラスのソースを変更するのは、おかしいよ、ということ。

◎概念の輪郭

DDD の「しなやかな設計」パターンの一つ、Conceptual Contours ですね。
ドメインのオブジェクトの粒度は、ドメインの概念の粒度と一致させる、ということ。

よく出てくる用語(概念)は、そのまま、ドメインオブジェクトとして表現すべき単位。

...

こういう議論は、なかなかチーム全員の共通意識にはならないけど、現場で具体例を使いながら、こういう考え方を含めて、意見交換をつづけると、まあまあ、だいたいの収まりの良い粒度が決まってくる。

経験から、言えば、次のような変化が起きた。

◎クラスは小さくなった (せいぜい100行)
◎メソッドも小さくなった (せいぜい10行)
◎名前は、クラス名、メソッド名、変数名、どれも、具体的で長めになった

パッケージのサイズ


ひとつのパッケージのクラスは、多くて10個程度、というガイドラインでやっている。

人間が一度に判断できるのは、せいぜい7個が限界、という認知工学の仮説(?)を尊重して、クラスの数を決めている。

アクセス修飾


クラスは、ほとんど、public になっているのが現状。
メソッドは、不要なものは、極力 private にしている。でも、private 以外は、public 、つまりどこからでも、グローバルにアクセスできるというのが実情。

構造の設計


こういう、粒度、パッケージサイズでドメインオブジェクトを作っていくと、クラスの数も、パッケージの数も増える。

パッケージは、ツリー構造でいちおう整理をしているけど、これは、ファイルの整理であって、ソフトウェアの(実行時の)構造設計とは、別の課題。

ドメインオブジェクト、ドメイン層のパッケージを整理して、参照関係を限定した、構造設計を、現場に浸透させるのは、なかなかたいへん。

パッケージ図、依存関係の矢印


構造設計は、ソースコードでは、検討できない。
ソースコードをいくら読みやすくても、ドメイン層全体の構造が、一目でわかる、なんていう手品はありません。

ちゃんとした構造設計をしようね、というなら、パッケージ図と、パッケージ間の依存関係の図示は、ぜったい必要な作業。

そういう図が存在しないプロジェクトは、構造設計なんて、誰も、気にしていない、ということ。

それでも、ソフトウェアは動くので、まあ、それはそれで一つのやり方なんだとは思います。

ただし、ドメインの構造の分析、その構造の表現をしていないソフトウェアは、変更がたいへんになることはまちがいない。

ドメインの構造と、ソフトウェア(のドメインモデル)の構造が、ほぼ対応がとれていれば、仕様変更が簡単に、合理的に、安全にできる。

ドメインとソフトウェアの構造がねじれている、あるいは、構造があやふやだと、技術者は仕様変更依頼がとても不合理で、理解不能な内容に見える。

この状態で、ソフトウェアを変更して、良い結果が生まれるわけがない。

パッケージ図を使って、パッケージの依存関係を描きながら、ドメインの概念の構造を分析・モデリングして、それをそのまま設計・実装に落としていくのが良いやり方。

構造の表現、構造のテスト


Java とか一般的な言語だと、パッケージをレイヤ構造で整理した内容を、素直に、実装する手段はありません。

下のレイヤから上のレイヤへのアクセスを制限する、なんていう便利なアクセス修飾の手段がない。

パッケージに、アクセス可能先を宣言したり、アクセス可能元を宣言するような、パッケージ単位のアクセス修飾宣言の仕組みがあったら、面白いのになあ、とか思っている。

パッケージ図の依存関係の設計を、そのままコードで表現する方法ということですね。

記述方法がないのだから、テスト方法もない。
まあ、ソースをリバースして、クラス図やパッケージ図を生成するくらいならできるけど、パッケージ間の依存関係、という宣言がないので、リバースエンジニアリングしたパッケージには、当然、パッケージ間の依存関係は登場しない。

こういう構造を、暗黙のルールではなく、明示的な宣言と、テスト方法がでてくると、ソフトウェアの構造設計技術が、ずいぶんと進歩するような気がする。

ドメイン層の構造設計のキーワード


DDD 16 章の最後の数ページから、ドメイン層の構造設計のキーワードをいくつか拾っておく。

Refactoring


もちろん、構造設計も Refactoring ですね。
最初から、良い構造なんてわからないわけです。

だから、開発を進めながら、時々、構造設計も見直して、リファクタリングを地道に進めるのが定石。
基本の手段は、

◎モデル駆動設計(パッケージ図を描く)
◎ユビキタス言語(ドメインの概念の構造を調べる)
◎継続的インテグレーション (パッケージ構成を、安全に変更しつづける)

Minimalism


構造は、できるだけシンプルにするのが良い。
構造がシンプルというのは、「参照関係」をできるだけ少なくする、ということ。

クラスを大きくすれば、参照関係は内部に取り込めるけど、これは、筋が悪い。
クラスを分割して、かつ、参照関係を、必要最小限に保つように、努力することが大切。

もちろん、双方向の参照や、循環参照は、ご法度に近い。
単一方向の参照がもっともシンプルで扱いやすい。

みんなで話す


構造は、ソースコードレビューや自動テストという、具体的な評価手段がない世界。

パッケージ図を描いて、それが、どういう意図で、コード上、実際にどうすべきか、ということを、チーム内でいつも共有することが必要。

この実践は簡単ではない。
「コードのいやな臭い」のように「感覚的」な話しになりやすく、なかなか、短時間で、効果的なコミュニケーションができない、というのが実感。

まあ、話しを続けることで、じょじょにだけど、チーム内に、共通の文化が生まれてくることは、実感できたきた。

ドメイン層の構造設計も、2年くらい、言い続ければ、それが、当たり前になってくれそう。

構造の改良は、しなやかな設計をうむ


ドメインの構造の理解が進み、その構造を、ソースコードの構造に反映できれば、ソフトウェアは「しなやか」になります。

扱いやすく、わかりやすいソフトウェアになる。
変更依頼にも、短時間で、自信を持って、対応できるようになる。

ドメインの概念の構造の理解と実装は、開発者の仕事をとても楽に、楽しいものに変えてくれる。

Responsibility Layers パターンを、実践の中で、発見し、体得していくと、ソフトウェアが、わかりやすく、柔軟に、同時に、堅牢になるのが、実感できる。

◇ ドメインの静的な制約を表現した Potential 層
◇ 業務で起きている事実を表現する Operation 層
◇ 業務の予定、予約を扱う Commitment 層
◇ 業務上、起きて良いこと/起きてはいけないことを動的に制御する Policy 層
◇ 業務の責任者が判断するための参考情報を提供する Decision Support 層

分析・設計を続けていく中から、こういうドメインの階層構造を、発見できた時に、ソフトウェアが見違えるように、わかりやすく、扱いやすくなることを、実際に体験すると、ドメイン層の構造設計の価値、ありがたさに目覚める。

コアがはっきりすると、仕事が楽になる


構造設計の改善を続けていくと、コアになるパッケージ、Generic Subdomain を実装したパッケージ、Cohesive Mechanism を実装したパッケージ、というように、パッケージの役割が明確になってくる。

ドメインのコアがはっきりしてくると、全体の構造、開発メンバーの配置、開発プロセスの進め方の軸がはっきりしてくる。

こうなってくると、ソフトウェア開発の仕事は、ずいぶんと楽になる。

コアがわからないと、要求仕様全体と格闘し、アーキテクチャが複雑化し、開発パワーも、全体に広く薄く割り当てることになる。

みんなで苦労するわりには、進みも遅いし、顧客の満足度も低い。

コアがはっきりしてくると、設計判断やプロジェクト管理の判断の軸が明確になる。

・なにを優先し、なにを先送りにするか?
・妥協して簡略にすませるか、本腰を入れて取り組むか?
・どこをどのチームが、誰が、担当するか?

こういう課題は、すべて、「コアドメイン」を軸に判断することで、答えが導きだしやすくなる。
もちろん、関係者の同意も取りやすい。

ドメイン層の構造設計


DDDの 16章のテーマは「ドメイン層の構造設計」

エバンスは、どこかの Qcon で「DDD 16章は、あまり活用の機会がないので、それほど重要ではない。本から省いても良いくらい」みたいなことを言っていた。

私は、そうは思えない。
小さな家だって、構造設計はちゃんとしていたほうが良いに決まっている。
もちろん、高層ビルと、自転車置き場では、問題の複雑さや難易度はぜんぜん違う。

でも、自転車置き場だって、ちゃんと構造設計するのと、そうじゃないのでは、利用者の利便性、構造物の価値、耐久性、将来の拡張性など、資産としての価値がまったく違ってくるはず。

どんな小規模なソフトウェアでも、基本的な構造設計は、ちゃんとできるチームでありたいと思う。

ドメイン層のフレームワークは見果てぬ夢か?

Domain-Driven Design(DDD) 16章の最後のパターンは、Pluggable Component Framework パターン。

DDD の例では、半導体製造プロセスの自動化、という問題領域(ドメイン)で、半導体メーカーと半導体製造装置のメーカーの団体 ( SEMATECH) が、 コンピュータ統合生産 ( CIM : Computer Integrated Manufacturing ) 用のドメイン層フレームワーク ( SEMATECH CIM Framework ) を例にあげている。

私は、半導体製造のドメインのソフトウェア開発は、経験がないこともあるけど、ほとんど興味がわかなかった。
この例を読んでも、現実的な解決策、動く実際のソフトウェアのイメージがぜんぜんわかなかった。

ドメイン層以外は、フレームワークを活用してる


私たちは、ドメイン層以外は、オープンソースのフレームワークを積極的に使うようにしている。

◎ IoC コンテナ Spring Framework
◎ UIコントロール Spring MVC, Spring Web Flow, Mobylet
◎ テンプレート式ビュー Velocity
◎ 認証 Spring Security
◎ SQL マッピング iBatis
◎ メッセージング Mule ESB
◎ テスト JUnit, Canoo Web Test
...

ドメイン層以外は、ありものを活用して、簡単に作れるなら、そのほうが、費用対効果が良い。

ドメイン層は、自分たちで、アプリケーションごとに、個別に、モデリングと設計・実装をしている。そこが、いちばんのソフトウェアの価値。
そういう価値を生み出せる、手ごろな製品、ライブラリ、フレームワークとかがないから、コストがかかり、リスクも高い、個別のアプリケーション開発プロジェクトをやっているわけだ。

ライブラリ、フレームワーク、ビジネスパターン


業務アプリケーションは、全体の構造、扱う情報、ビジネスルールの内容、など、なんとなく、共通な部分、同じようなところを感じている人は多いと思う。

でも、ほとんどの業務アプリケーションは、あちこちで、似たようなものを、個別につくっている。

ムダといえば、ムダ。

ドメイン層以外は、フレームワークやライブラリで、再利用することは、ここ10年間で、急速に広がってきた。

でも、ドメイン層の開発だけは、似たようなものを、毎度毎度、新規開発、という感じ。

ビジネスオブジェクトの共通ライブラリ、業務アプリケーションのフレームワーク、というような試みがないわけじゃないけど、あまり一般的ではない。

大昔、IBMが、オブジェクト指向の業務アプリケーションフレームワーク開発を目指した「サンフランシスコプロジェクト」なんていうのがあったけど、どうなったかなあ?

日本でも、ビジネスオブジェクトの再利用で、ソフトウェア開発シーンを劇的に変えるとか、さかんに宣伝していた会社がいくつかあったような気がするけど、最近は、聞かないなあ。

ビジネスパターンや分析パターンと呼ばれる、業務アプリケーション開発に役立つパターンがいろいろあると思うけど、これも、それほど、広く活用されているわけではない。

ビジネスオブジェクトのライブラリも、業務アプリのフレームワークも、ビジネスパターンも、結局、汎用性/再利用性と、わかりやすさ/使いやすさのバランスが、うまくとれていないんだと思う。

ファウラーの「アナリシスパターン」とかは、考え方とか参考なるけど、業務アプリ開発に、そのまま使えて、開発が楽になる、というようなものではない。

DDD にでてくるパターンは、考え方は、とっても大切だし、参考になるけど、現場で、即、役に立って、効果てきめん、というものじゃない。

さて、どうなるか


ドメイン層以外のフレームワーク、アジャイルな開発方法、IDEやテストなどのツール類、などは、ここ10年くらいで、大きく進歩して、一般化したと思う。

これらの技術を使えば、ドメイン層を分離する、というアーキテクチャでの開発は、10年前と比べれば、格段に進歩し、楽になった。ドメインモデルパターンも現実的なアーキテクチャになった。

また、インターネットを使ったシステム間連係(特に、REST スタイルの API )、それから、非同期のメッセージングも、ここ5年くらいで、気軽に使える技術になってきた。
業務アプリケーションの二大関心事である「記録」と「通知」のうち、「通知」という業務のモデルを、自然に、設計・実装できるようになったきた。

もしかしたら、ドメイン層でライブラリやフレームワークを活用する条件が、はじめて整ってきたのかもしれない。

マーチンファウラーの「アナリシスパターン」とか Hruby の「ビジネスパターン」とかを元ネタにした、ドメイン層向けのライブラリやフレームワークが、これからの10年で発展して、一般化するかもしれない。

日付や期間に関するライブラリとか、ファウラーの Event Sourcing パターンを元にした業務アプリのフレームワークとか、自分でも、ちょっとチャレンジしてみようかな、とか思っている。

一方、業務アプリケーションの汎用化は、結局、ソフトウェアをわかりにくく、扱いにくくする、という経験則も、見に染み付いているのも事実。

さて、世の中はどうなるか?
自分たちは、どっちに進もうか?

ドメイン層を実現するのに、手軽に使えて便利な、ライブラリやフレームワークがあれば、ぜひ、使ってみたいと思う。

とりあえず、自分たちで何か作りはじめてみるのも面白そうか?

Thing と Thing-Type に知識を分離する : Knowledge Level パターン

エバンスは、Knowledge Level パターンを、ドメインモデルの構造設計、特に、ビジネスルールの変更に動的に対応できるソフトウェアの構造という視点で、書いているらしい。

私は、どちらかというと、モデリングの基本テクニックとして、ドメインの概念・知識を、

● Thing-Type クラス
● Thing クラス

の2つに分離すると、うまく整理できることが多いよ、というモデリングの基本テクニックとしてとらえている。

性格の異なる知識を、別のオブジェクトに分離することで、片方の知識に変更があった時に、扱いやすくなる、というのは、もちろん大きなメリット。

でも、将来もあまり変化がないだろう知識でも、性格が異なる知識は、別のオブジェクトで管理したほう、ソフトウェアがわかりやすく、扱いやすくなる。

中古車


私が、Thing と Thing-Type に目覚めた(?)のは、中古車をネットで検索するソフトウェアを開発していた時。

個体識別


中古車は、同じ車種であっても、一台一台別のオブジェクト。
出品番号とかで、個別に識別する。

車の識別は、とても面白いテーマ。車のナンバープレート(登録番号)で、特定できるわけではない。中古車市場だと、ナンバープレートのない車もあるし、ナンバープレートは、変更可能。つまり、永続的な識別情報としてはふさわしくない。

車には、法律で刻印が強制された、車台番号というのがあって、例えば、盗難車の捜査で識別情報として使うのはこっち。

車台番号で、特定する個体が、Thing。

車の「モデル」で識別


中古車を検索するときには、メーカー(ブランド)やモデルから探すことが多い。

「トヨタ」の「プリウス」とか、「ホンダ」の「フィット」とか、いう感じ。

モデルが同じ中古車は、車両の状態がだいたい同じなら、走行距離、年式でだいたいの相場が決まっている。

モデルが、Thing-Type ですね。

情報の持ち方


車台番号100番の車(Thing)が持つべき情報としては、走行距離、色、オブションの装備状況とかある。

モデル「プリウス」が持つべき情報が実は難しい。
「プリウス」という名前以外に、すべてのプリウス車に共通の情報が以外と少ない。

「S]「L」「Sツーリングセレクション」、...、てな感じで、モデル名を詳細にすれば、もうちょっと共通化できるんだけど、この詳細なモデル名は、宣伝文句の性格が強く、中古車データベースに登録される時に、ちゃんとした識別情報として登録してもらのは、無理。

で、最初の設計は、基本は、全部、Thing 、つまり中古車の一台一台の情報としてすべてを記録する。

「プリウス」の燃料タイプなんて、ハイブリッド固定に決まっているけど、中古車ごとの情報として、「燃料タイプ=ハイブリッド」というデータを作成しておく。

まあ、最初のバージョンは、この設計で、なにも問題はなかった。

すご腕の店長


このシステムは、最初は、消費者が勝手に探すというより、店舗で、セールス担当者が接客しながら、いっしょに探すという使い方をしていた。

で、導入してしばらくたつと、めちゃくちゃ売上成績の良い店長が出現。

話をはしょると「この店長の売り方ノウハウをシステムに組み込んだら、普通のセールス担当者でも、もっと売れるのでは?」というのが、システム改善の大きなテーマになった。

で、店長の仕事ぶりを蔭から観察させてもらったり、ヒアリングしてみると、店長は、画面に表示される、モデル名、走行距離、色、年式などを材料に使っているけど、「こっちもなかなかいいですよ」という「リコメンデーション」をやっている。

最初は、色がまったく違っていたり、メーカーやモデルが違う車を突然、進めたりする。

私たちの造ったソフトウェアでは、同じ検索条件には絶対ならない車を比較しながら、商談している。

購入希望者と、ちょっと話をして、数台の車を提示して、その反応によって、店長の頭の中には、独自の「おススメの車一覧」がでてくるらしい。

後から聞いた話だけど、その店長は、中古車が登録されるたびに車情報は徹底的に頭に叩き込むし、暇な時に、ちょっと不思議な条件の組み合わせで、中古車検索システムを使ったりしていたらしい。

店長のおススメの秘密


店長の頭の中には、メーカーのモデル名とは別の独自の「車のタイプ」のリストがあって、そのタイプと、個々の中古車を結び付けているらしい。

このお客さんなら、この「タイプ」というイメージマップがある。
この車は、この「タイプ」というイメージマップがある。

それが、本人の思い込みではなく、お客さんのニーズにうまくフィットしているのは、抜群の営業成績が実証している。

まあ、結論からいうと、そのイメージマップを、うまく理解して、ソフトウェアとして実装することはできませんでした。

店長との話を手掛かりに、独自の「モデル一覧」を造って、こういう条件の中古車が、このモデルと一致する、という試作はした。

でも、結局、わけのわからない一覧になっちゃって、開発は、そこで終了。

ただ、人間は、頭の中の、「これとこれは同じタイプ」という判断をしていて、それが、とっても、役に立ち知識で、それをソフトウェアで実現できたら、めちゃくちゃ役に立つソフトウェアができそう、という印象が、強烈でした。

今、考えると、その店長は、自動車関連の雑誌とか、業界新聞とかも、こまめにチェックしていて、「ライバル車 対決特集」とか「ユーザの購入談話」とかのネタをもとに、「顧客」「車のタイプ」「個々の中古車」のマッピングイメージを作っていたんじゃないかと思う。

こっちも、そういう情報を共有していれば、もうちょっと、店長のノウハウをひっぱりだせたんじゃないかと思う。

Thing-Typeへの漠然としたあこがれ


結局、この時は、Thing とThing-Type に知識を分けることは失敗した。
でも、漠然とだけど、Thing の個々の情報とは、別のレベルの「Thing-Type」の知識をソフトウェアに盛り込めば、単純な検索システムではなく、役に立つ検索システムができそうだ、ということが強く印象に残った。

この時から、Thing と Thing-Type に知識を分けることがすばらしい、ということを、素朴に思い込んで、仕事をしてきている気がする。

ビジネスルールが入り組んできたら、Policy オブジェクトに、ビジネスの知識をカプセル化する、なんていう、Responsibility Layers のパターンは、ごく自然に受け入れている。

DDD の例


DDD の Knowledge Level パターンは、具体例として、「従業員(Employee)」に異なった、

・福利厚生(特に年金制度)
・給与制度

を適用する、という人事・給与システムの一部を取り出して、説明している。

最初は、Thing レベルの Employee クラスを、「時給制のEmployee」と「年俸制のEmployee」にサブクラス化する、というモデル。

ここに、職務(Job Title) で識別する EmployeeType クラスを導入することで、Thing( Employee )が持つ情報と、Thing-Type (EmployeeType) が持つ情報に分離する、方向に発展。

さらに、Payroll-Type (給与タイプ)と、RetirementPlanType(年金タイプ)というタイプオブジェクトを導入。

最初は、Employee という Thing レベルのオブジェクトと、年金タイプを直接関連づけていた。

Thing-Type レベルの導入


Thing-Type を導入して、発展させたモデルでは、Employee は、EmployeeType と関連づける。

そして、それぞれの EmployeeType(従業員タイプ) と、PayrollType(給与タイプ)、RetirementPlanType(年金タイプ) を関連づける。

つまり、給与制度、年金制度の選択肢を、Thing-Type のレベルで、記述し、Employee という Thing レベルとは、分離したモデルになっている。

最初の、Employee の給与タイプ別にサブクラス化して、年金タイプと直接関連づけたモデルでは、会社の制度として用意していない組み合わせを定義できちゃった。

タイプ間の関連として定義した最後のモデルだと、この「従業員タイプ」は、この給与制度で、年金制度は、これ、という会社の制度を素直に実現できた。

もちろん、制度の変更も、タイプとタイプ間の関連の変更程度で、わかりやすく、安全にできるモデルになっている。

Thing のサブクラスをThing-Type クラスへ


DDDの例に使っているモデルの before/afterを比べると、従業員のサブクラス( Thing のサブクラス)をやめて、Thing-Type のほうで、タイプ分けをしている。

モデルでは、Thing-Type でも、サブクラスがでてくるけど、実装では、extends ではなく、enum クラスで記述するのがよさそうなくらい、シンプルなオブジェクトになっている。

たぶん、Thing レベルで、サブクラス化しているモデルは、Thing-Type オブジェクトとして、タイプの違いを抽出し、enum クラスで実装、というのが、基本パターンなんだと思う。

あるいは、ドメインオブジェクトのフィールドで、String 定数や、int 定数で、区分分けをして、switch 分で処理しているような箇所を見つけたら、定数定義を、enum クラスとして抽出し、ロジックを、enum クラスに移動するとか、enum クラスを扱う Policy クラスを作って、ロジックは、そちらに移動すると、ドメインオブジェクトの役割分担がすっきりして、わかりやすいコードに改善できるはず。

calendar
     12
3456789
10111213141516
17181920212223
24252627282930
31      
<< December 2017 >>
システム設計日記を検索
プロフィール
リンク
システム開発日記(実装編)
有限会社 システム設計
twitter @masuda220
selected entries
recent comment
  • 番号より名前。 ニーモニックコードより名前。 【パターン】
    師子乃 (03/10)
  • Smart UI が優れている?
    masuda220 (03/10)
  • Smart UI が優れている?
    kagehiens (03/09)
  • オブジェクト指向プログラミングの教え方?
    masuda220 (12/05)
  • オブジェクト指向プログラミングの教え方?
    ZACKY (12/04)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (08/14)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    kompiro (08/14)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (06/13)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    JHashimoto (06/13)
  • 「オブジェクトの設計力」 スキルアップ講座やります
    masuda220 (02/28)
recent trackback
categories
archives
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM