Publicité

ドメイン駆動設計サンプルコードの徹底解説

ソフトウェアシステムの設計・構築 à システム設計
5 Apr 2019
Publicité

Contenu connexe

Présentations pour vous(20)

Similaire à ドメイン駆動設計サンプルコードの徹底解説(20)

Publicité

Plus de 増田 亨(20)

Dernier(20)

Publicité

ドメイン駆動設計サンプルコードの徹底解説

  1. ドメイン駆動設計 サンプルコードの徹底解説 2019年4月4日
  2. github.com/system-sekkei/ isolating-the-domain Spring Boot, Spring MVC, MyBatis, Thymeleaf, Semantic-UI
  3. なぜ作ったか? ©有限会社 システム設計 32019/3/22
  4. なぜ作ったか? 実アプリケーション並みの具体例がほしかった コードがいちばん具体的に伝えることができる 質問が具体的になり、考え方の違いがはっきりする 2019/4/4 4©有限会社 システム設計
  5. 何の具体例か? ©有限会社 システム設計 52019/3/22
  6. 2019/3/22 ©有限会社 システム設計 6 ソフトウエアの核心にある複雑さに立ち向かう
  7. ドメイン駆動設計とは 2019/3/22 ©有限会社 システム設計 7 関心の分離の工夫 モジュール構造の工夫
  8. ソフトウェアの核心にある複雑さに立ち向かう ©有限会社 システム設計 82019/3/22
  9. 複雑さに立ち向かう 三つのキーワード ©有限会社 システム設計 92019/3/22
  10. 2019/3/22 ©有限会社 システム設計 10 ドメインロジック 複雑さの根源 ドメインモデル 複雑さをモデルで整理 オブジェクト指向 モデルと実装の一致
  11. 3つのキーワードの要点を絞り込む ©有限会社 システム設計 112019/3/22
  12. 2019/3/22 ©有限会社 システム設計 12 ドメインロジック → ビジネスルール ドメインモデル → 計算モデル オブジェクト指向 → 型指向のプログラミング
  13. 何の具体例か? ビジネスルールが複雑さの原因 計算のモデリング 型指向でプログラミングする 2019/4/4 13©有限会社 システム設計
  14. 関心の分離の工夫 この2つを徹底的に分ける 同じモジュール(ソースファイル)に 計算と入出力は、いっしょに書かない 2019/4/4 14©有限会社 システム設計 計算(ビジネスルール)を実行するモジュール群 データを入出力するモジュール群
  15. モジュール構造の工夫 手続き的な入出力モジュールに計算を埋め込む (トランザクションスクリプト) 計算を型(値の種類)でモジュール化して組み合わせる (ドメインモデル → 計算モデル) 2019/4/4 15©有限会社 システム設計
  16. サンプルアプリケーションの概要 時給ベースの給与計算アプリケーション 背景にあるビジネスルール 雇用契約(時給単価, …) 労働基準法(深夜, 休日, 総労働時間, …) 計算に必要な事実 勤務実績(いつ、何時間) 給与計算ルールを62種類の型で記述 本日は、給与(Payroll)型を中心に説明 2019/4/4 16©有限会社 システム設計
  17. 給与(Payroll)型を中心にレイヤごとに説明 ①ドメイン層(ビジネスルール層) ②アプリケーション層 ③データソース層とデータベース ④プレゼンテーション層 2019/4/4 17 ④プレゼンテーション層 ②アプリケーション層 ③データソース層 ③データベース ①ビジネスルール層 ©有限会社 システム設計 設計も基本的にこういう順番でやっている 各ステップの説明ごとにQ&Aを入れます
  18. ドメイン層(ビジネスルール層) 2019/4/4 ©有限会社 システム設計 18 プレゼンテーション層 アプリケーション層 データソース層 データベース ビジネスルール層
  19. ビジネスルールを記述する3要素 Fact 事実の表現 ビジネスの状況の記録や通知に使う値の種類 ・ 数値、日付、場所、識別番号、名称、… Rule Factを使った 計算や判定のロジック 計算式 同一性の判定式 大小の比較式 Goal 知りたいこと 計算結果や判定結果を表現する値の種類 ・合計金額、予定日、残数、… ・出荷可否、受付可否、割引種類、… 2019/3/22 ©有限会社 システム設計 19
  20. 3要素の具体例 計算結果:Goal 給与の一覧画面 2月 支払い額 計算の元データ: Fact →勤務時間の一覧画面(勤務の履歴) →従業員の一覧→布川光義→時給の履歴画面 計算ロジック(Rule)を記述したモジュール群を集約したクラス domain.model.payroll.Payroll型 計算結果を表現するクラス Payroll#totalPayment() : PaymentAmount型 2019/4/4 20©有限会社 システム設計
  21. Payrollクラス 事実への参照 Contract型 (契約条件:時給単価、割り増しルール、…) Attendance型 (勤務実績) → TimeRecords型 (毎日の記録のコレクション) 計算の実行:totalAmount() 結果の表現:PaymentAmount型 2019/4/4 ©有限会社 システム設計 21
  22. ドメイン層の設計の考え方とやり方 計算モデルが息づく場所 model パッケージ 計算モデルの表現 type パッケージ モデルを表現するための基本部品のライブラリ 型指向のプログラミング → wiki : github.com/masuda220/business-logic-patterns/wiki/設計ガイドライン → スライド : 「ドメイン駆動設計本格入門」 → 書籍:「現場で役立つシステム設計の原則」 Plain Old Java Bean Validation → 有効な値の表明 → 自己文書化の一部 可読性 over Javaの習慣的な記法 (finalやprivateの省略) No getter, no setter, no Lombok, no JPA 2019/4/4 ©有限会社 システム設計 22 modelに置くか、typeに置くかは書いてみながら判断・調整
  23. 時給ベースの給与計算モデル 2019/4/4 ©有限会社 システム設計 23
  24. attendance.Attendance 勤怠 attendance.AttendanceStatus 勤怠状況 attendance.Recorded 勤務記録有無 attendance.TimeRecords 勤務実績一覧 attendance.TotalWorkTime 総勤務時間 attendance.WorkMonth 勤務月 contract.Contract 従業員契約 contract.Contracts 従業員契約一覧 contract.ContractStartingDate 契約開始日 contract.ContractStatus 契約状態 contract.ContractWage 契約給与 contract.ContractWages 契約給与一覧 contract.HourlyWage 時給 contract.MidnightHourlyExtraWage 深夜時給割増額 contract.OverTimeHourlyExtraWage 深夜時給割増額 contract.WageCondition 給与条件 employee.ContractingEmployees 契約中従業員一覧 employee.Employee 従業員 employee.EmployeeNumber 従業員番号 employee.MailAddress メールアドレス employee.Name 氏名 employee.PhoneNumber 電話番号 legislation.DailyOvertimeWork 時間外労働 legislation.ExtraPayRate 割増率(%) legislation.Midnight 深夜 legislation.MidnightExtraRate 深夜割増率 legislation.OverTimeExtraRate 時間外割増率 payroll.PaymentAmount 支払い金額 payroll.PaymentWorkTime 支払い対象時間 payroll.Payroll 給与 payroll.Payrolls 給与一覧 payroll.PayrollStatus 給与ステータス timerecord.ActualWorkTime 勤務時間実績 timerecord.bindingtime.BindingTime 拘束時間 timerecord.bindingtime.DaytimeBindingTime 日中拘束時間 timerecord.bindingtime.MidnightBindingTime 深夜拘束時間 timerecord.breaktime.BreakTime 休憩時間合計 timerecord.breaktime.DaytimeBreakTime 日中休憩時間 timerecord.breaktime.MidnightBreakTime 休憩時間(深夜) timerecord.DaytimeWorkTime 日中勤務時間 timerecord.EndTime 勤務終了時刻 timerecord.MidnightWorkTime 深夜勤務時間 timerecord.OverWorkTime 時間外勤務時間 timerecord.StartTime 勤務開始時刻 timerecord.TimeRange 勤務の開始と終了 timerecord.TimeRecord 勤務実績 timerecord.WorkDate 勤務日付 timerecord.WorkTime 勤務時間 amount.Amount 金額 amount.Percentage 率(割増や税などの金額に掛けられるもの) amount.RoundingMode 端数処理 date.Date 日付 date.DayOfWeek 曜日 date.Month 月 date.Year 年 date.YearMonth 年月 time.ClockTime 時刻を時分単位で表す time.ClockTimeRange 開始時刻と終了時刻を表現する(時刻間の時間間隔を返 time.Hour 時間(数) time.HourAndMinute x時間y分 time.Minute 分(数) time.QuarterHour 15分単位の時間 time.QuarterRoundClockTime 15分単位の時刻 time.QuarterRoundClockTimeRange 15分単位の時刻 給与計算に関するFact-Rule-Goalを表現したクラス群=ビジネスルール用語集 (ソースから自動生成) 2019/4/4 ©有限会社 システム設計 24
  25. 60種類の独自の型を 9つのパッケージで整理 パッケージ構造が ビジネスルールの概要説明になっている (ソースコードから自動生成したパッケージ図) 2019/4/4 ©有限会社 システム設計 25
  26. 区分ごとのロジックの整理 区分に依存するロジックの視覚化 (ソースコードから自動生成した区分の関連図) ソフトウェアの複雑さの大きな原因である、 区分ごとのロジックをenumで整理 enumを参照するクラスを特定し、 区分構造の影響範囲を可視化 2019/4/4 ©有限会社 システム設計 26
  27. Q&A : ドメイン層の設計とコード例 2019/4/4 ©有限会社 システム設計 27
  28. アプリケーション層 2019/4/4 ©有限会社 システム設計 28 プレゼンテーション層 アプリケーション層 データソース層 データベース ビジネスルール層 使う
  29. ビジネスルールの記述を独立させる プレゼンテーション層の モジュール群 アプリケーション層の モジュール群 データソース層の モジュール群 ビジネスルールを 記述したモジュール群 利用する 2019/3/22 ©有限会社 システム設計 29
  30. アプリケーション層の複雑さ ビジネスルールの記述を、ビジネスロジック層に移動する 理論的にはアプリケーション層はとてもシンプルになる 現実はアプリケーション層に複雑な記述が残りやすい アプリケーションの要素分解と組み立て 2019/3/22 ©有限会社 システム設計 30
  31. アプリケーションの要素分解 2019/4/4 ©有限会社 システム設計 31 Factory サービス 計算モデルのインスタンスを生成する → データソース層で事実を元に生成 Query サービス 計算結果を返す → プレゼンテーション層へ Operation サービス 計算結果を記録/通知する → データソース層へ
  32. アプリケーションの組み立て 2019/4/4 ©有限会社 システム設計 32 複合serviceクラス @Service 複数の単機能サービスを組み合わせた サービス 要素serviceをautowireする 例: PayrollQueryCordinatorクラス 要素servicクラス @Service 単機能のサービス repositoryをautowireする 例: ContractQueryServiceクラス AttendanceQueryServiceクラス 使う
  33. Q&A : アプリケーション層の設計とコード例 2019/4/4 ©有限会社 システム設計 33
  34. データソース層とデータベース 2019/4/4 ©有限会社 システム設計 34 プレゼンテーション層 アプリケーション層 データソース層 データベース ビジネスルール層 計算モデルとデータモデルの マッピング
  35. データソース層設計の考え方とやり方 データの入出力の実装 MyBatis SQL Mapper SELECTの実行→計算用のオブジェクトの生成 記録すべき事実を持ったオブジェクト→INSERTの実行 ContractDataSourceクラス TimeRecordDatasourceクラス 2019/4/4 35©有限会社 システム設計
  36. データベース設計の考え方とやり方 プログラムからは独立したデータの記録と参照の仕組み イミュータブルなデータモデル:事実の履歴+最新状態 事実の履歴 → INSERT オンリー 最新状態の導出結果 → DELETE/INSERT NO UPDATE NO updated_at カラム 制約指向 データ型 NOT NULL制約、外部キー制約、ユニーク制約 とことん日本語 スキーマ名、テーブル名、カラム名 実験だったけど、なかなか良い感じ(説明ドキュメント) 2019/4/4 36 https://www.slideshare.net/kawasima/ss-40471672 https://www.slideshare.net/kawasima/ss-44958468 川島さんのスライド ©有限会社 システム設計
  37. Q&A データソース層とデータベースの設計とコード例 2019/4/4 ©有限会社 システム設計 37
  38. プレゼンテーション層 2019/4/4 ©有限会社 システム設計 38 プレゼンテーション層 アプリケーション層 データソース層 データベース ビジネスルール層 計算モデルとビューのマッピング
  39. 計算モデルのビュー ドメインオブジェクトをそのまま表示 (naked object パターン指向) Spring MVC Direct Field Access → WebDataBinder#initDirectFieldAccess() Thymeleaf Semantic UI → Fomantic UI PayrollControllerクラス templates/payroll/list.html 2019/4/4 39©有限会社 システム設計
  40. Q&A : プレゼンテーション層の設計とコード例 2019/4/4 ©有限会社 システム設計 40
  41. なぜ作ったか? 実アプリケーション並みの具体例がほしかった コードがいちばん具体的に伝えることができる 質問が具体的になり、考え方の違いがはっきりする 2019/4/4 41©有限会社 システム設計
Publicité