5

OK、検索しましたが、私の問題に適した解決策が見つかりませんでした。POS システムの一部を再設計しています。次のクラスがあるとします。

TWorkShift = class
   Date: TDateTime;
   fTotalSold: Currency;
   fSales: TList<TSale>; 
public
   property TotalSold: Currency read fTotalSold write fTotalSold;
   property Sales: Currency read fSales write fSales;
end;

TSale = class
    fAmount: Currency;
    fWorkShift: TWorkShift;
public
    property Amount: Currency read fAmount write fAmount; 
    procedure Save;  
end;

今、私が直面している問題は、デメテルの法則に違反することなく最善のアイデアを見つけようとすることです. 私が達成しようとしていることは次のとおりです。

  1. 新しい TSales が保存されるたびに、それを現在のユーザーの TWorkShift の Sales リストに追加し、販売額を TWorkShift の「TotalSold」に合計したいと考えています。

私は2つの異なるアプローチを試しました:

アプローチ A:

// ID 1 の勤務シフトがあり、データベースから次のようにロードされるとします。 CurrentShift := TWorkShift.Create(1);

NewSale := TSale.Create;
NewSale.Amount:=100;
NewSale.Save;

CurrentShift.Sales.Add(NewSale);
CurrentShift.TotalSold := CurrentShift.TotalSold + NewSale.Amount;

このアプローチの問題は、一部のクラスまたは別の場所 (おそらく新しいクラス?) で合計のロジックをカプセル化したいため、テストが難しいことです。

アプローチ B:

私の他のアプローチは、TSale クラス自体の中にそのコードを含めることです。

procedure TSale.Save;
begin
    SaveToDataBase; 

    fWorkShift.Sales.Add(Self);
    fWorkShift.TotalSold := fWorkShift.TotalSold + Self.Amount;
end;

このアプローチは、デメテルの法則に違反していると思いますし、私には正しくないと感じています。

コードの単純さと将来のメンテナンスの容易さを最大化する「正しい方法」を見つけたいと思っています。したがって、任意の提案をいただければ幸いです。

ありがとう

4

2 に答える 2

3

TWorkShiftにセールを追加したい場合は、

TWorkShift.AddSale(aSale: TSale);
begin
  Sales.Add(aSale);
end;

言い換えれば、TWorkShiftは必要なものを「尋ねる」必要があります。

また、TSaleにTWorkShiftフィールドがある理由はわかりません。Workshiftには多くの売り上げがありますが、なぜSaleにWorkShiftがあるのでしょうか。

于 2012-04-26T23:38:07.220 に答える
0

OnNotify を使用できるように、アイテムを TList に追加するときに何かを行っています。アウレリウスもそのイベントを使用しているかどうかわからないので、そのためのコードを追加しました。NotifySales イベント ハンドラが上書きされる可能性があるため、リストが TWorkShift オブジェクトに割り当てられた後、OnNotify の割り当てがフレームワーク内で発生するかどうかを確認するだけで済みます。

type
  TWorkShift = class
  private
    Date: TDateTime;
    fTotalSold: Currency;
    fSales: TList<TSale>;
    fNotifySales: TCollectionNotifyEvent<TSale>;
    procedure NotifySales(Sender: TObject; const Item: TSale;
      Action: TCollectionNotification);
    procedure SetSales(const Value: TList<TSale>);
  public
    property TotalSold: Currency read fTotalSold write fTotalSold;
    property Sales: TList<TSale> read fSales write SetSales;
  end;

procedure TWorkShift.NotifySales(Sender: TObject; const Item: TSale;
  Action: TCollectionNotification);
begin
  if Assigned(fNotifySales) then
    fNotifySales(Sender, Item, Action);

  case Action of
    cnAdded: fTotalSold := fTotalSold + Item.Amount;
    cnRemoved: fTotalSold := fTotalSold - Item.Amount;
  end;
end;

procedure TWorkShift.SetSales(const Value: TList<TSale>);
begin
  if Assigned(fSales) then
  begin
    fSales.OnNotify := fNotifySales;
    fNotifySales := nil;
  end;

  fSales := Value;

  if Assigned(fSales) then
  begin
    fNotifySales := fSales.OnNotify;
    fSales.OnNotify := NotifySales;
  end;
end;
于 2012-04-27T09:23:43.850 に答える