[go: up one dir, main page]
More Web Proxy on the site http://driver.im/ PHP Mentors (Posts tagged dojo)
1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna

「ドメイン駆動設計読書会@大阪」第8回復習メモ

プログラミング道場生 kumamidori です。

「ドメイン駆動設計」読書会の第8回に参加しました。内容は、こちらのWikiにまとめられています。

この記事の前半では、復習として、関連、エンティティ、値オブジェクトについて、自問自答のQ&A形式でメモします。この道の先人から教えて頂いた内容が多いです。教えて下さった方、ありがとうとざいました。後半で、勉強会後に見つけた値オブジェクトのPHPサンプルを引用して紹介します。


Q&A


関連

Q. 情報と情報の関連は、(双方向ではなく)できるだけ一方向にすること、関連を限定することにより、 管理しやすくなる、という話があった。適切に関連を見出せるかどうかは、業務分析にかかっている。間違いなくそれを行うことはかなり難しいのでは?

A. 一発ではできない。設計、実装しながらモデルを直していく(蒸留)。 関連は、業務のユースケースにより決まってくる。ユースケースのイベントにおいて関連は発生する。実装としては、ORMレベルでは双方向で定義しておき、それを利用するときに、関連の方向、I/Fを検討すれば良いかもしれない。


エンティティ

Q. データモデリング分野では、エンティティはどう定義されているか?

A. これについては、astah*チュートリアルに書いてあった内容を、下記に一部改変して要約します。
一部改変した要約:ここから

・・・・・・・・・・・・・・・・・・・・

エンティティとは、システムの管理対象となりうるもので、人、モノ、イベント、履歴などがある。 エンティティには、リソース系、イベント系、サマリー系などがあり、以下のように分類される。

  • リソース系: 会社、顧客、商品など。
  • イベント系: 会員登録・変更・削除、発注、出荷など。
  • サマリー系: 購入履歴、出荷履歴など。

「発注日」、「出荷日」のように、「〜日」を付けることができるのがイベント系エンティティと言える。

・・・・・・・・・・・・・・・・・・・・

一部改変した要約:ここまで

  • 例1:DoorKeeperのような勉強会告知サイトのシステムを運用するとして、ユーザが勉強会に参加申込をする、参加申込をキャンセルする、という機能があるとすると、これらの機能を実現するにあたって、「参加申込」情報はシステムの管理対象、エンティティとして扱います。 「参加申込エンティティ」は、動詞的な行為の記録であり、イベント系エンティティに見えます。
  • 例2:家計簿アプリを作るとして、月次予算・実績サマリー一覧画面があり、詳細画面へと遷移すると、該当月の予算を変更することができる、というような機能が必要だとします。ここでは、「月次収支サマリ」がエンティティとして扱われることになります。

Q. Web開発の現場において、エンティティは実装としてはどう扱われているか?

A. ORM的なライブラリを使っていることが多く、これがエンティティとして扱われている。 モデルを実装コードに反映するテクニックとして、たとえばユーザIDをそのままむき出しで表示側や業務ロジックで扱うのではなく、 いったんユーザエンティティに変換してから使うという工夫が採られる。DTO的な考え方。


値オブジェクト

Q. 「エンティティ」はみんな昔から使っているけれども、モデル駆動設計の構成要素として挙げられているパターンである「値オブジェクト」は、開発現場で見たことが無い。 値オブジェクトは、属性セットから成るが、DTOとはどう違うのか?

A. 値オブジェクトは、エンティティと同様に、モデルを表現し、ユビキタス言語とひも付く。情報を保持する役割を持つ。 エンティティと異なる点は、同一性、連続性を必要としないこと(識別が不要であること)。
いわゆるDTOとは文脈が違う。属性セットが主役になるという意味で、コードの見た感じがたまたまDTOと似た形になることもあるというだけ。


Q. 値オブジェクトの分かりやすい具体例としては、何が挙げられるか?

A. ユーザプロフィールの「住所」、「趣味」。eコマースの「Money」。レストランレビューサイトの「評価」。


Q. エンティティと値オブジェクトは関連するのか?

A. 値オブジェクトは、エンティティと直接関連する形になることが多いけれども、そうでないものもある。


値オブジェクトのPHPサンプル

