141
ドドドドドドドドドドド ドドドドドド DDD ALLIANCE! ドドドドドドドドドドドドドド ドドドドドドドドド

20151110 ドメイン駆動設計によるサービス開発

Embed Size (px)

Citation preview

Page 1: 20151110 ドメイン駆動設計によるサービス開発

ドメイン駆動設計によるサービス開発DDD ALLIANCE! ドメイン駆動設計をやってみた 6つの現場からの報告

Page 2: 20151110 ドメイン駆動設計によるサービス開発

自己紹介名前:大西 真央(@mmmmao0530)

組織としての役割:DDD布教活動

チームとしての役割:リードエンジニア

(技術リーダー)

最近の関心ごと:効果的なドメインモデルの作成

         チームビルディング

Page 3: 20151110 ドメイン駆動設計によるサービス開発

概要ビッグローブでDDDを導入して早2年。この2年間、 ISP事業における主要なサービスをDDDで開発してきて、試行錯誤の連続でした。

今回は、試行錯誤の過程を経て生まれた、実際に実践している

 ・設計・実装の考え方(ドメインモデルやコード例やDB設計など)

 ・チーム環境の考え方(開発プロセスやチームビルディングなど)

の2つを軸に現場でのリアルな体験を紹介します。

また、最後に、試行錯誤における失敗談も紹介します。

Page 4: 20151110 ドメイン駆動設計によるサービス開発

アジェンダ

1. 導入• Biglobe × DDD

2. チーム環境の考え方• スクラム開発• チームビルディング

3. 設計・実装の考え方• アプリケーションコード• DB設計

4. 失敗談5. まとめ

Page 5: 20151110 ドメイン駆動設計によるサービス開発

導入  Biglobe × DDD

Page 6: 20151110 ドメイン駆動設計によるサービス開発

DDDの歴史と組織

Page 7: 20151110 ドメイン駆動設計によるサービス開発

DDD 適用サービスの歴史

2013年 2014年 2015年

Wi-Fiスポット

LTE/3G音声

Biglobe電話

Biglobe光

MVNO支援サービス

リニューアル ドコモ光

LTE/3G全部

新規サービス

LTE/3G帯域制御

NINJA SIM

※初回 S-inのみ記載。各サービスは現在も開発中。

Page 8: 20151110 ドメイン駆動設計によるサービス開発

5チーム /30人規模でDDD実践中!全開発者の30%

Page 9: 20151110 ドメイン駆動設計によるサービス開発

100名規模でDDDを実践できる組織にしたい!

Page 10: 20151110 ドメイン駆動設計によるサービス開発

組織として大事にしていること全開発者でDDDの価値を共有。

現状の課題分析と課題解決に向けての行動。

人材育成計画。

新たな技術にチャレンジ。

開発環境基盤の高度化もちゃんとやる。

Page 11: 20151110 ドメイン駆動設計によるサービス開発

DDDを採用する価値

Page 12: 20151110 ドメイン駆動設計によるサービス開発

開発現場の取り巻く環境

サービス

関心事が何か?明確化

誰の関心事なのか?価値の最大化

Page 13: 20151110 ドメイン駆動設計によるサービス開発

開発現場の取り巻く環境

サービス

関心事が何か?明確化

サービスを継続することが前提

誰の関心事なのか?価値の最大化

Page 14: 20151110 ドメイン駆動設計によるサービス開発

開発現場の取り巻く環境

サービス

関心事が何か?明確化

サービスを継続することが前提

誰の関心事なのか?

使われ続ける

変更し続ける

成長し続ける

価値の最大化

Page 15: 20151110 ドメイン駆動設計によるサービス開発

開発現場の取り巻く環境

サービス

関心事が何か?明確化

サービスを継続することが前提

誰の関心事なのか?

使われ続ける

変更し続ける

成長し続ける

関わる人も変わっていく

価値が変わる可能性大

価値の最大化

Page 16: 20151110 ドメイン駆動設計によるサービス開発

開発現場の取り巻く環境

サービス

関心事が何か?明確化

サービスを継続することが前提

誰の関心事なのか?

使われ続ける

変更し続ける

成長し続ける

関わる人も変わっていく

価値が変わる可能性大

価値の最大化

