[PoEAA] Learning Notes of Data Transfer Object
Data Transfer Object,故名思義,就是用來傳輸數據的對象。
在一個進程內,方法的調用是非常快的,但不同的進程間的調用卻慢的多,尤其在分布式應用程序中,遠程過程調用是非常耗時的,為了提高效率,我們就想到在每一次的調用中,盡可能傳輸多的數據(如果頻繁調用,而每次調用都只傳輸很小的數據量,比如第一次調用為了取得一篇文章的作者姓名,第二次調用為了取得作者所在的城市,那開銷是非常大的)。
在MSDN中有文章提到:
In modern IP routing-based networks (for example, the Internet), latency can be a bigger factor than throughput. That means it may take almost the same amount of time to transmit 10 bytes of data as it takes to transmit 1,000 bytes of data. This effect is particularly pronounced when using connectionless protocols such as HTTP. Faster networks can often increase the throughput(吞吐量), but latency(延遲) is much more difficult to reduce.
從上也可以看出,即使我們每次調用時傳輸很少的數據量,效率也不會有多大提升。
為了在一次調用中傳輸更多的數據,我們可以很自然的想到通過傳遞許多的參數,但是,想象一下,假如我們給遠程過程傳遞了10個字符串參數,那很可能會出錯的(比如在編程時把第二個和第三個參數寫反了),而如果要返回多個參數,那更是不可能的。
于是,Data Transfer Object (DTO) 出場了。它把前面講到的方法參數都抽過來當作自己的值域,并對它們設置getter和setter,這就是DTO,它是一個簡單的數據結構,沒有程序邏輯,它的任務就是以比較方便的方式讓遠程調用時能一次傳輸更多的數據。比如前面的那個場景,就可以把文章的標題,作者姓名,作者所在城市都放在DTO中,然后分別設置getter和setter。
DTO的值域要是很簡單的類型,因為要保證客戶端和服務器端都能輕松地認識它們,DTO更不該包含許多業務邏輯,它的目的就是用來在遠程過程調用時傳輸數據的。
DTO的值域一般都是從多個領域對象(Domain Object)中而來,比如前面的場景,那個DTO的值域就是從文章類和作者類中而來。
DTO一般是為了專門的客戶端用途而設計的,比如一個網頁要顯示的內容,一個GUI,同樣,這會使得在遠程調用很頻繁卻又不是都調用同樣方法時,為了遠程調用而設計大量的DTO,同時也要消耗體力去編寫這些DTO(當然也可以用代碼生成工具)
。
我們不應該讓領域對象依賴DTO,也不該在DTO中加入許多計算邏輯,所以,為了聯系DTO和領域對象,往往會有一個Assembler作為中間人:

上圖來自MSDN
但是這么一來,Assembler就過分依賴了DomainObject和DTO,Domain Object和DTO的改動都會影響到Assembler。
參考資料:
1. Martin Fowler : "Patterns of Enterprise Application Architecture";
2. MSDN : Data Transfer Object, http://msdn.microsoft.com/en-us/library/ms978717.aspx
浙公網安備 33010602011771號