Slide 1

Slide 1 text

Prisma を活⽤した TypeScript チーム開発 技術本部 Digitization部 データ化グループ 湯村 直樹

Slide 2

Slide 2 text

写真が入ります 2019年 Sansan株式会社に新卒⼊社。 名刺データ化システムなど複数のシステムの開発を 経て、現在はデータ⼊⼒システム⽤の認証基盤の開 発に従事。 湯村 直樹 Sansan株式会社 Digitization部 データ化グループ

Slide 3

Slide 3 text

データ化システムの認証基盤 - Digitization部では複数のデータ化システムを開発している。 - データ化システムを利⽤する⽅のアカウント管理、⼊⼒システムへの SSO を可能にする認証基盤を開発している。 - 認証基盤では TypeScript と Prisma を採⽤している。

Slide 4

Slide 4 text

Prisma とは? - Prisma は ORM - Prisma のスキーマを single source of truth として、アプリケーションの モデルの型とデータベースのマイグレーションファイルを⽣成できる。

Slide 5

Slide 5 text

Prisma とは? アプリケーションのモデル DB のスキーマ

Slide 6

Slide 6 text

Prisma は next-generation ORM - Prisma は従来の ORM とは異なるデータマッパー (※) - アプリケーションのモデルと DB のスキーマのマッピングは、マッピン グ⽤のクラスではなく、Schema から⽣成された Prisma のクライアン トが⾏う。 - アプリケーションのモデルはクラスで定義していたのに対して、Prisma では TypeScript の型が⽣成される。 - これによって型安全性を得ることができる。 (※) Is Prisma an ORM? https://www.prisma.io/docs/concepts/overview/prisma-in-your-stack/is-prisma-an-orm

Slide 7

Slide 7 text

実際に Prisma を使う - 素直に使うとデータの完全性を守るのが難しい。 Email のドメインは会社に登録された ものである必要があった

Slide 8

Slide 8 text

データの完全性をどう守るのか

Slide 9

Slide 9 text

Active Record パターンでの実装 - DB のテーブルに対応したクラスに、データアクセスのロジックとビジ ネスロジックを持たせる。 - データの完全性はレコード追加時に担保できればいい。 - インスタンスのメソッドを利⽤するために、Prisma Client が返すオブジ ェクトからインスタンスを⽣成する。

Slide 10

Slide 10 text

レコード追加時に 完全性を担保する

Slide 11

Slide 11 text

Data Mapper パターンでの実装 - データアクセスの役割を持つクラスを分ける。 - データの完全性をモデルクラスで担保する。 - モデルクラスのインスタンスを完全なデータとして信頼する。 - DB から取得した値は完全なデータとして扱う。

Slide 12

Slide 12 text

インスタンス⽣成時に 完全性を担保する 完全なデータとして 信頼する

Slide 13

Slide 13 text

改めて Prisma が従来の ORM とどう違うのか - Prisma は従来の ORM とは異なるデータマッパー (※) - アプリケーションのモデルと DB のスキーマのマッピングは、マッピン グ⽤のクラスではなく、Schema から⽣成された Prisma のクライアン トが⾏う。 - アプリケーションのモデルはクラスで定義していたのに対して、Prisma では TypeScript の型が⽣成される。 - Prisma によって⽣成された型と Prisma Client の関数を再実装している ことになるのでは? (※) Is Prisma an ORM? https://www.prisma.io/docs/concepts/overview/prisma-in-your-stack/is-prisma-an-orm

Slide 14

Slide 14 text

プレーンなオブジェクトを使った実装 - プレーンな JavaScript のオブジェクトをそのまま扱う。

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

プレーンなオブジェクトを使った実装 - クラスに変換する必要がない。 - クラスで実現できていたカプセル化の実現が困難。 - モジュールが肥⼤化しやすい。

Slide 17

Slide 17 text

Prisma Client Extensions - model - アプリケーションのモデルにメソッドを定義できる。 - client - Prisma Client にメソッドを定義できる。 - query - Prisma Client のクエリを加⼯できる。 - result - Prisma Client の返すオブジェクトにメソッドを定義できる。

Slide 18

Slide 18 text

Prisma Client Extensions result client model query

Slide 19

Slide 19 text

model の拡張 - モデルにレコードを追加するメソッドを追加する。

Slide 20

Slide 20 text

query の拡張 - create の実⾏時に値を検証する。

Slide 21

Slide 21 text

result の拡張 - Prisma Client が返すオブジェクトにメソッドを追加する。

Slide 22

Slide 22 text

Prisma Client Extensions まとめ - データの変換処理を⾏わず、型安全にビジネスロジックを実装できる。 - $allModels と $allOperations を利⽤して、モデルやオペレーションをま たいだ共通処理も実装できる。 - 複数のモデルが関連する処理を書きにくい。 - 関連するモデルを都度 DB から引き直す。 - Prisma.defineExtension を返す関数の引数に関連するモデルを渡す。 - Prisma 特有の知識が求められる。

Slide 23

Slide 23 text

認証基盤で採⽤したアプローチ - クラスを利⽤した Data Mapper のような考え⽅でプレーンなオブジェ クトを利⽤する。 - クラスに変換する必要がないので、データの取得は直接 Prisma Client を利⽤する。 - データの完全性をビジネスロジックを扱うモジュールで担保する。 - ビジネスロジックを扱うモジュールで⽣成されたオブジェクトを完全な データとして信頼する。 - 状態ごとに型を分けると、状態ごとのロジックを持たせやすい。 - コンパイル時に意図しない状態に気づくことができる。

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

不正な値を渡すと コンパイルに失敗する

Slide 26

Slide 26 text

認証基盤で採⽤したアプローチ - 型と関数を組み合わせることで状態に特化したロジックを実装しやすい。 - データの完全性をコンパイル時に担保しやすい。 - 型が増えるとそれらの関係を把握するのが難しくなる。 - コントローラーから関数を呼び出す側の実装が増えるケースがある。

Slide 27

Slide 27 text

[補⾜] 共通のクエリを実装するには? - satisfies (※) - ビルダーパターン (※) How TypeScript 4.9 `satisfies` Your Prisma Workflows https://www.prisma.io/blog/satisfies-operator-ur8ys8ccq7zb

Slide 28

Slide 28 text

[補⾜] satisfies を利⽤した共通のクエリ - 型の Widening を防ぎながらクエリを記述できる。

Slide 29

Slide 29 text

- Fluent な API を提供できる。 [補⾜] ビルダーパターンを利⽤した共通のクエリ

Slide 30

Slide 30 text

まとめ - 継続的にチーム開発を⾏うためにはデータの完全性を保つ仕組みが必 要。 - TypeScript と Prisma では様々なアプローチが可能。 - 重要なのはどのパターンを採⽤するかではなく、重要な原則を守るため の仕組み、共通認識を持つこと。

Slide 31

Slide 31 text

No content