ドメインエキスパート/エンジニアと語るDDD実践例 [CTO meetup イベントレポート]
※本記事は2023年3月に公開された内容です。
2023年2月9日に開催されたCTOmeetupのテーマは、ドメイン駆動設計(以降、DDD)です。
DDDのアウトプット方法は複数存在し、実際に導入しても何から始めればいいのか悩まれてしまうエンジニアの方は多いのではないでしょうか。
「DDD=難しい」というイメージから脱却し、具体的な開発イメージを膨らませるにはどうしたらいいのか。
今回はこの点について、特にモデリングに着目をしてディスカッションを実施。DDDの関連書籍の出版やYouTube、Twitter発信をされているログラス社の松岡さんをはじめ、エンジニアの村本さん、ドメインエキスパートの浅見さんをお招きして、DDDの実践例と開発のポイントについて解説いただきました。
目次
ドメイン駆動設計に関する目線合わせ
DDDの目的
松岡氏:
私はログラスに2年在籍していて、DDDを広めてきました。今日は「DDDは怖くない」という話ができると思いますので、よろしくお願いします。
村本氏:
エンジニアの村本です。私は松岡さんに憧れてログラスにジョインし、弟子入りしてDDDを学ばせていただいています。今日は社内のDDD活用や自分が実践してきた話ができればと思いますので、よろしくお願いします。
浅見氏:
カスタマーサクセス責任者の浅見です。ログラスに入ってプロダクト開発に関わる皆さんと一緒に仕事をするようになり、DDDのフレームワークが活用できたと思っています。今日はよろしくお願いします。
松岡氏:
まず、DDDがどのようなものなのかについてお話しさせていただきます。
DDDは、大きく言うと「機能性」と「保守性」を両方高めるためのものです。機能性を高めるには主に効果があるのがドメインモデリングで、保守性向上に主に効果があるのが作ったモデルをそのままコードに表現することです。そのための実装パターンがあるような関係になっています。
ドメインモデリング手法 ―sudoモデリング―
松岡氏:
DDDではモデリングの手法を1つに定義されていません。よく一緒に使われるものとしてRDRAやICONIXといったものがあります。これらはカバー範囲が多く、良いものではあるのですが、覚えることが多く習熟までのコストが大きいという課題がありました。
そこで私が軽量に価値を出せるモデリング手法として提唱しているのが、「sudoモデリング」です。”sudo”は作成する4つのモデル図の頭文字をつなげたものです。
松岡氏:
上記システム関連図・ユースケース図、ドメインモデル図、オブジェクト図の4つを用いたsudoモデリングはさまざまなケースで役立てられます。
例:「sudoモデリング」を活用した採用管理システム開発
システム関連図
松岡氏:
システム関連図は、開発するシステムと関わりのあるアクターや外部システムとの関連を示す図です。以下は採用管理システムをモデリングしたサンプルになっています。
松岡氏:
大した内容を書いていないようですが、実はこの中で「システムの中では応募を直接受け付けない」という、非常に大きな意思決定をしています。これによって、新規プロダクト開発時のスコープがかなり変わります。アクターが多くなっても1枚絵でわかるので、かなりコスパの良い図です。
ユースケース図
松岡氏:
次がユースケース図ですね。
ユースケースはUML(統一モデリング言語)と同じような内容で、ユーザーの要求に対するシステムの振る舞いを定義します。アクターがシステムを使うときにどんな操作をするのかが書かれていて、意外と自明ではなかった事柄を発見できたりします。
オブジェクト図とドメインモデル図
松岡氏:
次がオブジェクト図とドメインモデル図です。オブジェクト図が具体例で、ドメインモデル図がそれを一段階抽象化したものという関係になっています。
オブジェクト図はドメインエキスパートの方と一緒に、具体的な値を聞きながら書いていくのがポイントです。テーブル定義やコードには表現されない具体例を議論することで、エンジニアがシステムがどう使われるかの理解を深めます。
ドメインモデル図はオブジェクト図の具体例を抽象化したもので、エンジニア寄りの情報が増えていきます。左下に、募集ステータスや募集人数が更新可能である旨が書かれていますが、そういうビジネス的なルール、いわゆるドメイン知識を記載するのも大事ですね。確定したこと以外にも「将来こうなるかも」「こうしたいかも」といったことも書き残しておくと、便利な形で知識を伝達できます。
視聴者からの質問:モデリングは最初にラフなスケッチを記録してから清書をする流れですか?
松岡氏:
モデリングに清書の概念はありません。α版、β版をどんどん更新していくものだと思ってください。モデリングするタイミングは、最初でもコーディング時でもお客様へのヒアリング時でもいつでも大丈夫なので、とにかく更新し続けましょう。4つの図を行き来しながら作成するのがポイントです。
【ドメインモデリング事例.1】新規機能開発
実際どのように進めた?
松岡氏:
次はログラス社内における実例をお話ししていきます。複雑な新規機能開発案件を浅見さんと一緒にモデリングした経験があるので、実際の進め方についてご説明いただこうと思います。
浅見氏:
作ったのはワークフローに関する機能です。最初は簡単なモックをデザイナーに作ってもらい、そこからモデリングをエンジニアとCS、プロダクトマネージャー(以降PdM)で一緒に進めました。
松岡氏:
画面とモデリング、どちらを先に作るべきかよく聞かれるのですが、これも行ったり来たりでしたね。画面は最初から大掛かりには作らず、複雑なフローについては浅見さんと話しながらモデリングをしてアップデートしていきました。
浅見氏:
週次30分でアップデートしていくような形でしたね。私の業務経験だけでなく、想定顧客にヒアリングをした情報を持ち帰ってメンバーに伝えるようにもしていました。
松岡氏:
左の図がワークフローの承認ステップなのですが、こういう風に誰が何をやってどんな連鎖が生まれるのかを1枚絵で示せたのは、とてもわかりやすかったです。
浅見氏:
画面モックをお客さんに見せ、さまざまなユースケースを拾うのはすごく大事だと実感しました。ワークフローは差し戻しの概念があるのですが、抽象的なモデル図ではいろいろなパターンを想定できましたし、そのおかげで手戻り少なく開発に着手できた部分があったと思います。
実際にやってみて良かったこと
浅見氏:
ここまでの流れでも軽く触れましたが、DDDをやってみて良かったことをまとめ的にお話しします。
浅見氏:
1つ目は既にお話しした通りです。お客様がやりたいことを可視化して、開発メンバーとカスタマーサクセスの間に共通認識が生まれたのが非常に良かったと思います。
2つ目にあるように、お客様に見てもらった上でフィードバックをもらえるところにもポイントがありました。新規機能開発では、提供したもののあまり使われなかった、お客様の求める要件を満たせなかったといった状況が起こり得ますが、DDDで業務イメージをお客様と一緒に作り上げることで、極限までリスクを低減できました。
松岡氏:
モデリングで具体例を出すことで理解が深まり、エンジニアサイドから機能の方向性について意見が出たりもしましたね。
浅見氏:
3つ目については、ワークフローだと特にわかりやすいです。同じ差し戻しでも触るのが支店の方なのか、営業部長なのか、事業部長なのかによって使い方も異なります。部分的に承認したい、複数個差し戻ししたいなど、いろいろなケースがありました。そこも含めて検討できたので、すごく作りやすかったです。
ドメインエキスパートが考えるDDDを進める際のポイント
松岡氏:
最後に、ドメインエキスパート視点でDDDを進めるポイントを教えてください。
浅見氏:
新機能を作ろうと思うと、非常に多くのステークホルダーが関わります。エンジニアやPdM、カスタマーサクセス、お客様、さまざまな利害関係者の共通言語になるのがドメインモデルですから、「見てわかる」アウトプットにはこだわったほうがいいですね。最初から完璧を作るのではなく、ブラッシュアップして良いアウトプットを目指すのが大事です。
2つ目は、やはりモデルの継続的な改善ですね。1回でユースケースを全て洗い出すのは絶対に無理で、逆にモデルを作ることでユースケースが見えてくるんです。どんどん作り続けていきましょう。
最後はマインドセットのような部分です。双方歩み寄って、いろいろなことをキャッチアップしながら進めていくのが大切です。総合的に心理的安全性を保ちながらディスカッションできるといいなと思います。
【ドメインモデリング事例.2】既存機能改修/保守メンテナンス
実際どのように進めた?
松岡氏:
では次に、既存機能改修と保守メンテナンスの事例について、実際にどんな内容だったのかを村本さんからご説明いただけますか?
村本氏:
私が進めたのは、とあるマスタ管理機能の閲覧権限制御に関わる開発でした。マスタ情報は「こういう部署がある」という情報であれば単純にその通りに作ればいいだけなのですが、それを制約が多いツリー構造にするための機能拡張だったのが難しかったです。
ツリー構造で表現されているモデルはかなりイメージがしづらく、制約情報もさまざまな箇所に散らばっている状態だったので、一旦深く調査せずに実装してみたら全く制約が守れていないものが完成してしまったので、時間をかけてモデリングすることになったのです。
まずは、仕様の整理からスタートしました。マスタの更新処理はそこまで難しい要件ではありませんでしたが、閲覧権限はお客様がどう使いたいかが関連するところだったので、浅見さんのようにお客様にヒアリングをしながら整理を進めました。業務委託の方々もいたため、知識の平坦化をする意味でもドメインモデリングを実施。次にユースケース図、オブジェクト図を作っていきました。
松岡氏:
今回はドメインエキスパートを呼ぶのではなく、村本さんが詳しいメンバーとなって、チーム4人で図にしていったのでしょうか?
村本氏:
そうですね。リファクタリングなので振る舞いは変わりませんから、完成形をきちんと知っている人間がユースケースを洗い出していった形です。
実際にやってみて良かったこと
松岡氏:
その中で実際にやってみてよかったことはどんなところですか?
村本氏:
一言でいうと、非常にコスパが良かったです。たった1時間一緒にモデリングするだけで、周辺知識がなかった人が私と変わらないぐらいのレベルになって、「こうしたらいいのでは」と素晴らしい意見を出してくれました。
松岡氏:
1時間でそんなに作れたんですか?
村本氏:
はい。ユースケース図をわかる範囲で全部出して、オブジェクト図を作りました。
松岡氏:
既存機能なので新しく調べながらではない分、頭の中にある知識をバーっと書き出す感じでいけたんですね。2つ目はどうですか?
村本氏:
1つ目と重複する部分もありますが、私ともう一人のメンバーだけに知識がある状態だったところから、現状の課題感を全員で共有し、共通認識が得られたのは大きなメリットでした。持っている知識が同じだと、問題を発見したときにその人が直接解決できますし、メンバーに相談して巻き込むような動きも可能になります。
3つ目は、あまり意図していたわけではなかったメリットです。たまたま該当する部分のリニューアルをする予定だったデザイナーがいて、その人は機能の使われ方や制約がわからない状態だったんですよね。そこで作成したモデルを見たら理解ができたそうで、感謝されました。
松岡氏:
確かにデザインの影響範囲を調べようとしても、どんな使い方をされている機能なのかは意外とわかりませんからね。
モデリングからコード実装する上で感じた難しさ
松岡氏:
逆に、難しく感じた部分についてもぜひ教えてください。
村本氏:
既存のコードの理想的なモデルを描いたとしても、一定のギャップが生まれます。理想状態を作るまでに膨大なコストがかかってしまうため、なかなか実装に踏み切れない。そこで理想状態ではなく目的を達成するためにどんな改善をどの程度加えればいいのか、モデルから実装に落とし込むのが難しかったです。
松岡氏:
ここは、リファクタリングの時間をどう確保するのかという戦略の話も入ってきますね。2つ目はどうですか?
村本氏:
1つ目の話と近いです。理想的なモデルはあるけど一方で、実際の方針はコードと比べて話し合って決めなければいけません。自分一人で決めるのは不安なので、私より知識やスキルがあるメンバーの意見も反映させていきました。
3つ目については、例えば「改修に1ヶ月かかるが、機能に対してコストが見合わない」ケースがあると思うんですよ。機能に見合うようなリファクタリングの期間はどれぐらいなのか、ビジネス的にPdMと相談しながら決めないといけないのは難しかったです。
エンジニアが考えるDDDを進める際のポイント
松岡氏:
最後に、エンジニア視点でのDDDを進める際のポイントについてどのように考えていますでしょうか?
村本氏:
まずはモデリングをするときに、目的を明確にするのがポイントですね。作り込みすぎてもコスパが悪かったり投資回収できなくなったりする可能性があるので、やりたいことに対して過不足なく進めるのが重要です。
2つ目は、システムに詳しい人の知見を取り入れて可視化し、知識の平坦化を図ることです。やはり個人的には、1時間という短時間で非常に良い意見が出て、理想的なモデルについて議論できたのが衝撃でした。
最後は保守開発の重要なポイントですね。我々がやっているのはお客様に喜ばれるためのビジネス上のプロダクト開発であって、完璧なものを作ることが目的ではありません。やはり過不足ないモデリングを目指すのがポイントです。
松岡氏:
まさにアジャイルに進めていこうということですね。
本日のまとめ
松岡氏:
最後に、私から今日のまとめをさせていただきます。一番のポイントは、「DDDは怖くない」ですね。絶対にこうすべきというセオリーはありませんから、何のために役立てたいのかを意識して、気楽にやってみましょう。
松岡氏:
具体的なところでいくと、ビジネスサイドとエンジニアが一緒にモデリングをして知見を可視化し、残していくのがポイントの一つです。また、モデルを使って「役に立つかどうか」という視点で、完璧を目指さずフィードバックサイクルを回し、徐々に作っていくこと。最後に、モデルを使って理想の設計を考えるのも大事です。
Q&A
実際にシステムを作る際の手順やドメイン部分の設計書の記載方法は?
Q.実際にシステムを作る際には、sudoモデリングの後でUIや詳細設計書を作るのでしょうか?また作る場合、ドメイン部分の設計書はどのように記載する形になるのでしょうか?ドメインの機能は画面単位ではないと思うので…。
松岡氏:
モデル図は作りたいと思ったときが作り時なので、ホワイトボードに書くぐらいの感覚でやるといいですよ。モデリングやUI、そのほかの詳細な仕様詰めと並走する感じです。
ドメイン部分は、まずは今回ご紹介した形で考えてみてください。”sudo”は「どの現場でも使われる最低限」というパターンなので、ほかにも必要になった表現で記載してもらえると良いと思います。ドメインモデル図と併せて、ER図や状態遷移図を作ることは多いです。
理想的なモデルと現実のコードが乖離している場合、モデル図はどうすればいい?
Q.理想的なモデルと実際のコードが乖離しているがコストの観点からリファクタリングしない場合、モデル図はソースと乖離した理想状態のものを作成するのでしょうか?
村本氏:
時間があれば、共通認識を持つために作成すると思います。理想のモデル図を作ると、「こんな実装パターンができそうだ」といろいろ考えられて楽しいんですよね。時間を区切って理想状態を一旦作るのでもいいですし、方針だけを決めてもいいでしょう。
私はドメインモデルまで落とさなかったりするので、オブジェクト図からリファクタリングの方針を決めるところで止めるのもありです。
松岡氏:
状況によっては必ずしも理想通りにはできませんが、全てを諦めるのではなく、「どう役立つか」を考えればいいと思います。
新規であれば基本的にオブジェクト図とモデル図を作って、コードと一致させて進めればいいわけですよね。既存のモデル図を起こして一致させられないから諦めるというよりは、現状と理想で2つパターンを作ってしまいましょう。理想だけで作ったほうがいいときはそうすればいいですし。目的に合わせて作るといいですね。
(番外編)当日取り上げられなかった質問と回答を一挙公開!
モデルの名前付けにおいて意識すべきことは?
Q.モデルの名前付けで意識されていることはありますか?特に新たな概念を考える時に苦労することが多いです。
松岡氏:
具体例をなるべく多く出して帰納的に考えていくことが良いのではないでしょうか?
モックのデザインはどれくらい作り込む?
Q.Figma で作成するモックはどのくらいきれいなデザインとして作成されているのですか?
松岡氏:
用途に合わせて考えます。画面のレイアウトだけわかれば良い時はそれぐらいで、UIまで必要であればある程度作ると思います。
モデル図のメンテナンスはどうする?
Q.理想と現実のドメインモデルに乖離があるということでしたが、ドキュメントも「理想のモデル図」「現実のモデル図」を両方ともメンテナンスされているのでしょうか。
松岡氏:
現実のモデル図は必ずメンテします。理想のモデル図は必要に応じてメンテナンスしますが、その判断は目的に合わせます。
集約を作る単位として最適なものは?
Q.集約はライフサイクルの単位で作ることが多いのですが、ライフサイクル以外で良い単位があれば教えてほしいです。
松岡氏:
整合性をシンプルな実装で守りたい範囲の大きさ、トランザクションの排他制御の大きさ、一度に取得するデータのパフォーマンス観点のバランスから考えます。
テストの棲み分けはどうしているか?
Q.APIへのテストとUIでのテストの棲み分けをどのように行っているのか教えていただきたいです。
松岡氏:
まずはそれぞれ単体でそれぞれのに責務に対してテストをします。その後APIとUIを結合しないとテストできない観点でテストをします。この責務の切り分けが綺麗だとAPIとUIを分けても意味のあるテストができます。
DDDの教育に必要な期間はどれくらい?
Q.後から入ってくる開発者にDDDの教育が必要と思いますが、どれくらいの教育期間を設けてますでしょうか? Java経験者(3年程度)くらいだとどれくらいでしょうか。
松岡氏:
基本的な実装パターンはある程度コーディング規約のような形で既存の実装に合わせてもらうことで大体のパターンは真似すればキャッチアップしやすいです。
難しいのは集約で、そこはある程度説明が必要です。集約の範囲の設計は習熟者と一緒にモデリング経験を重ねることが必要です。その経験は人にもよるので一概にどれくらいと言う事はいうのは難しいです。
関数型プログラミングにおけるDDD
Q.関数型プログラミングでバックエンド開発してまして、DDDをどう適応するべきか社内で悩んでます(sudoモデルがオブジェクト指向言語にフィットさせたやり方だと思うので)
松岡氏:
個人的には関数型では徹底してやったことがないのであまり具体的なアドバイスができません。モデルとコードを極力乖離しないように、というのを意識して探求していただければと思います。
モデルと実装は必ずしも一致しない?
Q.モデルと実装は一致するイメージだったんですが必ずしもそうでないんですか?
松岡氏:
もちろん、一致できるのが理想です。ただ一致しなければもう諦めるかというとそうではなく、その場合はモデル図上にこの辺は実装と会議があるなどの説明をすることで、モデルと実装の行き来をしやすくすることができます。
リポジトリの取り扱いについて
Q.複数のテーブルをまたぐデータを保持した集約をリポジトリで取りだす時は、リポジトリ内で複数テーブルの情報を取り出して集約を構成して返却するのでいいのでしょうか?また、リホジトリ内から他のリポジトリを使うのはありですか?
松岡氏:
はい、その通りです。ドメイン層、ユースケース層では、テーブルが複数かどうかを意識せず、リポジトリに入れたものはそのまま返されるようにします。
インフラ層のリポジトリの実装クラスの中で複数テーブルをマッピングする必要があればします。リポジトリから他のリポジトリを使うのは、可読性を著しく下げるのでお勧めしません。
開発チームのDDDに関する知見をどのように高めていく?
Q.プロジェクトでDDDを採用しているのですが、チーム全体のDDDに対する知見の平均レベルがプロジェクトで必要としているレベルよりも低いという問題が現状あります。チーム全体のDDDに関する知見を上げるより良い方法がありましたら教えていただけると幸いです。
松岡氏:
もしよろしければ私のYouTubeなどをご覧ください。私もこれさえ見ておけば良いと言うほど良い日本語の情報がなかったので頑張って作ったと言う次第です。
まとめ
今回はログラス社が実際に行ったプロジェクト実例から新規機能開発、既存機能改修におけるDDDの有用性を語っていただきましたが、いかがでしたか?
企画者自身、DDDは難しくて怖いものだと思っていましたが、松岡氏がおっしゃる通り、まずは肩肘張らずに始めてみるのが良さそうです。
ビジネスサイドの方と共にDDDなどを活用しながら、ユーザーに価値あるプロダクト作りをこれからも続けていきましょう。
FLEXYのご紹介
FLEXYは、エンジニア、技術顧問、CTO、デザイナーの方向けに案件をご紹介するサービスです。
リモートワークや週1-5日、高単価案件など、ご希望に合った案件をご紹介いたしますので、是非お気軽にご相談ください。