Slide 1

Slide 1 text

混沌からドメインモデルへ 段階的リファクタリングの試み 2019/07/30@設計会議

Slide 2

Slide 2 text

発表者 topo / @Philomagi ● 主にフロントエンド主体のWEB系エンジニア ● ScalaとTypescriptとRubyが好き ○ Rubyは最近、公私共に若干疎遠 ● PHPは中々縁が切れない悪友 ○ 最近は、そう腐すほどでもないかなと思い始めてる

Slide 3

Slide 3 text

概要 ● 設計が存在しないプロジェクト ● 既存コードが色々とアレ ● まずはFat Modelで手元を見えるように ● 道具を揃えてからドメインモデルへ

Slide 4

Slide 4 text

1. 混沌

Slide 5

Slide 5 text

混沌とした状況 ● コードの重複 ● モデル貧血症 ● 詳細に依存 ● UtilityじゃないUtil

Slide 6

Slide 6 text

カプセル化?なにそれ美味しいの? $props = Hash::extract($item->get('props'), "{n}[name=/^{$propName}[.]/]" ※Viewのコード(イメージ)

Slide 7

Slide 7 text

カプセル化?なにそれ美味しいの? return [ 'stock.enough' => $item->get('stock.amount') >= 10, // 中略 'status.hoge' => count($item->extract("props.{n}[name={$hogeStatusName}]")) >= 1, ]; ※Utilのコード(イメージ)

Slide 8

Slide 8 text

View Controller Util Model Hash

Slide 9

Slide 9 text

View Controller Util Model Hash ● Fat View(Smart UI) ● Fat Controller ● Fat Util ● 貧血モデル

Slide 10

Slide 10 text

2. 混沌からFat Modelへ

Slide 11

Slide 11 text

Why Fat Model? ● 次々に飛んでくる回収要望・追加機能 ○ モデル分析のための時間も体力も確保し難い ● 取り敢えず、直近触るコードだけでも見通しよくした い

Slide 12

Slide 12 text

Fat Modelへ ● ロジックをDTOへ集約 ● 詳細へのアクセスをメソッド経由に ● 必要に応じてValueObjectも追加 ● Utilは基本的に削除 ○ 入り組んでるものは、可能ならModel経由の利用に変更

Slide 13

Slide 13 text

Before / After $props = Hash::extract($item->get('props'), "{n}[name=/^{$propName}[.]/]" $sizes = $item->getSizesWhere($sizeName);

Slide 14

Slide 14 text

Before / After return [ 'stock.enough' => $item->get('stock.amount') >= 10, // 中略 'status.hoge' => count($item->extract("props.{n}[name={$hogeStatus}]")) >= 1, ]; return [ 'stock.enough' => $item>stock()->isEnough(), // 中略 'status.hoge' => $item>isHoge(), ];

Slide 15

Slide 15 text

View Controller Util Model Hash

Slide 16

Slide 16 text

View Controller Util Model Hash ● Fat Model

Slide 17

Slide 17 text

3. Fat Model から Domain Model へ

Slide 18

Slide 18 text

● モデルを描いて共有 ○ 仕様を握っている人と認識を揃える ● 語彙を統一 ○ DDDにおけるユビキタス言語 ● 部分的に、使えるところから導入開始 ○ 一気の置き換えは狙わない Domain Model の導入

Slide 19

Slide 19 text

Domain Object の実装 ● 統一した語彙を、クラス名/メソッド名で使用する ● データとDomain Objectの分離 ○ DTO → Domain Objectのマッピング層を用意 ○ Factory、Repository ● Modelに集約したロジックをDomain Objectに移動 ○ ModelはただのDTOになり、ロジックはDomain Objectが持つ ● パッケージでコンテクストを表現 ○ パッケージ内のオブジェクトは、ひたすらそのコンテクストに特化

Slide 20

Slide 20 text

View Controller DomainObject DomainObject View Controller DomainObject View Controller Mapping Infrastructure Model(DTO) Mapping Mapping

Slide 21

Slide 21 text

振り返って プラマイ両方有ったが、マイナスが強い ● 「何が用意してあるのか」「何が用意されてないのか」を確認 できる ● 「とりあえず読めなくはない」には持っていける ● Modelに強く依存した実装になってしまう ○ DTOがプロジェクト全体を支配してしまうため

Slide 22

Slide 22 text

評価 ● 今回はとにかくスタート地点が真っ暗闇だった ● まずは手元に何が有り、何が無いのかを把握したかった ● 今回のケースでは、一定程度の妥当性は有ったかなと感じて いる ● 決して、Bestなプロセスでは無いと思う ○ 緊急回避的 ○ 経由せずに済むなら経由しない方が良い

Slide 23

Slide 23 text

反省点 ● 「設計しない」ための言い訳としてFat Model化し た感も有る ● 設計を後回しにしたことで首が締まったことも多い ● 複雑なシステムこそ、時間が無くともきちんと設計 すべき

Slide 24

Slide 24 text

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