書籍概要

エンジニア選書

実践TypeScriptバックエンド開発:データと関数によるドメインモデリングで堅牢性を高める

著者
発売日
更新日

概要

生成AI時代にも必要な設計の知識が一冊に!

こんな方におすすめ

  • 大規模なコードベースでアプリケーション開発に課題を感じているエンジニア
  • 関数型プログラミングの基本概念を理解しており,実務での応用方法を模索しているエンジニア
  • DDDを取り入れているが,オブジェクト指向設計に限界を感じているエンジニア
  • TypeScriptでも堅牢なバックエンド開発が可能か知りたいエンジニア

目次

第1章:型の機能と原則

  • 型の機能
  • 型の原則

第2章:データと振る舞い

  • データと振る舞いの一体化(クラス)の課題
  • データと振る舞いの分離

第3章:エラーハンドリング

  • 例外によるエラーハンドリングの課題
  • 戻り値によるエラーハンドリングの利点
  • 設計方針
  • Resultの概要

第4章:戻り値によるエラーハンドリングの実践

  • Result / ResultAsyncへのラップ
  • 関数適用
  • Resultのアンラップ
  • Resultリストの統合

第5章:スキーマを用いたバリデーション処理

  • バリデーションの課題
  • スキーマバリデーションのライブラリ(Zod)の概要
  • バリデーション
  • スキーマからの型推論

第6章:ドメインモデル

  • ドメインモデルの構成要素
  • ドメインモデルの実装

第7章:集約とリポジトリ

  • 集約の概要
  • リポジトリの概要
  • 集約の実装
  • リポジトリの実装

第8章:ドメインイベント

  • イベントソーシングの概要
  • データモデルの設計
  • ドメインモデルの設計
  • ドメインモデルの実装
  • イベントストアの設計

第9章:Always-Valid Domain Model

  • Always-Valid Domain Modelの概要
  • Always-Valid Domain Modelの実装

第10章:入出力の依存関係

  • 依存関係逆転の原則
  • 依存注入
  • ヘキサゴナル・アーキテクチャ

第11章:依存注入の構成管理

  • 依存注入の課題
  • DIコンテナ(typed-inject)の紹介
  • サンプル構成

第12章:ユースケース

  • ユースケースの概要
  • Railway Oriented Programmingの概要
  • ユースケース実装のパターン

第13章:データベースとの入出力

  • Drizzle ORMの概要
  • リポジトリの実装
  • リポジトリのテスト

第14章:クライアントとの入出力

  • Webフレームワーク(Hono)の概要
  • HTTP APIの契約と実装
  • サーバーの起動・停止

サポート

正誤表

本書の以下の部分に誤りがありました。ここに訂正するとともに,ご迷惑をおかけしたことを深くお詫び申し上げます。

(2026年10月19日最終更新)

第10章 P.240:10.3.3「サンプル実装」の「ドメインモデル」,register関数

誤
const register = (aggregate: Product): [Product, ProductRegistered] => {
  const event = R.pipe(
    parse({
      ...aggregate,
      sequenceNumber: Aggregate.incrementSequenceNumber(
        aggregate.sequenceNumber,
      ),
    }),
    DomainEvent.generate(aggregateName, ProductRegistered.eventName, {
      product: aggregate,
    }),
  );
  return [aggregate, event];
};
正
const register = (aggregate: Product): [Product, ProductRegistered] => {
  const product = parse({
    ...aggregate,
    sequenceNumber: Aggregate.incrementSequenceNumber(aggregate.sequenceNumber),
  });
  const event = R.pipe(
    product,
    DomainEvent.generate(aggregateName, ProductRegistered.eventName, {
      product,
    }),
  );
  return [product, event];
};

商品一覧