簡體   English   中英

ServiceStack請求和響應對象

[英]ServiceStack Request and Response Objects

是否可以(閱讀良好實踐)重復使用POCO進行請求和響應DTO。 我們的POCO是輕量級的(ORM Lite),只有屬性和一些裝飾屬性。

或者,我應該為請求和/或響應創建其他對象嗎?

謝謝,

我會說這取決於你的系統,最終它有多大和復雜,並且有可能成為。

ServiceStack文檔未指定您應使用的設計模式。 最終,它提供了將數據庫模型POCO與DTO分離的靈活性,但它也為它們的重用提供了支持。

使用OrmLite時:

OrmLite的設計使您可以將數據模型POCO重新用作請求和響應DTO。 從ServiceStack文檔中可以看出 ,這是框架的有意設計目標:

Micro ORMS中使用的POCO特別適合作為DTO重新使用,因為它們不包含重ORM具有的任何循環引用(例如EF)。 OrmLite更進一步,從NoSQL的劇本借閱頁面,其中任何復雜的屬性,例如List在無模式文本字段中透明地膨脹,促進了RDBMS關注不受限制的無摩擦Pure POCOS的設計。

考慮:

如果您確實選擇重新使用您的POCO,因為它受支持,您應該知道在某些情況下使用單獨的請求和響應DTO會更聰明。

在許多情況下,這些POCO數據模型已經形成了良好的DTO,可以直接返回,而不是映射到特定於域的DTO。

^並非所有情況 有時候選擇設計模式的難度是預見到它可能不適合重復使用的情況。 所以希望情景有助於說明潛在的問題。

場景:

  • 您有一個系統,用戶可以在其中注冊您的服務。
  • 作為管理員,您可以列出服務的用戶。

如果你采用OrmLite POCO重用方法,那么我們可能會有這個User POCO:

public class User
{
    [PrimaryKey, AutoIncrement, Alias("Id")]
    public int UserId { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string Salt { get; set; }
    public bool Enabled { get; set; }
}

當您創建“創建用戶”請求時,您將User POCO的UsernamePassword填充為對服務器的請求。

我們不能只是將這個POCO推送到數據庫中,因為:

  • Password字段中的Password為純文本。 我們是優秀的程序員,安全性很重要,因此我們需要創建一個salt,我們將其添加到Salt屬性中,並使用salt哈希Password並更新Password字段。 好吧,這不是一個主要問題,幾行代碼將在插入之前對其進行排序。

  • 客戶端可能已設置UserId ,但對於create,這不是必需的,並且將導致我們的數據庫查詢無法插入。 因此我們必須在插入數據庫之前默認此值。

  • Enabled屬性可能已與請求一起傳遞。 如果有人設置了這個怎么辦? 我們只想要處理UsernamePassword ,但現在我們必須考慮影響數據庫插入的其他字段。 類似地,他們可以設置Salt (雖然這不會是一個問題,因為無論如何我們都會覆蓋這個值。)所以現在你已經添加了驗證。

但是現在考慮我們何時返回List<User>

如果您重新使用POCO作為響應類型,則有許多字段不希望暴露給客戶端。 做起來並不聰明:

return Db.Select<User>();

由於您沒有針對列出用戶的緊密目的構建響應,因此需要在邏輯中刪除Password哈希和Salt ,以防止在響應中將其序列化。

還要考慮在注冊用戶期間,作為創建請求的一部分,我們想詢問是否應該發送歡迎電子郵件。 所以我們會更新POCO:

public class User
{
    // Properties as before
    ...
    [Ignore] // This isn't a database field
    public bool SendWelcomeEmail { get; set; }
}

我們現在擁有僅在用戶創建過程中有用的附加屬性。 如果您反復使用User POCO,您會發現隨着時間的推移,您添加的內容越來越多,不適用於某些上下文。

例如,當我們返回用戶列表時,現在可以填充SendWelcomeEmail的可選屬性 - 它只是沒有意義。 然后很難維護代碼。

要記住的一個關鍵事項是,在共享POCO對象時,它既可以用作請求對象,也可以用作響應對象: 作為響應發送的屬性將在請求中公開。 您將不得不對請求進行更多驗證,最終共享POCO可能無法節省成本。

在這種情況下,做起來不會容易得多:

public class CreateUserRequest
{
    public string Username { get; set; }
    public string Password { get; set; }
    public bool SendWelcomeEmail { get; set; }
}

public class UserResponse
{
    public int UserId { get; set; }
    public string Username { get; set; }
    public bool Enabled { get; set; }
}

public class User
{
    [PrimaryKey, AutoIncrement, Alias("Id")]
    public int UserId { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string Salt { get; set; }
    public bool Enabled { get; set; }
}

我們現在知道當我們創建一個請求( CreateUserRequest )時,我們不必考慮UserIdSaltEnabled

當返回用戶列表時,它現在是List<UserResponse>並且客戶端不可能看到我們不希望他們看到的任何屬性。

其他人看到代碼,請求所需的屬性以及響應中將會暴露的內容,這一點很清楚。

摘要:

對不起,這是一個非常長的答案,但我認為這解決了分享POCO的一個方面,有些人錯過了,或者最初沒有掌握,我就是其中之一。

