Các hàm tạo đối số không và các thực thể Luôn hợp lệ


8

Gần đây tôi đã đọc rất nhiều về các thực thể miền Luôn hợp lệ. Tôi đã tin rằng để đảm bảo các thực thể luôn hợp lệ, tôi cần phải:

1) Xóa nỗi ám ảnh nguyên thủy và đặt các quy tắc xác thực / tên miền vào các hàm tạo đối tượng giá trị như được giải thích ở đây: https : //enterpriseccraft Skill.com/2016/09/13/validation-and-ddd/ . 2) Đặt quy tắc xác thực / tên miền vào bộ tạo của các thực thể hoặc setters tài sản như được giải thích ở đây: http://gorodinski.com/blog/2012/05/19/validation-in-domain-driven-design-ddd/ .

Tuy nhiên, sau đó tôi xem xét một số dự án Nguồn mở như dự án này: https://github.com/gregoryyoung/mr . Từ những gì tôi hiểu, tác giả của dự án này là người ủng hộ mô hình miền luôn hợp lệ và tôi xem ở đây tại lớp InventoryItem: https://github.com/gregoryyoung/mr/blob/master/SimpleCQRS/Domain.cs . Tôi nhận thấy rằng tôi có thể làm điều này:

InventoryItem inventoryItem = new InventoryItem();

hoặc này:

InventoryItem inventoryItem2 = new InventoryItem(Guid.Empty,null);

Trong tâm trí của tôi điều này có nghĩa là thực thể được khởi tạo ở trạng thái không hợp lệ. Đây dường như là trường hợp trong tất cả các dự án Nguồn mở khác mà tôi đã xem gần đây, ví dụ như dự án này: https://github.com/dcomartin/DDD-CQRS-ES-Example/blob/master/src/Domain /Customer.cs .

