JavaScript中級

中級 JavaScriptで学ぶドメイン駆動設計|アンチパターン編

導入

ドメイン駆動設計(DDD)は、ソフトウェア開発においてビジネスのニーズを効果的に反映させるためのアプローチです。しかし、実際のプロジェクトでは、理論通りに進められないことが多く、アンチパターンに陥ることも少なくありません。本記事では、JavaScriptを用いた具体的なシチュエーションを通じて、よくある失敗例やその改善方法を探ります。

教科書レベルの解説(ドメイン駆動設計)

重要な概念の整理

ドメイン駆動設計では、ビジネスドメインに基づいたモデルを中心にソフトウェアを構築します。これにより、複雑なビジネスロジックをシンプルに表現し、メンテナンス性を向上させることが可能です。DDDの基本的な要素には、エンティティ、バリューオブジェクト、アグリゲート、リポジトリなどがあります。これらの要素を理解し、適切に活用することが成功の鍵となります。

コード例(JavaScript)


class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }

    updateEmail(newEmail) {
        this.email = newEmail;
    }
}

class UserService {
    constructor(userRepository) {
        this.userRepository = userRepository;
    }

    changeUserEmail(userId, newEmail) {
        const user = this.userRepository.findById(userId);
        user.updateEmail(newEmail);
        this.userRepository.save(user);
    }
}

コードの行ごとの解説

  1. Userクラス: ユーザーの情報を表すエンティティです。nameとemailをプロパティとして持ち、メールアドレスを更新するメソッドを提供します。
  2. UserServiceクラス: ユーザーに関連するビジネスロジックを管理するサービスクラスです。リポジトリを通じてユーザーを取得し、メールアドレスを変更します。

アンチパターン編

実際のプロジェクトでは、ドメイン駆動設計の原則を無視した実装が見られることがあります。例えば、以下のようなアンチパターンが存在します。

1. ドメインロジックの漏れ: ドメインオブジェクト(この場合はUserクラス)にビジネスロジックを持たせず、全てをサービスクラスに集約してしまうことがあります。これにより、ドメインオブジェクトが持つべき責任が分散し、コードの可読性と保守性が低下します。

改善案: ドメインロジックはエンティティ内に保持し、サービスはそのロジックを呼び出す役割に徹します。以下はその改善例です。


class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }

    updateEmail(newEmail) {
        // 追加のバリデーションを行う
        if (!this.validateEmail(newEmail)) {
            throw new Error('Invalid email format');
        }
        this.email = newEmail;
    }

    validateEmail(email) {
        // 簡易的なバリデーション
        return /\S+@\S+\.\S+/.test(email);
    }
}

このように、ドメインオブジェクト内でバリデーションを行うことで、ビジネスルールを明確にし、サービスクラスはよりシンプルになります。

まとめ

  • ドメイン駆動設計では、ビジネスロジックをドメインオブジェクトに持たせることが重要です。
  • アンチパターンを避けるためには、責任の分担を明確にし、コードの可読性を高める必要があります。
  • 実際の業務では、ドメインオブジェクトが持つべき責任を理解し、適切に設計することが求められます。