課題

Page 17: 20151110 ドメイン駆動設計によるサービス開発

独自言語だとつぎはぎで機能強化していくのでサービスの維持で

精一杯

Page 18: 20151110 ドメイン駆動設計によるサービス開発

機能強化に莫大な費用がかかる

Page 19: 20151110 ドメイン駆動設計によるサービス開発

サービス終了までの

トータルコストの削減が大事

Page 20: 20151110 ドメイン駆動設計によるサービス開発

DDDを採用する価値

トータルコスト削減

Page 21: 20151110 ドメイン駆動設計によるサービス開発

DDDを採用する価値

トータルコスト削減

変更コストを下げる

属人性を下げる

Page 22: 20151110 ドメイン駆動設計によるサービス開発

DDDを採用する価値

トータルコスト削減

変更コストを下げる

属人性を下げる

業務をコードで表現

Page 23: 20151110 ドメイン駆動設計によるサービス開発

チーム環境の考え方 スクラム開発

Page 24: 20151110 ドメイン駆動設計によるサービス開発

スクラムの概要

Page 25: 20151110 ドメイン駆動設計によるサービス開発

DDD目線でのスクラム

立ち上げ

初期ドメインモデルな

スプリント ドメインモデル

1W~3W

1W

24 H

コード

リリース

2M~3M

プロダクトバックログ

スプリントバックログ

プロダクト

Page 26: 20151110 ドメイン駆動設計によるサービス開発

立ち上げ

Page 27: 20151110 ドメイン駆動設計によるサービス開発

初期ドメインモデル

業務フロー図

ユースケースフロー図

スケルトンコード

DB設計

状態遷移図

コンテキストマップ

④ ③

Page 28: 20151110 ドメイン駆動設計によるサービス開発

初期ドメインモデル

業務フロー図

ユースケースフロー図

スケルトンコード

DB設計

状態遷移図

コンテキストマップ

④ ③

ドメインモデルを成長させる

Page 29: 20151110 ドメイン駆動設計によるサービス開発

例:ユースケースフロー図

アクター

処理の流れ

ユースケース単位にどのエンティティが

何の業務をするのか設計。

主にアプリケーション層の設計。

Page 30: 20151110 ドメイン駆動設計によるサービス開発

立ち上げ時の心構え

Page 31: 20151110 ドメイン駆動設計によるサービス開発

開発初期はわからない事だらけ

Page 32: 20151110 ドメイン駆動設計によるサービス開発

開発初期はわからない事だらけ方向付けレベルの設計に留める

Page 33: 20151110 ドメイン駆動設計によるサービス開発

コアドメインを議論することはサービスを理解する第一歩

Page 34: 20151110 ドメイン駆動設計によるサービス開発

サービスの複雑性と向き合う

Page 35: 20151110 ドメイン駆動設計によるサービス開発

スプリント

Page 36: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデル

ユースケースフロー図

コード

スプリントバックログ

各メンバーがスプリントバックログに着手。

Page 37: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデルとコードを結びつける ↓

モデルの持つ意図をコードに引き継ぎ コードを通してモデルにフィードバック

Page 38: 20151110 ドメイン駆動設計によるサービス開発

設計者と実装者を分離しない

Page 39: 20151110 ドメイン駆動設計によるサービス開発

スプリント時の心構え

Page 40: 20151110 ドメイン駆動設計によるサービス開発

コアドメインの設計・実装は

重点的に

Page 41: 20151110 ドメイン駆動設計によるサービス開発

プルリクエストのWIPを活用して効率的にレビューを!

WIP:Work In Progress(作業中)の略。

Page 42: 20151110 ドメイン駆動設計によるサービス開発

スプリントごとにドメインモデルから重要な概念を追加不要な概念を削除

Page 43: 20151110 ドメイン駆動設計によるサービス開発

普段の会話の

ぎこちなさに敏感になる

Page 44: 20151110 ドメイン駆動設計によるサービス開発

書き言葉と話し言葉が

ズレたら警告サイン

Page 45: 20151110 ドメイン駆動設計によるサービス開発

初期のドメインモデルや実装では重要と思わなかった問題が見つかる可能性がある

Page 46: 20151110 ドメイン駆動設計によるサービス開発

