Việc sử dụng DTO thay vì Entity là gì?


17

Tôi đang làm việc trên ứng dụng RCP, tôi chưa quen với ứng dụng này.

Đậu mùa xuân được sử dụng để viết logic kinh doanh để lưu / tìm nạp các thực thể.

Nhưng, thay vì gửi các thực thể trực tiếp đến máy khách, chúng tôi đang chuyển đổi sang DTO và ứng dụng khách. Trong khi lưu, chúng tôi lại chuyển đổi DTO thành thực thể và lưu.

Lợi ích của những chuyển đổi này là gì? Ai đó có thể giải thích?


What's the benefit of these conversions?tách mô hình dữ liệu bền vững từ mô hình dữ liệu (đại diện) được cung cấp cho người tiêu dùng. Lợi ích của việc tách rời đã được thảo luận rộng rãi trong SE Tuy nhiên, mục đích bên dưới DTOs là thu thập trong một phản hồi duy nhất khi có nhiều thông tin cần thiết cho khách hàng để lưu các cuộc gọi đến máy chủ. Điều gì làm cho máy khách-máy chủ giao tiếp mượt mà hơn.
Laiv


Ví dụ của bạn là tốt đẹp. Khi bạn là khách hàng (lượt xem ...) rất khó thay đổi, nhưng vấn đề lớn nhất là khi hệ thống đã tích hợp bên thứ 3, điều đó là không thể thay đổi (hợp đồng, phí ...). Nếu hệ thống của bạn sẽ có tích hợp bên thứ ba, hãy sử dụng DTO.
Lucas Gonçalves

Câu trả lời:


43

Bất cứ khi nào một nhà phát triển hỏi "ý nghĩa của việc làm này là gì?", Điều họ thực sự muốn nói là "Tôi thấy không có trường hợp sử dụng nào khi làm việc này mang lại lợi ích". Cuối cùng, hãy để tôi chỉ cho bạn một vài ví dụ.


Tất cả các ví dụ sẽ dựa trên mô hình dữ liệu đơn giản này:

Một Personthực thể có năm thuộc tính:Id, FirstName, LastName, Age, CityId

Và bạn có thể giả định rằng ứng dụng sử dụng dữ liệu này theo nhiều cách khác nhau (báo cáo, biểu mẫu, cửa sổ bật lên, ...).

Toàn bộ ứng dụng đã tồn tại. Tất cả mọi thứ tôi đề cập là một sự thay đổi đối với cơ sở mã hiện có. Điều này rất quan trọng để nhớ.


Ví dụ 1 - Thay đổi cấu trúc dữ liệu cơ bản - Không có DTO

Các yêu cầu đã thay đổi. Độ tuổi của người cần được lấy tự động từ cơ sở dữ liệu của chính phủ (giả sử dựa trên tên và họ của họ).

Vì bạn không cần lưu trữ Agegiá trị cục bộ nữa, do đó, nó cần phải được xóa khỏi Personthực thể. Điều quan trọng ở đây là nhận ra rằng thực thể đại diện cho dữ liệu cơ sở dữ liệu và không có gì nữa. Nếu nó không có trong cơ sở dữ liệu, thì nó không có trong thực thể.
Khi bạn truy xuất tuổi từ dịch vụ web của chính phủ, điều đó sẽ được lưu trữ trong một đối tượng khác (hoặc int).

Nhưng frontend của bạn vẫn hiển thị một tuổi. Tất cả các chế độ xem đã được thiết lập để sử dụng thuộc Person.Agetính, hiện không còn tồn tại. Một vấn đề thể hiện chính nó: Tất cả các quan điểm đề cập đến Agemột người cần phải được sửa chữa .


Ví dụ 2 - Thay đổi cấu trúc dữ liệu cơ bản - Với DTO

Trong hệ thống cũ, cũng có PersonDTOthực thể có cùng năm thuộc tính : Id, FirstName, LastName, Age, CityId. Sau khi lấy a Person, lớp dịch vụ chuyển đổi nó thành a PersonDTOvà sau đó trả về nó.

