はじめに
ORMは強力なツールである一方、(ORMに限ったことではないですが)銀の弾丸にはなり得ない付き合いかただったり境界の引き方がむずかしいツールの一つであります。
我々も、ちょうど最近、新規でバックエンドアーキテクチャーを策定するタイミングがありまして。
そのときの考慮ポイントであったり、結論を共有します。
※網羅的でなかったり恣意的な内容もあるかもしれません。ご了承くださいませ。
こんな人に読んでもらいたい!
- ORMとの付き合いかたを悩んでいる人
- これからバックエンドアーキテクチャを策定する人
悩めるORM事情
N+1問題
よく挙げられるのはこの問題でしょう。
注意してコーディングすることで防げることもあるようですが、ORMから生成されるSQLの状態を把握するには相応の時間とエネルギーが必要です。
たかが+1、多少のパフォーマンス劣化は目を瞑るかという現場レベルの整理もあるかとは思います。
されど+1、ユーザーアクセス増によるパフォーマンス劣化が無視できなくなったり、CPU/メモリ/ネットワークなどのリソースを消費などによる環境コスト増を考えると、防げるものは防ぎたいです。
また、DBアクセス部分は特にパフォーマンスに敏感な箇所であるため、メインの関心事は無視できないですね。
ORMの仕様に精通したエンジニアを育て上げるという固有のライブラリーに依存するためスキルの平準化がしにくい、そもそも主な関心事はORMの仕様でなく、仕様やデータ定義の妥当性でありため、むしろ投資の対象はそこにしたいです。
SQLが隠蔽される問題
前述した「ORMの仕様に精通したエンジニア」に多少かかる内容ですが、こちらも見過ごせない問題の一つです。
特にジュニア〜ミドルエンジニアのSQLレベルアップを妨げる原因の一つになるので、私はあまり好きではないです。
ORMで生成されるSQLが、おおよそイメージができるシニアレベルのエンジニアだけで運用されるのであれば問題ないですが、
ジュニア〜ミドルエンジニアにおいて、まずはSQLがどういう範囲のデータに影響を及ぼすか把握することを優先すべきと思います。
複雑化するメソッドチェーン
これもあるあるかと。db.Where().Where().Where().Join()...のように(ある程度それっぽいものを想像で書いてます...)、決してシンプルに書けないケースも往々にしてあるのではないでしょうか。
この辺りは好みの問題かもですね。どのみち複雑化するのであれば、SQLの状態で品質を把握しやすい形の方が嬉しいです。
結論
ORMを採用することにしました。あまり依存しすぎず一部機能をDBMSに委譲したりと境界はいじりましたが。
美味しいところだけ使う
デメリットに対して多く記載してきましたが、ORM自体は強力なツールであることには変わりはないです。
具体的には下記の機能です(ORMライブラリーに付随する機能もあります。)。
- ORM機能
- prepared statement
- migration機能
その他にも下記のようなライブラリー固有の強力な機能もあったりします。これは利用しない手はないです。
- Hibernate 2nd level cache
諸問題にどう対処したか
多くの問題はVIEWを活用することで解決しました。
N+1問題については、あらかじめVIEWとしてテーブル結合して結合ロジックをDBMS側へ委譲することで問題が解消しますし、
複雑化するメソッドチェーンやSQLの隠蔽問題もあらかじめVIEW定義しておくことで、コードをシンプルに保つことができました。