1
/
5

EdTechプロダクトのレガシーなバックエンドにモダンフレームワークよりも先にDDDを導入した話(後編)

learningBOX株式会社の開発部開発課に所属している末廣です。

前編ではDDD(ドメイン駆動設計)導入プロジェクトの立ち上げまでの経緯を説明させていただきました。

EdTechプロダクトのレガシーなバックエンドにモダンフレームワークよりも先にDDDを導入した話(前編) | learningBOX Engineer Blog
learningBOX株式会社の開発部開発課に所属している末廣です。前回はLaravel Collectionを導入した話をしました。今回はlearningBOX開発にDDD(ドメイン駆動設計)...
https://www.wantedly.com/companies/learningbox/post_articles/538584


後編では、プロジェクトをどのように進めていったかと、最終的にどのような形で導入したのかを紹介したいと思います。

プロジェクトの進め方

プロジェクトのメンバーは私を含めて3人で毎週時間を決めてミーティングを行い、以下のような順序で導入を進めていきました。

  1. 既存FWとの切り分け、ルーティングなど
  2. アーキテクチャの選定・ディレクトリ構造決め
  3. 名前空間ルール決め
  4. ドメインの分け方の指針決め
  5. モブプログラミングでのサンプルコードの作成
  6. 展開用資料作成
  7. 社内展開


当時の議事録

実際に導入した形

ディレクトリ構造
既存のアーキテクチャでは、設計パターンごとにファイルをまとめていました。

これはPackage by Layerといい、MVCで一般的に用いられることが多いディレクトリ構造です。
一見綺麗に整頓されているように見えますが、ドメインの関心事がレイヤーで分断されてしまうため、低凝集に陥りやすいといったデメリットがあります。


新しくDDDを導入する用のディレクトリでは、以下のようなディレクトリ構造にしました。



Package by Featureという機能ごとにパッケージングする手法で、ドメインごとのディレクトリを作り各ドメインの中でレイヤー分けを行うことで、関心事が同じものが集まり、ディレクトリ構造からも高凝集となるように配慮しました。

新しくルートディレクトリを切り、その中にドメインごとのディレクトリを置きます。
各ドメイン毎のディレクトリの中に「プレゼンテーション層」「アプリケーション層」「ドメイン層」「インフラストラクチャ層」の4層構成にして、各層の役割は以下のように定義しました。


プレゼンテーション層

ユーザーインターフェースや外部システムとのインターフェースを担当します。ユーザーからの入力を受け取り、適切なレスポンスを返す役割を果たします。また、ユーザーの操作をアプリケーション層に伝える役割もあります。


アプリケーション層

ユースケース(システムが提供する機能)を実現するための業務フローを制御します。具体的なビジネスルールはドメイン層で定義され、アプリケーション層はそれを組み合わせてユースケースを実現します。


ドメイン

ビジネスロジックやビジネスルールを表現する層です。エンティティ、値オブジェクト、ドメインサービス、リポジトリ(インターフェイス)など、ドメイン駆動設計の主要な要素がここに位置します。


インフラストラクチャ層

データベースや外部サービスとの通信、ファイル操作、ネットワーク通信など、具体的な技術的な詳細を担当します。他の層が具体的な技術から独立してビジネスロジックに集中できるように、この層がその詳細を隠蔽します。

MVCよりもより細かくレイヤー分けを行い各層の責務を明確化することで、高凝集低結合な実装を目指しやすくなりました。


ドメイン分けについて

ドメインの分け方については、大きく分けた場合と小さく分けた場合でそれぞれメリット・デメリットがあるので、明確な答えはないと思っています。
ただ一度分けたドメインを統合するのも、あとからドメインを分割するのも大変にはなるので、慎重に決める必要があります。


内製フレームワークとの接続

内製フレームワークを使っているからこその問題で苦労した部分はありましたが、逆に内製フレームワークだからこそ、フレームワークの改修で既存部分との繋がりを維持しつつ綺麗に接続できた部分もありました。
オープンソースのフレームワークだと、そう上手くはいってないなと思います。



社内展開

社内展開するにあたり、各レイヤーの役割や想定されるQ&Aを資料にまとめたり、サンプルコードを配布しました。



ただし、全ての開発をDDDで今後やっていくという方針にはしていません。
以下のような理由があるためです。

  • 学習コストが高く浸透するまでに時間がかかる
  • 単純なビジネス要件のものに対して用いると、余計に複雑になりコストデメリットの方が際立ってしまう
  • ビジネスロジック・ドメイン知識が複雑に絡み合ったレガシーコードを移植するコストが大きい


今回DDDの導入まではできましたが、今までと違うアーキテクチャが開発者全体に浸透していくのには時間がかかります。
地道に浸透させていくための草の根活動を、今後も続けていきたいと思っています。

難しかった点

DDDは概念的な所があり、決まったやり方は存在しません。
原典である「エリック・エヴァンスのドメイン駆動設計」でも具体的なやり方については書かれていません。

どのアーキテクチャを使うか、ドメインをどのように分割するか、集約の単位など、各プロダクトによってベストプラクティスがまったく異なります。
そのため、自分たちのプロダクトに導入するには、どのような形がベストなのかわかりませんでした。
その点はチームで相談しながら進めることができ、とても良かったと思います。


今後やりたいこと

今回はDDDのアーキテクチャのみの導入で、所謂「軽量DDD」というものに該当します。

モデリングに関してはやりたかったのですが、開発プロセスなどにも関わってくる話になりボトムアップでのミニマムスタートするのにはハードルが高く、今回は見送ることにしました。

しかしながら、モデリングも行ってこそのDDDなので、引き続き提案などはしていきたいと思っています。

最後に

今後「DDDを導入してみて、その後どう変わったか」も執筆したい所ではあったのですが
DDDの導入直後にプロジェクト発起人である私が、バックエンドエンジニアからSREエンジニアへの異動になりプロダクト開発からは距離を置くことになりました。
導入して良かった点、悪かった点、もっとここはこうしておいた方が良かったなどの改善点、実際に使ってみてわかる部分もあるかと思います。
心残りではありますが、その役目は現バックエンドチームに譲りたいと思います😇

learningBOX株式会社では一緒に働く仲間を募集しています
60 いいね!
60 いいね!
同じタグの記事
今週のランキング
learningBOX株式会社からお誘い
この話題に共感したら、メンバーと話してみませんか?