Nhưng bây giờ, các yêu cầu đã thay đổi. Độ tuổi của người cần được lấy tự động từ cơ sở dữ liệu của chính phủ (giả sử dựa trên tên và họ của họ).

Vì bạn không cần lưu trữ Agegiá trị cục bộ nữa, do đó, nó cần phải được xóa khỏi Personthực thể. Điều quan trọng ở đây là nhận ra rằng thực thể đại diện cho dữ liệu cơ sở dữ liệu và không có gì nữa. Nếu nó không có trong cơ sở dữ liệu, thì nó không có trong thực thể.

Tuy nhiên, kể từ khi bạn có một trung gian PersonDTO, điều quan trọng là để thấy rằng lớp này có thể giữ các Agetài sản. Lớp dịch vụ sẽ tìm nạp Person, chuyển đổi nó thành a PersonDTO, sau đó nó cũng sẽ lấy tuổi của người đó từ dịch vụ web của chính phủ, sẽ lưu trữ giá trị đó PersonDTO.Agevà chuyển đối tượng đó.

Phần quan trọng ở đây là bất kỳ ai sử dụng lớp dịch vụ đều không thấy sự khác biệt giữa hệ thống cũ và hệ thống mới . Điều này bao gồm cả frontend của bạn. Trong hệ thống cũ, nó đã nhận được một PersonDTOđối tượng đầy đủ . Và trong hệ thống mới, nó vẫn nhận được một PersonDTOđối tượng đầy đủ . Các quan điểm không cần phải được cập nhật .

Đây là ý nghĩa của chúng tôi khi chúng tôi sử dụng phân tách cụm từ mối quan tâm : Có hai mối quan tâm khác nhau (lưu trữ dữ liệu trong cơ sở dữ liệu, trình bày dữ liệu cho giao diện) và chúng cần một loại dữ liệu khác nhau. Ngay cả khi hai loại dữ liệu đó có chứa cùng một dữ liệu ngay bây giờ, điều đó có thể thay đổi trong tương lai.
Trong ví dụ đã cho, Agecó một sự khác biệt giữa hai loại dữ liệu: Person(thực thể cơ sở dữ liệu) không cần một loại Age, nhưng PersonDTO(loại dữ liệu lối vào) không cần nó.
Bằng cách tách các mối quan tâm (= tạo các loại dữ liệu riêng biệt) ngay từ đầu, cơ sở mã sẽ linh hoạt hơn nhiều đối với các thay đổi được thực hiện cho mô hình dữ liệu.

Bạn có thể lập luận rằng có một đối tượng DTO, khi một cột mới được thêm vào cơ sở dữ liệu, có nghĩa là bạn phải thực hiện công việc gấp đôi, thêm thuộc tính trong cả thực thể và DTO. Đó là kỹ thuật chính xác. Nó đòi hỏi một chút nỗ lực để duy trì hai lớp thay vì một.

Tuy nhiên, bạn cần so sánh những nỗ lực cần thiết. Khi một hoặc nhiều cột mới được thêm vào, sao chép / dán một vài thuộc tính sẽ không mất nhiều thời gian. Khi mô hình dữ liệu thay đổi về cấu trúc, phải thay đổi giao diện, có thể theo những cách chỉ gây ra lỗi khi chạy (và không phải lúc biên dịch), cần nhiều nỗ lực hơn và đòi hỏi nhà phát triển phải tìm kiếm lỗi.


Tôi có thể cho bạn thêm ví dụ nhưng nguyên tắc sẽ luôn giống nhau.

