😉

フロントエンドにDDDを導入する意義と実践

に公開

1. 導入

こんにちは、mk0812です。フロントエンドDDDという記事を読んで刺激を受けたことがきっかけで書いています。フロントエンド開発におけるDDD(ドメイン駆動設計)の有用性について、自分なりの理解を整理しました。

DDD(ドメイン駆動設計)はこれまで私自身、バックエンドに使うものという印象が強かったが、実はフロントエンドにこそ有効な場面が多いケースもあるなあと思いました。特に複雑なビジネスロジックを持つUIでは、DDD的な設計により可読性や保守性が大きく向上すると思います。

2. フロントでDDDが有効なパターン

上記で挙げた「複雑なビジネスロジックを持つ」という部分に特化すると大体下記が挙げられます(あくまでも一例、もちろんそれ以外も考えればあるとは思います)。

  • 複雑なフォームワークフロー
  • 業務ルールに応じて動的に変わるUI
  • ローカルステートで一時保存・編集が必要な画面

3. 簡単な実例:ステップ式応募フォーム

例として「ステップ式の応募フォーム」を挙げます。下記のようなStepを踏んで最終的に応募が完了するという想定です。

  • Step 1: 名前・年齢
  • Step 2: 職歴(数は可変)
  • Step 3: 職種によって変わるスキル入力
  • Step 4: 確認 → 送信

ここでは「年齢が18歳未満は応募不可」「職歴が最低1件必要」「職種に応じたスキル選択」など、UIの背後にビジネスルールが存在するとします。

こうしたルールをドメイン層にまとめることで、UIから切り離してテストしやすく、再利用しやすくなります。下記のコードはその一例です。

// domain/entity/Applicant.ts
export class Applicant {
  constructor(public name: string, public age: number) {}

  canApply(): boolean {
    return this.age >= 18;
  }
}

// application/usecase/submitApplication.ts
import { Applicant } from "../../domain/entity/Applicant";

export const submitApplication = (name: string, age: number): boolean => {
  const applicant = new Applicant(name, age);
  return applicant.canApply();
};

このようにロジックを切り出すことで、テストや再利用が容易になる。

4. ドメインルールとバリデーションの違い

上記で挙げた例、例えばユーザーの操作に関する制御は、「バリデーション」と扱うべきでは?という意見もあります。たしかに技術的にはバリデーションライブラリで形式を確認することもできますが、「その入力が現実世界のビジネス的な意味で有効か?」という視点は別物です。

ドメインルールとは、現実の業務ルールやポリシーに照らして判断されるべきものであり、たとえば「倉庫が休みなのでその日には発送できない」「未成年は応募できない」といった制約は、入力の形式とは無関係に、業務として受け入れ可能かを問うものです。

判定の種類 説明 チェック場所
バリデーション 入力形式が正しいかをチェック メール形式か?未入力でないか? UI層 or バリデーションライブラリ
ドメインルール ビジネス上その状態が成立するかをチェック 未成年は応募不可、在庫ゼロでは購入不可など ドメイン層(Entity / Service)

このように、"技術的な整合性"と"業務上の有効性"は切り分けて考える必要があります。

5. 実践Tips

  • 小さく始める:すべてDDDにしなくてもOK。まずはEntityとServiceを分けるだけでも効果あり
  • ドメイン層はライブラリとしてテストしやすく作る
  • UIとは疎結合にし、状態はアプリケーションサービスを介して管理

6. まとめ

DDDは「設計ルール」ではなく「ビジネス理解のための整理術」だと思っています。

フロントエンドでもドメイン知識がUIに影響を及ぼす場面もあり、そのタイミングでDDDを意識することで開発体験とコード品質の両方が向上すると考えられるのかなと思って、導入であった記事を深掘りしつつ自分の意見を記載しました。

今後は決して無理に取り入れるのではなく、複雑化し始めたときこそ、DDD的な視点で整理を試そうかなと思います。

Discussion