育てるTypeScriptアプリケーション
壊れやすいシステムを育てる
動物病院の予約・カルテ管理システムで学ぶサーバサイドTypeScript
執筆中
はじめに
ストーリー
危うく素朴に実装された動物病院の予約・カルテ管理アプリの開発・運用を任されたあなた。
しかし、次々と要件が増えていき、プロダクトはさらに複雑になっていきます。
それぞれの要件をそのまま素朴にAIエージェントへ任せると、思わぬ破綻が生じることでしょう。
章ごとに設計のヒントを得ながら、堅牢で変更容易性の高いサーバアプリケーションの作り方を学んでいきます。
ゴール
このシリーズは、他言語(Java / Go / Elixir など)の経験を持ちながら、サーバサイドTypeScriptの本番環境レベルでの実践に不安を持つエンジニアに向けて執筆しています。
完走することで、業務レベルで要求されるサーバアプリケーションの設計スキルが身につくことでしょう。
- Discriminated Union による状態モデリング
- Result 型と Railway Oriented Programming
- スキーマライブラリによる境界防御
- Sensitive 型による機微情報保護
本書の特徴
リファクタしながら学べる
最初から完成された設計を写経するのではなく、現場の実務のように開発とリファクタを繰り返しながら学習できます。
危うくて素朴な実装に対して、新たな要件に対応しながら設計を改善していくことで、それぞれの設計パターンをどのようなシーンで適用するべきか、身をもって体験できます。
エージェント時代の文脈
各章の冒頭で、同じ要件を素朴な指示でAIエージェントに依頼するとどう実装されがちか例示します。
これにより、私たちが設計の原則を理解せずにエージェントへ依頼することでどのような結果をもたらすか体感できます。
題材について
動物病院の予約・カルテ管理アプリを題材に選んだ理由は次のとおりです。
状態遷移の重要性
動物病院には予約 → 受付 → 診察 → 会計、そしてキャンセルという複雑な状態遷移があります。
これらの状態遷移が誤った方向へ進んでしまった場合の業務影響は大きい一方で、状態ごとに必要なプロパティが大きく違います。
高いデータ要件
検査機関 API からの結果取り込み、ペット ID と飼い主 ID の取り違え、診断名・処置内容といった機微情報のログ流出など、データの取り扱いに慎重さが求められるサービスです。
進め方
各章は次のように進行します。
- 新たな要件
- 素朴にエージェントに依頼してみる
- 発生する問題を認識する
- リファクタと要件対応を進める
なお、章ごとに 20〜30分程度の読了時間を想定しています。
執筆状況
本書は現在執筆中です。各章の本文は順次公開予定です。
目次
-
第0章 · 執筆中
動くけれど壊れやすいアプリ
「うちのクリニック向けに、予約とカルテをまとめて管理できる最低限のアプリを作って」という素朴な指示でAIエージェントに依頼して生まれた、動くけれど壊れやすい初期実装を起点に置きます。
-
第1章 · 執筆中
「会計済みの来院が、なぜか診察中に戻った」
業務インパクトの大きい不正な状態遷移を起点に、Discriminated Union による状態モデリング、純粋関数による状態遷移、assertNever による網羅性を導入します。
-
第2章 · 執筆中
「処方薬・所見・次回予約を診察に紐づけたい」
状態ごとに必要なデータが違うことを起点に、Discriminated Union の各バリアントへの固有フィールドと Companion Object パターンを導入します。
-
第3章 · 執筆中
「外部の検査機関APIから検査結果を取り込みたい」
外部APIの戻り値を as でキャストしていたら本番で undefined 参照で落ちた事故を起点に、Zod スキーマによる境界防御と Always-Valid Domain Model を導入します。
-
第4章 · 執筆中
「ペットIDと飼い主IDを取り違えた」
両方 string だったため引数の順序を間違えて、別のペットのカルテに無関係な飼い主の連絡先が紐づいてしまった事故を起点に、Branded Type を導入します。
-
第5章 · 執筆中
「エラー処理が if/throw で破綻している」
バリデーション失敗・状態遷移違反・外部依存エラーが入り乱れ try/catch のネストが手に負えなくなる過程を起点に、Result 型と Railway Oriented Programming を導入します。
-
第6章 · 執筆中
「ログにペットの病気の情報を出すことが法改正で禁止された」
動物医療情報の取扱いに関する規律強化を起点に、構造的部分型がなぜ機微情報を型レベルで止められないかを論じ、Sensitive 型 + ログ redact による多層防御を導入します。
-
最終章 · 執筆中
ふりかえりと、原則を継続適用するために
完成形のコードを第0章のコードと並べ章ごとの変化を振り返ります。同じ要件群を functional-ts-principles を導入したエージェントに依頼するとどう変わるかを実演し、原則は自分の手で書く力であると同時にエージェントを使いこなす力でもあることを示します。