seen from Greece
seen from Germany

seen from France
seen from China
seen from United States

seen from Germany
seen from United States
seen from Spain
seen from United States
seen from Tunisia
seen from China
seen from China
seen from Mexico
seen from Guatemala
seen from China
seen from United States
seen from China

seen from Greece

seen from Germany
seen from Canada
DDD読書会@大阪(最終回)のLT資料「ドメイン駆動設計で気づいたこと~権利の概念とERP分析への適用」 #dddosaka
DDD読書会@大阪(最終回)のLT資料「ドメイン駆動設計で気づいたこと~権利の概念とERP分析への適用」 #dddosaka from akipii Oga
オージス総研の「ドメイン駆動設計」の記事に、「戦略的DDDをエンタープライズアーキテクチャに適用した事例」の内容があったのでメモ。
「ドメイン駆動設計読書会@大阪」第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」。レストランレビューサイトの「評価」。
ref. 肥大化したActiveRecordモデルをリファクタリングする7つの方法:翻訳(値オブジェクトのサンプルがあります)
ref. 実践的な設計って、なんだろう?
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の主戦場(?)であるアプリケーションのコアドメインではなくて、汎用的なライブラリ(コアドメインから利用される、外側のパッケージに属している)と思います。汎用ライブラリを自分がこれから作る、という際には、そこが自分にとってドメインとなるのかなと思っています。
参考記事
PHPメンターズ -> 時計オブジェクト(ドメインクロック)を導入してテスト容易性と意図性を高める
振り返り
読書会も8回を経て、さすがに基礎部分の理解はできてきました。(これはDDD本に直接書いてあることではないけれど、)読書会で聞いた「共通性」、「可変性」という言葉を知っているだけでも、実務でのクラス設計が良い方に変わったのを感じます。今回のような復習ブログを書くのは、今後はお休みにして、以降はもう少し、自分自身がコード等でアウトプットできるような形でやっていけたら良いなと思っています。(現状だと、ブログを書くと、誰かの引用だけで力尽きてしまう感じなので、そこからもう一歩進められたらと)。
「ドメイン駆動設計読書会@大阪」第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設計の剥離が、目下の課題と考えておりましたので、大変勉強になりました。
コード・ファーストがその解に近いと思っておりますが、まだ考えがまとまっていないので、この点は改めて考えてみたいと思います。
「ドメイン駆動設計読書会@大阪」第6回復習メモ
プログラミング道場生 kumamidoriです。 5月6日に、「ドメイン駆動設計」読書会の第6回を行いました。今回で、第1部「ドメインモデルを機能させる」を読了できました。DDD本の基礎編を終了した形となります。公式レポートはこちらにあります。 今回は、スペシャルなゲストとして、IT勉強宴会の主催をされていらっしゃる、佐野さんにお越し頂くことができました。大変有意義なディスカッションとなりました。惜しみないシェアに感謝いたします。
この記事では、基礎編終了という1つの節目にあたり、個人的なまとめとして、下記の2テーマについて書きたいと思います。
「ドメイン駆動設計とは何か」を簡単に言うとしたら、どんなふうに説明できるか?
CodeIQに出題されていた、増田亨さんからのオブジェクト指向設計の問題(これまでの知識を使って自分なりに考えてみた)
「ドメイン駆動設計とは何か」を簡単に言うとしたら、どんなふうに説明できるか?
以前、飲み会で、デザイナさんに何気なく読書会の話をした時に、「ドメイン駆動設計?何ですか、それ?」と自然に聞き返されて、答えられなかったことがあります。(隣に座っていたエンジニアさんが、「それは、お名前ドットコムで、ドメイン取ってから開発することです」と真顔でジョークを言っておりました)。 自分なりの説明を書いてみたいと思います。
・・・・・・・・・・・・・・・・・・・・ ドメイン、という英語は、直訳すると、支配領域、という意味です。 システム化したい対象領域、というイメージが近いです。 たとえば、私が家計簿アプリをこれから作るとしたら、「預金」にはどういう種類があるものか?とか、残高とはどうやって計算するのか?とか、家計簿に関する知識をある程度持っていないと、作り始めることが難しいです。ソフトウェア開発の難しさは、プログラミング言語の習得とか、フレームワークの使い方とか、そういった解決方法ももちろん難しいわけだけれど、それ以上に、実は、そもそも作ろうとしている仕様そのもの、問題そのものが複雑で難しい。ごちゃごちゃとした仕様、対象を、分かりやすく表すために、まずは言葉を使って、問題の概念をきちんと整理すること、モデルを考えること、こういった設計情報を、そのまま実装コードにもシームレスに反映させましょう、という、考え方のことです。分かりやすく設計することで、スピーディに機能拡張ができると同時に、保守もやりやすくなります。 ・・・・・・・・・・・・・・・・・・・・
CodeIQに出題されていた、増田亨さんからのオブジェクト指向設計の問題
CodeIQの増田亨さんの問題、”「顧客区分」を列挙型で宣言し、「顧客区分」ごとに異なる振る舞いを持たせてみましょう。” を読んで、考えてみました。問題文の詳細は、設問1チラ見! というボタンから見ることができますので、そちらをご覧下さい。増田さんの出題内容とは、ずれている回答になってしまうのですけれども、これまで読書会を通して学んできた知識のまとめのつもりで、サンプルコードを作りました。
このサンプルコードで、元々の問題から大きく変えてしまっている箇所
本来は列挙型で書く問題なのだけれど、そうではなく、DB設計のデータ仕様として考えました。
回答言語:問題はJavaなのだけれど、PHPで書きました。
想定した仕様
設問からはユースケースが見えづらいので、まず、システムの目的を想像して、言葉にしてみました。このシステムでは、`顧客`とその属性(料金等)が主な関心事と思いました。
業務
営業は、自分の顧客リストを持っている。
営業は、顧客から料金を受領する仕事をするものとする。
このアプリケーションは、営業が顧客を管理することを目的とする
機能
顧客 には、3つの 顧客区分 がある。
受領する 料金 は、顧客区分に応じて決まる。
詳細仕様
顧客区分が、将来減った場合 (例:こどもが廃止された)
旧料金設定しか持たない顧客については、今回のアプリケーション外とする(運用で別途対処するイメージ)
顧客区分が増えた場合 (例:乳幼児が増えた)
新料金を顧客に設定する
料金が変わった場合 (例:100円が200円に値上がりした)
料金を更新
「料金の受領」以外にも仕事が増えた場合 (例:顧客区分に応じて、異なる文面で通知メールを送信する)
「顧客区分毎の文面」を管理対象に加える
モデリング
上記から、問題とは離れてしまいますけれども、顧客区分をデータ仕様によって表すことが、もっとも柔軟に拡張性を持たせられるように思ったので、それで考え進めてみることにしました。
データ仕様
データ仕様(渡辺幸三さんの記法(文末参考リンク[※1])を参考にした書き方です)
UML
アプリケーションレイヤーとドメインレイヤーの分離を考えました。
料金 は、誰に聞くか?で悩んだ結果、顧客 に聞くことにしました。
区分による振る舞いの制御は、継承で表現しました。
実装環境
Symfony2.4.4 ベースで作成したミニマムなコンソールアプリケーションを書きました。Githubのリポジトリはこちらです。
サンプルを書いた感想
没にした、一番最初のモデリングでは、「ものすごく変」なUMLを書いてしまい、一度捨てて、やり直したのが上記です。変になってしまった敗因としては、「設定情報は、普通、ブート時に最初からロードするよね・・・」といった、手続き的なところからスタートしてしまったからだと思います(汗 データ仕様の方はまともに書けていたので、それを足がかりにして、「料金を、誰に聞くか?」を入り口としてやり直したことにより、ましになったような気がします・・・。
参考
[※1] データモデリングのガイド
オブジェクトモデリングとデータモデリング
ドメインとアプリの区別を意識したコーディングを学ぶ
唐突だけれども、僕はユビキタス言語はAPIだと思った。APIリファレンスみたいな。 モデルはパッケージみたいな感覚で、ユビキタス言語はそのパッケージを表すAPI。 誰もが共通認識を持てる。同じ言葉で話が出来る。 ユビキタス言語の変更はモデルの変更を意味するみたいなところも妙に納得の行く感じで。 こう考えると、ユビキタス言語の導き方も割りとエンジニアリングに近い感覚で行えるような。
第四回ドメイン駆動設計読書会@大阪に参加した - hatajoeのブログ
深いモデルにするには、クラスは単なる名詞ではなく、業務ロジックやビジネス上のお金のやり取りも反映したものにすべき。 そのためには、やはり何らかの視点が必要。 その視点の一つが「責務のレイヤ」パターンであり、Policy-Control-Operationという考え方であり、T字型ERで言う事業過程・管理過程・組織過程の分類でもある。 そして、貨物輸送システムがビジネスで役立つシステムになるには、最終的には、お金のやり取りを具現化する「船荷証券」という権利をやり取りすることになる。 そこまで行き着いて、初めて、深いモデルになる。 深いモデルは、現れるクラスの凝集度が高い。 深いモデルになって初めて、モデルはユビキタス言語になる。
ユビキタス言語は概念群の凝集である: プログラマの思索