How to develop class dependence, trying to avoid the Law of Demeter

Well, I searched and did not find a suitable solution for my problem, I will redesign a part of our sales system. Suppose we have the following classes:

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;

Now the problem that I am facing is trying to come to a better understanding without violating the Law of Demeter. What I'm trying to accomplish is the following:

  • Each time a new TSale is saved, I want to add it to the current user’s TWorkShift sales list, and also want to sum the sales amount with TWorkShift “TotalSold”.

I tried two different approaches:

Approach A:

// Suppose we have a work shift with identifier 1 and load from the database: 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;

, , .

" ", . .

+5
2

TWorkShift,

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

, TWorkShift "" , .

, , TSale TWorkShift. Workshift , Sale WorkShift?

+3

-, TList, OnNotify. , Aurelius , . , OnNotify , TWorkShift, NotifySales.

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;
0

All Articles