りゅうじの学習blog

学習したことをアウトプットしていきます。

5/28 ドメイン駆動設計 Chapter8 8-2

8-2 コマンドラインインターフェースに組み込んでみよう

  • 開発者はCLIを好む傾向がある
    • その理由はさまざまである、代表的な例としては
      • グラフィックに関わる処理の実装が不要で単純であること
      • コマンドを正確に入力することが求められるので誤操作を起こしづらい
        • ここでは、前者を主な理由とします

CLIで動作させるコードを確認していきます。

まずは依存関係の登録を行うコードです。

※書籍ではC#で書かれており、C#のライブラリを使用しているのをTypeScriptに書き換えているので、差異があるかもしれません。

// IUserRepository.ts
interface IUserRepository {
  getUser(userId: string): User;
  // ...他のメソッド
}

// InMemoryUserRepository.ts
class InMemoryUserRepository implements IUserRepository {
  getUser(userId: string): User {
    // ユーザー情報を取得するロジック
  }
  // ...他のメソッドの実装
}

// UserService.ts
class UserService {
  constructor(private userRepository: IUserRepository) {}

  // ...その他のメソッド
}

// UserApplicationService.ts
class UserApplicationService {
  constructor(private userService: UserService) {}

  // ...その他のメソッド
}
// Startup.ts
function startup() {
  const userRepository = new InMemoryUserRepository();
  const userService = new UserService(userRepository);
  const userApplicationService = new UserApplicationService(userService);
}

// メインプログラムでスタートアップを呼び出す
startup();
  • NestJSのフレームワークを使えば、こちらの登録をせずとも勝手に依存性の登録をやってくれます
    • 手動でやった場合は、startupメソッドのように依存性を登録する必要があります

8-2-1 メインの処理を実装する

// main.ts
import { InMemoryUserRepository } from './InMemoryUserRepository';
import { UserService } from './UserService';
import * as readline from 'readline';

const userRepository = new InMemoryUserRepository();
const userService = new UserService(userRepository);

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.question('Enter user ID: ', (userId) => {
  const user = userService.getUser(userId);
  console.log(user);

  rl.close();
});
  • readlineはNode.jsの標準ライブラリで、コマンドラインインターフェース(CLI)を作成するために使用されます。readlineを使用すると、ユーザーからの入力を読み取ったり、ユーザーに対して質問をしたり、入力を改行ごとに処理したりといったことが可能です。
// Startup.ts
function startup() {
  // テスト用リポジトリから実体クラスのプロダクション用のリポジトリに差し替え
  // const userRepository = new InMemoryUserRepository();
  const userRepository = new UserRepository();
  const userService = new UserService(userRepository);
  const userApplicationService = new UserApplicationService(userService);
}

// メインプログラムでスタートアップを呼び出す
startup();
  • IoC Containerを活用することで、メインの処理に全く手を加えることなく、データストアの変更を実現できます。

参考

ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本