BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース LightSpeed - .NET の商用 ORM

LightSpeed - .NET の商用 ORM

原文(投稿日:2012/02/06)へのリンク

LightSpeed はエンティティのシリアライゼーション,堅牢な VS デザイナ,LINQ の組込サポート,DTO サポートなどの機能を誇る .NET 用 ORM 製品である。我々は Mindscape (LightSpeed の開発会社) の共同設立者である John-Daniel Trask 氏に連絡を取り,製品の詳細や ORM 一般に関する話を聞いた。

InfoQ: .NET にはオープンソースや有償のものなど,すでに多数の ORM 製品が存在します。その中で,新たに製品を開発した理由は何でしょう?

JD: LightSpeed は Mindscape にとって最初の製品です。IT サービス分野における,私たちのこれまでの経験から生み出されたものです。これまで既存の ORM (object-relational mapper) をいくつか使用してきましたが,当時 .NET 関連の選択肢はそれほど多くありませんでした。ほとんどが NHibernate を使うか,あるいはスクラッチから自身で組上げるかのいずれかで,多くの組織が自分たちで作る方を選択していたのです。私たちは既存の ORM のパフォーマンスや開発エクスペリエンスに満足できませんでした。そこで習得が容易でパフォーマンスの高い,優れた ORM を提供することで,他の製品や DIY 的アプローチよりも開発期間を短縮できれば,ビジネスとして成立するのではないかと考えたのです。

InfoQ: ORM が対処しなければならない重要なポイントは,どのようなものだとお考えですか?

JD: ORM の基本的な目的は,データベースとオブジェクトの世界をうまくマッピングすることですから,当然それは必要です。
 
その上で,パフォーマンスも非常に重要です。ORM に関してよく聞かれる不満にパフォーマンスの悪さがありますが,私たちは必ずしもそうは思っていません。優れた ORM はオブジェクトハイドレーションやクエリのバッチ実行,効率のよいクエリ生成,一括読み込み(eager loading),インテリジェントキャッシュなどの技術を自動化することで,ORM ベースのコードでも手作業で記述したものと同程度のパフォーマンスを実現しています。
 
生産性も重要です。ORM は実行速度の向上を目的に使用するものではありません。開発時間の短縮すなわちビルドの高速化,ミス全般の回避,優れたプラクティスの実施,迅速で信頼性の高いテストと開発の実現,などを行うためのものなのです。例えば LightSpeed では,クエリを自動的にパラメータ化することで,ハンドコードされた SQL に比較して SQL インジェクション攻撃の危険を大幅に削減しています。残った時間は強力なバリデーションやデータバインディング通知,編集ロールバックなどを実装するモデルの構築などに費やせばよいのです。LighteSpeed では,このような懸念をすべて "問題ない (it just works)" というカテゴリに片付けられるように努力してきました。データを直接アクセスしているコードを ORM 利用に移行するのは,アセンブラから C# や Java に移行するようなものと考えればよいでしょう。パフォーマンスに多少目をつぶらざるを得なかったとしても,考えていた程ではありません。しかもそれと引き換えに,数百倍という生産性の向上を達成できるのです!
 
.NET 用 ORM を決定的に特徴付けるものとして,LINQ のサポートがあります。LINQ の人気は大変なもので,それなしで開発を行うことはもはや考えられない程です。ですから,本当に信頼できる LINQ プロバイダを用意することが重要です。できの悪い LINQ プロバイダでさえ開発するのが大変なのですから,優秀なものを作り上げるのは *本当に* 大変なことです。私たちは何年もかけて LINQ プロバイダの改良を続けてきました。その結果,本当に自信の持てるものに仕上がりました。LINQ サポートは .NET 開発者のツールボックスには必須の機能になっていますから,LINQ をサポートしない,あるいは機能的に乏しい ORM を使うというのは受け入れられないことなのです。

InfoQ: LightSpeed では POCO (Plain Old CLR Object) を使用した,EF (Entity Framework) で言うコードファースト (code-first) 的なものはサポートされるのでしょうか?

