Đối tượng truyền dữ liệu là gì?


217

Đối tượng truyền dữ liệu là gì?

Trong MVC là các lớp mô hình DTO, và nếu không thì sự khác biệt là gì và chúng ta có cần cả hai không?


@ yegor256 và thực tế, cuốn sách trong bài viết đó biết cách lấy dữ liệu từ API và cả cách lưu trữ dữ liệu vào DB, và vì vậy vi phạm SRP, có ổn không?
Betlista

Câu trả lời:


222

Đối tượng truyền dữ liệu là một đối tượng được sử dụng để đóng gói dữ liệu và gửi nó từ một hệ thống con của ứng dụng này sang hệ thống khác.

Các DTO được sử dụng phổ biến nhất bởi lớp Dịch vụ trong ứng dụng N-Tier để truyền dữ liệu giữa chính nó và lớp UI. Lợi ích chính ở đây là nó làm giảm lượng dữ liệu cần gửi qua dây trong các ứng dụng phân tán. Họ cũng tạo ra các mô hình tuyệt vời trong mô hình MVC.

Một cách sử dụng khác cho DTO có thể là đóng gói các tham số cho các cuộc gọi phương thức. Điều này có thể hữu ích nếu một phương thức có nhiều hơn 4 hoặc 5 tham số.

Khi sử dụng mẫu DTO, bạn cũng sẽ sử dụng các bộ lắp ráp DTO. Các trình biên dịch được sử dụng để tạo DTO từ các Đối tượng Miền và ngược lại.

Việc chuyển đổi từ Đối tượng miền sang DTO và quay lại có thể là một quá trình tốn kém. Nếu bạn không tạo một ứng dụng phân tán, có lẽ bạn sẽ không thấy bất kỳ lợi ích tuyệt vời nào từ mẫu này, như Martin Fowler giải thích ở đây


7
"DTO tạo ra các mô hình tuyệt vời trong mẫu MVC" - nhưng không phải mô hình chứa tất cả dữ liệu của đối tượng và DTO có được tối ưu hóa với một phần dữ liệu không? Nếu tôi có mô hình A và tôi cần chuyển nó sang hai hệ thống con thì sẽ có A_DTO_1 và A_DTO_2 với các trường có liên quan của mỗi hệ thống? "Các DTO có thể đóng gói các tham số cho các cuộc gọi phương thức" -> Vì vậy, mọi lớp bao bọc các tham số là DTO ngay cả khi đây không phải là hệ thống phân tán? Không phải các mô hình trong MVC là đối tượng miền?
Yaron Naveh

2
Trả lời câu hỏi đầu tiên của bạn, tôi không nghĩ đã nói về điều tương tự. Mô hình trong MVC không nhất thiết phải là một lớp từ Mô hình miền của bạn. Đã nói rằng, nó cũng có thể được. Sử dụng DTO loại bỏ tất cả những thứ không cần thiết. Chỉ phụ thuộc vào kiến ​​trúc bạn sẽ làm. Tôi không chắc chắn chính xác làm thế nào để trả lời câu hỏi thứ hai của bạn. Cho dù nó có ở bên kia dây hay không, nó vẫn là một đối tượng đóng gói một loạt dữ liệu được truyền giữa các hệ thống (phụ), vì vậy tôi cho rằng đó là DTO.
Benny Hallett

12
"Một cách sử dụng khác cho các DTO có thể là đóng gói các tham số cho các cuộc gọi phương thức. Điều này có thể hữu ích nếu một phương thức có nhiều hơn 4 hoặc 5 tham số." Đây thực sự là một mô hình chống được gọi là lớp Poltergeist hoặc Gypsy Wagon. Nếu phương thức của bạn cần 4 đối số thì cung cấp cho nó 4, đừng tạo một lớp chỉ để di chuyển một đối tượng thành phương thức hoặc một lớp.
Wix

2
@Wix, điểm tốt. Tuy nhiên, tôi tranh luận rằng điều này là ổn nếu nó đúng về mặt ngữ nghĩa (giả sử nếu bạn vượt qua một lớp cài đặt với các thuộc tính chứ không phải chính các thuộc tính là giá trị). Những gì bạn không nên làm là ném vào tất cả các lý lẽ để vượt qua một đối tượng, vì chúng rất có thể không liên quan và gây ra những cơn ác mộng gỡ rối sau này.
Aram Kocharyan

