フロントエンドに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