Sử dụng các đối tượng kinh doanh trong các mô hình xem


11

Khi sử dụng các đối tượng kinh doanh có thể tái sử dụng, điều gì được coi là thực tiễn tốt nhất khi xây dựng các mô hình xem?

Chúng tôi sử dụng một đối tượng mà chúng tôi gọi Builderđể xây dựng các mô hình xem của chúng tôi. Một trình xây dựng cho mỗi đơn vị lượt xem logic (đơn hàng, người dùng, v.v.), trong đó mỗi đơn vị có thể chứa một số mô hình chế độ xem khác nhau (đơn hàng chứa tóm tắt, dòng đơn hàng, v.v.).

Nhà xây dựng có thể kéo dữ liệu qua một hoặc nhiều đối tượng kinh doanh tiêu chuẩn để xây dựng mô hình xem.

Điều gì được coi là thực tiễn tốt hơn khi sử dụng các đối tượng / mô hình kinh doanh trong các mô hình xem?

Cách tiếp cận 1

Cho phép sử dụng các đối tượng kinh doanh trong mô hình xem?

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary();
        obModel.Order = obOrder;

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public Some.Business.Logic.Order Order;
    //Other methods for additional logic based on the order
    //and other properties
}

Cách tiếp cận 2

Chỉ lấy dữ liệu cần thiết từ các đối tượng kinh doanh

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary()
        {
            OrderNum = obOrder.OrderNum,
            NumOrderLnes = obOrder.NumOrderLines,
        }

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public int OrderNum;
    public int NumOrderLines
    //Other methods for additional logic based on the order
    //and other properties
}

Tôi có thể thấy những lợi ích và nhược điểm của cả hai, nhưng tôi tự hỏi liệu có một cách tiếp cận được chấp nhận không? Trong cách tiếp cận 1, không có sự trùng lặp mã xung quanh các mô hình, nhưng nó tạo ra sự phụ thuộc vào logic nghiệp vụ. Trong cách tiếp cận 2, bạn chỉ lấy dữ liệu cần thiết cho chế độ xem, nhưng bạn sao chép mã xung quanh các mô hình.

Câu trả lời:


12

Tùy chọn 1 tạo khớp nối chặt chẽ giữa mô hình miền và chế độ xem. Điều này trái với các mô hình xem vấn đề rất được thiết kế để giải quyết.

Một mô hình khung nhìn "lý do để thay đổi" là nếu chính khung nhìn thay đổi. Bằng cách đặt một đối tượng mô hình miền trong mô hình xem, bạn đang đưa ra một lý do khác để thay đổi (ví dụ: tên miền đã thay đổi). Đây là một dấu hiệu rõ ràng về việc vi phạm nguyên tắc trách nhiệm duy nhất. Có hai hoặc nhiều lý do để thay đổi dẫn đến các mô hình xem cần nhiều bảo trì - có thể nhiều hơn so với chi phí bảo trì nhận thấy của sao chép trên các mô hình miền / chế độ xem.

Tôi luôn luôn ủng hộ cách tiếp cận 2. Thông thường, các mô hình xem có thể trông rất giống nhau, thậm chí giống hệt với các đối tượng mô hình miền, nhưng sự khác biệt như tôi đã đề cập là những lý do khác nhau để thay đổi.


Tôi có đúng không khi nghĩ rằng "lý do để thay đổi" bạn có nghĩa là thay đổi theo nghĩa bảo trì, không thay đổi theo nghĩa cập nhật (ví dụ: sự kiện ui)?
Andy Hunt

@AndyBursh yep điều đó đúng - xem bài viết này , đặc biệt là dòng "Robert C. Martin xác định trách nhiệm là lý do để thay đổi và kết luận rằng một lớp hoặc mô-đun nên có một, và chỉ một, lý do để thay đổi."
MattDavey