3
Không nên sử dụng các DTO để đóng gói các tham số cho các cuộc gọi phương thức (sẽ biến chúng thành LocalDTO), chúng được giới thiệu trong ngữ cảnh của các giao diện từ xa: martinfowler.com/bliki/LocalDTO.html
Rui

28

Định nghĩa cho DTO có thể được tìm thấy trên trang web của Martin Fowler . DTO được sử dụng để chuyển tham số sang các phương thức và dưới dạng các kiểu trả về. Rất nhiều người sử dụng những người trong UI, nhưng những người khác thổi phồng các đối tượng miền từ họ.


22

Một DTO là một đối tượng ngu ngốc - nó chỉ giữ các thuộc tính và có getters và setters, nhưng không có logic nào khác có ý nghĩa (ngoài việc thực hiện so sánh () hoặc bằng ()).

Thông thường các lớp mô hình trong MVC (giả sử .net MVC ở đây) là các DTO hoặc các bộ sưu tập / tổng hợp của các DTO


3
Những gì bạn đang mô tả là một LocalDTO: martinfowler.com/bliki/LocalDTO.html
Rui

3
Một trường hợp rất hữu ích khi sử dụng một cái gì đó giống như DTO là khi bạn có sự không phù hợp đáng kể giữa mô hình trong lớp trình bày của bạn và mô hình miền bên dưới. Trong trường hợp này, sẽ hợp lý khi tạo mặt tiền / cổng cụ thể trình bày ánh xạ từ mô hình miền và trình bày một giao diện thuận tiện cho việc trình bày.
Amitābha

14

Trong các đối tượng giá trị chung nên là bất biến. Giống như các đối tượng Integer hoặc String trong Java. Chúng ta có thể sử dụng chúng để chuyển dữ liệu giữa các lớp phần mềm. Nếu các lớp phần mềm hoặc dịch vụ chạy trong các nút từ xa khác nhau như trong môi trường microservice hoặc trong Ứng dụng Java Enterprise kế thừa. Chúng ta phải tạo ra các bản sao gần như chính xác của hai lớp. Đây là nơi chúng tôi đã gặp DTOs.

|-----------|                                                   |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------|                                                   |--------------|

Trong các hệ thống Java Enterprise DTO có thể có nhiều công cụ EJB khác nhau trong đó.

Tôi không biết đây có phải là cách thực hành tốt nhất hay không nhưng cá nhân tôi sử dụng Đối tượng giá trị trong các dự án khởi động / khởi động Spring như thế này:

        |------------|         |------------------|                             |------------|
-> Form |            | -> Form |                  | -> Entity                   |            |
        | Controller |         | Service / Facade |                             | Repository |
<- View |            | <- View |                  | <- Entity / Projection View |            |
        |------------|         |------------------|                             |------------|

Lớp điều khiển không biết thực thể là gì. Nó giao tiếp với FormXem các đối tượng giá trị . Đối tượng biểu mẫu có chú thích xác thực JSR 303 (ví dụ @NotNull) và Xem đối tượng giá trị có chú thích Jackson để tuần tự hóa tùy chỉnh. (ví dụ @JsonIgnore)

Lớp dịch vụ giao tiếp với lớp kho lưu trữ thông qua việc sử dụng Đối tượng thực thể. Các đối tượng thực thể có chú thích JPA / Hibernate / Spring Data trên đó. Mỗi lớp giao tiếp với chỉ lớp dưới. Giao tiếp giữa các lớp bị cấm vì phụ thuộc vòng / chu kỳ.

User Service ----> XX CANNOT CALL XX ----> Order Service

Một số ORM Khung có khả năng trình chiếu thông qua việc sử dụng các giao diện hoặc lớp bổ sung. Vì vậy, kho lưu trữ có thể trả về Xem đối tượng trực tiếp. Ở đó cho bạn không cần một chuyển đổi bổ sung.

Ví dụ, đây là thực thể Người dùng của chúng tôi:

@Entity
public final class User {
    private String id;
    private String firstname;
    private String lastname;
    private String phone;
    private String fax;
    private String address;
    // Accessors ...
}

Nhưng bạn nên trả về một danh sách người dùng được bao gồm chỉ bao gồm id, tên, họ. Sau đó, bạn có thể tạo Đối tượng xem giá trị cho phép chiếu ORM.

public final class UserListItemView {
    private String id;
    private String firstname;
    private String lastname;
    // Accessors ...
}

Bạn có thể dễ dàng nhận được kết quả phân trang từ lớp kho lưu trữ. Nhờ vào mùa xuân, bạn cũng có thể sử dụng chỉ các giao diện cho các phép chiếu.

List<UserListItemView> find(Pageable pageable);

Đừng lo lắng cho BeanUtils.copyphương pháp hoạt động chuyển đổi khác hoạt động tốt.


11
  1. Đối với tôi câu trả lời tốt nhất cho câu hỏi DTO là gì là DTO là những đối tượng đơn giản không chứa bất kỳ logic kinh doanh hoặc phương thức triển khai nào cần phải thử nghiệm .
  2. Thông thường mô hình của bạn (sử dụng mẫu MVC) là các mô hình thông minh và chúng có thể chứa rất nhiều / một số phương thức thực hiện một số thao tác khác nhau cho mô hình đó một cách cụ thể (không phải logic nghiệp vụ, điều này nên có ở các bộ điều khiển). Tuy nhiên, khi bạn chuyển dữ liệu (ví dụ: gọi điểm cuối REST ( GET/ POST/ bất cứ thứ gì) từ một nơi nào đó hoặc sử dụng dịch vụ web bằng cách sử dụng SOA, v.v.), bạn không muốn truyền đối tượng có kích thước lớn bằng mã không cần thiết cho điểm cuối, sẽ tiêu thụ dữ liệu và làm chậm quá trình chuyển.

Tại sao logic kinh doanh phải nằm trong bộ điều khiển?
AlexioVay

6

Với các đối tượng truyền dữ liệu MVC thường được sử dụng để ánh xạ các mô hình miền đến các đối tượng đơn giản hơn mà cuối cùng sẽ được hiển thị bởi khung nhìn.

Từ Wikipedia :

Đối tượng truyền dữ liệu (DTO), trước đây gọi là đối tượng giá trị hoặc VO, là một mẫu thiết kế được sử dụng để truyền dữ liệu giữa các hệ thống con ứng dụng phần mềm. DTO thường được sử dụng cùng với các đối tượng truy cập dữ liệu để lấy dữ liệu từ cơ sở dữ liệu.


3
Một đối tượng giá trị không phải là DTO .
coderpc

0

Đối tượng truyền dữ liệu (DTO) mô tả về một đối tượng mang dữ liệu giữa các quy trình, (Wikipedia) hoặc một đối tượng, được sử dụng để đóng gói dữ liệu và gửi nó từ một hệ thống con của ứng dụng tới một hệ thống khác (Câu trả lời chồng chéo).


0

DefN

Một DTO là một mô hình dữ liệu được hóa cứng. Nó chỉ giải quyết vấn đề mô hình hóa một bản ghi dữ liệu được xử lý bởi một mã hóa cứng quy trình sản xuất được hóa cứng, trong đó tất cả các trường được biết tại thời gian biên dịch và do đó được truy cập thông qua các thuộc tính được gõ mạnh.

Ngược lại, một mô hình động hoặc "túi tài sản" giải quyết vấn đề mô hình hóa một bản ghi dữ liệu khi quy trình sản xuất được tạo khi chạy.

Người Cvar

Một DTO có thể được mô hình hóa với các trường hoặc thuộc tính, nhưng ai đó đã phát minh ra một thùng chứa dữ liệu rất hữu ích được gọi là Cvar. Nó là một tham chiếu đến một giá trị. Khi một DTO được mô hình hóa với những gì tôi gọi là thuộc tính tham chiếu , các mô-đun có thể được cấu hình để chia sẻ bộ nhớ heap và do đó cộng tác với nó. Điều này loại bỏ hoàn toàn thông số truyền và giao tiếp O2O từ mã của bạn. Nói cách khác, các DTO có thuộc tính tham chiếu cho phép mã đạt được khớp nối bằng không .

    class Cvar { ... }

    class Cvar<T> : Cvar
    {
        public T Value { get; set; }
    }

    class MyDTO
    {
        public Cvar<int> X { get; set; }
        public Cvar<int> Y { get; set; }
        public Cvar<string> mutableString { get; set; } // >;)
    }