Tóm tắt

  • Các trách nhiệm riêng biệt (mối quan tâm) cần phải làm việc riêng biệt với nhau. Họ không nên chia sẻ bất kỳ tài nguyên nào như các lớp dữ liệu (ví dụ Person)
  • Chỉ vì một thực thể và DTO của nó có cùng thuộc tính, không có nghĩa là bạn cần hợp nhất chúng vào cùng một thực thể. Đừng cắt góc.
    • Như một ví dụ rõ ràng hơn, giả sử cơ sở dữ liệu của chúng tôi chứa các quốc gia, bài hát và con người. Tất cả các thực thể này có một Name. Nhưng chỉ vì tất cả chúng đều có một Nametài sản, không có nghĩa là chúng ta nên làm cho chúng được thừa kế từ một EntityWithNamelớp cơ sở chung . Các Nametính chất khác nhau không có mối quan hệ có ý nghĩa.
    • Nếu một trong các thuộc tính từng thay đổi (ví dụ: một bài hát Nameđược đổi tên thành Titlehoặc một người được FirstNameLastName), họ sẽ phải mất nhiều nỗ lực hơn để hủy bỏ quyền thừa kế mà bạn thậm chí không cần ở nơi đầu tiên .
    • Mặc dù không trắng trợn, nhưng lập luận của bạn rằng bạn không cần DTO khi bạn có một thực thể là như nhau. Bạn đang nhìn vào hiện tại , nhưng bạn không chuẩn bị cho bất kỳ thay đổi nào trong tương lai. NẾU thực thể và DTO hoàn toàn giống nhau và NẾU bạn có thể đảm bảo rằng sẽ không bao giờ có bất kỳ thay đổi nào đối với mô hình dữ liệu; sau đó bạn đúng rằng bạn có thể bỏ qua DTO. Nhưng điều là bạn không bao giờ có thể đảm bảo rằng mô hình dữ liệu sẽ không bao giờ thay đổi.
  • Thực hành tốt không phải lúc nào cũng trả hết ngay lập tức. Nó có thể bắt đầu trả hết trong tương lai, khi bạn cần xem lại một ứng dụng cũ.
  • Kẻ giết người chính của các cơ sở mã hiện tại là làm cho chất lượng mã giảm xuống, liên tục gây khó khăn hơn trong việc duy trì cơ sở mã, cho đến khi nó bị phá hủy thành một mớ hỗn độn vô dụng của mã spaghetti không thể nhận ra.
  • Thực hành tốt, chẳng hạn như thực hiện tách biệt các mối quan tâm từ get to, nhằm mục đích tránh độ dốc trơn trượt của bảo trì xấu, để giữ cho codebase duy trì được càng lâu càng tốt.

Như một quy tắc để xem xét tách các mối quan tâm, hãy nghĩ về nó theo cách này:

Giả sử rằng mọi mối quan tâm (UI, cơ sở dữ liệu, logic) được xử lý bởi một người khác ở một vị trí khác nhau. Họ chỉ có thể giao tiếp qua email.

Trong một cơ sở mã được phân tách rõ ràng, một sự thay đổi đối với một mối quan tâm cụ thể sẽ chỉ cần được xử lý bởi một người:

  • Thay đổi giao diện người dùng chỉ liên quan đến nhà phát triển UI.
  • Thay đổi phương thức lưu trữ dữ liệu chỉ liên quan đến cơ sở dữ liệu dev.
  • Thay đổi logic kinh doanh chỉ liên quan đến các dev kinh doanh.

Nếu tất cả các nhà phát triển này đang sử dụng cùng một Personthực thể và một thay đổi nhỏ được thực hiện cho thực thể đó, mọi người sẽ cần phải tham gia vào quá trình.