Tôi thích câu trả lời của bạn nhưng một số suy nghĩ ... Mô hình xem không nhất thiết phải thay đổi chỉ vì mô hình thay đổi. Chỉ khi bạn ràng buộc hoặc sử dụng một thuộc tính cụ thể đã thay đổi thì đây sẽ là một vấn đề vì tham chiếu của bạn là toàn bộ đối tượng. Có một tham chiếu đến đối tượng miền giúp dễ dàng thực hiện các thay đổi và lưu lại. Các phương thức lưu của bạn cũng phụ thuộc vào đối tượng miền, do đó bạn phải chuyển đổi mô hình xem lại hoặc thiết lập phương thức kinh doanh của bạn để chấp nhận các mô hình xem không tốt. Tôi vẫn nghĩ # 2 có ý nghĩa nhất, nhưng chỉ bằng hai xu.
KingOfHypocites 8/12/13

Nếu bạn không thể có các đối tượng miền trong VM, thì làm thế nào bạn thể hiện một cái gì đó phức tạp hơn như một mảng Đơn hàng?
Jeff

Điều này có nghĩa là những thứ như, định dạng dấu thời gian cho màn hình người dùng, phải thuộc về lớp xem chứ không phải lớp miền và các đối tượng cấp miền chỉ trả về dấu thời gian thô, chưa được định dạng cho các đối tượng xem và sau này là những gì nên chứa logic định dạng?
The_Sympathizer

2

Tùy chọn 1 là thích hợp hơn vì nó tránh được sự sao chép mã. Đó là nó.

Nếu mô hình miền thay đổi đáng kể, gần như chắc chắn rằng chế độ xem sẽ phải thay đổi. Với tùy chọn 2, sau đó bạn phải thay đổi mô hình khung nhìn VÀ trình xây dựng cũng như chính khung nhìn. Loại đó là chất độc tuyệt đối cho khả năng bảo trì. YAGNI.

Điểm có một mô hình chế độ xem riêng là giữ trạng thái chỉ có ý nghĩa đối với chế độ xem (ví dụ: tab nào hiện đang được chọn) tách biệt với mô hình kinh doanh. Nhưng dữ liệu kinh doanh nên được sử dụng lại thay vì trùng lặp.


YAGNI - sát thủ bí mật giải quyết hầu hết các vấn đề thiết kế phần mềm.
Martin Blore

6
Tôi xin lỗi nhưng đây là lời khuyên khủng khiếp cho tất cả trừ những ứng dụng tầm thường nhất. Xem mô hình không có nhà nước. Chúng là những đối tượng truyền dữ liệu. Tab nào được chọn là một phần của CẤU TRÚC của chế độ xem và KHÔNG CÓ gì để làm với DATA trong mô hình chế độ xem từ trước đến nay. Bảo trì không phải là một cơn ác mộng nếu bạn cấu trúc chương trình của mình đúng cách và sử dụng một cái gì đó như Automapper để hydrat hóa các mô hình xem của bạn.
Lucifer Sam

"Nếu mô hình miền thay đổi đáng kể, gần như chắc chắn rằng chế độ xem sẽ phải thay đổi." - Đã đồng ý. Nhưng những gì về khi bạn có một thay đổi nhỏ cho tên miền? Với tùy chọn một, mỗi thay đổi nhỏ đối với tên miền (thậm chí chỉ đổi tên một thuộc tính) yêu cầu thay đổi tương ứng với chế độ xem. Đây cũng là chất độc tuyệt đối cho khả năng bảo trì.
MattDavey

@MattDavey: nếu bạn đổi tên một thuộc tính thì với một mô hình chế độ xem riêng, bạn cũng phải thay đổi chế độ xem (hoặc bất kỳ bản đồ nào giữa tên miền và mô hình chế độ xem) và bây giờ có hai tên khác nhau cho cùng một thứ, điều này chắc chắn gây nhầm lẫn.
Michael Borgwardt

