2012-07-05 25 views
2

我正在研究一個大型項目,其中一部分是要替換現有的服務器堆棧。有了一個規模非常大的數據庫,顯然我們需要構建許多複合對象。我查詢之一的一個例子是這樣的: 我複合對象的定義:關於何時需要特定DTO類的另一個討論

[DataContract] 
public class CompositeEvent 
{ 
    Guid eventIdentity; 
    string accountIdentity; 
    string eventMessage; 
    DateTime eventLoggedOn; 
    string methodName; 
    string programName; 
    string userIdentity; 
    List<CompositeException> exceptions = new List<CompositeException>(); 
    List<CompositeParameter> methodParameters = new List<CompositeParameter>(); 
    List<CompositeParameter> databaseParameters = new List<CompositeParameter>(); 

    [DataMember] 
    public Guid EventIdentity 
    { 
     get { return eventIdentity; } 
     set { eventIdentity = value; } 
    } 
    [DataMember] 
    public string AccountIdentity 
    { 
     get { return accountIdentity; } 
     set { accountIdentity = value; } 
    } 
    [DataMember] 
    public string EventMessage 
    { 
     get { return eventMessage; } 
     set { eventMessage = value; } 
    } 

    [DataMember] 
    public DateTime EventLoggedOn 
    { 
     get { return eventLoggedOn; } 
     set { eventLoggedOn = value; } 
    } 

    [DataMember] 
    public string MethodName 
    { 
     get { return methodName; } 
     set { methodName = value; } 
    } 

    [DataMember] 
    public string ProgramName 
    { 
     get { return programName; } 
     set { programName = value; } 
    } 

    [DataMember] 
    public string UserIdentity 
    { 
     get { return userIdentity; } 
     set { userIdentity = value; } 
    } 

    public string QualifiedCreator 
    { 
     get 
     { 
      if (String.IsNullOrEmpty(programName) && String.IsNullOrEmpty(methodName)) 
       return string.Empty; 
      return string.Format("{0}:{1}", String.IsNullOrEmpty(ProgramName) ? "{undefined}" : ProgramName, String.IsNullOrEmpty(MethodName) ? "{undefined}" : MethodName); 
     } 
    } 
    [DataMember] 
    public int EventTypeIdentity { get; set; } 

    [DataMember] 
    public string EventTypeName { get; set; } 

    [DataMember] 
    public List<CompositeException> Exceptions 
    { 
     get { return exceptions; } 
     set { exceptions = value; } 
    } 

    [DataMember] 
    public List<CompositeParameter> MethodParameters 
    { 
     get { return methodParameters; } 
     set { methodParameters = value; } 
    } 

    [DataMember] 
    public List<CompositeParameter> DatabaseParameters 
    { 
     get { return databaseParameters; } 
     set { databaseParameters = value; } 
    } 
} 

在我的服務我的數據庫查詢:

  using (Framework.Data.FrameworkDataEntities context = new Data.FrameworkDataEntities()) 
     { 
      var list = from item in context.EventLogs 
         join typeName in context.EventLogTypes on item.EventTypeId equals typeName.Id 
         orderby item.EventLoggedOn, item.EventLogType 
         select new CompositeEvent 
         { 
          AccountIdentity = item.AccountIdentity, 
          EventIdentity = item.Id, 
          EventLoggedOn = item.EventLoggedOn, 
          EventMessage = item.EventMessage, 
          EventTypeIdentity = item.EventTypeId, 
          EventTypeName = typeName.EventTypeName, 
          MethodName = item.MethodName, 
          ProgramName = item.ProgramName, 
          UserIdentity = item.UserIdentity 
         }; 
      return new List<CompositeEvent>(list); 
     } 

現在是從我的複合對象的定義明確表示,它只包含數據,沒有業務規則,沒有其他持久性或暴露的業務結構,數據結構或其他任何東西。

然而,我的團隊隊友說這隻能存在於領域模型中,我必須花費週期將我的數據從這個定義良好的對象移動到DTO。不僅如此,而且a)所有的DTO必須在其名稱中包含DTO,並且b)它們只能存在用於通過網絡移動的目的。所以當我們開發客戶端代碼時,它必須a)創建每個對象屬性的屬性,並且b)從DTO移動到視圖模型屬性。

我覺得這是把DTO推向極端。這基於這些ARE數據傳輸對象的複合對象的定義。另外,我看到將此對象存儲在客戶端並直接綁定到客戶端中的此對象時完全沒有問題。由於我所做的全部工作都是將組合對象中定義的每個屬性都複製到DTO中,因此似乎大大浪費了時間和週期來創建一個對象,僅將其複製到另一個對象,然後再次將其複製到內部客戶端的屬性。

我對這個有其他意見。我覺得我沒有違反任何OOP規則,例如分離關注或單一責任原則......至少只要你不對這些問題變得非常肛門化。意見????

回答

2

那麼,你的同事們強調的所有MUST都讓他看起來有點OCD。但沒關係,因爲他確實有一點。

DTO的,特別是在MVC中,應該這樣設計,以便它們抽象底層數據模型,以便它們成爲視圖的實際模型。保持它們靠近對象只會導致您修改兩組對象,當其中只有一組對象實際需要更改時。

在SoA或N層架構中設計DTO時要考慮的另一件事是,它們不應該在視圖層和底層服務和模型之間創建一個契約。因此,如果數據庫中的某些內容(字段,表格,視圖等)發生變化,您應該能夠調整服務層中的所有內容,使得DTO不受影響。

視圖模型應該保持不變,至少只要不添加或刪除它的功能。任何潛在的變化都應該適應DTO(不是一直這樣 - 但並不總是可行的)。

現在我應該提到,我現在正在將一個項目從SoA和DTO切換到一個普通的2層架構(這是因爲性能問題,而不是DTO的:))。我有一個交叉領域層的簡單和複雜的對象,設計爲只能在內部使用。任何暴露的API都將使用DTO,因爲我不想殺死WS消費者。也許傷害他們一點:)。

但是你應該使用DTO,就像我上面提到的那樣。這將有助於你的情況(與MVC)。爲了更方便地映射到DTO,我建議使用AutoMapper。會讓你的生活變得更輕鬆(和你的同事開心)。

+1

我已經使用AutoMapper將數據從複合對象移動到DTO。我發佈的這個例子是我們在架構中包含的技術工具。我們其餘的查詢全部使用Repository,但是填充手工製作的複合對象。所以如果基礎數據結構發生變化,那麼複合對象不會。即使使用此工具,除非UI需要更改,組合對象也不會更改。基本上,正如我的問題所述,與數據層沒有直接關係,因爲組合對象是在查詢中動態構建的。 – 2012-07-05 20:07:22

+0

@SASS_Shooter:好的,聽起來像是一個DTO。但正如你所提到的,你構建了這些複雜對象的「許多」。這導致我得出結論,你沒有爲每個視圖做出這些對象中的一個。所以在一些視圖中,您仍然將其用作模型對象。正確? – 2012-07-05 20:17:01

+0

沒有。基本上每個視圖都有一個複雜的對象。 – 2012-07-05 21:47:28

相關問題