見つけた問題を放置するといつか困ったことになる

Page 47: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデルと実装を

改善するプロセスが大事

Page 48: 20151110 ドメイン駆動設計によるサービス開発

スクラム開発 まとめ

ドメインモデルは時間と共に進化。

立ち上げ時は方向付けレベルの設計。

スプリント内の設計活動が重要。

Page 49: 20151110 ドメイン駆動設計によるサービス開発

チーム環境の考え方 チームビルディング

Page 50: 20151110 ドメイン駆動設計によるサービス開発

SW開発におけるチームビルディングの

必要性

Page 51: 20151110 ドメイン駆動設計によるサービス開発

SW開発はチームスポーツであり技術的要因と同じだけ人的要因が

パフォーマンスに影響

Page 52: 20151110 ドメイン駆動設計によるサービス開発

チームメンバーが相乗効果を発揮

Page 53: 20151110 ドメイン駆動設計によるサービス開発

知識(要求)が絶えず変化するので知識の共有が大事

Page 54: 20151110 ドメイン駆動設計によるサービス開発

DDDにおけるチームビルディングの

必要性

Page 55: 20151110 ドメイン駆動設計によるサービス開発

本の紹介

Page 56: 20151110 ドメイン駆動設計によるサービス開発

チーミング素直に意見を言う 試みる 協働する 省察する

学習するための組織づくり境界を越えて通じ合う 失敗から学ぶ 心理的安全を生み出す 学習するための骨組みを作る

学習しながら実行する診断する デザインする 行動する 省察する 

学習しながら実行するための土台

Page 57: 20151110 ドメイン駆動設計によるサービス開発

チーミング

素直に意見を言う 試みる 協働する 省察する

学習するための組織づくり境界を越えて通じ合う 失敗から学ぶ 心理的安全を生み出す 学習するための骨組みを作る

学習しながら実行する診断する デザインする 行動する 省察する 

学習しながら実行するための土台

DDDで必須の考え方

Page 58: 20151110 ドメイン駆動設計によるサービス開発

効率を追求しながら実行する 学習しながら実行する

リーダーは答えを持っている リーダーは方向性を定める

決まったプロセスが導入される 出発点として意図的に仮の作業プロセスが設けられる

変わることは大変な労力を伴う仕事だと考えられる

絶えず少しずつ変化することが日常的になる

一方通行のフィードバックがなされる

双方向のフィードバックがなされる

社員の判断は阻止される 社員の判断は不可欠である

上司を恐れるのは普通のことである 不安があると試みや分析や問題解決が妨げられる

目標:今日にも利益を勝ち取ること 目標:長期的な価値を生み出すこと

Page 59: 20151110 ドメイン駆動設計によるサービス開発

効率を追求しながら実行する 学習しながら実行する

リーダーは答えを持っている リーダーは方向性を定める

決まったプロセスが導入される 出発点として意図的に仮の作業プロセスが設けられる

変わることは大変な労力を伴う仕事だと考えられる

絶えず少しずつ変化することが日常的になる

一方通行のフィードバックがなされる

双方向のフィードバックがなされる

社員の判断は阻止される 社員の判断は不可欠である

上司を恐れるのは普通のことである 不安があると試みや分析や問題解決が妨げられる

目標:今日にも利益を勝ち取ること 目標:長期的な価値を生み出すこと

当てはまる箇

所が多い

Page 60: 20151110 ドメイン駆動設計によるサービス開発

DDDに関連するチームビルディングの

内容

Page 61: 20151110 ドメイン駆動設計によるサービス開発

1つ目

Page 62: 20151110 ドメイン駆動設計によるサービス開発

全員で設計

Page 63: 20151110 ドメイン駆動設計によるサービス開発

メンバー全員が考える場を作る。メンバーの意見を引き出す。

メンバー間のギャップをなくす。

ファシリテーション重要

Page 64: 20151110 ドメイン駆動設計によるサービス開発

メンバー全員が

同じ地図(ドメインモデル)を理解するため

全員で設計する目的

Page 65: 20151110 ドメイン駆動設計によるサービス開発

設計の目的と効果をメンバー全員が理解して実装するため

全員で設計する目的

