- PR -

親子テーブルのクラス設計につきまして

投稿者投稿内容
骨骨★Rock!
常連さん
会議室デビュー日: 2007/09/11
投稿数: 38
投稿日時: 2008-07-22 16:13
表題の件ですが、皆様のご意見を拝借したく投稿させて頂きました。
N階層アーキテクチャを採用し、各階層間のデータの受け渡しは、カスタムクラス(データクラス)でやり取りしています。

//Orderのビジネスロジッククラス
//といっても殆どの場合、ビジネスロジックは特に無く下記の例のように
//データアクセス層(DAL)のメソッド(UpdateOrder)を呼び出しているだけです。(汗)
BLL.Order{
 GetAllOrder();
 GetOrderById(int orderId);
 UpdateOrder(OrderInfo orderInfo){
 例:
 return DAL.UpdateOrder(orderInfo)
};
 InsertOrder(OrderInfo orderInfo);
 DeleteOrder(int orderId);
}

//OrderDetailのビジネスロジッククラス
BLL.OrderDetail{
 GetOrderDetailById(int orderDetailId);
 GetOrderDetailByOrderId(int orderId);
 UpdateOrderDetail(OrderDetailInfo orderDetailInfo);
 InsertOrderDetail(OrderDetailInfo orderDetailInfo);
 DeleteOrderDetail(int orderDetailId);
}

//Orderのカスタムクラス
OrderInfo{
 int orderId
 DateTime orderDate
 .
 .
}

//OrderDetailのカスタムクラス
OrderDetailInfo{
 int orderDetailId
 int orderId
 int itemId
 decimal price
 .
 .
}

現状、親子関係のテーブルなどは特に考慮せずに取得する場合は、下記のように取得しています。

/*Order.aspx.cs*/

//オーダー情報を取得
OrderInfo orderInfo = Order.GetOrderById(1234);
//オーダー明細情報を取得
List<orderDetailInfo) orderDetailInfo = OrderDetail.GetOrderDetailByOrderId(1234);

これまで見たサンプルアプリ等では、OrderInfoの中にOrderDetailInfoを含み
OrderとOrderDetailの情報を同時に取得するケースを良く見ました。
下記の図を参照下さい。

//Orderのカスタムクラス
OrderInfo{
 int orderId
 DateTime orderDate
 ↓ココです
 OrderDetailInfo orderDetailInfo
 .
}

更新処理は、下記のような流れです。
/*Order.aspx.cs*/

using(TransactionScope ts= new TransactionScope()){
 //オーダーを更新
 int newOrderId = Order.UpdateOrder(OrderItemInfo);
 //オーダー明細の数だけループ処理
 for(int i=0; i<OrderDetailInfo.Count; i++){
  //オーダー明細を更新
  OrderDetail.UpdateOrderDetail(orderDetailInfo[i]);
 }
 ts.Complete();
}

ここで質問なのですが、OderInfoの中にOrderDetailInfoを持たせた方が
ベターでしょうか?
Orderテーブルの内容だけ参照したい場合、OrderDetailは特に必要ないケース
などがあります。

また更新処理ですが、Transactionなどの処理はビジネスロジックレイヤーにいれるべきものでしょうか?
そうなった場合、やはりOderInfoの中にOrderDetailInfoを持たせる必要があるかと思います。

クラス設計の考え方でアドバイスをいただけると幸いです。
宜しくお願いいたします。






【環境 VS2005 C# Webアプリ】
くまっち
大ベテラン
会議室デビュー日: 2008/01/18
投稿数: 169
お住まい・勤務地: 茨城県のどこか。
投稿日時: 2008-07-22 17:34
>OderInfoの中にOrderDetailInfoを持たせた方がベターでしょうか?
ベター。
OrderInfoとOrderDetailInfoに関連を持たせたい。

>OrderDetailは特に必要ないケースなどがあります。
OrderDetailInfoはオンデマンドで取得する仕組みにする。
詳細が必要な時、初めて詳細取得を(勝手に・自動で)行うようにすれば良いだけ。

>Transactionなどの処理はビジネスロジックレイヤーにいれるべきものでしょうか?
びみょう・・・けーすばいけーす・・・。
私的には・・・含めませんね・・・。


あとは・・・
OrderDetailInfoにはOrderIDは持たせず、OrderInfoへの参照を持たせるかな。
コンストラクタもOrderIDではなく、OrderInfoを受け取る形で。
(そうしないと親と子に違うOrderIDを渡すミスが発生するかも!? しれませんよね・・・)

と、思った次第です・・・。
骨骨★Rock!
常連さん
会議室デビュー日: 2007/09/11
投稿数: 38
投稿日時: 2008-07-22 18:19
くまっちさん、
ご返信いただきましてありがとうございます。
私なりに理解しようとしましたが、幾つかすっきり理解できない
部分がありましたので、ご教授いただけますでしょうか?

引用:

>OrderDetailは特に必要ないケースなどがあります。
OrderDetailInfoはオンデマンドで取得する仕組みにする。
詳細が必要な時、初めて詳細取得を(勝手に・自動で)行うようにすれば良いだけ。



下記のようにOrderInfoのプロパティーのGetterでOrderDetailInfoを取得すると
いう認識でよろしいでしょうか?
でもこれだと、このプロパティーにアクセスする度に、OrderDetailInfoを取得してしまう(汗)

private List<OrderDetailInfo> orderDetail;

public List<OrderDetailInfo> OrderDetail
{
 get { return BLL.OrderDetail.GetOrderDetailByOrderID(orderId); }
 set { OrderDetail = value; }
}

引用:

あとは・・・
OrderDetailInfoにはOrderIDは持たせず、OrderInfoへの参照を持たせるかな。
コンストラクタもOrderIDではなく、OrderInfoを受け取る形で。
(そうしないと親と子に違うOrderIDを渡すミスが発生するかも!? しれませんよね・・・)



