以前、Modelとはモデリングの成果物であるという説明をした。分かりにくかったかもしれないが、これは要するに「オブジェクト」であり、データおよび、それを操作するメソッドを含んだ「もの」ということだ。オブジェクト志向で何が嬉しいかというと、詳しくは、WEB+DB vol44を見ていただきたいが、一言でいうなら、
オブジェクト志向では、「もの」によって「できること(機能)」が連想できるのです。
- WEB+DB vol44 p76 豆蔵 萩本氏 -
普通に作るとModel=Entity+Blogic(業務ロジック)となる。「もの」が持つデータはEntity、「できること(機能)」がBlogicである。これはこれで問題ないように思えるのだが、実際にBlogicを実装していくと多くの問題に突き当たる。その原因の一つが、自分以外のモデルを参照する外部参照である。外部のModelは参照するけれども、主な責務は自分にあるので内部にメソッドを定義している、といったケースはよくある。しかし、そのメソッドが返す値は自分自身のEntityとは関係なかったりする。こうなってくると何でもアリになってくる。そして、「Entity重要」から「Blogic重要」になり、しまいには「あれ?Modelって何だっけ?」という話になる。これではモデリングの意味がないし「Entity重要」を強調するためにも、一旦、Blogicのことは忘れてEntityだけを設計することに注力すべきである。これがオブジェクト設計といえないことは前述したとおりである。なお、Blogicの解決策については、後半部分で触れる(太字で記す)
ここで、「Entity重要」の設計について整理してみたい。
1.分析クラスのEntityをもとにデータの構造体を実装する(entity0)
2.entity0のCRUDを実装する
問題は外部参照だ。Entityは他のEntityとコミュニケートできないとされるので、うかつに関係線を引くとモデラーの先生に叱られることになる。であるなら、関係のない新たなEntityを作成すればよい。(ただし外部参照のEntityへは内包線が引かれることになるので注意する)
Entityを内包するためにControlを使う。
Controlの定義
1.CRUDメソッドの実装部分を受け持つ
2.Blogicや外部参照のEntityを複数呼べる
3.トランザクションを管理する(1UOW)
具体的には、次のような、controlXを追加する形になる。
1.分析クラスのEntityをもとにデータの構造体を実装する(entityX)
2.外部のEntity(entity0,entity1)を参照して内部のEntity(entityX)にマッピングする(controlX)
3.entityXのCRUDを実装する
(省略)
サンプル
// Entityクラス
public class EntityX extends ControlX{
public String item0; // 要素0
public String item1; // 要素1
}
// Controlクラス
public class ControlX {
private Blogic blogic = new Blogic(); // Blogicクラス(業務ロジック)
public EntityX retrieve(EntityX entityX) {
Entity0 entity0 = (new Entity0()).retrieve(entityX.item0);
Entity1 entity1 = (new Entity1()).retrieve(entityX.item1);
entityX = blogic.convert(entity0,entity1); // マッピング
return entityX;
}
public EntityX create(EntityX entityX) {
・・・
}
public EntityX update(EntityX entityX) {
・・・
}
public EntityX delete(EntityX entityX) {
・・・
}
}
また、例のように、外部参照のEntityは複数あっても構わないが、内部EntityのCRUDは1UOWとする必要がある。すなわち、複数の外部参照のEntityをトランザクションで括る必要がある。(この実装はちょっと難しい。内部APIのような密結合であれば、実質的にはSQLになるのでDBMSのトランザクション管理を利用すればよいが、サービスのような疎結合では2phase commitなどを考慮しないとうまく管理できない。いずれにしても、この実装では、ロングトランザクションではなく、Atomicなトランザクション管理が要求されることになる。)
また、convertというBlogicが登場している。これはentity0,1からentityXにマッピングするメソッドであり、entityXのModelに属するものだ。さらにいえば、controlXもentityXのModelに属する。Entityの中にControlが入ることになるが、これも内包として考える。(内包は再帰的に考える)
そして、convertに限らず、BlogicはすべてEntityを入れてEntityを返すとしてよさそうである。ただし、BlogicにI/Oを持たせてしまうと外部参照となってしまうため基本的にNGである。ResourceへのアクセスはEntityのCRUDメソッドだけが許されるものとし、さらにBlogicからはそれを呼ぶこともできないとする。EntityのCRUDメソッドを呼べるのはControlからだけだ。
Blogicで可能なことは、Entityを元に計算や変換処理を行って、Entityに詰めなおして返すだけ。なんとも制約の多いものだが、これがカプセル化として働くため、非常に安定したシステムとなる。(後ほど説明するがテストも楽になる)
したがって、Blogicの定義は次のようにする。
1.entity = blogic(entity)
2.Blogicは揮発性である(ステートレスでありデータを保持しない。また、外部リソースへのI/Oはない)
このように、「Entity重要」の設計を行っていくと、自然とBlogicが整理されてくる。
Blogicが追加されて最終的に出来上がったものがModelである。そして、そのModelがさらに他の参照元になりえるという再帰的なModelとなる。(Groovyコンファレンスデモの実装の例を記事に書いているので参考にしていただきたい。=>リソースの実装)
Controlは、Modelの中に内包されてEntityとしても振舞う。考え方としてMashupに近い。
以上が私の考える「Entity重要」のリソース志向設計である。
独自色が強いのでおすすめはあまりできないが、何か設計の参考になれば幸いである。
0 件のコメント:
コメントを投稿