Tại sao các đối tượng truyền dữ liệu (DTO) là một mô hình chống?


132

Gần đây tôi đã tình cờ nghe mọi người nói rằng các đối tượng truyền dữ liệu (DTO) là một mô hình chống .

Tại sao? Các lựa chọn thay thế là gì?


11
Có lẽ bởi vì các đối tượng kinh doanh là chính họ có khả năng vận chuyển dữ liệu của riêng họ cảm ơn bạn rất nhiều!
Zoidberg

13
"Chống mẫu" cũng có thể là ứng cử viên của tôi cho "cụm từ có 15 phút đã được sử dụng từ lâu." Bây giờ đồng nghĩa với "Tôi không quan tâm đến việc biện minh cho suy nghĩ của mình", như "Nó nổi tiếng là ..."
Craig Stuntz

6
Zoidberg, gửi các đối tượng bằng các phương thức qua dây đã cho chúng tôi CORBA, DCOM và các trải nghiệm khác mà tôi cố gắng xóa trí nhớ của mình. Vấn đề là, sớm muộn người ta cũng muốn gọi những phương thức đó.
Craig Stuntz

10
DTOs quán triệt nguyên tắc DRY, mà tiếc là trong J2EE là viết tắt của việc phải làm lặp lại chính mình.
joeforker

Bạn có thể muốn đọc điều này: Đối tượng truyền dữ liệu là một sự xấu hổ
yegor256

Câu trả lời:


139

Một số dự án có tất cả dữ liệu hai lần . Một lần là đối tượng miền, và một lần là đối tượng truyền dữ liệu.

Sự trùng lặp này có chi phí rất lớn , vì vậy kiến ​​trúc cần phải nhận được lợi ích rất lớn từ sự tách biệt này để có giá trị.


5
Xin hãy giải thích về "chi phí rất lớn". Ngoài ra, hãy nói lý do tại sao chi phí không thể được loại bỏ bằng cách sử dụng các kỹ thuật tạo mã để tạo các lớp DTO.
John Saunders

70
+1. Hai lần? Chỉ khi bạn may mắn :-) Các dự án sao chép các thực thể miền như DTO cũng có xu hướng có các hạt UI khác nhau gần như giống nhau nhưng rất tinh tế để bổ sung cho chúng. Đó là 3. Và nếu, chúa cấm, có một số loại điều khiển từ xa (dịch vụ web / xml-rpc / bất cứ điều gì) đang diễn ra, bạn có thể dễ dàng đến 4 hoặc 5.
ChssPly76

17
Tôi hiện đang làm việc với một kiến ​​trúc lasagna 14 lớp enterpricy (KHÔNG KIDDING). Tôi có thể đảm bảo với bạn rằng các lớp 11 hoặc hơn chủ yếu dành cho bộ truyền dữ liệu không miễn phí.
KarlP

10
Ngoài ra, trong khi tôi hoàn toàn yêu thích các trình tạo mã khi làm việc với các thiết kế ngu ngốc, thì chúng là một) điều chắc chắn rằng bạn đang làm sai khi bắt đầu. b) họ không đến miễn phí.
KarlP

7
Xin lỗi, nhưng điều này chỉ không chính xác và câu trả lời sai đã được bình chọn cao và được chấp nhận. Trước hết, bạn có thể sử dụng sự phản chiếu để tạo DTO một cách nhanh chóng. Thứ hai, bạn có thể sử dụng "định nghĩa gốc", ví dụ như trong hệ thống CASE hoặc trong oAW và tạo BO và DTO (s). Thứ ba, bạn có thể sử dụng XSD và JAXB để tạo DTO và sử dụng DTO làm cơ sở cho BO hoặc bạn có thể tạo cả hai từ XSD ... dù sao đi nữa, nếu có ai dám chuyển EJB mới được nạp từ DB qua kết nối với chương trình khách hàng ... trong môi trường tôi làm việc, đầu anh ấy sẽ nằm trên một tấm bạc khá sớm ...
Angel O'Sphere

128

DTO không phải là một mô hình chống. Khi bạn gửi một số dữ liệu qua mạng (giả sử, đến một trang web trong cuộc gọi Ajax), bạn muốn chắc chắn rằng bạn tiết kiệm băng thông bằng cách chỉ gửi dữ liệu mà đích sẽ sử dụng. Ngoài ra, thường thì thuận tiện cho lớp trình bày có dữ liệu ở định dạng hơi khác so với đối tượng kinh doanh gốc.

Tôi biết đây là một câu hỏi hướng Java, nhưng trong các ngôn ngữ .NET, các kiểu ẩn danh, tuần tự hóa và LINQ cho phép các DTO được xây dựng nhanh chóng, giúp giảm việc thiết lập và sử dụng chúng.


15
@ John, Điều này không chính xác. Tôi làm nó suốt. Tuần tự hóa sử dụng sự phản chiếu, hoạt động tốt trên các loại ẩn danh. Chỉ cần chuyển nó đến serializer như một đối tượng. Và một khi nó được tuần tự hóa (ví dụ xml hoặc json), tất nhiên bạn có thể trả về nó từ một phương thức.
Gabe Moothart

