2015-01-22 18 views
7

Từ những gì tôi đã đọc và triển khai, DTO là đối tượng chứa một tập hợp con giá trị từ một mô hình Dữ liệu, trong hầu hết các trường hợp, đây là các đối tượng không thay đổi.Khi nào nó thích hợp để ánh xạ DTO trở lại đối tượng Entity của nó

Còn trường hợp tôi cần chuyển giá trị mới hoặc thay đổi về cơ sở dữ liệu thì sao?

Tôi có nên làm việc trực tiếp với mô hình dữ liệu/thực thể thực tế từ DAL của tôi trong lớp Trình bày của tôi không?

Hoặc tôi nên tạo DTO có thể được chuyển từ lớp trình bày sang lớp nghiệp vụ, sau đó chuyển đổi nó thành thực thể, sau đó được cập nhật trong DB qua cuộc gọi ORM. Đây có phải là viết quá nhiều mã không? Tôi giả định rằng điều này là cần thiết nếu lớp trình bày không có khái niệm về mô hình dữ liệu. Nếu chúng ta đang đi với phương pháp này, tôi có nên lấy lại đối tượng ở lớp BLL trước khi thực hiện thay đổi không?

Trả lời

3

Tôi có nên làm việc trực tiếp với mô hình dữ liệu/thực thể thực tế từ DAL của tôi trong lớp Trình bày của tôi không?

Điều này là ổn đối với các dự án vừa và nhỏ. Nhưng khi bạn có một dự án lớn với hơn 5 nhà phát triển, nơi các lớp khác nhau được chỉ định cho các nhóm khác nhau, thì dự án sẽ hưởng lợi từ việc sử dụng DTO để tách Lớp dữ liệu khỏi Lớp trình bày.

Với một DTO ở giữa, bất kỳ thay đổi trong các lớp trình bày sẽ không ảnh hưởng đến lớp dữ liệu (ngược lại)

Hoặc tôi nên tạo một DTO có thể được truyền từ các lớp trình bày vào lớp kinh doanh sau đó chuyển đổi nó thành một thực thể, sau đó được cập nhật trong DB thông qua một cuộc gọi ORM. Đây có phải là viết quá nhiều mã không? Tôi giả định rằng điều này là cần thiết nếu lớp trình bày không có khái niệm về mô hình dữ liệu. Nếu chúng ta đang đi với phương pháp này, tôi có nên lấy lại đối tượng ở lớp BLL trước khi thực hiện thay đổi không?

Để tạo một thực thể mới, thì đó là cách thông thường để đi (ví dụ "người dùng mới").Để cập nhật thực thể hiện tại, bạn không chuyển đổi DTO thành thực thể, thay vì bạn tìm nạp đối tượng hiện có, ánh xạ các giá trị mới sau đó bắt đầu cập nhật ORM.

UpdateUser(UserDto userDto) 
{ 
    // Fetch 
    User user = userRepository.GetById(userDto.ID); 

    // Map 
    user.FirstName = userDTO.FirstName; 
    user.LastName = userDTO.LastName; 

    // ORM Update 
    userRepository.Update(user); 
    userRepository.Commit(); 
} 

Đối với các dự án lớn có nhiều nhà phát triển, bất lợi khi viết quá nhiều mã là tối thiểu so với lợi thế lớn của việc phân tách nó cung cấp.

Xem bài của tôi về Why use a DTO

+1

"Để cập nhật thực thể hiện tại, bạn không chuyển đổi DTO thành thực thể, thay vì bạn tìm nạp đối tượng hiện có, ánh xạ các giá trị mới", bạn sẽ không viết cùng một mã ánh xạ hai lần theo cách này? – Reek

1

Ý kiến ​​của tôi là DTO đại diện cho các hợp đồng (hoặc thông điệp, nếu bạn muốn) tạo thành cơ sở cho sự tương tác giữa một gốc tổng hợp và thế giới bên ngoài. Chúng được định nghĩa trong miền và AR cần có khả năng xử lý cả các cá thể đến và cung cấp các cá thể gửi đi. (Lưu ý rằng trong hầu hết các trường hợp, các trường hợp DTO sẽ được AR cung cấp hoặc được AR xử lý, nhưng không phải cả hai, vì có một DTO chảy cả hai cách thường là vi phạm tách mối quan tâm.)

Đồng thời, AR chịu trách nhiệm cung cấp logic nghiệp vụ thông qua đó dữ liệu chứa trong DTO được xử lý. Lớp trình bày (hoặc bất kỳ diễn viên nào khác bao gồm lớp truy cập dữ liệu, cho vấn đề đó) được tự do đặt bất kỳ điều gì mà nó muốn vào DTO và yêu cầu AR xử lý nó và AR phải có khả năng diễn giải nội dung của DTO như vô nghĩa và đưa ra một ngoại lệ.