Nguồn: http://www.powersemantics.com/

DTO động là một thành phần cần thiết cho phần mềm động. Để khởi tạo một quy trình động, một bước biên dịch là liên kết mỗi máy trong tập lệnh với các thuộc tính tham chiếu mà tập lệnh xác định. Một DTO động được xây dựng bằng cách thêm Cvars vào bộ sưu tập.

    // a dynamic DTO
    class CvarRegistry : Dictionary<string, Cvar> { }

Sự tranh chấp

Lưu ý: vì Wix đã gắn nhãn việc sử dụng DTO để tổ chức các tham số dưới dạng "chống mẫu", tôi sẽ đưa ra ý kiến ​​có thẩm quyền.

    return View(model);  // MVC disagrees

Kiến trúc hợp tác của tôi thay thế các mẫu thiết kế. Tham khảo các bài viết trên web của tôi.

Các thông số cung cấp kiểm soát ngay lập tức của một máy khung stack. Nếu bạn sử dụng điều khiển liên tục và do đó không cần điều khiển ngay lập tức, các mô-đun của bạn không cần tham số. Kiến trúc của tôi không có. Cấu hình trong quá trình của máy (phương thức) thêm độ phức tạp nhưng cũng có giá trị (hiệu suất) khi các tham số là loại giá trị. Tuy nhiên, các tham số loại tham chiếu làm cho bộ nhớ cache của người tiêu dùng bị mất để lấy các giá trị khỏi heap - do đó, chỉ cần định cấu hình cho người tiêu dùng với các thuộc tính tham chiếu. Thực tế từ kỹ thuật cơ khí: sự phụ thuộc vào các tham số là một loại tiền xử lý, bởi vì bản thân việc xử lý (chế tạo linh kiện) là lãng phí. Tham khảo bài viết W của tôi để biết thêm thông tin. http://www.powersemantics.com/w.html .

Fowler và công ty có thể nhận ra lợi ích của DTO bên ngoài kiến ​​trúc phân tán nếu họ từng biết bất kỳ kiến ​​trúc nào khác. Lập trình viên chỉ biết hệ thống phân tán. Các hệ thống hợp tác tích hợp (hay còn gọi là sản xuất hay sản xuất) là thứ tôi phải tự nhận là kiến ​​trúc của riêng mình, vì tôi là người đầu tiên viết mã theo cách này.

Một số người coi DTO là một mô hình miền thiếu máu, có nghĩa là nó thiếu chức năng, nhưng điều này giả định rằng một đối tượng phải sở hữu dữ liệu mà nó tương tác. Mô hình khái niệm này sau đó buộc bạn cung cấp dữ liệu giữa các đối tượng, đây là mô hình để xử lý phân tán. Tuy nhiên, trên một dây chuyền sản xuất, mỗi bước có thể truy cập vào sản phẩm cuối cùng và thay đổi nó mà không cần sở hữu hoặc kiểm soát nó. Đó là sự khác biệt giữa xử lý phân tán và tích hợp. Sản xuất tách sản phẩm từ hoạt động và hậu cần.

Không có gì sai với việc xử lý mô hình hóa như một nhóm nhân viên văn phòng vô dụng, những người gửi e-mail làm việc cho nhau mà không giữ dấu vết e-mail, ngoại trừ tất cả các công việc làm thêm và đau đầu mà nó tạo ra trong việc xử lý các vấn đề hậu cần và trả lại. Một quy trình phân tán được mô hình hóa đúng sẽ gắn một tài liệu (định tuyến hoạt động) vào sản phẩm mô tả các hoạt động mà nó đến và sẽ đi đến. Định tuyến hoạt động là một bản sao của định tuyến nguồn quy trình, được viết trước khi quá trình bắt đầu. Trong trường hợp có lỗi hoặc thay đổi khẩn cấp khác, định tuyến hoạt động được sửa đổi để bao gồm các bước hoạt động mà nó sẽ được gửi đến. Điều này sau đó chiếm tất cả các lao động đã đi vào sản xuất.

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.