向上させることができます。前回はこのパターンの概要についてお話しました。今回はDataAccessMethodパターンを適用する事でDBの仕様変更が柔軟になるということを解説します。継承ではなく委譲BusinessObjectとDataAccessMethodの特性IntelligentDataGatewayパターン進捗遅延対策パターン採用の注意デザインパターンのプラクティス暗黙知確保おわりにはじめにDataAccessObjectパターンによる開発でDAOジェネレータを使うケースが増えてきました。DAOジェネレータを使う目的は開発コストの削減です。リリースを急ぐプロジェクトはDAOジェネレータの使用方法をメンバに十分理解させないうちに開発を始めてしまいます。Hibernateのような高度なO/RマッピングフレームワークであればOO(オブジェクト指向)およびRDB(関係データベース)に関する高度な知識が必要となります。ところが、平均的な技術者にそのような知識はありません。本来であれば、開発工数を削ってでも彼らの理解を確保するための教育をしなければなりませんが、予算と納期といった制約上の理由からそれがされないのが現状です。DAOジェネレータは知識のある技術者にとっては便利でも、そうでない技術者にとっては学習コストのかかる厄介な代物であることを管理者は理解すべきです。殆どの技術者は後者ですから、DAOジェネレータを使う場合、相当な学習コストを覚悟する必要があります。学習を軽視すれば、コスト削減のために導入したはずのDAOジェネレータが逆にコストを生みプロジェクトは逼迫してしまいます。DataAccessMethodパターンはこうした問題を解決します。このパターンはDB仕様が変更された場合にも柔軟な解決方法を提供します。本稿は、前稿『DAOパターンの欠点を補う「DataAccessMethodパターン」』の続きにあたりますので、併せてご覧ください。前回は概要について述べましたが、今回は設計よりの話題を中心に具体的に説明します。企業情報システムではRDBMSによる情報の永続化が行われるのが一般的ですが、RDBMSの仕様は各ベンダによって大きく異なります。そのため、プロジェクトに召集された開発メンバーがRDBMSの仕様について十分な知識を持っていなければなりません。十分な知識を持っていなければ、プロジェクトリーダは彼らが設計を始める前に最低限の知識を習得させねばなりません。ところが、実際には予算や工期の制約があり、十分に教育することは難しいのが現状です。した問題への解決策としてFacadeパターンがあります。これは「特殊なAPI」を使った処理をFacadeに集中させるというパターンです。Facadeパターンの本質は、その「特殊なAPI」に関する学習を誰か一人に押し付けるというプロセスにあります。Facadeパターンによりプロジェクトは下記の利点を享受できます。特殊APIの隔離:学習コストを軽減する事が出来るリスクの隔離:問題が発生しても影響範囲を最小限に抑える事が出来るCJ2EEのDataAccessObjectパターンはGoFのFacadeパターンの一種です。このパターンにはDataAccessObjectというFacadeに相当するクラスがあります。DataAccessObjectの開発は専門家でなければできないため、通常はDBMSの製品に精通した技術者が担当します。OracleやDB2の資格保有者や経験を積んでいるDBスペシャリスト等、データアクセスに詳しい上級開発者にデータアクセスロジックの開発を任せます。すると『DataAccessObjectをDAOジェネレータで自動生成できるなら、その分の人件費も削減できるはず』と信じている管理者がいるかもしれません。確かにDAOジェネレータによりDataAccessObjectは簡単に自動生成されます。DAOジェネレータを扱う開発者にはDAOジェネレータやDataAccessObjectに関する高度な知識が要求されます。それがなければ自動生成されたDataAccessObjectの品質は保証されません。DataAccessObjectパターンの問題DAOジェネレータの問題DataAccessObjectパターンにはDAOジェネレータの問題があります。先に説明したようにDAOジェネレータは扱いが難しいのです。インピーダンスミスマッチや性能問題を解決するには高い専門知識と経験が必要です。ツールによりどのように改善されるのかを説明できる能力も必要です。ところが彼らのような専門家は少ないのです。DAOジェネレータを上手く利用すれば品質の高いシステムを効率よく開発できます。大勢の上級技術者を安価で雇っているようなものです。彼ら、つまりDAOジェネレータには癖があります。彼らを扱えるのは彼らを良く知る者だけです。彼らを知らない非専門家や似非専門家が彼らをコントロールしようとしても結果は出ません。多くのプロジェクトはこの問題に苦しんでいます。教育の問題というのもあります。DataAccessObjectを開発するメンバには経験が必要です。専門家を雇えばそういったメンバの教育の機会を奪います。専門家がプロジェクトから抜ければ、他のメンバーがタスクを引き継いだとしても経験不足が原因で低品質のシステムを納品してしまうかもしれません。専門家を雇っている間に引継ぎ候補のメンバーを教育しておけば良いのですが、この教育も作業としての優先順位が低いプロジェクトが大半と思います。これは「技術者なら独学で知識を身につけるのは当たり前だ」と突き放す考えがSI業界で支配的だからかもしれません。昔と違い今は何を学ぶべきかの選択肢が多い時代です。メンバにそのリスクを負わせるべきはありません。今の時代、教育コストはプロジェクトが負担するのが当然なのです。DataAccessObjectパターンのような専門性の高い分野の教育は、研修による体系的知識習得と並行してOJT教育による経験を積ませるの良い解決策です。メンターによる徒弟制度は知識習得と経験を同時に満たす素晴らしい制度です。これも多くのプロジェクトでは施行は困難です。兼ね備えたメンターが見つからないからです。開発効率面でDataAccessObjectは誰が開発すれば良いかという問題もあります。DataAccessObjectの仕様を良く知る専門家か、それともDataAccessObjectを直接必要とする各開発者か。後者を選択するプロジェクトが少なくありませんが、筆者は前者であるべきと考えます。プロジェクトがDataAccessObjectパターンの専門家に担当を委ねたがらないのは、DataAccessObjectパターンの専門性が低いと評価しているからです。機能自体は単純なのだから、独学で習得できるはずと。DAOジェネレータがあるのだから、開発コストは殆どかからないはずと。業務の専門化が開発する方が品質も高いはずと。全ての開発者が勤勉であるとは限りません。勉強した者とそうしない者の開発効率は乖離します。1人の担当者に全てのDataAccessObject開発を委ねるべきか、全ての開発者に自分達に必要な分だけ開発させるべきか。DataAccessObjectがFacadeであれば前者であるべきは自明です。その場合1つの機能が複数の担当者により開発される事になります。した関心分離の開発をスライス開発といいます。この手法は多少の管理コストがかかりますが柔軟性に優れています。広く認知されていないのでプロジェクトはこのスライス開発手法のリスクが高いと考えてしまい導入したがりません。知られていない新しい手法(関心の分離によりタスクを分割し振り分ける手法)より伝統的な手法(業務機能単位にタスク分割し振り分ける手法)を安全と考えてしまうのです。仕様は突如変わるものです。開発者間の認識のズレや実装可能性の低さは突如判明するものです。)が低下することもあるでしょう。このような場合、クラスだけではなくテーブルの構造にも逐次最適が必要ですが、プロジェクトでは限界があります。多くのプロジェクトで適用されるウォーターフォール型プロセスには逐次最適という概念はありません。「最初から正しく」という基本方針で、「戻りはない」という制約を守る事が推奨されます。戻りがあったとしても前工程までです。それ以上であれば予算が増大し納期が大幅に遅れるというリスクがあるからです。一般的に基本設計の修正期限は詳細設計工程までで、DB論理設計が実装工程に入ってから変更される事はありません。これを解決する手法がイテレーション型プロセスで、多くの迅速開発ではこの手法が適用されます。ところが、イテレーション型プロジェクトでもDataAccessObjectパターンは仕様変更を阻害してしまうのです。DataAccessObjectパターンが仕様をロックしてしまうからです。これについては次節で解説します。仕様変更に柔軟な構造にするには、機能を関心毎に分離する必要があります。このとき業務的抽象レベルの最も高いクラス(業務ロジックが定義されているクラス)がBusinessObjectです。レベルが低いクラスは様々です。これらは全て分離対象の関心事ですが、その中でも企業システムでは必ずといっていい程採用されるDBアクセスという関心を分離する事は極めて重要です。この種のクラスは単純であり、設定ファイルが明確であればジェネレータによる自動生成が可能です。関心の隠蔽DBの仕様変更が突如発生しても耐えられるようにDataAccessObjectの外部仕様をBusinessObjectから隠蔽します。これを可能にするためにDataAccessObjectとBusinessObjectの間にBoundaryObjectを設置します。BoundaryObjectはDataAccessObjectを抽象化した(つまり粒度を粗くした)BusinessObjectに委譲されるFacadeです。Facade(DataAccessObject)との間に更にFacade(BoundaryObject)を設置するわけです。仕様変更はFacade(BoundaryObject)により吸収されるのでBusinessObjectへの影響は軽減されDB変更に強いシステムになるのです。開発者の負担このようにBoundaryObjectを設置することで可変性や保守性の向上を期待する事ができます。同時に開発メンバにBoundaryObjectの定義という負担を強いることになります。作業だけでなく学習も大きな負担です。これを軽視して無理矢理BoundaryObjectを作らせても「無駄なクラスを開発している」という意識によりモチベーションは落ちるかもしれません。ならないようにBoundaryObject導入による開発者の負担とシステムに与える効果を説明できなければなりません。ハリウッドの原則そこで開発者の負担を少しでも軽減するために、DataAccessMethodパターンを採用しBoundaryObjectをBusinessObjectの継承クラスとして定義します(委譲クラスとして定義する方法は後述します)。DataAccessMethodパターンでは、DataAccessMethodがBoundaryObjectに相当します。継承パターンは委譲パターンに比べ開発者の負担が軽減されます。ハリウッドの原則が適用されるため依存性は逆転します。ハリウッドの原則が適用されたパターンとそうでないパターンの依存関係を比較します。BusinessObjectハリウッドの原則を適用する場合、BusinessObjectはDataAccessMethodに依存しません。BusinessObject開発時にDataAccessMethodは必要ないのです。これは何を先に開発すべきかという問題です。DataAccessMethodを適用すればBusinessObjectを先に、DataAccessObjectを適用すればBusinessObjectを後に開発します。これにより仕様のロックという問題を解決する事が出来ます。著者プロフィール瑞瑞(ズィーズィー)Java屋。圧縮・解凍UNIX基本講座@CodeZine『CodeZine(コードジン)』の公式アカウントです。【NEW】デブスト2019デブサミ2019福岡・関西デブサミ2019夏デブスト関西デブサミ2019×ログインEメールパスワード※旧SEメンバーシップ会員の方は、同じ登録情報(Eメール&パスワード)でログインいただけます。イラストの無断転載を禁じます。記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。