Page 66: 20151110 ドメイン駆動設計によるサービス開発

熟練者のノウハウを

経験が浅いメンバーに

伝授するため

全員で設計する目的

Page 67: 20151110 ドメイン駆動設計によるサービス開発

2つ目

Page 68: 20151110 ドメイン駆動設計によるサービス開発

モデリング済みの部分も積極的にモデリング

Page 69: 20151110 ドメイン駆動設計によるサービス開発

実施タイミング

 大規模な機能強化時 プランニング時 バックログの着手時 コードレビュー時 朝会後に 行き詰った時

ホワイトボードがあれば

いつでもモデリングできる

Page 70: 20151110 ドメイン駆動設計によるサービス開発

経験が浅いメンバーはモデリングする機会を増やすこ

とが成長につながる

既存部分をモデリングする目的

Page 71: 20151110 ドメイン駆動設計によるサービス開発

新規加入メンバーはドメインを理解する

チャンス

既存部分をモデリングする目的

Page 72: 20151110 ドメイン駆動設計によるサービス開発

モデリングは

メンバー自身に実施させる

大事なこと

Page 73: 20151110 ドメイン駆動設計によるサービス開発

チームビルディングの結果

Page 74: 20151110 ドメイン駆動設計によるサービス開発

チームの設計力が強化

Page 75: 20151110 ドメイン駆動設計によるサービス開発

変更コスト /属人性が下がる

設計力が強化すると

Page 76: 20151110 ドメイン駆動設計によるサービス開発

DDDを採用する価値

トータルコスト削減

変更コストを下げる

属人性を下げる

業務をコードで表現

DDDを採用する価値につながる。

Page 77: 20151110 ドメイン駆動設計によるサービス開発

チームビルディング まとめ

DDDはチームビルディングが必須。

全員で設計することが大事。

既存部分も積極的にモデリングすることが大事。

Page 78: 20151110 ドメイン駆動設計によるサービス開発

設計・実装の考え方 アプリケーションコード

Page 79: 20151110 ドメイン駆動設計によるサービス開発

組織で行ったDDD勉強会のコードを紹介

Page 80: 20151110 ドメイン駆動設計によるサービス開発

動作環境言語 :  Java8

フレームワーク :  SpringFramework

O/Rマッピング : MyBatis

DB : Oracle(ローカルはH2)

ビルドツール : Gradle

Page 81: 20151110 ドメイン駆動設計によるサービス開発

ユースケース

Page 82: 20151110 ドメイン駆動設計によるサービス開発

コンテキストマップ

Page 83: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデル

Page 84: 20151110 ドメイン駆動設計によるサービス開発
Page 85: 20151110 ドメイン駆動設計によるサービス開発

入会仕様入会可能条件20歳以上である。利用可能なクレジットカードを保持している。

接続コースは「ベーシック」または「ニコニコ」で申し込む。

入会の際、会員登録情報として申込者の個人情報を必要とする。

Page 86: 20151110 ドメイン駆動設計によるサービス開発

レイヤー構造

ドメイン層

API層 アプリケーション層

インフラストラクチャ層

ドメイン層を独立させる

ドメイン層に依存させる

Page 87: 20151110 ドメイン駆動設計によるサービス開発

ここからコードで

Page 88: 20151110 ドメイン駆動設計によるサービス開発

アプリケーション層入会サービス

Page 89: 20151110 ドメイン駆動設計によるサービス開発

アプリケーション層入会審査サービス

Page 90: 20151110 ドメイン駆動設計によるサービス開発

ドメイン層会員エンティティ

Page 91: 20151110 ドメイン駆動設計によるサービス開発

ドメイン層リアルタイム審査

Page 92: 20151110 ドメイン駆動設計によるサービス開発

データソース層会員リポジトリ

Page 93: 20151110 ドメイン駆動設計によるサービス開発

データアクセス層会員リポジトリのMapper

Page 94: 20151110 ドメイン駆動設計によるサービス開発

設計・実装の考え方  DB設計

Page 95: 20151110 ドメイン駆動設計によるサービス開発

イミュータブルデータモデル

Page 96: 20151110 ドメイン駆動設計によるサービス開発

業務が発生すると、業務履歴をひたすら記録

( insert)

これだけ