  • 是的,您可以重復使用POCO進行請求和響應。
  • 文檔說這樣做是可以的。 實際上它是設計的。
  • 在許多情況下,重復使用會很好。
  • 有些情況下它不合適。 (我的場景試圖展示這一點,但是當你發展自己的真實情況時,你會發現。)
  • 考慮可能會暴露多少其他屬性,因為您的共享POCO嘗試支持多個操作,以及可能需要多少額外的驗證工作。
  • 最終,這是關於你很舒服的維護。

希望這可以幫助。

我們有其他方法,我的回答是自以為是。

因為我們不僅使用C#客戶端,而且主要使用JavaScript客戶端。

請求和響應DTO,路由和數據實體之間進行協商

客戶和前端分析師。 它們是詳細形式的規格的一部分。

即使“客戶”,在某些情況下,也是我們的產品UI。

這些DTO在沒有重要原因的情況下不會改變,並且可以在雙方重復使用。

但是數據層中的對象可以是相同的也可以是部分類或不同的,

它們可以在內部更改,包括敏感或工作流信息,

但它們必須與API的規范兼容。

我們首先使用API ,而不是數據庫或ORM。

           Person  { ... }

           Address  { ... }

           ResponceDTO
           { 
             public bool success {get; set;}
             public string message {get; set;}
             public Person  person {get; set;}  
             public List<Address> addresses {get; set;}  
    //customer can use the Person & Address, which can be the same or different
   //with the ones in the data-layer. But we have defined these POCO's  in the specs.                           
            }
           RequestDTO
           { 
             public int Id {get; set;}
             public FilteByAge {get; set;}
            public FilteByZipCode {get; set;}
            }               
           UpdatePersonRequest
           { 
             public int Id {get; set;}
             public bool IsNew {get; set;}
             public Person  person {get; set;} 
             public List<Address> addresses {get; set;}   
            }                  

我們不公開請求或響應DTO。

人員和地址與客戶協商,並在API規范中引用。

它們可以與數據層內部實現相同或部分或不同。

客戶將其用於其應用程序或網站或移動設備。

但重要的是我們首先設計和協商API接口。

我們經常使用requestDTO作為業務層函數的參數,

它返回響應對象或集合。

通過這種方式,服務代碼是業務層前面的瘦包裝器。

        ResponseDTO  Get(RequestDTO  request)
         {
                      return GetPersonData(request);
          }

同樣來自ServiceStack wiki, API-First開發方法

如果您可以公開數據對象的結構(如果這是一個公開使用的API),那么這不會成為問題。 否則,Restsharp將與簡單的POCO一起使用:)

我認為這一切都取決於你如何使用你的DTO,以及你希望如何平衡代碼的可重用性和可讀性。 如果您的請求和響應都使用了DTO上的大部分屬性,那么您將獲得大量的可重用性,而不會降低可讀性。 例如,如果您的請求對象有10個屬性(反之亦然),但您的響應只需要其中的1個,那么如果您的響應對象只有1個屬性,則有人可以提出一個更容易理解/讀取的參數。

總之,良好的做法只是干凈的代碼。 您必須評估您的特定用例,以確定您的代碼是否易於使用和閱讀。 另一種思考方式是為下一個閱讀它的人編寫代碼,即使那個人就是你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM