[英]ServiceStack Request and Response Objects
是否可以(閱讀良好實踐)重復使用POCO進行請求和響應DTO。 我們的POCO是輕量級的(ORM Lite),只有屬性和一些裝飾屬性。
或者,我應該為請求和/或響應創建其他對象嗎?
謝謝,
我會說這取決於你的系統,最終它有多大和復雜,並且有可能成為。
ServiceStack文檔未指定您應使用的設計模式。 最終,它提供了將數據庫模型POCO與DTO分離的靈活性,但它也為它們的重用提供了支持。
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的Username
和Password
填充為對服務器的請求。
我們不能只是將這個POCO推送到數據庫中,因為:
Password
字段中的Password
為純文本。 我們是優秀的程序員,安全性很重要,因此我們需要創建一個salt,我們將其添加到Salt
屬性中,並使用salt哈希Password
並更新Password
字段。 好吧,這不是一個主要問題,幾行代碼將在插入之前對其進行排序。
客戶端可能已設置UserId
,但對於create,這不是必需的,並且將導致我們的數據庫查詢無法插入。 因此我們必須在插入數據庫之前默認此值。
Enabled
屬性可能已與請求一起傳遞。 如果有人設置了這個怎么辦? 我們只想要處理Username
和Password
,但現在我們必須考慮影響數據庫插入的其他字段。 類似地,他們可以設置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
)時,我們不必考慮UserId
, Salt
或Enabled
。
當返回用戶列表時,它現在是List<UserResponse>
並且客戶端不可能看到我們不希望他們看到的任何屬性。
其他人看到代碼,請求所需的屬性以及響應中將會暴露的內容,這一點很清楚。
對不起,這是一個非常長的答案,但我認為這解決了分享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.