Page 97: 20151110 ドメイン駆動設計によるサービス開発

とある業務に対する変更業務も

当たり前のように記録( insert)

Page 98: 20151110 ドメイン駆動設計によるサービス開発

変更業務でUpdateすると記録の改ざん

これは、極論です(笑)

Page 99: 20151110 ドメイン駆動設計によるサービス開発

業務を中心に捉えると業務ごとにデータが残る方が自然

Page 100: 20151110 ドメイン駆動設計によるサービス開発

現実はInsertオンリーなDB設計は難しい

Page 101: 20151110 ドメイン駆動設計によるサービス開発

テーブルの種類

Eventテーブル業務が発生するとひたすら insertしていくテーブル。

Stateテーブル業務が発生すると必要に応じて updateしていくテーブル。ステータスなど最新の情報を管理。

Page 102: 20151110 ドメイン駆動設計によるサービス開発

Eventテーブルが中心。

Stateテーブルは補助。

Page 103: 20151110 ドメイン駆動設計によるサービス開発

Stateテーブルの使いどころパフォーマンス改善が図れる場合。

DB側で業務イベントの発生ルールを完璧にコントロールしたい場合。(詳細は後程。)

Page 104: 20151110 ドメイン駆動設計によるサービス開発

Stateテーブルはデータアクセス層

の関心ごとで利用

Page 105: 20151110 ドメイン駆動設計によるサービス開発

イミュータブルデータモデルを徹底すると

副次効果としてNULL項目が減る!

Page 106: 20151110 ドメイン駆動設計によるサービス開発

具体的な話

Page 107: 20151110 ドメイン駆動設計によるサービス開発

DDD勉強会のDB設計

Page 108: 20151110 ドメイン駆動設計によるサービス開発

biglobeID入会日

biglobeID(FK)退会日

入会 退会

会員に関連するテーブル

Page 109: 20151110 ドメイン駆動設計によるサービス開発

abc123452015/10/10

abc123452016/10/10

退会イベント入会イベント

入会 退会

業務が発生すると、関連するテーブルに業務履歴を記録( insert)

Page 110: 20151110 ドメイン駆動設計によるサービス開発

biglobeID入会日退会日

会員

ミュータブルデータモデル

だけ

Page 111: 20151110 ドメイン駆動設計によるサービス開発

abc123452015/10/10null

abc123452015/10/102016/10/10

会員 会員

update

退会イベント入会イベント

Page 112: 20151110 ドメイン駆動設計によるサービス開発

もう少し難しく

Page 113: 20151110 ドメイン駆動設計によるサービス開発

契約エンティティに対するDB設計の場合

申込中

契約中

解約予約中

解約済

申込キャンセル

Page 114: 20151110 ドメイン駆動設計によるサービス開発

申込 ID申込 ID(FK)

申込契約

申込 ID(FK)

キャンセル

解約 ID申込 ID(FK)解約日

解約

解約 ID(FK)解約キャンセル

Page 115: 20151110 ドメイン駆動設計によるサービス開発

申込 ID申込 ID(FK)

申込契約

申込 ID(FK)

キャンセル

解約 ID申込 ID(FK)解約日

解約

解約 ID(FK)解約キャンセル各テーブルの外部キーにより

業務イベントの流れをコントロール

Page 116: 20151110 ドメイン駆動設計によるサービス開発

これにStateテーブルを足すなら

Page 117: 20151110 ドメイン駆動設計によるサービス開発

申込 ID申込 ID(FK)

申込契約

申込 ID(FK)

キャンセル解約 ID申込 ID(FK)

解約

解約 ID(FK)解約キャンセル

申込 ID(FK)

ステータス

Page 118: 20151110 ドメイン駆動設計によるサービス開発

申込 ID申込 ID(FK)

申込契約

申込 ID(FK)

キャンセル解約 ID申込 ID(FK)

解約

解約 ID(FK)解約キャンセル

申込 ID(FK)

ステータス

契約とキャンセルは排他な関係。

Page 119: 20151110 ドメイン駆動設計によるサービス開発

契約とキャンセルが同時に発生した場合、アプリケーションコードと Eventテーブルだけで、この制約を実現できない。