PHPだと、初期化やバリデーションを考えると、気軽に値オブジェクトを定義する道具立ては無いそうです。現状のライブラリだと、自ドメインの値オブジェクトをエンティティにカスタム定義することは、できなくはないけれども、手間がかかるとのことです。(モデル側でのビューモデルや、ビュー側でのヘルパー機能を使って、ある程度はすでに工夫できているのが実情かもしれないと思いました)。調べたらサンプルが見つかったので、翻訳引用の形で紹介します。


PHPサンプル:Timeオブジェクト

Mathias Verraes さんがTimeオブジェクトのサンプルコードを紹介しています。元記事は名前付き引数についての考察なのですが、値オブジェクトと関係あるところだけを翻訳引用します。

翻訳引用ここから(原文記事リンク:Named Constructors in PHP

・・・・・・・・・・・・・・・・・・・・

(中略)

ユビキタス言語

コードは良い具合にきれいになってきました。時刻クラスは、大変使いやすい初期化の方法を持つようになりました。設計が良くなって、以前の設計上の欠陥はなくなり、分かりやすくなっています。時刻のインターフェイスを見てみて下さい。

<?php
$time = Time::fromValues($hours, $minutes);
$time = Time::fromString($time);
$time = Time::fromMinutesSinceMidnight($minutesSinceMidnight);

気づきましたか?3つの言葉を混同することがなくなりました。

  • fromString は、PHP実装の詳細です。
  • fromValues は、一般的なプログラミングタームでの並べ方です。
  • fromMinutesSinceMidnight は、ドメインの言語の一部です。

言語ギーク、DDDファンとしては、まだ納得がいきません。時刻はドメインの一部なので、ユビキタス言語によって取得を分けるスタイルの方が私は好きです。

  • fromString => fromTime
  • fromValues => fromHoursAndMinutes

文字数が長くなってしまうことを気にする人がいるかもしれないけれども、タイピングする必要は無いのです。コンテキストでコード補完のできるエディタを使いましょう。

・・・・・・・・・・・・・・・・・・・・

翻訳引用ここまで

※上記で翻訳紹介した「時刻」は、DDDの主戦場(?)であるアプリケーションのコアドメインではなくて、汎用的なライブラリ(コアドメインから利用される、外側のパッケージに属している)と思います。汎用ライブラリを自分がこれから作る、という際には、そこが自分にとってドメインとなるのかなと思っています。


参考記事



振り返り

読書会も8回を経て、さすがに基礎部分の理解はできてきました。(これはDDD本に直接書いてあることではないけれど、)読書会で聞いた「共通性」、「可変性」という言葉を知っているだけでも、実務でのクラス設計が良い方に変わったのを感じます。今回のような復習ブログを書くのは、今後はお休みにして、以降はもう少し、自分自身がコード等でアウトプットできるような形でやっていけたら良いなと思っています。(現状だと、ブログを書くと、誰かの引用だけで力尽きてしまう感じなので、そこからもう一歩進められたらと)。

ddd dddosaka dojo entities

「ドメイン駆動設計読書会@大阪」第8回感想

プログラミング道場生 kawakawaです。   

ドメイン駆動設計読書会の第8回に参加してまいりましたので、感想を報告させていただきます。   

    

読書会の内容は、レポート担当者さんにより、wikiにまとめて頂いております。   
第8回「ドメイン駆動設計読書会@大阪」公式レポートWiki  

 

第8回では、第5章の「エンティティ」「値オブジェクト」が範囲でした。 
(「サービス」は次回(第9回)予定) 

 

 

「エンティティ」と「値オブジェクト」

「エンティティ」「値オブジェクト」は、それぞれDDD本の用語解説から抜粋すると、  

エンティティ 

  • 本質的に、属性によってではなく、連続性と同一性の連なりによって定義されるオブジェクト。 

 

値オブジェクト 

  • ある特徴や属性を記述するが、同一性の概念を持たないオブジェクト 

以上のように記載されております。 

読書会では、この「連続性」と「「同一性」について話題が上がりました。 

同一性とは、 

  • 概念的な同一と認識するもの 

  • 同一性は追跡できるようにしておくこと 

  • 同一性を間違えると、データ破損に繋がる 

DDD本には、同一性について以下の記載がされていました。 

   第5章 「エンティティをモデル化する」より抜粋 

  • 同一性の定義はモデルから現れる。 

  • 同一性を定義するには、ドメインを理解しなければならない 

 これは、同一性というのは絶対的なものでなく、ドメインによって変化するものという事を、暗示しているのだと思います。 

 

 また、連続性については、 

  • ライフサイクル内において、同一性が続くこと 

  • 例えると、犬は年々成長し、体格は変わっていくが、その犬という概念は変化していない 

 つまり、一定期間(ライフサイクル)内で、同一性が保証される事が、連続性であると言えると思います。 

 

読書会で面白いと思った意見は、東京のミッキーマウスを叩いたら、アメリカのミッキーは痛がるのかどうかという話でした。 

単純に考えると、痛がれば「エンティティ」、痛がらないのなら「値オブジェクト」と言えそうですが、ミッキーは世界で一人(一匹?)という建前があるので、痛がらないといけないわけですね。 

 

エンティティと値オブジェクトの見分け方

エンティティと値オブジェクトの違いは、DDD本から抜粋すると、 

   第5章「 ソフトウェアで表現されたモデル」 

  • あるオブジェクトは、状態が異なったり、さらに別々の実装をまたいだりしたとしても追跡されるような、連続性と一意性を持ったものを表現しているのか? それとも、他の何かの状態を記述する属性なのか? これがエンティティと値オブジェクトとの基本的な区別である。 

とあります。  

そのまま抜き出すと、 

 エンティティ・・・実装をまたいでも、それと判る連続性と一意性を備えているもの 

 値オブジェクト・・・何等かの状態を記述する属性 

このように見る事ができます。 

 

また、第5章「関連」では下記のように記載されています  

  • 多対多の関連を辿る方向を制限することで、実装は一対多へと効果的に減らされる。これははるかに容易な設計である。 

  • ドメインにおける重要度を反映させるように、関連を一貫して限定することによって、その限定された関連は、伝達力がより豊かになり、実装もシンプルになる。 

  • ある区別をすることによって、モデルが明確になり、より現実に即して実装できるようになる 

 

オブジェクト同士の関係を単純化していくことで、モデルが明確になっていき、 エンティティや値オブジェクトを見つけやすくなりそうです。 

しかし、モデルによっては同じオブジェクトでも、エンティティ・値オブジェクトが変わる可能性がある事を、意識しておく必要がありそうです。

何故「エンティティ」と「値オブジェクト」を分ける必要があるのか?

 

オブジェクトをすべて、エンティティとみなす事への注意点として、下記のように記載されております。 

第5章 「値オブジェクト(VALUE OBJECTS)」より抜粋 

  • エンティティの同一性を追跡するのは本質的なことだが、それ以外のオブジェクトに同一性を与えてしまうと、システムの性能を損なうことになり、分析作業が増え、さらに、すべてのオブジェクトの見た目が同じになってしまうことでモデルが台無しになりかねない 

 

ドメインにとって、必要以上にエンティティを設けると、間違いを犯したり、分析に時間がかかってしまうなど、モデルが台無しになってしまうようです。 

無駄なオブジェクトの省き、モデルを単純化するという作業の中には、このようにエンティティを見極めるという作業も含まれている事を知ることが出来ました。

 

 

エンティティとデータベースの関係性

 エンティティのDB登録で、Ruby on RailsのようなActiveRecordパターンを使った実装話で盛り上がりました。 

 話の趣旨としては、 

  • SQLを書くと、間違いやミスが発生しやすい 

   (IDEによる補助を受けらない場合が多いから) 

  • SQLでは、DB実装を意識させられてしまう 

  • DBの構造と、エンティティや値オブジェクトの構造に差異がある場合が多い 

 などの理由により、如何にSQLを書かずに、実装できるかという内容でした。 

個人的には、モデルの変更スピード、コードの変更スピード、DBの変更スピードそれぞれの差異による、モデルとDB設計の剥離が、目下の課題と考えておりましたので、大変勉強になりました。 

コード・ファーストがその解に近いと思っておりますが、まだ考えがまとまっていないので、この点は改めて考えてみたいと思います。 

 

dojo ddd event design dddosaka modeling

BEAR.Sundayチュートリアル・スクリーンキャスト

プログラミング道場生 kumamidori です。

5月31日に、Nagoya.php vol.5 に参加しました。

vol.5 のテーマは、「PHPフレームワークの1つであるBEAR.Sundayを触ってみよう」でした。 参加者全員で、BEAR.SundayワークショップWiki(チュートリアル)の内容に取り組みました。 私が見つけられた範囲だと、@kenji_sさん、@qckanemoto さんがブログにまとめられていますので、そちらをご覧頂ければと思います。記事の文末にそのリンクを貼ります。

BEAR.Sundayチュートリアル・スクリーンキャスト

この記事では、スクリーンキャストで、BEAR.Sundayチュートリアルのデモを、初心者なりの解説をまじえつつ紹介します。(見る人、誰もいないかもしれませんけれど・・・。)

※今回動画を掲載することについて、フレームワーク作者に事前に許可を頂いております。

PHPカンファレンス関西について

BEAR.Sundayの作者である郡山さんは、6月28日(土)に開催されるPHPカンファレンス関西2014の基調講演をされる予定です。関西方面でご興味のある方は、懇親会の方にも申し込みされると良いかと思います。@hidenorigotoさんも遠方から来訪、参加されるそうです。

参考リンク

BEAR.Sundayに関するリンク
スクリーンキャスト内で引用した書籍

PHPメンターズブログにおける関連記事
Nagoya.php vol.5 に関するリンク

※6月29日追記:

名古屋の方から、「写真、撮っていましたよね?」とリマインドを頂いたので、貼っておきます。

image
dojo bear.sunday dependency.injection aop

ドメイン駆動設計のリポジトリパターンをプロジェクトへ持ち込む時の話

プログラミング道場生Hatajoeです。 ドメイン駆動設計読書会@大阪には初回から参加させて頂いています。 今回は、読書会で得られた知見を業務に導入する際の気付きをお話したいと考えています。

なぜリポジトリなのか

話をする前に、なぜドメイン駆動設計な開発を導入しようと思ったのかの前提を説明させて下さい。

私は普段、チームでWebアプリケーションの開発を行っています。 チームには、自分を含めて3名のプログラマーが在籍しています。 言語はPHPで、CodeIgniterというWebアプリケーションフレームワークを使用しています。

現在、私達は以下の問題を抱えています。

  • ファットコントローラー
  • コピペコード
  • テスト無し

既存機能の改修難易度が高く、機能追加でレガシーなソースが量産されるという悪循環です。 私は、これに対処するために、複雑で重複したビジネスロジックを切り出す必要があると考えました。 しかし、切り出されたビジネスロジックを如何に扱うかという点に悩まされ、 余計に手に負えないソースが散らばるという悲惨な状態になったりもしました。

ドメイン駆動設計について学びを進めていくと、ビジネスロジックの扱いについて、1つの個人的な知見を得ることが出来ました。 それは、ビジネスロジックはユビキタス言語の実装であり、ユビキタス言語は「モデル」の振る舞い(API)である。 そして、「モデル」は抽象化されたデータと振る舞い(API)から成る、という知見です。

さて、上記で示した「モデル」ですが、実際に実装するにためにはまだ部品が足りていないことに気が付きます。 それは、アプリケーションコードの中で「モデル」をどのように扱うのか、という点です。 そこでリポジトリが登場します。

実際に、「モデル」を使用したアプリケーション実装を行ってみると、仕様から「モデル」を切り出す作業が最も難しいと感じます。 「モデル」を切り出す作業には答えがありません。 日々、改善を繰り返す部分だと思っています。(出来るか出来ないか、は置いておいて…)

一方で、リポジトリの実装はパターン化出来るのではないかと考えています。 例えば、チームメンバーに自分と同じ負担を強いるのは現実的ではありません。 チーム開発においては、各々、自身が得た知見をチームのコンテキストに沿って還元することが必要だと感じています。 そのため、「モデル」を切り出す時に必要な概念的複雑さはひとまず置いておいて、未熟な「モデル」で機能を実装出来る方法。 この時、リポジトリは非常に重要な存在になるように思えたわけです。

リポジトリの役割

エリック・エヴァンス氏は、リポジトリをモデルのライフサイクルを管理するオブジェクトだと定義しています。 ライフサイクルを管理する、ということが一体どういったことなのか。 自身の開発に落としこんでみると、ファットコントローラーからビジネスロジックとデータを切り出したそれらを扱うグルーのような存在であることに気が付きます。

ここで、説明を単純化するために、ビジネスロジックとデータを切り出して作り上げたオブジェクトを「ドメインクラス」と呼ぶことにします。 ドメインクラスについての詳しい説明はひとまず置いておいて、リポジトリの役割について注目します。

端的にリポジトリの役割を示すと以下のようになるかと思います。

  • リポジトリは、ストレージからデータを取得し、ドメインクラスにデシリアライズする。
  • リポジトリは、ドメインクラスをシリアライズし、ストレージに保存する。
  • リポジトリは、ビジネスロジックを持たない。

これまでは、コントローラーからデータを直接取得していたところ、リポジトリを使用して、ドメインクラスを取得するように設計します。 これは、コントローラーがモデルの振る舞い(API)を利用してデータ操作(仕様)を実現するという形です。 こうすることで、仕様変更(データの変更)はリポジトリ内に局所化されるようにし、また、ビジネスロジックはドメインクラスに局所化するように設計します。(これはこれで結構難しいですが。。)

ドメインクラスがモデルのインターフェースとして機能し、それはユビキタス言語を実現したモデルのAPIとして振る舞い、データを隠蔽する。 リポジトリは、これらの一端を担う重要なファクターになると思います。

リポジトリの実装

以下を実装することになります。

  • データストレージからデータを取得してドメインクラスを生成する
  • ドメインクラスからデータを受け取ってデータストレージへ保存する

CodeIgniterを使用する場合、データストレージへのアクセスはCodeIgniterのモデルクラスを使用します。 リポジトリは、CodeIgniterのモデルクラスを利用してデータストレージからデータを取得し、ドメインクラスを生成します。

<?php 

// とあるドメインクラス
// RPGのプレイヤークラスとする
class Player
{
    private $id;
    private $name;
    private $items;

    public function __constract($id, $name) {
        $this->id   = $id;
        $this->name = $name;
    }

    public function get_id() { return $this->id; }
    public function get_name() { return $this->name; }
    public function set_items($items) { $this->items = $items; }
    public function get_items() { return $this->items; }
}

// とあるドメインクラス
// RPGのアイテムクラスとする
class Item
{
    private $id;
    private $name;
    private $num;

    public function __construct($id, $name, $num) {
        $this->id   = $id;
        $this->name = $name;
        $this->num  = $num;
    }

    public function get_id() { return $this-id; }
    public function get_name() { return $this->name; }
    public function get_num() { return $this->num; }
    public function consume() { $this->num -= 1; }
}

// プレイヤーリポジトリ
// CodeIgniterのモデルクラスからデータを取得し、Playerを生成する
class PlayerRepository
{
    private $CI;

    public function __construct($CI) {
        $CI->load->model('Tbl_player');
        $this->CI = $CI;
    }

    // プレイヤーのみ取得
    public function resolve_by($player_id) {
        $p = $this->CI->Tbl_player->find_by_id($player_id);
        return new Player($p->id, $p->name);
    }

    // プレイヤーと所持アイテムを取得
    public function resolve_with_items_by($player_id, $item_repository) {
        $player = $this->resolve_by($player_id);
        $items = $item_repository->resolve_by($player_id);
        $player->set_items($items);
        return $player;
    }
}

// アイテムリポジトリ
// CodeIgniterのモデルクラスからデータを取得し、Itemを生成する
class ItemRepository
{
    private $CI;

    public function __construct($CI) {
        $CI->load->model('Tbl_item');
        $this->CI = $CI;
    }

    // プレイヤーの所持アイテムを取得
    public function resolve_by($player_id) {
        $items = [];
        foreach ($this->CI->Tbl_item->find_by_player_id($player_id) as $i) {
            $items[] = new Item($i->id, $i->name, $i->num);
        }
        return $items;
    }
}

ドメインクラスを保存する場合はリポジトリ経由でCodeIgniterのモデルクラスへデータを渡し保存します。

<?php 

class ItemRepository
{
    public function register($item) {
        $this->Tbl_item->update($item->get_id(), $item->get_num());
    }
}

まとめ

ドメイン駆動設計と言いながら、肝心なドメインモデルの設計・実装は必要最小限に止め、まずは導入してメリットを得るためにリポジトリパターンにフォーカスしました。必ずしも、ドメイン駆動設計という枠の中で開発を行わなければいけないということはないと思います。 重要なのは、今出来る改善をチームで実行出来る状態にすることだと考えています。 自身のコンテキストに沿ったドメイン駆動設計を考えてみると、案外手近なところに改善案が見つかるかもしれません。

参考

dojo ddd repository codeigniter

「ドメイン駆動設計読書会@大阪」第6回感想

プログラミング道場生 kawakawaです。
ドメイン駆動設計読書会の第6回に参加してまいりましたので、感想を報告させていただきます。

読書会の内容は、レポート担当者さんにより、wikiにまとめて頂いております。
第6回「ドメイン駆動設計読書会@大阪」公式レポートWiki


今回でDDD本の第1部の範囲が終読致しました。
そこで、第1部全体での振り返りを行いたいと思います。

(2014/06/10 追記)
本から抜粋と記しているところを、抜粋元が不明瞭とのご指摘を頂きましたので、引用元箇所を明記しました。

ドメイン、モデル、ユビキタス言語の関係性

DDD本(第1部範囲)から記載されていた言葉を抜粋すると、

ドメイン

「第1部 ドメインモデルを機能させる」(中国世界地図の後)
すべてのソフトウェアプログラムは、それを使用するユーザの何らかの活動や関心と関係がある。ユーザがプログラムを適用するこの対象領域が、ソフトウェアのドメインである。ドメインの中には、物理的な世界をふくんでいるものもある。

モデル

「第1部 ドメインモデルを機能させる」(中国世界地図の話)
モデルとは簡素化である。つまり、当面の問題を解決する上で関連する側面を抽象化し、それ以外の詳細を無視することによって行われた、現実に対する1つの解釈なのだ。

「第2章 コミュニケーションと言語の使い方」(章の冒頭)
モデルとは、プロジェクトに携わる人々の頭の中で構築された概念の集まりであり、ドメインについての洞察を反映した、用語と概念間の関係性からきている。

ユビキタス言語

日本語推薦文:榊原 彰氏
書籍の冒頭からドメイン知識を得ることの有用性と、抽象的な議論に陥らずにドメインエキスパートとIT 技術者が有益な協力を行うことの重要性に言及している。
この書籍の中で新しく提唱された言葉である「ユビキタス言語」という考え方はまさにそうした根本概念を端的に表すものだと言ってもいいだろう。

日本語推薦文:平鍋健児氏
私自身がDDDの中で特に気に入っているのは「ユビキタス言語」。
ケント・ベックがエクストリームプログラミングにおいて「メタファ」(Metaphor)というプラクティスで表現しようとしたのは、顧客から開発者までが会話できる共通ボキャブラリの提供です。
これこそが、DDDにおいてユビキタス言語と呼ばれているプラクティスであり、ソフトウェアデザイン活動のコアであろう、と私は考えています。

(※2014/05/25 追記)
kumamidoriさんから、DDD本巻末に記載されている用語解説から、説明文を引用されてはと、ご提案頂きました。
確かに、その方が適切かと思いますので、下記に用語解説から、それぞれの解説文を記載致します。
(上記の単語解説文は、DDD本第1部範囲から、私が抜粋したものとなります)

DDD本用語解説

  • ドメイン・・・知識、影響、または活動の領域。
  • モデル・・・ドメインにおける選択された側面を記述し、そのドメインに関連した問題を解決するのに使用できる抽象の体系。
  • ユビキタス言語・・・ドメインモデルを取り巻いて構築され、チームのあらゆる活動をソフトウェアと結びつけるために、チームメンバ全員によって使用される言語。

DDD本の第1部から、私が感じ取ったイメージを図にすると下記のようになりました。

image

図1:ドメイン_モデル_ユビキタス言語の関係図

ドメインは、見方や観測者によって姿・形が変わる雲のようであり、そこから、抽象化(≒誰が見ても同じ形に見えるように)取り出したのがモデルで、モデルはユビキタス言語にて構成されているイメージです。

モデルは、モデルA・B・Cのように、抽象化した内容が異なれば、その分ドメイン内に複数存在することになります。
抽象化によっては、ユビキタス言語(語彙2)を通じて、モデルAとBが重複しているように、モデル同士の領域が重なる事もあります。

ユビキタス言語は、ドメインに対してユニークであり、ユビキタス言語(語彙1~5)は、それぞれ個別の語彙である事を示しています。

(※2014/05/22 追記)
久保さんから、「モデルの名前も、ドメイン内でユニークであるのなら、ユビキタス言語の語彙といえると思います」とのご指摘を頂きました。
なるほど、確かにモデル名もユビキタス言語と言えると思います。ご指摘有難うございました。

DDDにおける「モデル」とは?

DDD本では、モデルは関係者間のコミュニケーションツールであると、書かれていますが、 別の見方をすると、モデルこそが、開発者とドメインエキスパートが、ドメインを認識しあえる 唯一のツールでは無いかと思っています。

モデルという語彙が示すものという話になりますと、言葉の綾的な処がございますので、 実際にモデルはどのようなものなのかを考えてみたいと思います。

まず、思い浮かぶのが図・UMLや、業務分析シートや要求仕様書などのドキュメント関係を思い浮かべますが、DDD本に記載されていたモデルとは、

「第2 章コミュニケーションと言語の使い方」「ドキュメントと図」(中盤)
言語に対するこうした変更は、ドメインモデルに対する変更として認識され、用語の意味が変わった場合には、チームがクラス図を更新して、コード中のクラスやメソッドの名前を変えたり、ふるまいを変更したりすることにまでつながる。

「第2 章コミュニケーションと言語の使い方」「ドキュメントはコードや会話での表現を補わなければならない」(最初)
動作しているコードが嘘をつくことはないが、他のドキュメントだとその可能性がある。
動作しているコードのふるまいには、あいまいなところがないのだ。

「第2 章コミュニケーションと言語の使い方」「ドキュメントと図」(後半)
常に覚えておいて欲しいのは、モデルは図ではないということである。
図の目的は、モデルについてコミュニケーションし、説明するのを助けることにある。

「第3 章モデルと実装を結びつける」「モデル駆動設計」(後半)設計で使用する用語法と責務の基礎的な割り当てをモデルから引き出すこと。コードはモデルの表現となるから、コードに対する変更はモデルに対する変更になるかもしれない。
その影響は、プロジェクトの他の活動全体へと適宜伝わっていかなければならない。

「第3 章モデルと実装を結びつける」「骨格を見せる:なぜモデルがユーザにとって重要なのか?」(終盤)

モデルが明らかになれば、ユーザはソフトウェアの潜在能力にもっと触れられるようになり、ふるまいは一貫した予測可能なものになる。

と記載されています。 

一般的にイメージしがちな、図・UMLなどドキュメントを、モデルと見なすことに、警告を示されています。

確かに、図・UMLだけでは、簡易表記により、誤解を招いたり、逆に詳細に記述し過ぎて、視認性を悪くしたりして、モデルの意図・目的が上手く伝わらない危険性があるかとは思います。

しかし、コミュニケーションツールとしてのモデルを考えた場合、プログラムコードだけでは、ドメインエキスパートとコミュニケーションとるのは難しそうです。 

やはり図やUMLなどドキュメント類が欲しい処です。

DDD本で紹介されていた手法としては、先にプログラムコードを書き、その補足として、図・UMLを書きなさいと記載されておりました。 

従来の図・UMLからプログラムコードへの手法と逆になりますが、先にプログラムを書くことで、図・UMLで設計する必要がなくなり、図・UMLが無駄のない、目的を明確化したドキュメントになるという事で、成程と思いました。

ウォーターフォールでDDDはできるのか?

ウォーターフォールの開発環境でも、DDDはできるのでしょうか。
DDD本で、ウォーターフォールに関して記載された箇所を抜粋すると、

「第1 章知識をかみ砕く」「知識のかみ砕き」(中盤)
旧来のウォーターフォール手法では、ビジネスエキスパートがアナリストに話をして、アナリストがかみ砕き、抽象化して、その結果をソフトウェア作成者であるプログラマに伝える。
このアプローチがうまくいかないのは、フィードバックが完全に欠けているからだ。
アナリストはモデルを作成する全責任を負っているが、基になるのはビジネスエキスパートから得た情報だけだ。
プログラマから学んだり、ソフトウェアの初期バージョンを体験したりする機会は全くない。
知識は一方向に少しずつ流れるだけで、蓄積されないのである。

「第1 章知識をかみ砕く」「知識のかみ砕き」(後半)
チームメンバ間のやりとりは、メンバ全員がモデルを一緒にかみ砕くことで変化する。
ドメインモデルを絶えず改良すると、開発者は、自分が力を貸しているビジネスにおける重要な原理を習得するように強いられ、機械的に機能を作り出すことがなくなる。
一方、ドメインエキスパートは、自分の知っていることを蒸留して本質を抽出するように強いられることによって、しばしば自分の理解を精緻にし、ソフトウェアプロジェクトが必要とする概念の正確さを理解するようになる。

「第1 章知識をかみ砕く」「知識のかみ砕き」(後半)
改善されるにつれて、モデルは、プロジェクトの中を流れ続ける情報を体系化するためのツールとなっていく。
モデルは、要件を分析することに焦点を合わせているが、プログラミングや設計とも深く相互作用する。好循環が起きれば、こうしたモデルの性質によってチームメンバのドメインに対する洞察が深まり、状況がより明確に理解できるようになって、モデルがさらに精緻化される。
このようなモデルは、決して完成することがない。
代わりに、進化していくのだ。

「第1 章知識をかみ砕く」「継続的学習」(後半)
アプリケーションのコアは別にあることがわかったので、その側面を舞台の中央へ持ってくるようにモデルが変更されたのである。
ドメインエキスパートがより多くを学んだことで、アプリケーションの目標が明確になったのだ。

ウォーターフォールでDDDが、出来る/出来ないとは書いていませんが、アジャイル開発と比べて次の点でDDD実践は難しそうです。

  • モデルを修正・補正する機会が無い 
  • ドメインエキスパートが情報蓄積・学ぶ機会が無い 


フィードバッグループが大きくなってしまうという、ウォーターフォールのデメリットがネックになりそうです。

余談ですが、読書会で出た話として、

  • アメリカは内製開発が多く、日本は外部開発が多い 
  • 日本の場合、SIerのほうが、顧客よりもドメインエキスパートになっているときがある 

という話題がありました。

これらから推測すると、

  • 日本はSIerなど外部がウォーターフォールで開発を行う。 
  • 開発で得られた知識は、顧客ではなく、SIerに蓄積されていく。 

このような流れになっていると思われます。

ウォーターフォール開発については、開発側視点で納期や予算などで問題が多いという議論は多いですが、発注側の「知の蓄積欠如」・「学びの機会損失」という視点は想定していなかったので、面白い発見ができたかなと思います。

第1部のまとめ

ソフトウェア開発を「設計」と「実装」にわけると、それは「戦略」と「戦術」のような関係だと捉えています。
今まで、「戦術」部分を磨くべく、学んできましたが、「戦術」だけでは太刀打ちできない、「戦略」の壁を感じる事が多くなってきたので、「戦略」を学ぼうと思ったのが、DDD本を読み始めたキッカケでした。

DDD本第1部を読み終えて思うことは、この本は「戦略」方法が直接書いているわけではなく、「戦略」のための「戦略」が書いているのだと。
その為、多少判りにくい処のはありますが、まずは最後まで読み終えてみたいと思います。

また、第1部で生じた疑問点は、第2部以降、続きを読み続けていく中で、解消していきたいと思います。


  • 疑問1 :深いモデルを作りだすコツはあるのか? 
  • 疑問2 :DDDの実践方法(プラクティスやツールなど)。どうやって現場に広げるのか。 
  • 疑問3 :複雑なドメインとはどのような事を示すのか? 

振り返り

Keep

  • 第1部まで読み終える事ができた

Problem

  • 第1部内でも理解が足りない処がある(特に第3章)
  • 感想文の提出が1週間超えてしまった。

Try

  • 第1部読み直し。
  • 感想文提出1週間を目指す。
dojo ddd event kpt design dddosaka modeling