@Lucifer Sam: rõ ràng chúng ta có những khái niệm rất khác nhau về mô hình khung nhìn là gì. Đối với tôi nghe có vẻ rất, rất kỳ lạ, giống như bạn đang mô tả các ứng dụng máy tính lớn cho các thiết bị đầu cuối câm, nhưng chắc chắn không phải là các ứng dụng web hoặc ứng dụng khách hiện đại.
Michael Borgwardt

2

Nguyên tắc và thần chú đôi khi có giá trị cho thiết kế hướng dẫn ... nhưng đây là câu trả lời thiết thực của tôi:

Hãy tưởng tượng các mô hình xem của bạn được tuần tự hóa thành JSON hoặc XML. Nếu bạn cố gắng và tuần tự hóa các mô hình miền của mình, bạn sẽ kết thúc với một mớ hỗn độn văn bản gớm ghiếc và rất có thể gặp vấn đề với các tham chiếu vòng tròn và các vấn đề khác.

Mục đích của mô hình khung nhìn là không nhóm các mô hình miền lại với nhau để khung nhìn có thể tiêu thụ chúng. Thay vào đó, mô hình chế độ xem phải là một mô hình hoàn toàn phẳng của chế độ xem ... thực tế bạn đang nhìn trên màn hình. Logic khung nhìn của bạn chỉ nên quan tâm đến việc cấu trúc dữ liệu có trong mô hình khung nhìn.

Lý tưởng nhất là mô hình khung nhìn của bạn nên được cấu thành gần như hoàn toàn các chuỗi được định dạng trước. Hãy suy nghĩ về điều đó ... bạn thậm chí không muốn có DateTime hoặc thập phân trong mô hình chế độ xem của mình bởi vì sau đó bạn bị mắc kẹt khi thực hiện định dạng logic trong C #, Javascript, Objective-C, v.v.


2
Tôi chưa bao giờ có bất kỳ vấn đề nào với việc nối tiếp các mô hình miền. Và chuyển đổi mọi thứ thành chuỗi trong một mô hình? Nghiêm túc?
Michael Borgwardt

3
@MichaelBorgwardt Vâng, đây là những gì một mô hình xem NÊN. Bạn không muốn tuần tự hóa các mô hình miền của mình và gửi chúng đi khắp nơi. Tất cả logic kinh doanh nên ở nhà an toàn ở một nơi. Tuy nhiên, các chế độ xem phải linh hoạt và có thể được hiển thị trên bất kỳ thiết bị nào, đó là lý do tại sao bạn muốn tách biệt hoàn toàn CẤU TRÚC, DỮ LIỆU và PHONG CÁCH của bạn.
Lucifer Sam

Xin lỗi, nhưng đó là lời khuyên khủng khiếp cho bất kỳ ứng dụng, thời gian. Nó dẫn đến các ứng dụng áp đảo đầy đủ mã trùng lặp hoàn toàn trái ngược với tính linh hoạt.
Michael Borgwardt

1
@MichaelBorgwardt có vẻ như bạn đã từng làm việc với các mô hình miền thiếu máu trong đó các thực thể ít hơn các túi tài sản với rất ít hoặc không có hành vi. Trong trường hợp đó, mô hình DTO / View về cơ bản sẽ là một bản sao. Tuy nhiên, nếu bạn có một mô hình miền phong phú với các mối quan hệ phức tạp, một lớp mô hình DTO / View-model trở nên cần thiết và chúng sẽ không giống với các thực thể miền.
MattDavey

@MattDavey: Nghe có vẻ như các mô hình miền mà bạn đã từng làm việc với không chỉ là những kleptocats giàu có mà còn thực sự. Tôi cũng không thích các mô hình thiếu máu, nhưng chúng vẫn là các mô hình và hành vi của chúng nên được giới hạn để đại diện cho miền. Nguyên tắc trách nhiệm duy nhất và tất cả những điều đó ...
Michael Borgwardt
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.