Software engineering from east direction

六本木一丁目で働くソフトウェアエンジニアのブログ

ドメイン駆動設計についてpospomeさんの話を聞いた | Gopher道場課外学習Ⅰ参加ログ

Gopher道場卒業生向けのイベントとして、ドメイン駆動設計について@pospomeさんの話を聞かせていただきました。

mercari.connpass.com

その際に話されていた内容についてざっとメモを残させていただきます。

ドメイン駆動設計とは

  • ドメイン
    • = 問題領域
    • ソフトウェアを適用する業務や関心事
    • ドメイン = 業務
  • 例:弥生会計
  • 業務で設計を駆動すること = ドメイン駆動設計

    merit of ddd

  • 既存の業務駆動ではない設計手法
    • DOA(データ中心アプローチ)
      • テーブル構造がModelになるMVCフレームワークではDOAになりがち
      • DBにデータを格納することを前提としている
      • -> DBの特性・目的に合わせたデータ設計になる
        • 特性:redis・RDBMS等でデータ設計が異なる
        • 目的:頻度・データ量によって異なる
      • DOAによる設計はプログラミングに対して最適かどうかはそうとは言えない、可読性の低下の可能性
        • 業務上存在する概念をコード上で扱えない
        • ex: UserAcountテーブルの構造体とプロフィール変更
          • プロフィール変更についてどのカラムがプロフィールなの?ということに関して表現できていない
          • UserProfile structを作って何がプロフィールかをコード上で表現する
        • ex: Boss
          • rankをもっている、big: 大ボス、middle: 中ボス
          • 大ボスのみAttack()できるという仕様をどう表現するか、Attackはいつ発動するのか(中ボスからAttackを呼んだときになにもしないという事がわからない。)
          • BigBoss / MiddleBossでそもそも分けてしまう。別々のモデルにすることでそれぞれ何ができるかが明確になる
  • DOAで設計したデータ構造をそのままプログラミングで扱うのが問題
  • 可読性が下がる根本原因 = 業務とコードの乖離
    • 問題:業務の理解・コードの理解、両方を理解しないといけない
      • ex: type, status, flg といった謎カラム
  • DDDではデータ構造をそのままプログラミングで利用しない、プログラミングに適したデータ構造を利用する
    • -> 業務とコードの乖離を可能な限り少なくし可読性を分ける
    • -> 業務を理解 -> コードも理解できる
    • -> 実装詳細に踏み込みやすいコードになる
  • 業務を反映したデータ構造 + 振る舞い => 業務駆動開発(DDD(

何をすればDDDになるのか

  • 実装がゴール、実装のための分析・設計
  • 分析
    • 業務をコードに落とし込めるように分析する
    • 実装がゴール、そのゴールを達成するための分析
  • 設計
    • 分析結果をコードに落とし込むための設計
  • 実装
    • 実装する
  • 各フェーズに対応したテクニックが存在する
    • レイヤ構造は実装のための設計、分析・設計・実装のための一つの要素に過ぎない。
    • リポジトリパターンは実装テクニック、同上でただの一つの要素に過ぎない
  • 戦略(分析&設計)・戦術とDDDは分けている
  • 戦略(分析&設計)が大事
  • 戦術のみ適用する = 軽量DDD、アンチパターン
    • ex. レイヤ構造・リポジトリパターンを適用したよ = 軽量DDD
    • 分析をしていない、業務とコードに乖離が生じる
  • 分析→設計→実装を通して初めてDDDになる

demerit of ddd

  • 学習コスト
  • 分析コスト
  • 実際可読性が上がるかはわからない、分析結果によっては可読性が上がらない可能性がある
  • モデルとDBのデータ構造が異なる、モデルとDBがほぼ同一である前提であるRailsのようなフレームワークを使っている場合の実装の手間

解決できないこと

  • 業務の複雑さに伴うコードの複雑さは解決できない
    • そもそも業務が複雑であれば、それをそのまま反映する
  • 実装者の設計スキルが低いと可読性落ちる

necessity of DDD

DDD不要な例

  • DBのデータ構造がプログラミングに適している場合
    • ex: 単一概念のCRUD
    • DDD不要
  • 業務とコードのか入が問題にならない
    • 保守しない、業務が単純

軽量DDD

  • DDDではないが、単なる実装パターン詰合せとしては優秀

GoとDDDの相性

GoでDDDは相性

  • ORM問題 Java > Go
    • モデルとデータベースのマッピング
    • ORMでマッピングを任せられると
    • インピナンスミスマッチを埋められるか
      • Goにはない、というか他の言語にもあまりない、Java特有かもしれない
  • アノテーションベースのAOP Java > Go
  • 情報量 Java/Scala > Go
    • Javaの実践例はPHP/Rubyでも参考になる
    • Goはすこし言語仕様が異なるので実践した情報量が少ない

Q&A

  • メルカリで使っているか
    • 現状使っていない、ビジネススピードなどによりWeb系で導入していない
  • microserviceとの相性
    • 相性はいいっちゃいい、業界付けられたコンテキストのテクニックは相性がいい
    • ただし、DDDとマイクロサービスの設計の親和性は要件による。
      • データ構造がプログラミングに適しているかどうか。
    • 密結合を分割 -> 分断されたモノリス
  • マイクロサービス間で重複したコードを書く問題
    • マイクロサービスをやるならコードの重複を受け入れるのが前提のスタンスと必要になる
    • その上で共有したい場合は、ライブラリ化・サブモジュール化というアプローチもあるが、各サービスで必要なメソッド・フィールドを足していったりするとカオスになる。
    • サービスごとに必要とすることが異なるケースが多い。
  • コードが成果物 = コードを見ることで業務を知ることができる
    • DDDの目的は可読性の高いコードを書くこと
  • いい設計を行うためのアプローチ
    • 作る対象の業務を知る必要がある
    • 業務の理解度を上げることでコードの質が上がる
    • ただし、設計の引き出しが多い人が勝つ、設計スキルが低いとそもそも可読性が下がる
    • たくさん書いてたくさん失敗すること
    • なれている自分の設計パターンと違うアプローチを取り入れてみる、いつものパターンは人から見たら良くないかもしれない。

最後に

ドメイン駆動設計について、何をやったら「ドメイン駆動設計」なの?とふわふわしていたのですが、「業務(ドメイン)で設計を駆動する」がどういうことなのか解説いただいたのがとても参考になりました。

次回はGCPについてのお話が聞けるということでとても楽しみです! mercari.connpass.com