チュートリアルでDDD体験: ドメインモデルの成長を紹介
2023年11月29日(水)10時0分 BIGLOBE Style
プロダクト技術本部の川口です。
3年間、ビッグローブ光といった固定回線のインフラ部門に所属していましたが、今年の4月に BIGLOBE の基幹システムのリニューアルを推進していく部署に異動することになりました。
所属するチームでは、ドメイン駆動設計(DDD)で開発しています。
チームにジョインすると開発チュートリアルをやることになっており、そこで IntelliJ や Spring Boot での開発の仕方を学んだり、チュートリアルを通して DDD を学んだりします。
今回は、DDD のチュートリアルで実際に作成したドメインモデルがどういう風に成長していったかについて紹介します。
勤怠管理アプリ チュートリアル
お題は GitHub のパブリックリポジトリに公開されています。
https://github.com/biglobe-isp/kintai
チュートリアルの内容を簡単に説明すると既存のコードと仕様に沿ってリファクタリングしていくといったものです。
このチュートリアルでは以下のような流れで DDD を学んでいきます。
- チュートリアルの課題をよく読む
- ドメインモデルを作成する
- ドメインモデルのレビューを受ける
- 2 と 3 を繰り返しある程度めどがついたらコードを書く
- コードのレビューを受ける
- 2, 3, 4, 5 を繰り返す
今回は 2, 3, 4 の工程 をメインに紹介します。
ドメインモデルは PlantUML を使って作成します。
※今回は触れてませんがJavaでコーディングしています。
初期ドメインモデル
まず最初にドメインモデルを作ってみようといわれてみたものの、クラス図の作り方とかよくわかっておらずインターネットで調べながら作成し、最初にレビューを受けたモデルはこうなりました。
図1
((ヽ(´Д`;)ノ)) ワカラン …
データモデルにもなってないような感じです。
チームメンバーとモブプロをしながらクラス図の書き方のアドバイスをもらいつつ、このとき受けたレビューでは
- ドメインを用いてユーザが必要とする形に加工するサービスクラスが必要
- どのクラスで休憩時間を抜いた実際の労働時間と残業時間を算出するかモデルに記述する
- 勤務情報の登録で使うクラス、月間累計時間の参照で使うクラスでパッケージを切る
といったコメントをいただきました。
チュートリアルではドメインエキスパートにあたるような人物は存在しないため、ユビキタス言語のように開発者とドメインエキスパートが使う共通のドメイン用語も明確になっていません。
問題文を再度読みながら考察すると、時間にはx時間といった幅とx時x分といった時点を表す表現や休憩時間を含めた / 含めない労働時間があることに気づきました。
弊社で使っている勤怠管理システムを見れば、より適切なドメイン用語が見つけられると思い参考にしてみました。
勤怠管理システムと考察した結果はこうなりました
- 時間は幅、時刻は時点と定義する
- 休憩時間を含めない実際の労働時間 =「実働時間」と命名する
- 実働時間と残業時間を算出するには勤務開始・終了時間と休憩時間が必要そう
- 始業時間と終業時間、休憩時間は「就業規則」と言ってもよさそうなので一つにまとめたクラスを作成する
そのため、弊社で使っている勤怠管理システムの用語を参考にクラス名をつけました。
上記のコメントと考察を踏まえ、修正したモデル図は以下となりました。
図2
図1と比べるとドメインの理解が進んでる感じがしています。
図1のモデルには登場しなかった「実働時間」や「残業時間」、「就業規則」といったクラスが登場しています
図1のモデルではよくわからず矢印をつけていましたが、参照するクラスに矢印をつけました。
このモデル図でレビューを受けたときのコメントは
- CSVに保存される6項目を保持するクラスをつくる
- 6項目を保持するクラスを永続化するためのリポジトリを定義して、サービス層から呼び出す線を引いてみる
です。
このチュートリアルでは日付、勤務開始時間、勤務終了時間、実働時間、残業時間、勤怠登録をした時刻をCSVに保存する必要があります。
サービスクラスから呼び出してデータを永続化するためのリポジトリも必要です。
以上の観点に加え、再度モデル図を見直した際に以下のように考察しました。
- 勤務時間の登録と月間で集計した勤務時間の参照、この2つのユースケースを実現するサービスクラスが必要そう
- 勤務登録する際に必要な日付と始業時間・終了時間を保持するクラスが必要そう
- 勤務情報クラスが永続化したいクラスのように見えるが、永続化したい情報が足りておらず、サービス層でドメインを扱うには不便な状態になっている
- 残業時間を算出するために、実働時間と就業規則の始業・終業時間から算出される規定勤務時間が必要そう
上記のコメントと考察を踏まえて、再度モデルを修正しました。
中期ドメインモデル
図3
変更点としては、新たに勤務情報登録サービスと勤務情報リポジトリを追加しました。
実働時間の算出のために就業規則パッケージを作成し、規定勤務時間クラスを作成しました。
この図を見て「おやっ」と思った人がいるかもしれません。
リポジトリのインターフェースはドメイン層に置く人が多いかもしれませんが、チームではサービス層に置くようにしています。
理由としては、リポジトリはデータの永続化が責務でありアプリケーションの機能と認識しました。そのためビジネスルールを表現するドメイン層ではなく、アプリケーションの要求を表現するサービス層の方が適していると考えたためです。
このモデル図のレビューでは以下の内容のコメントをいただきました。
- 就業規則を変更するために就業規則パッケージと変更用のリポジトリを用意してもよい、勤務情報登録サービスがリポジトリから就業規則を受け取れるようにする
- 時間と時刻の表現の統一
- 就業規則 ->休憩時刻の線は 1 対 1..n
ここまでくるとクラス名や多重度にも着目したり、お題には書かれていないですが今後の仕様変更やビジネスの要求のために拡張性を持たせて変更を容易に行えるようにモデルを考える必要が出てきました。
このモデルを作り終えた時点でコードを書き始めました。
コードを書いていると、モデルでは現状こうしてるけど実装してみるとこっちのほうがいいなという場合がありました。
月間累計時間を算出する際に中期のモデル図の内容で書いていたところ、月毎の勤務実績の集合である月間勤務実績があったほうが実装がしやすいと感じたことと、累計実働時間と累計残業時間を別々のクラスにするメリットを余り感じなかったため、変更しました。
後期ドメインモデル
最終的に以下のようなモデルになりました。
図4
主な変更としては、就業規則が後で変更になる場合を考慮して就業規則パッケージと就業規則リポジトリを追加したこと、
月間勤務実績クラスとそれを参照できる月間勤務実績リポジトリ、累計実働時間、累計残業時間を持つ月間累計勤務時間クラスを追加しました。
仕様が変わる可能性を踏まえて、最終的に4つのパッケージに分類しました
- 勤務情報
- 就業規則
- 月間累計勤務時間
- 勤務時刻入力
就業規則は会社の勤務ルールが変わる場合、月間累計勤務時間は参照したい情報が変わる場合、勤務情報は仕様が変わる可能性は低いと思いましたが、モデルの中心となるドメインとして分類しました。
中期モデルでは勤務時刻入力は勤怠情報パッケージに入ってましたが、勤務時刻入力の内容は加工されて勤怠情報として登録されること、今回の要件にはありませんが有給休暇の情報を入力できるように変更する場合(そうなるとパッケージ名の変更の検討が必要そうですが)も考えて、パッケージを分けました。
最後に 専門家の方に説明しながら見てもらいました。
- 勤怠の怠という意味合いにあたるような概念は今回のモデルだと出てこない
- 欠勤とか遅刻とかの概念が出てくるのであれば、違和感はない
- Input / 入力という言葉はドメインの言葉としてはおさまりが悪い
- システムとしては入力してるような動作かもしれないが、ドメインはビジネスのルールを表現するので入力という言葉は持ち込みたくない
といったコメントをいただきました。
適当なクラス名を1つ考えるだけでも難しいなと感じました。
学んだこと、感想
- モデリング、特にクラス名に適当な名前を付けることが難しかった
- どのパッケージ、クラスでビジネスロジックを表現するのかが難しかった
- ドメインモデルの描き方やどれくらいの単位でクラス・パッケージを分割すればよさそうかといったイメージができるようになった
- ドメインモデルをイテレーティブに改良することが重要と実感できた
書籍だけで DDD を学ぼうとすると、抽象的な内容が多かったり、実感が湧かなかったりして理解するのが難しいですが、お題を通して DDD を実践したことで理解が進み、モデリングやコーディングのスキルを磨くことができました。
あくまで今回はチュートリアルで、実際の業務ではさらに複雑なビジネスロジックが存在します。複雑なビジネスに対してドメインエキスパートとメンバーで議論しながら「ユビキタス言語」や「境界付けられたコンテキスト」を見つけ出していくことが DDD の醍醐味ではないかと思います。
そういった経験を今後増やして、ビジネスの変化に強くて柔軟性がある設計ができるようになりたいです。
※ IntelliJ は、JetBrains s.r.o.の商標または登録商標です。
※ GitHub は、GitHub Inc.の商標または登録商標です。
※ Javaは、Oracle、その子会社及び関連会社の米国及びその他の国における登録商標です。
注目されているトピックス
-
ファイテンの自信作「健光浴シャワー」。契約件数トップ店舗が生み出した、お客様に「ワクワク感」をもたらすファイテンショップの3分間体験の提案とは
ファイテン株式会社は「すべては健康を支えるために」をスローガンに、あらゆる人の健康をサポートしているボディケアカンパニーです。その技術の粋を結集した光テクノロジ…
4月5日(金)12時0分 PR TIMES STORY
-
職場の理不尽な"しわ寄せ"に悩む声 「できる人に仕事が集中」「管理職の残業が慢性化」
みなさんは仕事中に、他の人の業務を押し付けられたり、負担を強いられたりした経験はないだろうか。働き方や労働時間など、同じ会社でも扱いや待遇が違い、不公平さを感じ…
9月2日(月)7時0分 キャリコネニュース
-
ブラック上司の暴虐!「ミスしたら殴られ、肋骨にひびが入った」
画像はイメージキャリコネニュースでは「ブラック企業」をテーマにアンケートを行っている。兵庫県の20代男性(建築・土木技術職/年収400万円)は、上司の傍若無人な…
3月1日(火)11時55分 キャリコネニュース
-
Checkstyleでクリーンアーキテクチャをチェックする
こんにちは、なおしむです。私はシステム企画部でシステム全体のアーキテクトとレガシーシステムの改善開発をしています。弊社ではドメイン駆動設計を使って開発をしていま…
2月13日(木)15時7分 BIGLOBE Style
-
「出会ったのは私が19歳、彼が38歳の時」30年あまり不倫関係を続ける女性
画像はイメージ夫よりも不倫相手との関係のほうが長いということもあるらしい。「現在不倫中」と明かす40代後半の女性(専業主婦・夫)は、自身が19歳のころに出会って…
11月8日(水)17時23分 キャリコネニュース
-
ジブラルタ生命は賞与年4回「完全歩合で年収1億円超えも。弱肉強食で働きたい人にオススメ」保険業界の年収ランキング最新版
企業口コミ・給与明細サイト「キャリコネ」は10月4日、「保険業界の年収ランキング」を発表した。本ランキングは、「キャリコネ」のユーザーが投稿した情報をもとに、平…
10月17日(水)7時0分 キャリコネニュース
-
職場のトイレへの不満「男女共用でナプキンは持ち帰り。しかも以前は和式でした」
画像はイメージ社員しか使わないトイレの環境整備は後回しにされがちだが、トイレの使いやすさは働きやすさに直結する。会社が社員をどんな風に扱うかは、従業員が使うトイ…
6月17日(土)1時17分 キャリコネニュース
-
不倫されても離婚しない妻の胸中「夫お手伝いさん。子どもが自立したら絶対捨てます。今も貯金に励んでます」
「不倫は家族を裏切る、許されざる行為です」。50代女性の語気は強い。会社経営をする夫の不倫相手は、女性の部下だった。女性は夫の会社で経理をしており、事務員として…
7月9日(金)11時20分 キャリコネニュース