TypeScript上級

上級 TypeScriptで学ぶクリーンアーキテクチャ|練習問題編

導入

クリーンアーキテクチャは、システムの可読性や保守性を高めるための設計原則を提供します。特に、ビジネスロジックとインフラストラクチャの分離が重要です。今回は、TypeScriptを用いて、実務でよくある「ユーザー管理システム」を例に挙げ、クリーンアーキテクチャの実践的な適用方法を探ります。

教科書レベルの解説(クリーンアーキテクチャ)

重要な概念の整理

クリーンアーキテクチャでは、アプリケーションの構成を層に分け、依存関係の方向を内向きに保つことが求められます。具体的には、以下の4つの層があります:

  • エンティティ層: ビジネスロジックやルールを定義する層。
  • ユースケース層: アプリケーションの機能を実現するためのインターフェースを提供する層。
  • インターフェース層: ユーザーや外部システムとのやり取りを担当する層。
  • フレームワーク層: データベースやUIフレームワークなど、外部の技術を扱う層。

コード例(TypeScript)


interface User {
    id: number;
    name: string;
    email: string;
}

interface UserRepository {
    findUserById(id: number): Promise;
    saveUser(user: User): Promise;
}

class UserService {
    constructor(private userRepository: UserRepository) {}

    async getUserProfile(userId: number): Promise {
        return await this.userRepository.findUserById(userId);
    }

    async createUser(name: string, email: string): Promise {
        const newUser: User = { id: Date.now(), name, email };
        await this.userRepository.saveUser(newUser);
        return newUser;
    }
}

コードの行ごとの解説

  1. interface User: ユーザー情報を表す型を定義。システム全体で再利用できる。
  2. interface UserRepository: ユーザー情報の取得や保存を行うためのインターフェースを定義。実装の詳細を隠蔽。
  3. class UserService: ユーザーに関連するビジネスロジックを実装。リポジトリへの依存を注入し、テスト容易性を向上。
  4. getUserProfile: ユーザーIDを基にユーザー情報を取得するメソッド。
  5. createUser: 新しいユーザーを生成し、リポジトリに保存するメソッド。IDは一時的に生成。

練習問題編

以下に、クリーンアーキテクチャに関連した練習問題を用意しました。各問題に対する模範解答も記載しています。

  1. 問題1: UserRepositoryインターフェースに、ユーザーをメールアドレスで検索するメソッドを追加してください。
    模範解答:

    
    interface UserRepository {
        findUserById(id: number): Promise;
        saveUser(user: User): Promise;
        findUserByEmail(email: string): Promise; // 新規追加
    }
    
  2. 問題2: UserServiceに、ユーザーの情報を更新するメソッドを追加してください。
    模範解答:

    
    async updateUser(userId: number, name: string, email: string): Promise {
        const user = await this.userRepository.findUserById(userId);
        if (!user) throw new Error('User not found');
        user.name = name;
        user.email = email;
        await this.userRepository.saveUser(user);
        return user;
    }
    
  3. 問題3: ユーザーの削除機能をUserServiceに追加してください。
    模範解答:

    
    async deleteUser(userId: number): Promise {
        const user = await this.userRepository.findUserById(userId);
        if (!user) throw new Error('User not found');
        // ここで削除処理を行うメソッドをリポジトリに追加する必要がある
    }
    

まとめ

  • クリーンアーキテクチャは、ビジネスロジックとインフラを分離することで、可読性と保守性を向上させる。
  • TypeScriptを用いることで、型安全性を保ちながら、堅牢なアーキテクチャを構築できる。
  • 練習問題を通じて、実際の業務での適用方法を体験し、理解を深める。