Tôi nhận thấy có xác thực theo ngữ cảnh trong các dự án nguồn mở này ( https://martinfowler.com/bliki/ContextualValidation.html ). Tôi cũng nhận ra rằng các ORM cần một hàm tạo trống mặc định nếu được ánh xạ tới mô hình miền.

Là một đối tượng miền ở trạng thái hợp lệ nếu nó được khởi tạo với các giá trị mặc định bằng cách sử dụng hàm tạo đối số bằng không / được khởi tạo với các giá trị rỗng / null?


2
Bạn thực sự không thể khái quát. Có thể là. Nó có thể không. Có vấn đề gì không? IMHO không, đặc biệt là các cuộc đàm phán DDD sớm đã quên nghĩ rằng thực tế là khác nhau và ví dụ, ORMs / ngôn ngữ / khung quy định một số quy tắc (và giá để phá vỡ chúng có thể quá cao hoặc không xứng đáng). Ok, cũng là dự án mà bạn đã liệt kê dường như không phải là mã .NET tốt nhất có thể từng có ...
Adriano Repetti

@Adriano Repetti, bạn có biết bất kỳ dự án nguồn mở cqrs tốt nào không? Bạn có đặt xác nhận trong các lệnh của bạn?
w0051977

2
Tôi muốn phân biệt xác thực tham số với xác thực tên miền (khi áp dụng). Ví dụ, một tham số null không liên quan gì đến tên miền, nó xuất phát từ một chi tiết triển khai (ngôn ngữ bạn đang sử dụng). Trước đây tôi luôn làm, không có vấn đề gì và ở đâu. Xác thực tên miền khó khăn hơn nhưng nếu bạn thực sự lo lắng về những bất biến bị hỏng thì IMO, bạn nên xem xét các đối tượng bất biến . Chúng (một lần nữa theo quan điểm của tôi), thường là, sự đánh đổi tốt hơn là một cuộc chiến thần thánh chống lại các ngôn ngữ mà chúng ta thực sự sử dụng (và đó là một sự phê phán đối với nhiều DDD cũ hơn)
Adriano Repetti

Câu trả lời:


7

Trước khi tôi giải quyết các loại cân nhắc đi vào việc tạo đối tượng, trước tiên chúng ta hãy giải quyết động lực đằng sau câu hỏi của bạn: cụm từ "Các thực thể miền luôn hợp lệ". Cụm từ này, tốt nhất là, gây hiểu lầm và ít có ý nghĩa trong bối cảnh của DDD. Điều này nên rõ ràng vì hai lý do liên quan:

Đầu tiên là nó hoàn toàn chuyển sự tập trung của bạn ra khỏi hành vi của hệ thống, thay vào đó, yêu cầu bạn xem xét xác nhận chỉ về mặt trạng thái. Mặc dù bề ngoài điều này có vẻ có ý nghĩa (tất nhiên xác nhận là về trạng thái!), Bạn phải nhớ rằng hiệu trưởng cơ bản của DDD là một hệ thống được mô hình hóa theo hành vi . Động lực cho điều này khá đơn giản là bối cảnh, hoặc chính quá trình kinh doanh , thường là một sự cân nhắc quan trọng khi xác định liệu một số trạng thái có hợp lệ hay không. Mô hình hóa một hệ thống theo cách này có thể làm giảm đáng kể sự phức tạp của nó.

Điều này đưa chúng ta đến lý do thứ hai, liên quan đến các yêu cầu thực tế mà một hệ thống sẽ đòi hỏi. Để tạo một hệ thống "Các thực thể miền luôn hợp lệ", nó sẽ yêu cầu một mô hình hóa mọi hoán vị trạng thái theo quy trình kinh doanh trong đó trạng thái được sử dụng. Một ví dụ đơn giản có thể minh họa những hạn chế của điều này:

Quy tắc:

  • Customer phải trên 18 tuổi để đăng ký
  • Customer phải dưới 25 tuổi để đủ điều kiện giảm giá khi đăng ký
  • Customer phải trên 25 tuổi để đặt phòng

Điều đầu tiên bạn cần chú ý là tất cả các quy tắc này (giống như gần như tất cả các quy tắc) áp dụng cho một số quy trình kinh doanh. Chúng không tồn tại trong chân không. Các quy tắc này sẽ được xác nhận trên customer.Register()customer.Reserve(). Điều này dẫn đến một mô hình khai báo và mô tả nhiều hơn bởi vì nó rõ ràng nơi các quy tắc được thực thi.

Nếu chúng ta muốn mô hình hóa các quy tắc này sao cho nó dẫn đến hệ thống "Các thực thể miền luôn hợp lệ", chúng ta sẽ cần phân vùng Customerthành RegistrarReservercác thực thể. Và trong khi điều đó có vẻ không tệ cho ví dụ này, vì các quy tắc trở nên phức tạp và phong phú hơn, bạn sẽ kết thúc với một lớp nổ như thế này đại diện cho trạng thái "bên trong" một số bối cảnh hoặc quá trình. Điều này chỉ đơn giản là không cần thiết và chắc chắn sẽ tạo ra các vấn đề khi hai đối tượng như vậy phụ thuộc vào cùng một lát cắt trạng thái.

Ngoài ra, một cái gì đó giống như Customer c = new Customer()là một nơi tồi tệ để ném ngoại lệ vì không rõ quy tắc kinh doanh nào có thể áp dụng. Điều này đưa chúng ta đến cuộc thảo luận cuối cùng của chúng tôi.

Tôi chỉ sẽ đi ra và đi xa để nói rằng có nên không xác nhận các quy tắc kinh doanh xảy ra trong nhà xây dựng. Xây dựng đối tượng hoàn toàn không liên quan gì đến lĩnh vực kinh doanh của bạn và vì lý do đó, ngoài các lý do trên liên quan đến bối cảnh và sự gắn kết, tất cả các quy tắc kinh doanh nên được thực thi trong các cơ quan phương thức của thực thể (có thể các phương thức được đặt tên theo quy trình kinh doanh đúng ?).

Hơn nữa, "làm mới" một đối tượng không giống như tạo một thực thể mới trong miền của bạn. Đối tượng không đi ra từ đâu cả. Nếu có các quy tắc kinh doanh liên quan đến việc một thực thể mới có thể xâm nhập vào hệ thống của bạn như thế nào, thì nó nên được mô hình hóa trong miền của bạn . Dưới đây là một số thảo luận thêm về chủ đề của một bậc thầy thực sự http://udidahan.com/2009/06/29/dont-create-aggregate-roots/


3

Là một đối tượng miền ở trạng thái hợp lệ nếu nó được khởi tạo với các giá trị mặc định bằng cách sử dụng hàm tạo đối số bằng không / được khởi tạo với các giá trị rỗng / null?

Nó có thể.

Không có gì chống lại các quy tắc về việc tạo một đối tượng miền hợp lệ bằng cách sử dụng một hàm tạo mặc định.

Không có gì chống lại các quy tắc về việc tạo một đối tượng miền hợp lệ với các giá trị trống.

Không có gì chống lại các quy tắc về việc tạo một đối tượng miền hợp lệ thiếu các yếu tố tùy chọn.

Không có gì chống lại các quy tắc về việc tạo một đối tượng miền hợp lệ bằng cách sử dụng null.

Trường hợp xảy ra sự cố: tạo các đối tượng miền không tuân theo đại số ngữ nghĩa của riêng chúng.

Việc thực hiện đúng phụ thuộc vào một cách giải thích chính xác về ngữ nghĩa.

Đó là một điều bình thường để có một đại diện tha thứ cho một khái niệm miền và theo các bước áp dụng các ràng buộc bổ sung. Đây là một trong những lĩnh vực mà các ngôn ngữ triển khai giúp dễ dàng thêm các loại (ví dụ: F #) có lợi thế hơn các ngôn ngữ vụng về như Java.

Ví dụ: nếu chúng ta có một miền quan tâm đến các số và trong miền đó có một số khả năng dành riêng cho các số nguyên tố hoặc các số nguyên tố Mersenne, thì một cơ chế tự nhiên để sử dụng là tạo ra ba loại khác nhau; làm cho khái niệm rõ ràng rằng có các tập hợp ràng buộc khác nhau được áp dụng cho các đầu vào trong các phần khác nhau của giải pháp của bạn.

Number n = new Number(...)
Optional<Prime> p = n.prime()
if (p.isPresent()) {
    Optional<MersennePrime> mp = p.mersennePrime()
    // ...
} 

Trong kiểu thiết kế này, "xác nhận" rằng số thực sự là Prime sẽ tồn tại trong chính hàm tạo của Prime. Trong bối cảnh chúng ta cần ràng buộc bổ sung rằng tham số là số nguyên tố Mersenne , chúng ta sử dụng chuyển đổi Prime-> MersennePrime, đảm bảo rằng kiến ​​thức về ràng buộc Mersenne có một thẩm quyền ("không lặp lại chính mình").

"Làm cho ngầm, rõ ràng"


Cảm ơn. Bạn có thể giải thích đại số ngữ nghĩa là gì với một ví dụ? Bạn cũng có thể giải thích làm thế nào mẫu mã có liên quan. +1 cho "không có gì chống lại ....".
w0051977

Chắc chắn một thực thể không có ID trống là một điều xấu? Trừ khi có các kịch bản trong đó bạn khởi tạo lớp miền với các giá trị mặc định và sau đó xây dựng nó tăng dần?
w0051977
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.