ちょっと『OrderInfoへの参照を持たせるかな。
コンストラクタもOrderIDではなく、OrderInfoを受け取る形で』
の部分が理解できなかったです。
現在、OrderDetailInfoの引数付きのコンストラクタは以下のようですが、
ここで、 orderIdの代わりにOrderInfoを渡すという事でしょうか?

public OrderDetailInfo() { }

public OrderDetailInfo(int orderDetailId, int orderId, int itemId...){
 this.OrderDetailId = orderDetailId;
 this.OrderId = orderId;
 .
 .
}
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2008-07-22 18:23
引用:
骨骨★Rock!さんの書き込み (2008-07-22 16:13) より:
ここで質問なのですが、OderInfoの中にOrderDetailInfoを持たせた方が
ベターでしょうか?
Orderテーブルの内容だけ参照したい場合、OrderDetailは特に必要ないケース
などがあります。


OrderInfo と OrderDetailInfo は密接な関係にあるので、集約パターンを適用するといいと思います。(で、そうすると OrderDetail クラスは不要となるはずです。)
Aggregates(集約)パターン
OrderDetail が特に必要ないケースもあるかと思いますが、基本的に集約内のエンティティはまとめて扱います。
どうしても OrderDetailInfo を読み込みたくない場合は、レイジーロードパターンを使用すれば OrderInfo から OrderDetailInfo を取得可能にしつつ、OrderDetailInfo が必要になるまで読み込みを遅延させることができます。
PofEAA's Wiki - LazyLoad
LINQ to SQL とか O/R マッパーはレイジーロードをサポートしてたりします。自前で実装する場合は↓を参考にしてみてください。(※ レイジーロードにはこの他にも種類があります)
C#と諸々 仮想プロキシによるレイジーロード

# あと、クラスの名前付けが適切でない気がします。

# PofEAA's Wiki - LazyLoad へのリンクと※部分を追加しました。
_________________
C#と諸々

[ メッセージ編集済み 編集者: よこけん 編集日時 2008-07-22 18:25 ]

[ メッセージ編集済み 編集者: よこけん 編集日時 2008-07-22 18:34 ]
くまっち
大ベテラン
会議室デビュー日: 2008/01/18
投稿数: 169
お住まい・勤務地: 茨城県のどこか。
投稿日時: 2008-07-22 19:25
よこけんさんが全て説明されていますが・・・

こんな感じにすればいいのではないでしょうか。
(あくまでサンプルっすよ)

【コンストラクタについて】
コード:

//OrderDetailのカスタムクラス
OrderDetailInfo{
 int orderDetailId;
 OrderInfo parentOrder; // 親データへの参照
 .
 .
}

public OrderDetailInfo(int orderDetailId, OrderInfo parent, int itemId...){
 this.OrderDetailId = orderDetailId;
 this.parentOrder = parent; // 親データへの参照を保持
 .
 .
}



【オンデマンド読み込み】(↓OrderInfoクラス内です)
コード:

private List<OrderDetailInfo> orderDetail;
public List<OrderDetailInfo> OrderDetail
{
 get
{
// また詳細を読み込んでない場合は、詳細取得を行う。
if(orderDetail == null) orderDetail = BLL.OrderDetail.GetOrderDetailByOrder(this);
// ここは、自分自身を渡してOrderDetailInfoのコンストラクタに引き継がせます↑

return orderDetail;
}
// Setterは不要。
}



オンデマンド読み込みは、よこけんさんの提示しているレイジーロードってのとやってる事は同じです。

[コメント追加]

[ メッセージ編集済み 編集者: くまっち 編集日時 2008-07-22 19:28 ]
骨骨★Rock!
常連さん
会議室デビュー日: 2007/09/11
投稿数: 38
投稿日時: 2008-07-22 20:18
よこけん様、
ご回答いただきましてありがとうございます。
よこけん様のブログを以前拝見させて頂いた事がありました。
リンク先など勉強になりました。レイジーロードなど軽く見た事がありましたが、
どういった場面でつかうものかさっぱり分らなかったのですが、こういった場合に
有効なのですね!

引用:

# あと、クラスの名前付けが適切でない気がします。


具体的にどこがおかしいか突っ込んでいただけるとうれしいです。
骨骨★Rock!
常連さん
会議室デビュー日: 2007/09/11
投稿数: 38
投稿日時: 2008-07-22 20:29
くまっち様、
引き続きご教授いただきましてありがとうございます。
わざわざサンプルコード頂いて嬉しかったです。
大変勉強になりました。
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2008-07-22 22:42
引用:
骨骨★Rock!さんの書き込み (2008-07-22 20:18) より:
よこけん様のブログを以前拝見させて頂いた事がありました。


あらま、ありがとうございます。

引用:
骨骨★Rock!さんの書き込み (2008-07-22 20:18) より:
具体的にどこがおかしいか突っ込んでいただけるとうれしいです。



例えばこんな感じですかね。

Order → OrderRepository
OrderDetail → OrderDetailRepository
OrderInfo → Order
OrderDetailInfo → OrderDetail

特に上 2 つのクラス名は変えた方がいいかと。(〜Repository という名前じゃなくてもいいですが)
データストアから注文データを取得したり更新したりするためのクラスの名前が "注文" ではおかしいと思います。


ところで、骨骨★Rock!さんの最初の投稿で
> /*Order.aspx.cs*/
と書かれてますが、書き間違いですよね?(aspx じゃないですよね?)

_________________
C#と諸々

[ メッセージ編集済み 編集者: よこけん 編集日時 2008-07-22 22:46 ]

スキルアップ/キャリアアップ(JOB@IT)