radioc@?

レディオキャットハテナ

【勉強会メモ】Mix Leap Study 特別編 - レガシーをぶっつぶせ。現場でDDD! コラボカンファレンス

yahoo-osaka.connpass.com

  • 日時:2019/08/31(土) 13:00 〜 20:00
  • 場所:ヤフー株式会社 大阪グランフロントオフィス

5月に東京で開催されたイベント の再演も含めた大阪特別編が開催されました。ヤフーさん主催だからこそできることだと思いますが、東京で開催されたイベントが大阪でも開催される機会はあまり多くないのでありがたいイベントです。私はチームとしてのDDDの取り組みや教育をテーマにしたものが多かったA会場の発表に興味があったのでメモは全てA会場のものです。

レガシーをぶっつぶせ趣旨説明

DXレポート

www.meti.go.jp

レガシーシステムの問題点

ちゃんと設計しよう

  • ドメイン駆動設計の「成長を続ける」ソフトウェア
  • きれいな理論というよりは現場のドロドロ感

基調講演:ドメイン駆動設計という設計スタイル

増田 亨さん

www.slideshare.net

話すこと

  • 設計スタイルの選択
  • ドメインロジックに焦点をあわせる
  • 開発現場での実験結果と考察

設計スタイルの選択

設計スタイルの3つの側面

  • 関心の分離のアプローチ
    • 何を分けて何を一体化するか
  • モジュール構造の考え方
    • どう分割し、どう組み立てるか
  • 20:80のとらえ方
    • 重要な2割が全体の8割に影響を及ぼす
    • 2割が大事

設計スタイルの違い

ドメイン駆動設計のスタイル

  • ビジネスルールに基づく計算と判断のロジックに焦点を合わせる
  • ビジネスルールに藤蔵する値の種類に注目して独自の型を定義してロジックを整理する
  • ビジネスルールを記述する部分の設計と実装がアプリケーション全体の構造と秩序を左右する

ドメインロジックに焦点をあわせる

ドメインロジック、ドメインの知識

ビジネスの活動
↑制約する/促進する
ビジネスルール
↑ビジネスに基づく計算と判断のロジック
ビジネスロジック

ビジネスルール

  • ビジネスの活動を成約し促進する決め事
  • 物理法則のような論理的な体系ではない
  • 過去の意思決定の積み重ね
  • 現在のビジネスルール体系は通過点
  • これからもビジネスルールの追加や変更が続く
    • 変更用意性は少し違和感⇒変更を容易にしているわけではない
    • どんなものが来てもまあ何とかなるという感じ

ビジネスルールを学び続ける

  • ビジネスルールの知識を広げると、要求の意味が理解できる
  • ビジネスルールを深く理解すると、関係性や構造が見えてくる
    • 深く理解すると非合理に見えても実は関係していることがわかる
    • 精神衛生上良い
  • 詳細な仕様の補完力と提案力が増す
    • ビジネス側が本当の中身のことまで言ってくれることはない
    • 自分たちで補完してじゃあこうしたらいいですよねと提案する
  • ビジネスとビジネスルールは時間とともに変化し続ける
    • 生きているビジネスを相手にすることは常に勉強してアップデートしていく

現場で役立つビジネスルールの基礎知識

ドメイン層の全体構造を設計する時の指針

  • 文書化(構造化)されたビジネスルール
  • 顧客の利益vs自社の利益
    • 折り合いのつけ方の決め事
  • 競争戦略とビジネスルール
  • ビジネスルールの階層構造

文書化(構造化)されたビジネスルール

  • 説明
  • 契約書
  • 業務マニュアル
  • 簿記・予実管理

↑俯瞰的なものは日常会話からは出てこない

顧客の利益vs自社の利益をどこで折り合いをつけるかの決め事

  • 顧客価値
  • 顧客からみたコスト
  • 顧客の利便性
  • 顧客とのコミュニケーション

競争戦略とビジネスルール

  • リーダー
  • チャレンジャー
  • フォロワー
  • ニッチャ
↑こだわりポイントが変わる
⇒パッケージ構造が変わる

ビジネスルールの改造構造

  • ポリシー
  • 約束
  • 運用
  • 能力

ビジネスルールをコードで表現する基本テクニック

ビジネスルールとコード表現

  • スライド参照

ビジネスルールの構成要素

  • Fact
  • Rule
  • Goal

独自の型を定義する

  • 型は値の種類
  • 型は値の範囲を制限する
  • 型は可能な操作(演算)を制限する
  • 型はプログラムに構造と秩序をもたらす
  • 型の名前がコードの意図を豊かに表現する

現場で役立つ独自の型の設計パターン

値オブジェクト(独自の型)の効果

  • 独自の型はロジックを集約する
    • なかなか理解してもらえない
  • 独自の型は可読性を向上する
    • わりとすぐ理解してもらえる
  • 独自の型は信頼性を向上する
    • 時間がかかる
  • 独自の型はコードの追跡を容易かつ確実にする
    • 即効性がある

条件分岐との戦い

  • if文、booleanで表現された暗黙の区分
  • レガシーで怪しげなコード体系

型を使った列挙

ビジネスルールの記述にコレクションを使う

  • Mapを使った料金ルールの早見表
  • Setを使ったスキルセットのマッチングロジック
  • Listを使った集約、最適要素の発見
  • ビジネスロジックを集約した複合型のコレクション

ビジネスルールを独自の型で表現する役立つ技法の学び方

エヴァンス本の拾い読みのススメ

現場で確認できたこと

  • コードを考えて書く人
    • 意図ややり方は確実に伝わる
    • サンプル、ツール、ガイドラインも整った
    • どのくらいしみついているか?発想が柔軟か?
  • コードを書かない人
    • 言葉で伝えるのは無理
    • 設計やその影響に関心を持っている人は一部
    • その人の関心の文脈で見せる

コードで確認できる発想の変化

  • 独自の型の量と質
  • パッケージの構造、パッケージ名
  • 入出力の記述箇所への独自の型の浸透

言葉と会話で確認できる発想の変化

  • タスク名、ToDo名、コミットログ
  • 質問やアドバイスに登場する言葉
  • パッケージ名、クラス名、メソッド名の相談
  • ロジックの置き場所の相談

DeliveryとQualityを両立させるために僕らがやったこと〜トラベルシステムの技術全面刷新〜

関口 岳志さん

www.slideshare.net

レガシー刷新案件の話

  • 制約の中Quality高いものを作り維持し続けること
  • Quality
    • 可用性
    • パフォーマンス
    • 保守性
  • 制約
    • 予算
    • 工期
    • 技術力

設計の工夫

  • アーキテクチャのコンセプト
  • UI/UXとAPIをとにかく汚染させない
  • きれいにつくって維持し続ける

刷新前

まずはAPIをキレイに

WebとAPIの乖離

Data

  • データ定義が荒れているためそれを操作するAPIが腐敗する
  • 先にDataを整理するのはリスク
  • 整理が難解で時間がかかる
  • APIが固まってから手を入れたほうが良い

インテグレーション層を追加

  • データ操作をインターフェイスで提供
  • 複数のDBMSを閉じ込めることができる
  • DBまわりは専門性が違うので分離できるメリットもある

GW系

  • フロントGW
  • APIGW層

JobSchedulerはジョブ管理

DDDの話

コンポーネント分割イメージ

  • API層をDDDで分解
  • システム全体をDDDは難易度高すぎると考えた

分割の流れ

0) インプット

  • エヴァンス本
  • レディマイクロサービス
  • 増田さんのDDDワークショップ

1) 対象コンポーネントとメンバーを決定

  • 対象は「予約」
  • 技術メンバー3人、Dir1名、Cre1名
  • 概念や分割の流れを説明
  • いびつでいいのでアウトプットを必ず出す
  • 限られた時間でアウトプット

2) 関心事の各自理解

  • モデル化

3) チームの言語基盤を作る

  • 例)料金なのか金額なのか

4) 骨格を説明する

  • 文章化
  • 重要な順に
  • 論理的な文章が書ける⇒論理的なクラス設計

5) モデルと実装を紐付ける

  • 部品を揃えていく
  • 概念クラス図に落とし込む
  • 1つ目でダメでも2つ目をやってみる
  • 役に立つ部品を見つける
  • 文章ごとに独立して実装できたほうがいい
  • アウトプット最優先

学び

  • インプットは付け焼き刃じゃ無理
  • 対象にした予約が難しすぎた
  • モチベーションや向き不向きの差

難易度低いものからやっていくほうがいい