Nhưng bằng cách sử dụng các lớp dữ liệu riêng biệt cho mỗi lớp, vấn đề đó không phổ biến:

  • Miễn là nhà phát triển cơ sở dữ liệu có thể trả về một PersonDTOđối tượng hợp lệ , nhà phát triển doanh nghiệp và giao diện người dùng không quan tâm rằng anh ta đã thay đổi cách lưu trữ / truy xuất dữ liệu.
  • Miễn là nhà phát triển kinh doanh lưu trữ dữ liệu trong cơ sở dữ liệu và cung cấp dữ liệu cần thiết cho giao diện, nhà phát triển cơ sở dữ liệu và giao diện người dùng không quan tâm nếu anh ta quyết định làm lại quy tắc kinh doanh của mình.
  • Miễn là UI có thể được thiết kế dựa trên `PersonViewModel, thì nhà phát triển UI có thể xây dựng UI theo cách họ muốn. Cơ sở dữ liệu và nhà phát triển kinh doanh không quan tâm đến việc nó được thực hiện như thế nào, vì nó không ảnh hưởng đến họ.

Cụm từ chính ở đây là vì nó không ảnh hưởng đến họ . Việc thực hiện một sự phân tách tốt các mối quan tâm tìm cách giảm thiểu ảnh hưởng (và do đó phải liên quan) các bên khác.

Tất nhiên, một số thay đổi lớn không thể tránh được bao gồm nhiều hơn một người, ví dụ: khi một thực thể hoàn toàn mới được thêm vào cơ sở dữ liệu. Nhưng đừng đánh giá thấp số lượng thay đổi nhỏ mà bạn phải thực hiện trong suốt thời gian sử dụng ứng dụng. Những thay đổi chính là một thiểu số.


Câu trả lời toàn diện, Cảm ơn. Tôi có câu hỏi; Đánh giá cao nếu bạn trả lời: 1 - Sửa lỗi cho tôi, nếu tôi sai. Đối tượng doanh nghiệp hoặc Đối tượng xem là để chuyển dữ liệu giữa Lớp trình bàyLớp doanh nghiệpĐối tượng thực thể là để truyền dữ liệu giữa Lớp doanh nghiệpLớp truy cập dữ liệu . và DTO có thể được sử dụng như một BO câm. 2 - Giả sử rằng hai chế độ xem cần thông tin khác nhau của một công ty thì chúng ta cần hai công ty khác nhau?
Arash

1
@Arash (1) "DTO" thực sự là một định nghĩa bắt tất cả cho bất kỳ lớp dữ liệu nào được sử dụng để trao đổi giữa hai lớp. Một đối tượng kinh doanh và một đối tượng xem đều là DTO. (2) Điều đó phụ thuộc rất nhiều vào rất nhiều thứ. Tạo một dto mới cho mọi bộ sưu tập các lĩnh vực bạn yêu cầu là một nhiệm vụ nặng nề. Không có gì sai khi chỉ trả lại một công ty đầy đủ DTO (hợp lý) và sau đó để cho chế độ xem chọn các lĩnh vực mà nó quan tâm. Đó là vấn đề tìm sự cân bằng giữa việc thực hiện tách biệt mối quan tâm và tránh lặp lại quá mức và lặp đi lặp lại vô nghĩa.
Flater

Bây giờ điều đó có ý nghĩa với tôi. Cảm ơn rất nhiều. Flater.
Arash

Thêm một câu hỏi nữa. Bạn nói "đối tượng kinh doanh đối tượng xem". Tôi nghĩ rằng cả hai đều bằng nhau. Khi tôi tìm kiếm, tôi nhận ra rằng Business Object có ý nghĩa chung để so sánh với View Object . Nhưng Đối tượng kinh doanh nên được bắt nguồn từ ca sử dụngĐối tượng thực thể nên được lấy từ Mô hình dữ liệu do đó chúng khác nhau, phải không? bạn có thể giải thích một chút được không?
Arash

@Arash: Sự khác biệt giữa những gì bạn gọi là "đối tượng kinh doanh" và "đối tượng xem" là bối cảnh . Đối với con người chúng ta, sự phân biệt đó quan trọng để hiểu mọi thứ đúng đắn. Nhưng trình biên dịch (và bằng cách mở rộng chính ngôn ngữ) không thấy sự khác biệt kỹ thuật giữa chúng. Khi tôi nói chúng giống nhau, tôi có nghĩa là từ góc độ kỹ thuật. Cả hai chỉ là một lớp với các thuộc tính nhằm giữ dữ liệu và được truyền xung quanh. Về vấn đề đó, không có sự khác biệt giữa chúng.
Flater
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.