2012-04-26 4 views
5

좋아, 나는 내 문제에 대해 적절한 해결책을 찾았으며 찾을 수 없었다. 판매 시스템의 일부를 재 설계하고있다. Let's 우리는 다음과 같은 클래스가 있다고 가정계급 법칙을 피하려고 노력하는 계급 의존성을 설계하는 방법

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; 

지금, 나는이 직면하고있는 문제는 데메테르의 법률을 위반하지 않고 최선의 아이디어에 와서 노력하고있다. 내가 달성하기 위해 시도하고있는 다음 새로운 TSale 내가 현재 사용자의 TWorkShift의 판매 목록에 추가 할, 또한 나는 양을 합계를 저장

  1. 때마다 TWorkShift의 "TotalSold"판매.

    접근 A : : // Let's 우리가 ID 1로 작동하는 변화를 가지고와 데이터베이스에서로드되는 가정

    :

I've는 두 개의 서로 다른 접근 방식을 시도 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; 

내가 나에게 바로 느낌이 나던 데메테르의 법칙을 위반하는 생각이 접근 .

나는 코드 단순성을 극대화하고 앞으로 유지 보수가 용이하도록 "올바른 방법"을 찾고 싶습니다. 그래서 어떤 제안이라도 인정 될 것입니다. 당신이 TWorkShift에 판매를 추가하려는 경우, 당신은 즉

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

, TWorkShift가 필요로하는 일에 대해 "요청"해야 있어야한다

감사

답변

3

.

또한 TSALE에는 TWorkShift 필드가있는 이유가 없습니다. Workshift에는 많은 판매가 있지만, 왜 Sale에는 WorkShift가 있습니까?

+0

감사 닉 정보를 얻기 위해, 그럼 나는 아우렐리우스 ORM 프레임 워크를 사용하고이 경우에 그래서는 "협회"가 같은 : '판매 : = Manager.Find (1); ShowMessage ('ID가있는 근무 교대로 판매되었습니다 :'+ IntToStr (Sale.Shift.ID)); ' 때때로 판매에 대한 모든 정보 (판매 변경, 날짜, 계산원 등)를 표시해야하기 때문에 필요합니다. –

+1

Luis, 프레젠테이션 계층에 문제가 있습니다. BL이 아니야. 프리젠 테이션 계층은 필요한 모든 정보를 수집해야합니다. 따라서 귀하의 경우에는 작업 대상에서 판매 오브젝트를 검색하여 모든 정보를 얻을 수 있습니다. – whosrdaddy

+0

Luis - ORM이이를 수행하도록 강요하는 경우 다른 ORM을 사용하는 것이 좋습니다. 그것은 나쁜 디자인입니다. 판매는 발생한 워크 쉬프트에 대해 아무 것도 모를 것입니다. Workshift에서 일을 멀리 팔고 싶다면 어떻게해야할까요? –

0

TList에 항목을 추가 할 때 뭔가 작업을하므로 OnNotify를 사용할 수 있습니다. Aurelius도 해당 이벤트를 사용하고 있는지 알 수 없으므로이를위한 코드를 추가했습니다. 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; 
+0

스테판에게 감사드립니다. 나는이 질문을 게시 한 후 당신의 접근 방식을 시도했다. 의도적으로 작동한다고해도 나는 복잡하게 생각하고 닉의 접근법을 더 쉽고 이해하기 쉽다. 답해 주셔서 감사합니다. 저는 제 실험을 위해 매우 귀중했습니다. –

관련 문제