登り方の工夫

  • 一括全面刷新はやらない
    • 品質リスク
      • リリースしたけど効果が出ないリスク
    • 工期的なリスク
      • 新旧両方
    • 案件Goを通せない
      • 刷新案件は特質上、失敗したら二度とできない

段階的な刷新の流れ

  • スモールスタートで一部を刷新
  • 並行稼動で検証
  • 品質を満たせば残りを対応開始
  • 実績ができた現行コンポーネントは削除

スモールスタートをどうやったか

  • トラベルのMyページを対象
  • カナリアリリースで現行と並行稼動して効果検証
  • Proxyを立てて10%を新しいほうに流す
    • ユーザー固定

検証項目

  • システム観点
    • 機能落ちしてないか
    • 障害発生ないか
    • メトリクス値
    • パフォーマンス
  • 保守性視点
    • 開発効率
    • 運用フロー
    • 障害対応フロー

検証完了したらProxyで100%流す

  • いらなくなった現行を削除

スモールスタートでハマったこと

  • 暗中模索
    • 分からないこと不安が多い
  • 仕様書の消失
    • 資料がない、メンテされていない
  • 新しいことをたくさんやりたい欲求
    • せっかくなので色々チャレンジしたい

暗中模索対策

  • 中心的に進める人と壁打ち役の選定
  • 中心的…技術力・PM力、サービス理解
    • バランス良く総合力高い人がやらないとうまくいかない
  • 壁打ち役
    • 中心の人と同等かそれ以上の人
    • いない場合はフリーのエンジニア
    • 分からないことのアドバイス
    • 人材が全然いない

仕様書の消失

  • DDDで書き起こすチャンスと捉える
  • ビジネスモデルの理解、共通認識が協力にできる

新しいことをやりたい欲求対策

  • やるべきことに加えて3個までにする

残りの刷新

  • きれいを維持
  • 人が増えてぐちゃぐちゃになりがち
  • WGを作る⇒組織として壁打ちする

ガイドラインと承認フロー

対応コストをなるべくへらす

  • 選択と集中
  • ×全てのコンポーネントを全力で完璧にする
  • 効率化
    • 非重点なところは最低限の刷新にする
  • 全社的に求められているところは必ずやる
    • 言語やアーキテクチャは現行から変えない
    • 全社と違うとサポート受けれない
  • 効率が上がらないなどのリスクはある

KPI貢献度、保守コストが高いものが重要

  • 数年のトレンド分析
  • 斜陽だがKPI貢献
  • KPI貢献がないものはクローズ
  • KPIとは
    • 売上貢献
    • コンバージョン

最終的にシステムに組織をあわせたい

登り方はスモールスタートが大事

非エンジニアの同意と承認の工夫

  • ビジネスメリットで語る
  • サービスKPIにどう貢献するか

だめなもの

  • 概算値
  • 外部引用
  • 一般論

よいKPI

  • 実績値
  • 開発効率の向上度合い

スモールスタート前の承認のとり方

  • ビジネスメリットと一般論でゴリ押し
  • スモールスタートして効果検証してFBすることも約束
  • 工数は全体のうちの一部だけを強調

実績値のとり方

  • 刷新前後のシステム上で全く同じPDCA

フェーズごとに比較

  • 全工程でコスト減
  • テストが減少
  • 副次効果で工期短縮
    • 人員を効果的に配置
  • Bad
    • 詳細設計増加
    • UT増加
      • もともと書いてなかったので
  • 合算で28%向上

非エンジニア向けにパッケージング

  • 開発効率⇒サービスの巡航速度
  • PDCAサイクルの速度128%
  • チャレンジできる

ビジネスメリットと実績値で語る

ドメイン駆動設計とマイクロサービス

三石 広樹さん

www.slideshare.net

はまらないマイクロサービス

対象サービス

  • コンテンツ表示サービス
    • 例)ポイントプレゼント表示、レコメンド表示など
    • マイクロサービス化するのは入稿システム

開発のモチベーション

  • モダンなシステムを目指して開発
  • エンジニア育成⇒重点
  • マイクロサービス
  • Twelve Factors

データモデル

  • ER図
    • ページ情報
    • コンテンツ情報
    • シナリオ情報

マイクロサービス…?

  • まるでモノリシックなシステムのパッケージをAPI化しただけのような…
  • マイクロサービス化してもモノリシックなサービスと変わらない課題

