今まで2〜3年に一度、ORMのようなものを開発してる気がする。腕試しとしてORMは最適で、とにかく難しい。正直プログラミングしていて、楽しいというより辛い。ただ自分のコーディングが改善できているのは実感できる。
ということで、また作り始めたORM。
さて、どんなのを作ろうか、ということで、ざっと既存のORMについて自分の感覚をまとめてみた。
Doctrine2:
複雑。バグが出たら対応できない。モデルとDB構造が結びついてないか?それも複雑怪奇な方法で。そしてUpsertなどDAOで対応したい場合があっても、出来ない。
Eloquent:
簡単で便利だけれど、コード補完が出来ないケースが多い。ActiveRecordパターンは、ひとつのクラスの責務が多すぎるんじゃないだろうか。本体のLaravelとバージョンが結びついてそうで不安。
Idiorm/Paris:
簡単で便利。でもレイヤーが一枚足りない感じ。この上に一枚欲しくなる。
まとめてみると、自分の欲しいORMが見えてきた。
- DAOとEntityクラスが分離していること。そして独自のDAOを使うことができること。これで細々とした要求に対応できる。
- 複合キーに対応していること。たまーに複合キーを使う場合があるので、完璧に対応して欲しい。
- CRUD(Create, Read, Update, Delete)はもちろん、リレーションに対応すること。
- 簡単に使えること。
一方で、必要ないと思ったものは、こんな機能。
- Eager LoadingとN+1問題の対応。これはクエリー用のクラスを提供することで対応。あるいはAtlasORMなどを使えばいいのでは。
Unit of Work
のような、エンティティのキャッシュ。あるいは処理を最後まで待って、一気に処理する方法。- 複雑なSQLクエリ構築。これは、専用のライブラリを用いればOKでしょう。ただ、複雑なクエリ結果をエンティティオブジェクトに変換はできて欲しい。
複雑になりがちなクエリーは別ライブラリを使うという前提で、エンティティのCRUDに特化したORMが欲しい、という感じです。
で、作りはじめて、一応「version0.1.1」まで来た所。テストも書いて、READMEは何とか書いているところ。
できとしては、まぁ満足。今回は機能を絞っているので、比較的コーディングが楽だった。
今の段階でできなかったことは、
- Entityクラスは、EntityInterfaceを実装する必要があること。このインターフェースが、思った以上に複雑になったこと。出来れば何の制約もないのが理想だが、それはそれで実装が複雑になるので諦めた。
- 一方DaoはRepositoryInterfaceを実装する必要があるが、実際にライブラリとして必須なのはごく一部のみ。とは言え、インターフェースとして定義しておかないと、コード補完の際に不便なので追加した。これはGenericsとかがあれば問題なくなるのだろうか。
- クエリー用クラス
Assembly
の機能が限定的。機能拡張のアイディアはあるが、基本機能を拡張する必要があるので、今のところは我慢する必要がある。 - 機能を減らしてもいいから、構造を簡単にすべきか悩んでいるところ。
- DaoからQueryの情報の受け渡しを見直してみたい。