JD: モデルファースト (model-first) とコードファーストには,データベース構造に先立って開発者がコードでモデルを表現するという面で,概念的に近いものがあります。LightSpeed は確かに,何年も前からモデルファーストをサポートしています。ただしデータベース変更の作成や管理だけでなく,定義されたモデルに基いたクラス生成にも LightSpeed モデルデザイナでの作業が必要なのです。EF のコードファーストは,モデルファーストを私たちのアプローチよりも一歩進んでいます。開発者がクラスを記述すれば,デザイナを介さずに,そのクラスから生成された更新がデータベースに適用されるのです。このサポートの追加に関する要望はほとんどありません。クラスを自動生成してくれる現状から,アプリケーションに必要なすべてのエンティティの手書きが必要な状態に移行するのは,生産性の面でのロスが非常に大きいからです。

POCO に関しては,デフォルトとしては推奨していません。LightSpeed のエンティティは 'Entity' 基底クラスに依存しています。率直に言って私たちは,開発者にとってこれが大きな意味を持つと思っているのです。ORM の目的が生産性にあることを思い返してください。POCO を支持する人たちはよく,INotifyPropertyChanged のようなインターフェースの実装クラスの開発,フィールド更新の追跡,あるいはバリデーションを処理する T4 テンプレートの管理に時間を費やしています (もっとひどい場合には,コードジェネレータを使わずにこれらの問題をすべてハンドコードしているのです!)。そんなコードを手書きするくらいなら,もっと他にやるべきことがあるのではないでしょうか。私たちの経験から言えるのは – 意外なことでもないですが – 特別な継承レベルを持つことには,それに見合うだけの十分なメリットがある,ということです。一般に開発者たちが LightSpeed を好むのは,コードの繋ぎ合わせを手作業で組み上げたり書いたりする必要がないために,実際の問題解決に集中することができるからなのです。

そうは言っても,分散シナリオでは POCO にも大きなメリットがあります。そのため LightSpeed では,分散開発用に2つのアプローチをサポートしています。

  • エンティティのシリアライゼーション転送と 'DistributedUnitOfWork' により,クライアント上での LINQ クエリが可能です。LightSpeed がそれを自動的にサーバに転送,クエリを実行して,結果を返送します。変更されたエンティティのみを返送することで速度を向上するなど,高度な処理も行っています。こちらのアプローチは機能面でより完全なものですが,ある面で "マジック" のように思えるかも知れません。
  • DTO - LightSpeed Designer を使って DTO を生成可能なだけではなく,サーバ上にある完全に独立したエンティティオブジェクトに対して, DTO を容易にインポートする方法も提供します。シンプルであまりマジック的ではありませんが,こちらを好む開発者もいるでしょう。

InfoQ: 自動マイグレーション (Automatic Mirgation) に関してはどうでしょう?

LightSpeed は,自動マイグレーションよりも優れたものをサポートしています。
 
LightSpeed は VisualStudio を拡張して,統合型のスキーママイグレーション管理機能を追加します。これは ORM としては類のないものです。変更のキャプチャ,存在するマイグレーションの表示,データベースへの適用と変更スクリプトの生成 (使用しているデータベースを問わない) などの機能が用意されています。もちろん,サーバに VisualStudio をインストールするのは適当ではありませんので,稼働しているデータベース用のマイグレーションを実行するコマンドラインツールも用意しています。API を使ってアプリケーションに組み込むことも可能です。
 
マイグレーションはストーリの一部分です -- モデルの変更が必要であると確信すれば,通常はマイグレーションを行うでしょう。LightSpeed Designer は,私たちが最初のリリース時から "360 データベース・ラウンドトリップ" と呼んでいる機能をサポートしています。ユーザにも非常に好評です。例えばモデルファーストを希望するなら,ドメインをモデル化して,右クリック - "データベースを更新 (update database)" を実行すればよいのです。LightSpeed Designer があなたの開発データベースとモデルとの差分処理を実行して,変更を適用するかを問い合わせてきますので,あとは 'OK' をクリックさえすれば,データベースが更新されます。
 
では,データベースファーストにしたい場合はどうなのでしょう? こちらも簡単で,モデルを右クリックして "データベースから更新 (Update from database)" とすればよいのです。LightSpeed Model Designer が再び変更を検出して,それをエンティティに適用する前に,実行確認の問い合わせを行います。ここで素晴らしいのは,混在が可能であること - モデルファーストを好む開発者とデータベースファーストを好む開発者がいる場合,どちらも好きな方法を選択して,同時に実行することができるのです。

InfoQ: あなたはブログポストの中で,LightSpeed はひとつの Entity Model Designer で2,000に及ぶエンティティをサポートし,なおかつユーザフレンドリ性を保っている,ということを書いています - どのようにしてそれを達成しているのか,説明して頂けますか?

