はじめに
こんにちは、@momo-0826です。
約1年程前からクラウドリンクスで主にバックエンドを中心とした開発業務に携わっています。
クラウドリンクスではDDDを使用した開発が行われているのですが、DDD未経験だった私が約1年程DDDに触れて感じた自分なりの感想を書いていこうと思います。
この記事の対象者
この記事ではDDDの簡単な概要や実際にDDD未経験の私が触れてみての感想を記載しています。
よって読者は以下のような方を想定しています。
- DDD未経験や初心者の方
- DDD導入するか迷われている方
- DDD導入して実際に良いことあるの??と疑問をお持ちの方
クラウドリンクスで採用している詳細なアーキテクチャについてはこちらの記事を参照してください。
結論
早速ですが、私個人の結論としては以下になります。
- DDDは保守性に非常に富むが、全てを解決するものではない
- 長期的な開発に対するメリットは大きいが、導入には考慮すべき点がある
銀の弾丸は存在しないということは色々なところで言われていることなので当たり前なのですが、何故この結論に至ったのかをDDDとは何かというところから振り返っていこうと思います。
DDDとは
ドメイン駆動設計(DDD)とはビジネス領域に焦点を当て、ドメインの複雑な仕様を適切にシステム設計に落とし込むアプローチのことです。
ビジネスルールをシステムの中心に据えることでビジネスロジックの分散を防ぎ、保守性の高い開発を実現できます。
DDDで解決できること
DDDの概要を説明しましたが、そもそもDDDとは何を解決してくれるものなのでしょうか??
ここではDDDが解決することを抜粋して簡単に説明しようと思います。
- ビジネスルールの欠如・分散
- ビジネスルールに関連するコードの漏れや、様々な箇所に分散して修正時のコスト増加を防ぐことができます。
- 保守が困難なコードを生み出すこと
- DDDによりビジネスルールの欠如・分散を防ぐことで、コードがスパゲッティコードとなることを防ぐことができます。
- その結果として、システム肥大化による保守の難しさの増加率を抑えることができます。
- ドメイン知識の偏り
DDDを構成する要素
ここではDDDを行う際に出てくる基本的な要素について簡単に説明しようと思います。
- 境界づけられたコンテキスト
- ある言葉が特定の意味を持つ範囲のことです。
- 言葉はその文脈によって意味が変化するのでそもそもの文脈を決める必要があります。
- 例えばソーシャルゲームアプリで考えると、ゲームコンテキストにおける「お金」はゲーム内で使用できるマネーという意味を持ちますが、課金コンテキストにおける「お金」はリアルマネーという意味を持つので文脈を決めることは重要になってきます。
- ドメインオブジェクト
- エンティティ
- システム内で一意に識別されるオブジェクトになります。
- ライフサイクルを持ちます。
- 例えば、ユーザーは識別子としてユーザーIDを持ち、最初に登録した住所が変化したとしてもそのユーザーは同じユーザーであることに変わりはありません。
- 値オブジェクト
- エンティティとは異なり識別子によって同一性のチェックは行われません。
- 例えば、ユーザーAとBが同じく「山田太郎」という名前を保持していた場合、ユーザーというエンティティの観点では別物ですが、名前という値オブジェクトでは同じものと見なされます。
- 集約
- 集約は関係するエンティティと値オブジェクトをグループ化して一貫性を保つことを目的に作成されます。
- 集約内のエンティティの変更は必ず集約のルート(Aggregate Root)となるエンティティを通して変更されることを保証し、グループ単位でDB操作を行うことで一貫性を保つことができます。
- クラウドリンクス(https://crowdlinks.jp/projects)の例では以下のようになります。
Project集約 - 集約を決めるということはある意味で、トランザクション境界を決めるといったことに近いのかと思います。
DDDのメリット、デメリット
- メリット
- デメリット
実際にDDDでの開発に触れて感じた良かった点、苦労した点
ここまでは教科書的にDDDの概要やメリット、デメリットを見てきました。
ここからは実際にDDD未経験の私がDDDを使用した開発で感じた良かった点と苦労した点を見ていこうと思います。
- 良かった点
- ドメイン毎に責務が明確なため、コードの修正時などに影響範囲の特定が容易
- DB関連の操作は集約にまとまっているため、Aという処理では必要なテーブルが正しく更新されるのに、Bという処理では漏れがあるなどということが起きない
- システムのリプレイスに伴い、ユーザーの新規登録機能を開発した際にこの点が個人的には感動しました。
- ユーザーの新規登録なのでユーザープロフィールのデータを作成する必要がありましたが、当然様々なテーブルへの登録が必要でした。
- この場合関係するDB更新処理を漏れなく呼び出す必要がありますが、DDDではデータの一貫性を保つため集約を使用するのでその集約の処理さえ呼び出せば容易にDB更新を行うことができました。
- 共通の言葉をビジネスサイドとエンジニア間で使用するので仕様確認や説明時にコミュニケーションコストを抑えることができた
- コードを見ればある程度仕様がわかる
- ビジネスルールがエンティティや値オブジェクトにコードとして反映されるのでチームへのジョイン時などにコードを読むことでも仕様の把握ができます。
- 苦労した点・課題
- DDDの概念の理解自体も難しい上に、ヘキサゴナルアーキテクチャやイベントソーシング、CQRSといった要素も出てきて初期のキャッチアップコストが高かった。
- 疑似的なイベントソーシングを用いてコンテキストを跨ぐ処理を行なっている関係でイベントで発行した処理が失敗した際のリトライ機能などが充分ではないことが課題として残っています。
- シンプルな機能実装に対して書くコード量が多く感じる
- 新規でコンテキストを作成する場合ドメインモデルから作成する必要があるため、コードを書く際に他のコンテキストにも存在するような値オブジェクトを再度作成する必要があるなど、コードを書く量が増える傾向がありました。
- 初期リリースまでに時間がかかりそう(あくまで予想)
まとめ
これらの経験を踏まえて私個人のDDDに対する印象としては以下のようになりました
- DDDは全てを解決する魔法のツールではない
- しかし、適切に使うことで長期的な保守がしやすいシステムを作り上げることができる
- チームの状態やビジネスの要件を考慮して導入を検討すべき
私自身モデリングがまだまだ上手くできなかったりと自分の知識が足りない点があることは認識しているので、これからもより良いプロダクトにしていけるように日々学んでいきたいと思います!!
クラウドワークスではエンジニアを募集しています。興味のある方は以下のリンクからご応募ください。