DataSet vs カスタムエンティティ
.NETを用いた業務アプリケーション開発において、データベースとのデータの受け渡しにDataSetかカスタムエンティティクラスを用いるか過去さまざまな議論が色々な箇所で行われていますが、傾向としてJava界から転向して来た場合にはカスタムエンティティに慣れていることもありDataSetが嫌われている気がします。
VisualStudioのデザイナが生成するTableAdaptorがいけてないとか(これには同意)、プレーンなオブジェクトではないためNGとか色々主張がありますがそもそも全ての要求を満たす物は存在しませんしVisualStudio・.NETFramework・サードパーティ製コンポーネントがDataSetを優先的にサポートしているため上手く使いこなせばよいのではないかと思っています。
.NETを使い始めた当初DataSetの機能が良く判らず、ADO-RecordSetと比較して冗長な部分が多くて嫌気が差しカスタムエンティティクラスを使う方向へ一度傾きかけたが、VBから移行してきたメンバーで構成されるプロジェクトではそもそもカスタムエンティティクラスを使う概念が判らずRecordSetの置き換えとしてDataSetを使うケースが圧倒的に多い。
嫌々ながらDataSetを中心とした構成を調査するに従い完璧には遠いが大抵の利用ケースで70〜80点をとれる良く考えられている技術だと考えが改まった。
具体的には
DataSetの長所・短所
○VisualStudioのデザイナで生成可能
○レコード毎にデータの状態を保持
○メモリ上でソート、クエリ、フィルタリング処理が可能
○メモリ上の更新操作をコミット、ロールバック可能
○XMLでスキーマとデータをエクスポート、インポート可能
○型指定した場合は集計値項目などDBスキーマとは異なるカスタム項目を保持可能
○型指定した場合はDBへ送信前に参照整合性検証などの論理検証が可能
○階層構造を持ったコントロール(ツリーやN次元グリッド)にDataRelationでDatabind可能
○DataAdaptorで容易に操作が可能
○規定でシリアル化対応
○DataBaindで更新、ソートに自動対応
○データ操作時にコールバックされるイベントのエントリポイントが豊富
×他のプラットフォームと相互連携がし難い
×DBカラムをプリミティブ型にしかマップ不可能
×オーバーヘッドが大きい
×型指定していない場合は方情報が失われコンパイルチェック不可能
×Partialクラスで緩和されたが拡張性・再利用がいまいち
×非常に複雑なデータ構造には対処しにくい
カスタムエンティティクラスの長所・短所
○他のプラットフォームと相互連携が容易
○非常に複雑なデータ構造にも対処可能
○DBカラムを疎粒度のオブジェクト型にマップ可能
○オーバーヘッドが小さい
○上手く作れば拡張性・再利用が向上する
○BindingSourceで更新系バインド対応など利用しやすくなったがソートは実装が必要
×コンストラクタ、シリアル化、Equals、HashCode、ToStringをオーバーオード・ライドする必要がある
×標準以外のジェネレータを用意する必要がありキチンと出力する決定的な物がない
×メモリ上でソート、クエリ、フィルタリング処理を実装するのは大変
×レコード毎にデータの状態を保持するDirtyチェックロジックを実装するのは大変
×DataRelationで自動展開するコントロールに対応出来ない
キリがないので辞めておくが大体各々の長所・短所が逆転しているのが判ってもらえるだろうか?
現在の考えとしては、パーケージ製品の開発ではなく小中規模の業務アプリを構築する場合の使い分けの基準としては更新系として扱うデータは型指定したDataSet、参照系で単純なリスト表示はオーバーヘッドの少ないカスタムエンティティクラスのコレクションとしプレゼンテーション層でのソートに対応するならDataSetの方が楽なので用件に応じて判断する。
ClickOnceのオフライン実行やデータキャッシュとして使う場合はDataSet、Webサービスなど相互連携が必要な箇所はカスタムエンティティとする。
ClickOnceでリソース系は一旦DBから取得したDataSetからXML出力してディスクへ保存しておき
通常はXMLからリストアしバージョンが更新された場合だけDBからDataSetへ反映するとか更新系の処理を幾つかのRowに行いDataSet上で整合性検証を実行した上で、実際に更新されたデータのみを抽出してWebサービス経由で複数の更新行をバッチ転送し楽観的同時実行制御で撥ねられたRowを識別&最新取得を行ってリトライする処理をカスタムエンティティクラスで実装するのは非常に困難だがDataSetはそのような処理を意図した機能がはじめから用意されている。
複雑なデータモデルをカスタムエンティティクラスでDomainModelとして表現しその資産価値が重要となるようなパッケージ製品の開発等はDataSetの出番が少なくなるだろうが通常の利用ケースにおいては稀なのではないかと思う。少なくとも私の携わる案件はそうだ。
オブジェクト指向の観点で綺麗じゃないとかそんな事は重要ではなく、決められた期限や予算の中で現実のプロジェクトをこなすためには上手に使い分ければ良いということですね!
S2Unit.NETとMbUnit
なぜ最新版のMbUnitをS2Unit.NETが使っていないかというと、MbUnitの最新版(いつのバージョンからは調べてません)のアセンブリが署名されなくなっているからなのです。それが原因でどうしようかと検討している段階です。まだMbUnit-2.3RC1ということなので、今後のMbUnitの出方を様子見しています。
MbUnitのバージョンは現在のところ上記の理由により最新へ追従していませんm(__)m
VS2003とTestDriven.NET2.0.1605+MbUnitが2.3.0の組み合わせだとTest With MbUnitでMbUnitGUIでの起動ができませんがRunTestsだと上手くいきます。MbUnit2.3.47をインストールしても動作させる場合はSystem.EnterpriseServicesの機能を利用していない事が前提ですが、S2Unit.NETが参照しているMbUnitのバージョンを最新にして厳密署名の指定を外してビルドしなおしてください。
この場合テストプロジェクトも厳密署名不可になりますがテストコードは署名しなくてもOKだと思っています。
2.3.47の場合Test With MbUnitのメニューが選択できるようになります。
Seasar Conference 2006 Spring その後
見たいと思っていたid:habuakihiroさんのABDとid:t-wadaさんのSOAセッションも結局コミッタブースに居て見ることが出来なかったので配布資料とブログでのエントリなどから色々考えてみる。
まずABDだがデブサミの資料から雰囲気は何となくイメージできたような気がしてたけど至極端的にいうと、関連にも実態と同様にIDを与え一級市民の立場に引き上げてやるって事ですね。負荷に対するコメントや受け答えが有りましたが余程のデータ量で無い限りボトルネックには成らないってのは、リフレクションやスクリプティング、Lispの流れを汲んだオーバーヘッドの高い言語やテクニックの盛況具合からみて、仮に今問題があったとしてもムーアの法則が続く限り誤差の範囲って事で。それより気になるのは単純なIDカラム同士の関連で全てを繋げたモデルってのは関連の種類が
- 参照関連
- 親子関連
の親子関連だった場合は如何なるのって思ったんだけど、よく考えたらイベント系の扱いを前提にした話だから親子関連は無いって事になるよね。
ORMとか使う場合に親子関連をID+インデックス制約か複合キーにするかはっきりした回答を聞いた事がないので何時も悩むんですよね。
JPAの話を.NET環境に置き換えて考えるとManyToManyアノテェーションに変わるカスタムアトリビュートを用意して交差エンティティを簡単に扱える仕組みは欲しいですね。
次にSOAセッションに関しては、3段階の導入ステップをSOA大全での分類とは異なって
- 孤島段階
- ネットワーク化段階
- プロセス制御段階
と分類していましたが、ついこないだSOA大全を読んだばかりなのでセッション資料の内容は非常に分かり易かった。
Seasarプロダクトファミリーでココまで統合されたエンタープライズ環境が整ってきつつあるのは凄い事だと思います。
では、これまた.NET環境に置き換えて考えてみると
- 同期通信はS2Remoting.NETがとりあえずあるよと
- 非同期通信はJMSに対応するMessageQueueサービスで同等の仕組みがS2MQ.NETとして実現可能なのかな?ちょっとソース見てもピンと来ませんでしたがorz
- ワークフローはWinFXに搭載されるWFが控えていますが、Biztalkとの住み分けが良く分からんのとS2と連動可能なのかが要調査。S2Buriのポーティングもマンパワーがあれば不可能じゃないのでしょうけど、ワークフローの監査やトレースはBiztalkやWFの方が強いでしょうね、OSSのS2Buriと結構なお値段のするBiztalk比べてもしょうがありませんが・・
- 相互運用性はJavaOneでなにやらタンゴなるWCF連携ミドルが控えているようなのでそいつでややこしい事考えなくても繋がるようになるといいなぁ
またPOJO+Unitテスト事が資産だってのは確かに仰るとおりで、.NETに閉じているならDataSetでええやんって事になりますがプレーンなクラスと相互変換する機能が欲しいケースが出てくる可能性もありますね。
Architecture Journal日本語版
architecturejournal - Bingの日本語PDFが提供されています。内容はタイムリーな事に興味のあったWFとSOAに関する物なのでありがたい。
Seasar Conference 2006 Spring
睡眠不足で疲れたけど.NETチームの皆にあえて楽しかったです。
自分のミニセッションは欲張りすぎてビシッと決まらなかったのでかなり反省orz
他のイベントで公聴している方を見てても、自分が講師とかやった経験でも面白く分かりやすく噛み砕いてプレゼンしないと楽しんで貰えないのは分かっているつもりなんだけどorz
技術者としてどーしても技術的な部分を上手く端折れないのよね〜
魚を与えずにつり方を教えたいんだけど、それは自分の驕りでいきなりは聞いて貰えないんですよね。
次回機会があればリベンジ出来るよう精進します!
ユースケースによるアスペクト指向ソフトウェア開発 読了
読了、AOPってあくまでオブジェクト指向を補完するために味付け程度に使うもんだと思っていたけどAOSDとして紹介されている内容はアスペクト技術が前面に押し出された内容で勉強になった。
分析段階から責務の分離を今まで以上に促進する為にアスペクト(InterTypeとアドバイス)を用いてオブジェクト指向原則に新たなパッケージング方法をプラスするとこが可能になり再利用・保守・拡張性を向上できる。
適当な説明するとInterTypeを使って基本実装クラスに拡張のテンプレート実装クラスを継承することなくmix-in的に組み合わせテンプレートに用意したジョインポイントにアドバイスを与える事で肉付けするって感じ。内容は良いのだけど実プロジェクトでは従来のS2におけるインターセプタみたいな裏方ではなくなるので、プロジェクトメンバーがキチンと理解していないと導入が難しそうだ。
現状.NET環境ではAspectJのようなアスペクトコンパイラやビジュアルにアスペクトの構造を認識できるツールが無いのでコンセプトをそのまま実現するのは難しいがpartialクラスを使ってユースケーススライスを表す事が可能な気がする。
partialクラスは同一アセンブリ内でしか使用不可なのでレイヤー毎にアセンブリを分割した場合はスライスがバラバラになるけどUI層より下位のレイヤーは同一アセンブリに定義しても問題無い気がするので適用可能性を検討したい
RealProxyとCastle.DynamicProxyとの切り替え案
現在のAopProxyUtilのAspectWeaverで行っている処理を、WeaveAspectというメソッドを持つIAspectWeaver実装クラスに行わせるのはどうだろう?と思っています。
実装の切り替えにかんしては、id:sugimotokazuyaさんの案で良いと思います。
所々で透過プロキシだった場合の振り分け処理とかs2remotingも合わせて確認Or対応がいるでしょうね。
ただ、DynamicProxyの実装クラスをSeasarアセンブリに持つとすればDynamicProxyへの参照が必要ですよね?そうなるとSeasarを使うクライアント側のプロジェクトが同時にIbatis.NETとかDynamicProxyを使う他のプロダクトも組み合わせる場合はNGになるのかと。
上記も回避しようとすればID=Kazzzさんの言われるようにDynamicProxyをSeasarへ取り込んでしまうか、DynamicProxy用のIAspectWeaver実装だけ別アセンブリに分ける必要があるかな?
前者は
DynamicProxyは.NET Framework 2.0に既に対応しているが、まだ暫くはこのように細かいFixが続くかもしれない。そういう意味ではid:wataru87さんの懸念はもっともだし、他のOSSを利用するということは、そういうことなのだろう。
に言及されているように追従が大変になるので今の段階では避けたいですね。
落ち着くまではNANTか手動で解決してDynamicProxyへの参照を含む物と含まないSeasar.dllを配布しても良いかな?