AnDeriensのブログ

個人的なブログです

Prismaとリポジトリパターンの相性

※結論や答えのようなものはこの記事には含まれていません。

Prismaリポジトリパターンの議論

node.jsのORMであるPrismaを使っていて、リポジトリパターンを実装したくなって色々調べてみたら、どうも相性が悪そうなのでちょっと整理する。

どうやら、モデルをプロパティに持たせて、標準メソッド (find findMany etc...) をラップして共通リポジトリを実装するようなことは難しいようだ。

同様に、すべてのモデルに対してCRUDを提供できるようなラップを考えている人がいるが、これも現在進行形で議論されている。(2022/07/22現在)

いちおう方法は提示されている(https://github.com/prisma/prisma/issues/5273#issuecomment-767453556)が、それほどまでしてラップするべきなのか。できないことにはなにか理由があってそれを尊重したほうがリスクの少ない実装ができるような気がする。

(追記:補助的なツールを作っている人もいた。https://github.com/krsbx/prisma-repo

Prismaの思想

これらの議論の中で、

Userをジェネリックに置き換えようとしているので、Prismaではあり得ません。特にTypeScriptでは、指定されたモデルに基づいてどのようなデータを渡す必要があるかを知る必要があるため、多くの労力が必要になります。 https://github.com/prisma/prisma/discussions/3929#discussioncomment-98676

というコメントがある。

「これはPrismaではない」その言葉の本当の意味を探るため、私達はアマゾンの奥地(公式ドキュメント)に向かった。

すると、ちゃんと書いている。Prismaの特徴を列挙している中に、

Queries not classes to avoid complex model objects

複雑なモデルオブジェクトを避けるために、クラスではなくクエリを使用

SQL, QueryBuilder, ORMを扱う際の自由度と生産性の観点から整理しつつ、以下のようにまとめている。

After all, developers should only care about the data they need to implement a feature and not spend time figuring out complicated SQL queries or massaging query results to fit their needs.

結局のところ、開発者は機能を実装するために必要なデータにだけ関心を持てばよく、複雑なSQLクエリを考えたり、クエリ結果を自分のニーズに合わせて加工したりすることに時間を費やすべきではないのです。

Why Prisma? Comparison with SQL query builders & ORMs | Prisma Docs

要約と考察

オブジェクト指向の歴史などもそれほど理解していないので間違っている可能性は大いにあるが、Prismaが言いたいのはつまりこういうことかもしれない。

「開発者が扱うのは抽象化されたデータではなく、データそのものだ。」

userモデルがあれば、userモデルをそのままコードに起こすべきで、Genericsが必要になるような抽象化をするべきではない。userには名前があり、postにはタイトルがある。それらを抽象化して「モデルには文字列の属性がある」などの表現に落とし込むべきではない。

なるほどたしかに一理あるような気はする。自分の実感として、抽象化には勇気がいる。勇気というのは、抽象化に合わないデータの特性が後から見つかるんじゃないかという不安に対する抵抗のようなものだが、Prismaはその不安を取り除いてくれるのかもしれない。

ただ、99%そんな特性は見当たらないと思えるような=それほど不安のない抽象化をしたいときはある。 そんなときにどうすればいいのかはもうすこし考える必要がある。