追記(2018/9/29)
元々は炎上ネタに近いなにかだったのでやや僕も書き口が辛辣だったのですこしマイルドにしました。
当時、割と燃えた割に反論記事がなかったので、この人の抽象論を変に解釈して生SQL信者みたいなのが発生しても困るので書いた事情がありましたが、ややこの記事の存在自体が用済みになってきた感もありますね。
はじめに
この記事は、以下の記事への指摘です。
この記事の目的
上記の記事がそれなりに反響があり、ほとんどの人は真に受けていないと思うのですが、有望な若手が道を逸らすことがないようにまとめてあります。
O/Rマッパを使うメリット
O/Rマッパを使うメリットは「再利用性」と「安全性」が特に重要な要素で、ここに(私が想定しているのはRailsの)ActiveRecordならテーブルの1行をオブジェクトにマッピングすることで、オブジェクト指向の恩恵が得られます。
再利用性の良い例に、scopeを使ってwhere,order,joins(includes,references)などの条件を記述しておくことによる恩恵があります。
あるカテゴリ(categories)に属する記事(entries)を抽出するときのSQLとRailsでActiveRecordを使った例を以下に書きます。
SELECT * FROM entries WHERE category_id = 1;
Entry.where(category_id: 1)
(scopeを定義して Entry.filter_category(category)
としても良いでしょう。ここでのcategoryにはCategoryのインスタンスが入っているはずです。)
さて、ここで単純にページングしつつ記事を10件表示する画面を作るとします。
この場合、kaminariというgemを使うと、RailsのActiveRecordなら以下のコードで書けてしまいます。
@entries = Entry.where(category_id: 1).page(params[:page)
kaminariの内部でcountと実際の取得を上手にやってくれるから出来る芸当です。
これは簡単すぎる例ですが、SQLを生で使う場合は「件数を取得」して「PAGEとLIMITでいま表示すべき内容を抽出する」少なくとも2つのSQLを構築する必要が出てきます。
また、この場合のWHERE文の使い回しは文字列の連結で行う必要があり、少しのミスがセキュリティホールに繋がります。
WHERE文がさらに複雑だった場合はどうするのでしょう? 検索条件を複数指定出来て動的にWHERE文を構築したい場合は?
仕様が複雑になるほど、生SQLでは重複コードとメンテナンスコストが跳ね上がるのです。
たとえば、後から「ホーム画面にはView数が10を越えた記事だけを表示する」といった仕様変更をした場合、COUNT側のSQLを書き換え忘れたらページングがバグりますよね。これを私はメンテナンス性と捉えています。再利用性を高めると往々にしてメンテナンス性が上がります。 (DRY原則とほぼ同じ話ですね)