tsucchi’s diary(元はてなダイアリー)

はてなダイアリー(d.hatena.ne.jp/tsucchi1022)から移行したものです

最近のお仕事の話とか、ORM のはなしとか

たまに書いてますが、最近は、Teng使ったりしてます。ほかの ORM はあんま知らないです。つーか、ちゃんとした Web アプリとかあんまり書いたことないし、つまり、Web系の前線とかには全然居ない人です。地味に MES(製造実行システム)のバックエンドを作ってる人なのです。なので話半分くらいで見てもらえれば幸いです。

さてさて、そんな私ですが、

  • 内製の WAF を使って、Web-API を書いてます
  • WAF の機能は、ストアドを実行して XML を返す物体でした*1
  • クライアントは簡単には変えれないので、XML のレスポンスは当面そのままでしょうねー*2
  • ストアド書くのは楽しくないし、色々問題がでた(詳細はMySQL のストアドプロシージャの話を参照)ので、普通の SQL を叩けるように改造しました*3
  • SQL 叩けるだけだと、簡単な SQL 書くのがだるいので、自分でテーブルデーゲートウェイを書きました
  • 自分で書いたテーブルデーゲートウェイのメンテがだるいので、ありものを使おう、と思って、Teng を使えるようにしました(イマココ!)

と、言うわけで、最近は難しい機能の場合はめんどくさい SQL を手で書いて実行して、簡単なやつは ORM(Teng)に振るような感じで、過ごしていたわけです。

で、Teng に限らず、大抵の ORM はスキークラスを持っているのですが、僕はアホなので、テーブルの変更があったのにうっかりスキーマクラスを更新するのを忘れて、「ひでぶ」となることが多々あります。で、結構テーブルの変更は頻繁にあるので、「ひでぶ」も結構頻繁に起こります。テーブル数はアホみたいに多いので、スキーマクラスを動的に作成とかしたくありません。

いろいろ悩んだのですが、まあ解は2つかなー。

前にも書きましたが、スキーマの変更をテストしてるので、ORM のスキーマクラスもそのタイミングでテストしちゃえ、ってのが後者。で、基本的には前者でいきたいんだけど、Teng にその方向に手を入れるのは無理くさいし、自作するのはそれはそれで大変だなー、と思ってたりします。*4

つーか、そもそも何でスキーマクラスって必要なんだろ???と思ってちょっと考えてみたのですが、

  • 重量級の ORM だと、そもそも DDL 管理もやってるから必要だよねー
  • 軽量級(Teng とか DDL 管理やってないやつ)なら無くてもやってけるけど、そうすると Row オブジェクトが何にもできなくなっちゃうよねー

という感じかなー、と思います。例えば Teng だと、Row オブジェクトから UPDATE かけたりできるんですが、スキーマクラスが無いと主キーが分からないからできなくなっちゃいますよね。INSERT で Row オブジェクトを返すとかもできなくなっちゃう。あとは inflate/deflate もスキーマクラスがあった方がやりやすいかな。*5

上記のようなトレードオフやその他を検討した結果、

  • スキーマクラスはなくしたい
  • Row オブジェクトの機能はそんなに求めてない*6
  • 生の DBI はちょっとさすがに厳しいので、もう少し簡単にしたい
  • 名前付きプレースホルダーが使いたいなー

あたりが今やりたいことのようです。名前付きプレースホルダー以外は DBIx::Simple で機能的にはよさげなんですけどねー。

色々考えてみたわけですが、新旧 ORM は色々ありますが、歴史あるものは(僕が思いつきで作ったものと違って)それなりの理由とか思想があって良くできてるんだなー、と思った次第であります。

*1:だいぶ改造したけど、僕が書いたものではない

*2:これはこれで問題あるんだけど、今回の話とは関係ないので割愛

*3:SQL::Library というモジュールを使ってます。mod_perl じゃなかったら Data::Section::Simple を使いたかった。

*4:長期スパンで、自作の方向で検討してます。Teng とある程度互換性のあるブリッジが作れればいいかなー、と思ってます。

*5:inflate は Row オブジェクトで代替してもいいんじゃないかな、と思ってますが

*6:前述の Row オブジェクトから UPDATE はあればうれしいけど、INSERT で Row オブジェクトとか使ったことないや。どうやら欲しかったのはちゃんとしたテーブルデーゲートウェイだったようだ。最初にちゃんと作れば良かった...