8
Ừm, John, điều đó không đúng. Bạn có thể tuần tự hóa các loại ẩn danh thành JSON. Hãy thử nó trong một ứng dụng MVC: return Json (new {Foo = "Xin chào!}); Tôi hứa với bạn rằng nó hoạt động tốt. Có lẽ, tốt hơn so với các loại không ẩn danh, vì các loại ẩn danh thường không có chu kỳ trong biểu đồ đối tượng của chúng , phá vỡ trình tuần tự hóa JSON.
Craig Stuntz

1
Json serialization không phải là một DTO theo nghĩa này, và do đó không áp dụng. Sau đó, tất nhiên, các lý lẽ của tôi ở trên cũng áp dụng, đến một lúc nào đó, chúng chỉ dừng lại ở việc có giá trị.
Jim Barrow

1
Gabe đã đúng, DTO không phải là một mẫu chống lại (nhưng có thể nếu được sử dụng không chính xác!) Khi không có sự trùng lặp dữ liệu. Ví dụ: BO có thể tổng hợp dữ liệu từ các nguồn khác nhau thành DTO.
astro

3
+1. Và còn nhiều lý do khác ngoài việc bảo tồn băng thông mà bạn sẽ muốn DTOs. Bạn thậm chí có ĐƯỢC PHÉP (theo chính sách của công ty hoặc luật pháp) để gửi mọi lĩnh vực qua dây không? Ngoài ra, trong công ty của chúng tôi, DAO của chúng tôi rất phức tạp vì nó cần thực hiện tất cả những tối ưu hóa này - hoạt động trong tầng dịch vụ, tôi thực sự rất vui khi họ sử dụng DTO và không khiến chúng tôi lo lắng về mối quan hệ mà Object X có đến một số bảng n-to-n khác.
dùng64141

25

DTO một AntiPotype trong EJB 3.0 nói:

Bản chất nặng của Đậu Entity trong thông số kỹ thuật EJB trước EJB 3.0, dẫn đến việc sử dụng các mẫu thiết kế như Đối tượng truyền dữ liệu (DTO). Các DTO đã trở thành các đối tượng nhẹ (đáng lẽ là hạt đậu thực thể ở vị trí đầu tiên), được sử dụng để gửi dữ liệu qua các tầng ... giờ đây, thông số EJB 3.0 tạo ra mô hình Entity bean giống như đối tượng Java cũ (POJO). Với mô hình POJO mới này, bạn sẽ không còn cần phải tạo DTO cho từng thực thể hoặc cho một tập hợp các thực thể ... Nếu bạn muốn gửi các thực thể EJB 3.0 trên tầng, hãy thực hiện chúng chỉ cần thực hiện java.io.Serialiazable


6
Đúng khi bạn chuyển đối tượng giữa các phương thức trong cùng một JVM, trong bộ nhớ. Không đúng khi bạn thực sự tuần tự hóa qua dây và muốn kiểm soát mức độ sâu để tuần tự hóa và / hoặc duy trì tải lười biếng.
wrschneider

Có, và ngay cả trong cùng một JVM, bạn thực sự nên cẩn thận ở cùng một vị trí nếu bạn sử dụng quản lý giao dịch JEE / Spring.
Marc

20

Tôi không nghĩ rằng các DTO là một mô hình chống lại mỗi se, nhưng có các phản hạt liên quan đến việc sử dụng các DTO. Bill Dudney đề cập đến vụ nổ DTO là một ví dụ:

http://www.softwaresummit.com/2003/speaker/DudneyJ2EEAntiPotypes.pdf

Ngoài ra còn có một số lạm dụng DTO được đề cập ở đây:

http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-potype-in-java-world/

Chúng có nguồn gốc do ba hệ thống cấp (thường sử dụng EJB làm công nghệ) làm phương tiện để truyền dữ liệu giữa các tầng. Hầu hết các hệ thống Java hiện đại dựa trên các khung công tác như Spring đều có chế độ xem đơn giản hóa thay thế bằng cách sử dụng POJO làm đối tượng miền (thường được chú thích bằng JPA, v.v.) trong một tầng duy nhất ... Việc sử dụng DTO ở đây là không cần thiết.


3
Bạn hoàn toàn đúng khi nói rằng DTO là một mẫu tốt , không phải là mẫu chống, khi được sử dụng trong bối cảnh thích hợp của chúng. Liên kết thứ hai của bạn dường như đã chết ngay bây giờ, nhưng sự lạm dụng lớn nhất mà tôi đã thấy là nơi mọi đối tượng miền có "DTO" tương ứng cho cơ sở dữ liệu tương tác không có giá trị và hoàn toàn không phải là DTO!
David

19

Những người theo chủ nghĩa thuần túy OO sẽ nói rằng DTO là chống mẫu vì các đối tượng trở thành biểu diễn bảng dữ liệu thay vì các đối tượng miền thực.


9

Một số người coi DTO là một mô hình chống do lạm dụng có thể có của họ. Chúng thường được sử dụng khi chúng không nên / không cần phải như vậy.

Bài viết này mơ hồ mô tả một số lạm dụng.


1
Bài viết mô tả chính xác hơn nhiều về DTO như một mô hình có thể bị lạm dụng.
Craig Stuntz

Điều này có nghĩa là một câu trả lời chỉ liên kết, nó thực sự cần ít nhất một trích dẫn từ bài viết. không biết làm thế nào điều này được quản lý để không bị gắn cờ là Không trả lời.
Nathan Hughes


7

Nếu bạn đang xây dựng một hệ thống phân tán, thì DTOs chắc chắn không phải là một mô hình chống. Không phải ai cũng sẽ phát triển theo nghĩa đó, nhưng nếu bạn có một ứng dụng Xã hội mở (ví dụ) thì tất cả đều chạy JavaScript.

Nó sẽ đăng tải dữ liệu lên API của bạn. Điều này sau đó được giải tuần tự hóa thành một số dạng đối tượng, điển hình là đối tượng DTO / Request. Điều này sau đó có thể được xác nhận để đảm bảo dữ liệu được nhập là chính xác trước khi được chuyển đổi thành một đối tượng mô hình.

Theo tôi, nó được coi là một mô hình chống vì nó được sử dụng sai. Nếu bạn không xây dựng một hệ thống phân tán, rất có thể bạn không cần chúng.


4

Mục đích của Đối tượng truyền dữ liệu là lưu trữ dữ liệu từ các nguồn khác nhau và sau đó chuyển dữ liệu vào cơ sở dữ liệu (hoặc Mặt tiền từ xa ) cùng một lúc.

Tuy nhiên, mẫu DTO vi phạm Nguyên tắc Trách nhiệm duy nhất , vì DTO không chỉ lưu trữ dữ liệu mà còn chuyển dữ liệu từ hoặc đến cơ sở dữ liệu / mặt tiền.

Sự cần thiết phải tách các đối tượng dữ liệu khỏi các đối tượng kinh doanh không phải là một antipotype, vì có lẽ nó được yêu cầu để tách lớp cơ sở dữ liệu .

Thay vì DTO, bạn nên sử dụng Mẫu tổng hợp và Kho lưu trữ, phân tách bộ sưu tập các đối tượng ( Tổng hợp ) và truyền dữ liệu ( Kho lưu trữ ).

Để chuyển một nhóm đối tượng, bạn có thể sử dụng mẫu Đơn vị công việc , chứa một bộ Kho lưu trữ và bối cảnh giao dịch; để chuyển từng đối tượng trong tổng hợp riêng trong giao dịch.


4

DTO trở thành một điều cần thiết và không phải là BỆNH NHÂN khi bạn có tất cả các đối tượng miền của mình tải các đối tượng liên quan EAGERly.

Nếu bạn không tạo DTO, bạn sẽ có các đối tượng được chuyển không cần thiết từ lớp doanh nghiệp sang lớp máy khách / web của bạn.

Để hạn chế chi phí cho trường hợp này, thay vì chuyển DTO.


1

Câu hỏi không nên là "tại sao", mà là " khi nào ".

Chắc chắn đó là mô hình chống khi chỉ sử dụng kết quả là chi phí cao hơn - thời gian chạy hoặc bảo trì. Tôi đã làm việc trên các dự án có hàng trăm DTO giống hệt với các lớp thực thể cơ sở dữ liệu. Mỗi lần bạn muốn thêm một trường mà bạn quảng cáo để thêm id như bốn lần - vào DTO, thành thực thể, để chuyển đổi từ DTO sang các lớp hoặc thực thể miền, chuyển đổi ngược lại, ... Bạn đã quên một số vị trí và dữ liệu nhận được không nhất quán

không chống mẫu khi bạn thực sự cần sự đại diện khác nhau của các lớp miền - phẳng hơn, giàu hơn, hẹp hơn, ...

Cá nhân tôi bắt đầu với lớp tên miền và vượt qua nó, với kiểm tra thích hợp ở đúng nơi. Tôi có thể chú thích và / hoặc thêm một số lớp "người trợ giúp" để tạo ánh xạ, vào cơ sở dữ liệu, cho các định dạng tuần tự hóa như JSON hoặc XML ... Tôi luôn có thể chia một lớp thành hai nếu tôi cảm thấy cần.

Đó là về quan điểm của bạn - Tôi thích xem một đối tượng miền là một đối tượng duy nhất đóng nhiều vai trò khác nhau, thay vì nhiều đối tượng được tạo từ nhau. Nếu vai trò duy nhất mà một đối tượng có là vận chuyển dữ liệu, thì đó là DTO.


1

Tôi nghĩ mọi người có nghĩa là nó có thể là một mô hình chống nếu bạn triển khai tất cả các đối tượng từ xa dưới dạng DTO. DTO chỉ đơn thuần là một tập hợp các thuộc tính và nếu bạn có các đối tượng lớn, bạn sẽ luôn chuyển tất cả các thuộc tính ngay cả khi bạn không cần hoặc không sử dụng chúng. Trong trường hợp sau thích sử dụng mẫu Proxy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.