変化に弱い

  • ビジネス上のルール変更の要求
    • 改修範囲が広い
    • 改修箇所の特定が困難
    • デプロイが複雑
  • レガシー化

なにかの「考え」が足りていない

  • ビジネスとサービスの不一致

ドメイン駆動設計で切り込む

  • モチベーション
    • マイクロサービスの切り方がよくない
    • マイクロサービス化の指標がほしい
    • ドメイン駆動設計の発想・手法に着目
    • ソフトウェアはビジネス課題(ドメイン)を解決する
    • ひとつのマイクロサービスでひとつのドメインの問題を解決

これまでの設計

  1. データ設計
  2. Web APIに切り分け

データに着目して設計したら巨大なモノリシックができる

これからの設計

  1. モデリング
  2. Web APIに切り分け

  3. コンテキストの境界を探る

  4. 集約を見つける
  5. ドメインで分割
データ(技術視点)をベースにシステムを考える
↓
モデル(ビジネス視点)をベースにシステムを考える

現場で実践

企画から新しい案件

  • コンテンツを一括作成できるツールがほしい
  • 共通と個別をバルクインサート
  • 別のシステムで承認して取り込む

ドメインモデリングしよう

  • ユーザーはなににどんな関心があるのか?
  • 関心事をモデリング(設計)しよう

モデリング

  1. モデルを洗い出す
  2. 関係を整理する

気付き

  • 表面化していないモデルを定義
  • まだ曖昧なモデルを見つけた
  • これから必要になると予想した
  • ビジネスも常に成長途中
  • エンジニアがモデル明確化をフォロー

集約をユースケースから考えた

  • 集約とコンテキスト
  • ユーザーの操作対象がなにかを追求した
  • 操作する単位をビジネスサイドと議論
  • ビジネス視点で考えてドメインを操作したい単位を見極める

クリーンアーキテクチャでパッケージ設計

  • ビジネスルールがつまったドメイン設計のレイヤーを切り離す

実装を終えて

得られたメリット

  • 改修範囲が広い
    • ビジネスとサービスの単位一致により局所化
  • 改修箇所の特定が困難
  • デプロイが複雑

ドメイン駆動設計が守る

  • リファクタ
  • 機能追加
  • 考慮漏れ
  • 仕様変更

気づいた難しさ

  • チーム
    • ドメイン駆動設計の理解を得難い
    • 複数チームだと難しい
  • 技術
    • 初期実装コストが高い
    • ドメインを守ることが大変

これから守りたいポイント

現場のDDD体験共有

薮内 聖也さん

ヤフーダイニングのレガシーはビジネスロジックが整理されていない

戦略的設計

ビジネスロジックの散在(レガシー)

API化を目指す

取り組み

  1. システム全体に存在するシステムのグループ分け
  2. 重要度の高い「新規予約:ユースケースの調査
  3. 「新規予約」ユースケース関連のシステム構成設計

できたサブドメイン

  • 店舗
  • 予約
  • ユーザー
  • 特集

戦術的設計

レガシーコード

  • 場当たり的な改修で読解不可能な領域
  • 例)完了クラス
    • なんでも完了できる
    • 場当たり的なif文
      • 新規予約
      • 予約変更
      • 即予約
  • 副作用を多用
    • 多くのメソッドはフィールドを書き換え

場当たり的対策

ユースケース分離が理解を簡単に

副作用がたくさん

  • 副作用の制限
  • 普遍なオブジェクトを中心にコーディング

失敗したこと

  • 戦略的設計における分析不足

店舗と予約

  • 店舗名とPR文⇒関係性高い
  • 予約と在庫の有無⇒関係性高い
  • 元々巨大な店舗テーブルの存在
  • 100カラム以上

ぎこちない責務分け

  • 店舗と予約は分けられる気がする

重要なビジネスロジックの所属場所の考察

  • 「在庫があるかないかの判断」をするのはどこ?

店舗と予約

  • 在庫有無の判断を「予約」側に寄せる考察の理由
  • 在庫の有無の判断を分けるほうが良かった
    • 店舗掲載情報
    • 店舗在庫設定

まとめ

  • 戦略的設計で分離
  • オニオンアーキテクチャでコードがシンプル
  • 戦略的設計の成功には深い業務知識とDDD経験が必要

