Ok,I´ve searched and couldn´t find a suitable solution for my problem, I am redesigning a part of our point of sale system. Let´s 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 I am facing is trying to come to the best idea without violating the Law of Demeter. What I am trying to accomplish is the following:
I´ve tried two different approaches:
Approach A:
// Let´s suppose we have a working shift with the ID 1 and gets loaded from database with: CurrentShift := TWorkShift.Create(1);
NewSale := TSale.Create;
NewSale.Amount:=100;
NewSale.Save;
CurrentShift.Sales.Add(NewSale);
CurrentShift.TotalSold := CurrentShift.TotalSold + NewSale.Amount;
The problem with this approach is that It´s difficult to test, because I want to encapsulate the logic of the sum in some of the classes or somewhere else (a new class maybe?).
Approach B:
My other approach is including that code inside the TSale class itself:
procedure TSale.Save;
begin
SaveToDataBase;
fWorkShift.Sales.Add(Self);
fWorkShift.TotalSold := fWorkShift.TotalSold + Self.Amount;
end;
This approach I think violates the Law of Demeter and doesn´t feel right to me.
I Want to find a "right way" to do it maximizing code simplicity and easy of maintenance in the future. So any suggestions would be appreciated.
Thanks
If you want to add a sale to TWorkShift, then you should have
TWorkShift.AddSale(aSale: TSale);
begin
Sales.Add(aSale);
end;
In other words, TWorkShift should "ask" for the thing it needs.
Also, I don't see any reason that TSale would have a TWorkShift field. A Workshift has many sales, but why would a Sale have a WorkShift?