Ok, tôi đã tìm kiếm và không thể tìm ra giải pháp phù hợp cho vấn đề của mình, tôi đang thiết kế lại một phần của hệ thống bán hàng của chúng tôi. Giả sử chúng ta có các lớp sau:Làm thế nào để thiết kế sự phụ thuộc của lớp học để tránh Luật Demeter
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;
Bây giờ, vấn đề tôi đang đối mặt đang cố gắng đưa ra ý tưởng tốt nhất mà không vi phạm Luật Demeter. Những gì tôi đang cố gắng để thực hiện như sau:
- Mỗi khi một TSale mới được lưu Tôi muốn thêm nó vào danh sách bán hàng của TWorkShift của người sử dụng hiện nay, và tôi cũng muốn tổng số tiền bán cho "TotalSold" của TWorkShift.
Tôi đã thử hai cách tiếp cận khác nhau:
Cách tiếp cận A:
// chúng ta hãy giả sử chúng ta có một sự thay đổi làm việc với ID 1 và được nạp từ cơ sở dữ liệu với: CurrentShift: = TWorkShift.Create (1);
NewSale := TSale.Create;
NewSale.Amount:=100;
NewSale.Save;
CurrentShift.Sales.Add(NewSale);
CurrentShift.TotalSold := CurrentShift.TotalSold + NewSale.Amount;
Vấn đề với phương pháp này là Nó rất khó để kiểm tra, bởi vì tôi muốn để đóng gói logic của tổng trong một số các lớp học hoặc ở một nơi khác (một lớp mới có thể?).
Cách tiếp cận B:
cách tiếp cận khác của tôi là bao gồm cả mã bên trong lớp TSale bản thân:
procedure TSale.Save;
begin
SaveToDataBase;
fWorkShift.Sales.Add(Self);
fWorkShift.TotalSold := fWorkShift.TotalSold + Self.Amount;
end;
Cách tiếp cận này tôi cho là vi phạm Luật Demeter và doesn't cảm thấy đúng với tôi .
Tôi muốn tìm một "đúng cách" để làm điều đó tối đa hóa sự đơn giản của mã và dễ bảo trì trong tương lai. Vì vậy, bất kỳ đề xuất sẽ được đánh giá cao.
Cảm ơn
Cảm ơn Nick, Vâng trong trường hợp này tôi đang sử dụng khuôn khổ Aurelius ORM vì vậy tôi có một "Hiệp hội" để có được các thông tin như: 'Bán: = Manager.Find (1); ShowMessage ('Bán đã được bán trong ca làm việc với ID:' + IntToStr (Sale.Shift.ID)); ' Điều này là cần thiết vì đôi khi tôi cần hiển thị tất cả thông tin về bán hàng, như thay đổi trong đó bán, ngày, thủ quỹ, v.v. –
Luis, đó là vấn đề đối với lớp trình bày không phải BL. Lớp trình bày nên tập hợp tất cả thông tin cần thiết. Vì vậy, trong trường hợp của bạn, bạn có thể lấy đối tượng bán hàng từ đối tượng tính toán và có tất cả thông tin. – whosrdaddy
Luis - nếu một ORM đang buộc bạn phải làm điều đó, thì có thể bạn cần xem xét sử dụng một ORM khác. Đó là thiết kế tồi tệ - một Bán nên không biết gì về Workshift nơi nó xảy ra. Điều gì sẽ xảy ra nếu bạn muốn bán mọi thứ từ bất kỳ Workshift nào? –