JD: そうですね,ひとつのモデル内に 2,000 エンティティというのが本当にユーザフレンドリになることはありえないのですが,私たちは,ユーザが非常に複雑なモデルをうまく扱えるように,いろいろと工夫しています。

例えば私たちは,モデルから必要なエンティティを簡単に検索する方法を提供しています - 名前をタイプし始めると同時にフィルタダウンして,一致するエンティティを絞り込むのです。さらに関連するエンティティを含むように拡張したり,全体を統合することもできます。もし個別の集合体としてではなく,サブドメイン全体を – 販売,物流といった具合に – 見たいのであれば,エンティティをタグ付けして,そのタグでフィルタすることが可能です。モデルを絞り込んで,現在注目しているいくつかのエンティティに戻すことも簡単です。複数のファイルで – サブドメインごとに1ファイルというように – モデルを構成することも可能です。統合性はありませんが,複数の作業者が別々の作業を同時に行うような環境であれば,ソース管理の問題解決に有効です。

些細なことですが,大規模モデルにはとても有効なのが,エンティティの色付けです。比較的少数の重要なビジネスエンティティがあって,モデルの他の部分がそれらを取り巻いている,という構成は珍しいものではありません。このようなエンティティを色分けして表示すれば,一目瞭然に見分けられるようになります – 他の部分よりも断然目立つからです。

低レベル処理に関しては,データベースのメタデータ取得の効率化についても,かなり力を注ぎました。例えば,必要のないテーブルのメタデータ取得を回避すること – 肥大したレガシーなデータベースを扱うような場合には,これによって大きな違いが生じます。

これらのことがあって,大規模でも効率のよいスキーマのラウンドトリップが実現できているのです。

InfoQ: 現在 NHibernate あるいは Entity Framework を使用しているアプリケーションに対して,コードを大きく変更する必要のない,簡単なマイグレーションパスは存在するのでしょうか?

JD: アプリケーションの構築方法によって条件が大きく違ってきます。
 
LINQ (Entiry Framework あるいは LINQ to SQL など) を使っているなら,マイグレーションはとても簡単です。Entiry Framework 上に構築された重要なアプリケーションを,わずか2時間で LightSpeed にコンバートしたユーザの例もあります。この作業が簡単なのは,すでに LINQ を使っているならば,クエリの書き直しが必要ないからです。セッションオブジェクトを LightSpeed UnitOfWork に置き換えて,モデルを LightSpeed モデルに移行し,アプリケーションにいくらかの設定を加えるだけでよいのです。反対にクエリロジックの多くが HQL (Hibernate Query Language) で記述してある場合には,もっと多くの作業が必要になります!
 
モデルに関しては,Entiry Framework あるいは LINQ to SQL モデルから LightSpeed へのマイグレーションを支援する機能が用意されています。EDMX ファイルあるいは LINQ to SQL モデルファイルを LightSpeed モデルサーフェース上にドラッグすれば,Lightspeed Designer がモデルを読み取って追加してくれるのです。ただし,モデルマイグレーションは開発プロセスの完了ではなく,普通は開始であることは忘れないでください!もっとも重要なのはテストです - 例えば,非常に複雑なクエリでは特に,LINQ プロバイダの違いという問題に付き当たるかも知れません。
 
また,通常のマイグレーションと同じように,移行するプラットフォームを最大限に活用したいという考えもあるでしょう。独自のバリデーションコードをバリデーション統合フレームワークに移行したい,先行読み込みをセットアップしてクエリをもっと効率的にしたい,というような具合にです。ただし一般的な LINQ 文法とモデルインポートサポートの間では,LightSpeed へのマイグレーションの作業量は大きく違う場合もありますから,それが本当にアプリケーションに適しているかどうかの検討は必要です。

InfoQ: 普段要求されている機能の中で,ORM の責任範囲ではない,とあなたがお考えのものがありますか,また,その理由は何でしょうか?

JD: データベースで作業しなければならない作業をすべて,ORM で置き換えたいと希望する開発者が一部にいます。例えばデータベースレプリケーションのように,通常はデータベースの問題であるものを,ORM で管理するという要求です。スコープに入らないような問題であっても,理屈の上では ORM に追加することは可能です。しかし,それによってメリットを受けるユーザの数は非常に少ないでしょうから,そのような作業は開発コスト面で引き合いません。サポート予定のない機能要望のほとんどが,このカテゴリに入るものです。

この記事に星をつける

おすすめ度
スタイル

BT