ドメイン駆動設計でモブワークしました

辻 陽平さん

準備編

ドメインを隔離できるアーキテクチャを採用する

モブする範囲を決める

  • 開発のすべてをモブする必要はない
    • 手段(How)の部分はモブしなくていい
    • 何がどうあるべきなのか(What/Why)
    • 人の解釈を伴う部分はモブしながら共通認識を作っていく
  • つまりドメインレイヤ(とアプリケーションレイヤ)だけモブ

マルチプロジェクト化する

  • アーキテクチャで論理的にに分割しただけではレイヤを無視したコードがかけてしまう
  • モブ中の議論がついつい手段の話しに行きがち
  • マルチプロジェクト化してレイヤを物理的に分割することでレイヤの制約を強制し、議論の焦点をドメインレイヤに集中させる
  • Java/KotlinならGradleで、Scalaならsbtでマルチプロジェクト構成

実践編

会話しながらコードを書く

  • ドメインについての自分の理解・解釈を超えに出して会話することが重要
  • 必要ならラフにモデルズを描いて会話
  • だいたいのイメージが掴めてきたらコードに落としてみるを繰り返す

ドメインとアプリケーションを行ったり来たりする

  • ドメインだけで実装していると終わりが見えなくなってくる
  • アプリケーションサービスがドメインの表現力を映す鏡になる
  • アプリケーションサービスのコードがその使用をユビキタス言語で自己文書化できているのが理想的

アダプタの実装は後回しする

  • アダプタレイヤはいったんから実装やダミー実装にしておいて、本実装は後回しにする
  • アダプタレイヤの実装をやりはじえmると、ついつい意識が実現手段に向いてしまい、ドメインへの注意力が切れてしまう
  • アダプタレイヤの実装はモブしなくてもペアやソロで十分

まとめ

設計人材を育てるために DDD をどう使うべきか?

萩原 利士成さん

speakerdeck.com

  • 新規開発でもレガシーでも設計は大事
  • 良い設計は人が作り、人が育てる
  • 設計できる人がたくさんいれば大きな絵が描けるようになる
  • 自分が設計できる!=メンバーが設計できるようになる

どうやって人を育てるか?

  • 設計と実装は似ているようで違う
  • エヴァンス本を読

そもそも設計とは?

design
art or action

  • 技術や工芸みたいなこと
  • 意思決定や選択がある
  • 職人的な要素

利用者の関心事=システムの外

様々な抽象度でモデルが必要になる

  • 実装上の制約がコンセプトレベルで影響を与えたりすることもある

Artを師匠から弟子へと伝える

なぜDDDか?

  • ドメインモデルがシステムの外(ユーザーの関心)とシステムの中(クラス設計)をつなぐ
  • 実装とも無理なくつながる&ドメイン層を隔離できる
  • 設計のArtを体験しやすい

「DDDでやって」だけだと難しい

ポイント1:ドメインモデルで議論する

  • 実装圧力に負けずに責務をちゃんと考える
  • 責務の分割と組み合わせ=設計の基礎となる力
  • プロパティだけでなくメソッドについて議論を振ると見えてくる

ポイント2:別の視点で

  • ドメインモデルの中だけで切ろえんしても見えてこないことがある

ポイント3:全体が連動する感覚を体験する

  • 設計は一方通行ではない
  • 師匠の問いかけ力

実践

  • 全体を見渡せるサイズ感
  • ユーザーや管理者の行動もある
  • 緊急ではない

気付き

  • ちゃんと時間を確保する
  • 視点を変えられるようにする
  • ユーザー価値と結びつける
  • 責務について質問して自分の言葉で語ってもらう
  • ふるまいやユースケースを洗い出す
  • 実装との対応関係や実装ロードマップを議論
  • コードに落としてみる

良かったこと

  • ドメインモデル上で議論
  • 別の視点との行き来
  • 継続的なコミュニケーション

やってみての改善点

  • 実装とドメインモデルの距離が遠い
  • 時間変化についての議論が漏れがち⇒どこから作るか?どう変えるか?
  • ValueObjectがうまく作れない

反省点はあったが、設計のArtを伝えるという意味で一定の成果はありそう

設計力をどう測るか?次の課題


他会場の資料

www.slideshare.net

東京のイベントの資料

genbade-ddd.connpass.com