Stateテーブル更新時のWhere句でステータスも条件(ステータス=申込中)に入れることにより、この制約を維持できる。

Page 120: 20151110 ドメイン駆動設計によるサービス開発

申込 ID申込 ID(FK)

申込契約

申込 ID(FK)

キャンセル解約 ID申込 ID(FK)

解約

解約 ID(FK)解約キャンセル

申込 ID(FK)

ステータス

解約キャンセルするユーザが少ないと判断して、 Stateテーブルは導入しない。最新の解約レコードから判断。

Page 121: 20151110 ドメイン駆動設計によるサービス開発

失敗談

Page 122: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデル関連ドメインモデルが古い

ドメイン層関連Policyクラスの乱立

Page 123: 20151110 ドメイン駆動設計によるサービス開発

データアクセス層関連Repositoryの saveメソッド

他集約の Repositoryを操作

SQLに業務ロジックが混在

Page 124: 20151110 ドメイン駆動設計によるサービス開発

失敗談 ドメインモデルが古い

Page 125: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデルが古い内容日々変化するドメインモデルが最新化されない。

問題点値オブジェクトを全部管理していたので、更新が追い付かない。最新のドメインモデルが把握できない。

対策最初に作成するドメインモデルと Keepするドメインモデルを分離。Keepのドメインモデルは重要な概念や本質のみ。

Page 126: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデルが古い

最初に作成するドメインモデル

Page 127: 20151110 ドメイン駆動設計によるサービス開発

ドメインモデルが古い

Keepするドメインモデル

Page 128: 20151110 ドメイン駆動設計によるサービス開発

失敗談  Policyクラスの乱立

Page 129: 20151110 ドメイン駆動設計によるサービス開発

Policyクラスの乱立内容業務チェックのために、ドメイン層に Policyクラスを用意。

問題点エンティティから業務ロジックが抜けていく(エンティティ貧血症)。

対策基本的には、エンティティに業務チェックを記述。明示的にクラス化したい業務チェックのみ、専用のクラスを用意。

Page 130: 20151110 ドメイン駆動設計によるサービス開発

Policyクラスの乱立

Policyパッケージを作った時点で負け

Page 131: 20151110 ドメイン駆動設計によるサービス開発

失敗談  Repositoryの saveメソッド

Page 132: 20151110 ドメイン駆動設計によるサービス開発

Repositoryの saveメソッド内容永続化のメソッドを saveメソッドのみで対応。

問題点テーブル構成がドメイン層に浸食。saveメソッドでどのテーブルが登録・更新されるか不明。saveメソッドをメンテナンスできるメンバーが限定。

対策業務イベントごとに専用のメソッドを用意。

Page 133: 20151110 ドメイン駆動設計によるサービス開発

失敗談 他集約の Repositoryを操作

Page 134: 20151110 ドメイン駆動設計によるサービス開発

他集約の Repositoryを操作内容他集約の Repositoryをデータアクセス層で操作。

問題点アプリケーション層のコードだけでは関連する集約が把握できず、全てのコードを読む必要がある。

影響範囲の特定に時間がかかる。ミスする。

対策他集約の Repositoryは操作しない。

Page 135: 20151110 ドメイン駆動設計によるサービス開発

失敗談  SQLに業務ロジックが混在

Page 136: 20151110 ドメイン駆動設計によるサービス開発

SQLに業務ロジックが混在内容SelectのWhere句に業務ロジックが記述。

問題点業務ロジックがドメイン層から流出。いつかの仕様変更でバグの温床に。

対策可能な限り業務ロジックはドメイン層に集約。

Page 137: 20151110 ドメイン駆動設計によるサービス開発

検索条件は主キーのみにしてステータスの絞り込み条件はド

メイン層で記述

Page 138: 20151110 ドメイン駆動設計によるサービス開発

まとめ

Page 139: 20151110 ドメイン駆動設計によるサービス開発

DDD本と現場での実践を行ったり来たりして

理解を深めていくことが重要

Page 140: 20151110 ドメイン駆動設計によるサービス開発

サービスが存在する限り

変化し続け成長し続け

価値を届け続けるソフトウェアを作ることが重要

Page 141: 20151110 ドメイン駆動設計によるサービス開発

ご静聴ありがとうございました。