Open5

スキーマ駆動についての感想

convers39convers39

自分のチームでも、近いことをやっていると思うので、少し感想を。

まずスキーマ駆動というと、コアにあるのは以下の4つくらいかと思い、これを持って堅牢なシステムを作る目標が立てそう

  • カタの定義はSingle Source Of Truthにする(したい)
  • 依存関係をなくす、decentralizationとも言える
  • スキーマへのバリデーション
  • スキーマ変更への検知
convers39convers39

自分のチームで実装する際に、tRPC, zod, ts-patternを利用している

  • BE側の1箇所に型をzodで定義することで、FE側にも参照可能になる→SSOTにまだいえない(理由は下に)が、開発体験は非常に良い
  • 依存関係はやはりBE側の定義に依存、decentralizationとはいえない
  • スキーマチェックは、zodを利用して、APIリクエストのパラメータや、データアクセス時のスキーマをバリデートする
  • スキーマ変更への検知は、
    • 一致しないとCIとかでタイプチェックは失敗するという意味では検知されている
    • ts-patternでenum型に対して全部exhaustiveにしている
convers39convers39

tRPCのやり方の限界と問題

  • DBのスキーマもマイグレーションファイルで定義する必要があり、2つのsource of truthをメンテしないといけない
    • 片一方の変更では、CIのタイプチェックではわかりずらい
    • 基本zodのスキーマの変更+DB定義の変更が都度必須
    • open api の定義とか1つにまとめて、zod & DB schemaをそちらから生成する、若干難しそう→一歩譲って、CIでバリデーションかけるのができるかもしれない
  • 依存性は存在(だが、ここは一定tradeoffとも考えられる)
    • FE側はBE側の定義を依存する(ただ開発体験の意味ではむしろメリット)
    • もしFE側で重複定義するとメンテナンス性が一気に下がる
    • 基本開発エンジニアにはフルスタックの視野を持ってほしくなる
  • スキーママッピング一致性の問題(かなり共通問題)
    • 例えば、DBのデータタイプと、TSのタイプとのマッピング
    • BE -> FEの時のシリアライズ化によって、例えばDate型をやむを得ずStringにするなど
convers39convers39

sansanさんの事例について

  • ルーター・コントローラーにリクエストを振り分けるまえに、バリデーションのミドルウェアを最初の構成から入れるべき(anyで受け取るのは正直驚きました)
  • openapi スキーマからFE側のクライエントとBE側のタイプ定義を生成するのは嬉しい
    • 同じくDBのスキーマ定義はどうなるか気になる
    • やはりDBのレーヤーも含めてSSOTを求めるのが厳しい?(そもそも求めるべきではない説も)
  • huskyで変更検知は良いアイディア
  • スキーマのファイルはBE側においている
    • monorepoで、スキーマを定義、そしてタイプ・クライエント生成する部分のスクリプトを、一つのパッケージにまとめるのはどうかなと