Do yêu cầu này, không bao giờ thích hợp để ánh xạ một DTO trở lại đối tác Entity của nó.

DTO phải luôn được xử lý thông qua logic trong AR để ảnh hưởng đến các thay đổi trong thực thể có thể mang đến trạng thái được mô tả bởi DTO.

+0

Tôi cũng sẽ thêm rằng nếu bạn đang thực hiện DDD/CQRS, Tổng hợp gốc sẽ không bao giờ cung cấp DTO, bởi vì chúng sẽ đến từ mô hình khung nhìn. Tuy nhiên, vì câu hỏi là ** không ** về DDD/CQRS, tôi giả sử bạn đang sử dụng AR để lấy dữ liệu được trình bày bởi lớp trình bày. – arootbeer

+1

Tôi đồng ý với tuyên bố của bạn bằng chữ in đậm, nhưng không phải với phần về giao diện DTO. Một DTO không có hành vi theo định nghĩa, và mục đích của một giao diện là cung cấp một hợp đồng hành vi, vậy tại sao một giao diện DTO? Ngoài ra, các thực thể miền không chấp nhận DTO thô từ khách hàng, phần lớn thời gian nó đi qua một lớp ứng dụng đầu tiên. Các dịch vụ lớp ứng dụng biết cách gọi các phương thức Entity/AR, truyền cho chúng các đối tượng giá trị hoặc các giá trị nguyên thủy đơn giản (nhưng không phải của DTO trong ý nghĩa "truyền dữ liệu" của thuật ngữ). – guillaume31

+0

Tôi cho rằng tôi đang sử dụng hiểu biết một chút về thuật ngữ * giao diện * - tôi đang nghĩ về ngôn ngữ C#, trong đó khái niệm "thuộc tính chỉ đọc" có thể được hiển thị ở cấp độ giao diện. Theo nghĩa hẹp nhất, điều này mang lại cho "hành vi" DTO: "Tôi có một giá trị, và bạn được chào đón để xem nó, nhưng bạn không thể thay đổi nó". Ý định của tôi là nhiều hơn rằng ** giao diện ** cho phép các DTO không thay đổi được mã nhận. Trong mọi trường hợp, đặc điểm kỹ thuật của * giao diện * trong câu trả lời là không liên quan, vì vậy tôi sẽ loại bỏ nó. – arootbeer

15

Một vài suy nghĩ:

  • DTO là một thuật ngữ quá tải, nhưng vì nó là viết tắt của dữ liệu Chuyển Object, tôi thấy nó nhiều hơn như một kỹ thuật thuần túy, có khả năng nối tiếp container để nhận dữ liệu từ điểm này sang điểm khác, thường qua các tầng hoặc có thể là các lớp. Bên trong một lớp giao dịch với các mối quan tâm kinh doanh, chẳng hạn như lớp Domain trong DDD, các cấu trúc dữ liệu nhỏ này có xu hướng được đặt tên là Value Objects, vì chúng có ý nghĩa kinh doanh và là một phần của ngôn ngữ Ubiquitous của miền. Có tất cả các loại khác biệt tinh tế giữa DTO và Value Objects, như bạn thường không cần so sánh DTO, trong khi so sánh và bình đẳng là một mối quan tâm quan trọng trong VO (hai VO là bằng nhau nếu dữ liệu đóng gói của chúng bằng nhau).

  • DDD chú trọng vào ý tưởng về mô hình miền phong phú. Điều đó có nghĩa là bạn thường không chỉ đơn giản là ánh xạ một đối một của DTO với các thực thể miền, nhưng cố gắng mô hình hóa các hành động nghiệp vụ như các phương thức tiết lộ có chủ ý trong các thực thể của bạn. Ví dụ: bạn sẽ không sử dụng trình cài đặt để sửa đổi 'Street, CityZipCode nhưng thay vào đó, hãy gọi phương thức moveTo(Address newAddress), Address là đối tượng giá trị được khai báo trong lớp Miền.

  • DTO thường không tiếp cận lớp Miền nhưng đi qua bộ lọc của lớp Ứng dụng. Nó có thể là Bộ điều khiển hoặc Dịch vụ ứng dụng chuyên dụng. Đó là ứng dụng lớp đối tượng mà biết làm thế nào để biến DTO của họ nhận được từ khách hàng, vào các cuộc gọi chính xác cho các thực thể lớp miền (thường là tổng hợp Roots nạp từ kho). Một mức độ tinh tế khác ở trên là xây dựng tasked-based UIs nơi người dùng không gửi DTO tập trung vào dữ liệu nhưng các Lệnh phản ánh mục tiêu cuối cùng của họ.

Vì vậy, ánh xạ DTO đến thực thể không thực sự là cách làm DDD, nó biểu thị nhiều hơn một cách tiếp cận theo định hướng CRUD.

Các vấn đề liên quan