[現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法](https://gihyo.jp/book/2017/978-4-7741-9087-7) のメモ 本のサンプルソースはJavaで書かれているが、勉強も兼ねてGo言語にアレンジしている。 # Chapter4 ドメインモデルの考え方で設計する ## ドメインモデルの考え方を理解する ### ドメインモデルで設計すると何が良いのか >[name=Yusaku Matsuki] > 業務ロジックがシンプルな場合は手続き型の設計でも良いということか。 ### ドメインモデルの設計は難しいのか ### 利用者の関心事とプログラミング単位を一致させる ### 分析クラスと設計クラスを一致させる > [name=Yusaku Matsuki] > 要件定義から、設計、プログラミングをする人がやるべきというのは、Scurmの源流でもある"The New New Product Development Game"でも書かれており、Scrumとオブジェクト指向(ドメインモデル)が相性が良いのではないか。 > むしろ両者ともこの論文にある程度影響されているのではないか? > > 特にTypeCは全工程のメンバーがひとつのラグビーチームかのようにボールを回しながらゴールへ向かっていることを意味しています。 > > そして、この論文ではTypeCのようなチームを”Scrum”と名付けました。 > > [“The New New Product Development Game”とAgile with ScrumとLean](https://medium.com/i35-267/the-new-new-product-development-game-%E3%81%A8agile-with-scrum%E3%81%A8lean-883578439651) ### 業務に使っている用語をクラス名にする ### データモデルではなくオブジェクトモデル > [name=Yusaku Matsuki] > データモデル = 手続き型 > ドメインモデル = オブジェクト指向 ### ドメインモデルとデータモデルは何が違うのか ### なぜドメインモデルだと複雑な業務ロジックを理解しやすいのか ## ドメインモデルをどうやって作っていくか ### 部分を作りながら全体を組み立てていく ### 全体と部分を行ったり来たりしながら作っていく > [name=Yusaku Matsuki] > オブジェクト指向では個々の部品から作っていく。 > 一方で全体を俯瞰するのも必要。 > 俯瞰する道具として以下を使う。 > - パッケージ図 > - 業務フロー図 ### 重要な部分から作っていく ### 独立した部分を組み合わせて機能を実現する ### ドメインオブジェクトの機能を一部として設計しない > [name=Yusaku Matsuki] > 「機能の分解構造や時間的な依存関係を持ち込まれた」形の具体例がしりたい。 ## ドメインオブジェクトの見つけ方 ### 重要な関心事や関係性に注目する - 業務に必要なドメインオブジェクトを、最初から網羅的に見つけることはできない。 - 機能を組み立てていく過程で明らかになる。 - 業務アプリケーションは対象とする業務データの種類が多く、そのデータを使った判断/加工/計算の業務ロジックをプログラムで実現するには多くの業務知識が必要。 - 闇雲に手を出すのではなく、業務の重要な関心事とそれほど重要でない関心事を区別し、重要な関心事から手を付ける。 - 重要な関係性や構造を発見するにはどうすればよいか?次節から説明される。 ### 業務の関心事を分類してみる - 業務を分解し理解する技法やパターンは様々ある。 - ひとつに、業務の関心事を**ヒト/モノ/コト**の3つに分類する方法がある。 | 分類 | 例 | | -------- | -------- | | ヒト | 個人、企業、担当者、など | | モノ | 商品、サービス、店舗、場所、権利、義務、など | | コト | 予約、注文、支払、出荷、キャンセル、など | - ヒト - 業務活動の当事者。意思があり、判断し、行動する主体。 - ヒトという関心事に対応するドメインオブジェクトは、ヒトの意思/判断/行動についてのデータを持ち、データを使った判断/加工/計算のロジックを持つ。 - モノ - ヒトが業務を遂行するときの関心の対象。 - 物理的なモノだけでなく、権利や義務のような概念的に認識している対象もモノに属する。 - モノに対する関心事を表現する属性は以下。 - 数量、金額、率 - 説明、注釈 - 状態 - 日月や期間 - 位置 - モノを表現するオブジェクトは、これらの属性を表現するデータと、データに対して業務的にどういう判断/加工/計算をしたいかをロジックとして持つ。 - コト - 業務活動で発生する様々なコト(事象)。 - 業務アプリケーションの基本的な関心事は、コトを記録し、コトの発生を通知すること。 - ヒトの意思決定や行動の結果。 | 属性 | 説明 | | -------- | -------- | | 対象 | 何についての発生した事象か | | 種別 | どういう種類の事象か | | 時点 | いつ起きた事象か | - 事象が、業務的に起きて良いことなのかの判断や、起きた場合に何をすべきかの判断は、重要な業務の約束事。 ### コトに注目すると全体の関係を整理しやすい - 3分類するだけでは業務知識を整理できない。 - 何が重要かを見極め、関心事の関係を明らかにする。 - そのためには「コト(事象)」に注目して整理するとこが効果的。 - たとえば、 1. 受注するために顧客に見積書を提示 1. 受注できたら出荷 1. 出荷したら請求 1. 期日までに入金されたことを確認 - 仕事の流れを一連のコトの連鎖として捉えるとで、開発者にとって具体的で比較的とりつきやすい業務知識になる。 - コトに注目すると次の関係も明らかになる - **コトはヒトとモノの関係として出現する(だれの何についての行動か)** - **コトは時間軸の流れに沿って明確な前後関係を持つ** - ヒトとモノに注目すると発散しがち。 - ヒトは様々な業務の当事者として登場する。ヒトに関連するデータとすべての業務ロジックを調べ上げるのは簡単では無いし、業務の基本的な流れや重要な関連性が膨大な情報の中に埋もれてしまう。 -> 重要な関心事を見つけられない。 - モノもヒトと同様。 ### コトは業務ルールの宝庫 - コトの背後には様々な業務ルールが隠されている。 - 開発者が業務知識を明確に理解すればするほど、ドメインモデルは、業務の知識を正確に反映した役に立つ業務アプリケーションの基盤になる。 - 販売活動を例に時間軸に沿った一連の出来事の発生と、それぞれの出来事とヒト/モノの関係を考える。 - 受注 - 出荷 - 請求 - 入金 - 販売管理アプリケーションは、これらの順番に発生する出来事(業務の流れ)を適切にすすめるための道具。 - 受注を起点に、出荷指示をし、請求書を発行し、入金されたらそれを記録して1つの業務サイクルが完結する。 - 4つのコトの中で受注は他と異なる点が2つある。 - **発生源が外部のヒトである** - **将来についての約束である** - この2点が、コトを軸にした業務ルールを把握するための要点になる。 - 受注は、買い手が注文し、売り手が同意することで成り立つ。 - つまり、買い手という外部のヒトと、売り手という内部のヒトの二者の合意。 - また、将来についての約束というのは、売り手は出荷を約束し、書いては支払いを約束すること。 - この約束を適切に管理し、実行を追跡し、約束どおりに完了させることが販売アプリケーションの基本目的。 ### 何でも約束してよいわけではない - 受注は約束。 - 受注というコトが発生したときには、内容が妥当であることを確認しなければならない。 - 在庫はあるか(出荷可能か) - 与信限度額を超えてないか - 自社の販売方針に違反してないか - 相手との事前の決め事(取引基本契約)に違反してないか - ... - 妥当性を確認するために業務ロジックが必要。 - このデータとロジックの置き場所がドメインオブジェクト。 - 妥当性の業務ルールは、以下のような複雑さを持っている。 - 約束の相手が誰かによって、約束して良い範囲が異なる - どの商品についての約束かによって、金額や納期が異なる - どのタイミングの約束かによって、金額や納期が異なる - 注文内容が適切でなかった場合に、どのような行動を起こすべきかも重要なビジネスの決め事。 - 妥当性のルールを特定したら、そのルールを実現するデータとロジックの組み合わせを考える。 - 数量に関する業務ロジックは数量クラスにまとめる。 - 数量が個数単位と箱単位での扱いが必要なら数量単位クラスを追加。 - いくつまで受注してよいかを判断するロジックを販売可能数量クラスに持つ。 - これらをまとめたクラスを数量パッケージにまとめる。 - 数量パッケージは受注機能の一部ではない。 - 「数量」という狭い関心事に焦点を当て、その部分だけを独立させて、業務ロジックを整理したもの。 - ドメインモデルの設計のアプローチは、まず部品を特定し、その部品ごとに独立したクラスを設計すること。 - 数量パッケージと同じように、与信パッケージや基本契約パッケージについても独立して設計する。 - ある程度の部品が揃ってきたら、組み合わせを考える。 - 組み合わせながら、個々の部品を知りしたり、不足している部品を追加することで、受注ルールを網羅できるだけのドメインオブジェクトが整っていく。 ### 期待されること、期待されないこと - 注文(売買契約)は売り手と買い手の双方向の約束。 - 約束の実行を支援し、監視するのが業務アプリケーションの基本機能。 - 受注という「コト」の発生を起点として、以降に発生するコトについて、次の判断や行動に関するルールが存在する。 - 期待された通りの内容科判断する - 期待されていた場合の次のアクション - 期待されていなかった場合のアクション - 商品10個の注文について、約束した期日までに5個しか出荷できなかったら期待された結果ではない。 - 残りの5個についてどのように対応するか一定の取り決めが必要。 #### 実行されなかったことの検知と対応 - 検知には以下が必要。 - 予定を記録する - 実績を記録する - 差異を記録する - 約束したこと(予定)を記録し、実行したこと(実績)を記録し、適切なタイミングで、予定と実績の差異を出す。 - 差異が見つかった場合、一定の決め事に従って通知を行う。 - このような業務ルールを実現するためのクラス候補は、予定クラス、実績クラス、差異クラスなど。 #### 取り決めのない取り決め - より深い業務知識として、取り決めがなかったケースが実際に起きた場合の対応ルールがある。 - どこまで実装するかは別として、以下の点を心に留めておくと、業務ルールの発見や理解に役立つ。 - 業務では必ず想定外のことが起きる - 想定外のことが起きたときに、どう対応するかの原則がある - 多くの場合は、適切な関係部署に想定外のコトがおきたことを通知して、対応自体は業務担当者にまかせることになる。 #### 業務ルールの記述 ~手続き型とオブジェクト指向の違い - プログラムを書く視点からは、業務ルールの実態は以下の判断ロジック。 - 数値の一致や大小比較 - 日付の一致や前後比較 - 文字列の一致/不一致の判断 - 膨大で複雑な業務ルールも、if文の判定と場合ごとのアクションに分解できる。 - 手続き型の場合は、データクラスを受け取った機能クラスで、条件分岐を実行する。 - 条件の組み合わせは基本的にif文の入れ子になる。 - トランザクションスクリプトと呼ばれる手続き型の業務ルールの記述方法。 - オブジェクト指向の場合は、判断のもとになるデータとロジック毎にオブジェクトを生成する。 - if文の入れ子構造にならない。 #### 業務ルールの追加や変更への対応 - 先述したアプローチの違いによって、業務ルールの追加や変更時に、プログラミングのやりかたに違いが出る。 - 手続き型は元々のif文の分岐構造に新たな分岐を追加する。 - 業務ルールが増えるほど分岐構造が複雑になる。 - 同じデータを受け取る可能性がある別のトランザクションスクリプトにも同じような分岐の追加が必要になる可能性がある。 - 変更が厄介で危険になる。 - オブジェクト指向のドメインモデルでは、新たなルールの追加は、ルールの判断のもとになるデータを持つオブジェクトの判断ロジックを追加する。 - 1つのドメインオブジェクトが持つデータは大抵の場合1つか2つ。 - 少ないデータに関連するロジックだけなので、変更は単純になり、楽で安全になる。 ## 業務の関心事の基本パターンを覚えておく ## ドメインオブジェクトの設計を段階的に改善する ## 業務の理解がドメインモデル洗練させる > [name=Yusaku Matsuki] > - ドメインエキスパートとコミュニケーションをとってドメインモデルを洗練させましょうという話 > - 要件定義や仕様検討段階で使えるテクニック ### 業務知識を取捨選択し、重要な関心事に注力して学ぶ - ドメインモデルは、開発者が理解している業務知識の広さと深さを反映する。 - 一方でありとあらゆる業務知識が必要なわけでない。 - 業務を効果的に学び、役立つドメインモデルを設計するための基本が2つある。 - 重要な言葉とそうでない言葉を判断する - 言葉と言葉の関係性を見つける ### 業務知識の暗黙知を引き出す - 業務知識は、実際に業務を経験している人の頭の中にあり、体系的に整理されたものではない。 - 言語化されていない業務知識を開発者が知る手がかりが「言葉」と「会話」。 - 会話することで「聞き慣れない」言葉や使い方に「違和感」がる言葉が出てくる。 - 開発者が業務知識を獲得して業務を整理する重要な手がかりになる。 - 業務経験者の言葉はクラス名やメソッド名の候補になる。ドメインモデルを設計する基本の活動。 ### 言葉をキッチする - 聞き慣れない言葉や理解できていない言葉は気逃しがち。また、自分が知っている言葉に無意識に置き換えたり、相手の意図とは異なる意味に勝手に解釈しがち。 - 会話後にアウトプットしてみて、他の人に確認してもらうことで上記を可視化できる。 - 次のような方法で言語化する - ホワイトボード(+写真) - チャットやメールなどのQ&A - ディスカッションボード(テーマごとに議論を記録して読み返せるオンラインツール) - オンラインのTo-Do管理ツール ### 重要な言葉を見極めながらそれをドメインモデルに反映していく - 業務経験者との会話で、用語を適切に使い、かつその内容が業務の重要な関心事があれば相手の反応が積極的になる。 - その言葉をそのままクラスにし、クラス間の関係を言葉と言葉の関係に対応させれば、ドメインモデルの中核が形になる。 ### 形式的な資料はかえって危険 - 形式的なドキュメントを大量に作っているときは「思考停止」が始まっている。 - 重要な言葉が何で、骨格となる関係は何かを判断することに時間を使うべき。 - また、業務を理解するには、詳細を網羅した情報よりも、まずは業務の専門家にとって重要な関心事や、業務の基本構造を理解することが重要で効果的。 - 全体を俯瞰しながら要点と重要な関係を共通理解にするために次の図法が役に立つ。 - コンテキスト図 - 業務フロー図 - パッケージ図 - 主要クラス図 | 図法名 | 目的 | | -------- | -------- | | コンテキスト図 | システムの目的を表す言葉を探す(重要なクラスの発見の手がかり) | | 業務フロー図 | コトの発生を時系列に整理する | | パッケージ図 | 業務の関心事を俯瞰する(用語との全体的な整理) | | 主要クラス図 | 重要な関心事とその関係を明確にする | - 考えるための道具で、公式ドキュメントとして維持する必要はない。 > [name=Yusaku Matsuki] > - ラフ画を書いてシェアするというのは実践したい。 ### 言葉の曖昧さを具体的にする - 会話は「感覚的」であいまいさがつきまとう。 - あいまいな言葉を取っ掛かりに、具体的な手がかりを得る。 > [name=Yusaku Matsuki] > - あいまいな言葉に対して5W1Hで質問し続ければ具体化できそう。 ### 基本語彙を増やす努力 - ドメインモデルの設計のやり方として、まず対象業務の基本知識を身に着けるところからはじめなければならない。 1. その業務のマニュアルや利用者ガイドを読んで見る 1. その業務の一般的な知識を書籍などで勉強する 1. その業務で使っているデータに何があるか画面やファイルを調べる 1. その業務の経験者と会話する - 順番にやるのが良い。 ### 繰り返しながらしだいに知識を広げていく - 開発者は業務の専門家では無い。 - 専門家との会話や資料の中に見落としや勘違いがあれば、修正を繰り返していくことが大切。 - そうやって業務知識を広げ、プログラムの設計に取り入れることで、役立つソフトウェアになる。 ### 改善を続けながらドメインモデルを成長させる - 業務アプリケーションの変更理由で多いのは「業務ルールが変わる」こと。 - 設計の見直しの絶好の機会。 - ドメインモデルの設計に模範解答は無いが、関係者でレビューを行うことが「より良い」解答を探し続ける方法。 - 「言葉」の使い方のチェックを行う。 - ドメインモデルに登場する変数名/メソッド名/クラス名/パッケージ名を使って、業務の流れを声に出して説明する。 - 意図が伝わればOK。伝わらなければ改良の余地あり。 ## 第4章のまとめ ###### tags: `ISBN-978-4-7741-9087-7`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up