Cạm bẫy của thiết kế hướng tên miền với khung thực thể


12

Rất nhiều hướng dẫn về DDD tôi đã nghiên cứu chủ yếu bao gồm lý thuyết. Chúng đều có các ví dụ mã thô sơ (Pluralsight và tương tự).

Trên trang web cũng có một số nỗ lực của một số người để tạo ra các hướng dẫn bao gồm DDD với EF. Nếu bạn bắt đầu nghiên cứu chúng chỉ trong một thời gian ngắn - bạn nhanh chóng nhận thấy chúng khác biệt rất nhiều với nhau. Một số người khuyên nên giữ ứng dụng ở mức tối thiểu và để tránh giới thiệu các lớp bổ sung, ví dụ như kho lưu trữ trên đầu của EF , những người khác quyết định tạo thêm các lớp, thậm chí vi phạm SRP bằng cách tiêm DbContextvào Rễ tổng hợp.

Tôi xin lỗi khủng khiếp nếu tôi hỏi một câu hỏi dựa trên ý kiến, nhưng ...

Khi đi vào thực tế - Entity Framework là một trong những ORM mạnh nhất và được sử dụng rộng rãi. Thật không may, bạn sẽ không tìm thấy một khóa học toàn diện bao gồm DDD với nó, thật không may.


Khía cạnh quan trọng:

  • Entity Framework mang UoW & Rep Kho ( DbSet) ra khỏi hộp

  • với EF mô hình của bạn có thuộc tính điều hướng

  • với EF tất cả các mô hình luôn sẵn tắt DbContext(họ được thể hiện dưới dạng một DbSet)

Cạm bẫy:

  • bạn không thể đảm bảo các mô hình con của bạn chỉ bị ảnh hưởng thông qua Root tổng hợp - các mô hình của bạn có các thuộc tính điều hướng và có thể sửa đổi chúng và gọidbContext.SaveChanges()

  • với DbContextbạn có thể truy cập mọi mô hình của mình, do đó phá vỡ Root tổng hợp

  • bạn có thể hạn chế truy cập cho trẻ em các đối tượng gốc của thông qua ModelBuildertrong OnModelCreatingphương pháp bằng cách đánh dấu chúng như các lĩnh vực - Tôi vẫn không tin rằng đó là con đường đúng để đi về DDD cộng thật khó để đánh giá những gì loại phiêu lưu này có thể dẫn đến trong tương lai ( khá hoài nghi )

Xung đột:

  • mà không thực hiện một lớp kho lưu trữ khác trả về Uẩn, chúng ta thậm chí không thể giải quyết được một phần các cạm bẫy đã nói ở trên

  • bằng cách triển khai thêm một lớp kho lưu trữ, chúng tôi bỏ qua các tính năng tích hợp sẵn của EF (mọi thứ DbSetđã là repo) và làm phức tạp ứng dụng


Kết luận của tôi:

Xin thứ lỗi cho sự thiếu hiểu biết của tôi, nhưng dựa trên thông tin trên - Khung thực thể không phù hợp với Thiết kế hướng tên miền hoặc Thiết kế hướng tên miền là một cách tiếp cận không hoàn hảolỗi thời .

Tôi nghi ngờ mỗi phương pháp đều có giá trị của nó, nhưng hiện tại tôi đã hoàn toàn lạc lối và không có ý tưởng nhỏ nhất về cách dung hòa EF với DDD.


Nếu tôi sai - ít nhất có ai có thể nêu chi tiết một bộ hướng dẫn đơn giản (hoặc thậm chí cung cấp các ví dụ mã hợp lý) về cách thực hiện DDD với EF không, làm ơn?


Tôi chi tiết các bước ở đây theo sự hiểu biết của tôi về cách thức hoạt động của EF. Tuy nhiên, các bước này không xử lý vấn đề tiếp cận trẻ em bằng cách điều hướng. thuộc tính hoặc bởi DbSets tắt DbContext.
Alex Herman

Câu trả lời:


8

DDD và EF không có gì nhiều để làm với nhau.

DDD là một khái niệm mô hình. Nó có nghĩa là suy nghĩ về Tên miền, Yêu cầu nghiệp vụ và mô hình hóa chúng. Đặc biệt là trong bối cảnh hướng đối tượng, nó có nghĩa là tạo ra một thiết kế phản ánh các chức năng và khả năng kinh doanh.

EF là một công nghệ bền bỉ. Nó chủ yếu liên quan đến dữ liệu và hồ sơ cơ sở dữ liệu.

Hai người này đã ly dị. Thiết kế DDD có thể sử dụng EF ở một số dạng dưới mui xe, nhưng cả hai không nên tương tác theo bất kỳ cách nào khác.

Một số giải thích về Thiết kế hướng tên miền thực sự ủng hộ mô hình hóa dữ liệu và tôi nghĩ đây là câu hỏi của bạn. Theo cách hiểu này, "Các thực thể" và "Đối tượng giá trị" về cơ bản chỉ là các chủ sở hữu dữ liệu không có chức năng và thiết kế liên quan đến chính các thuộc tính này và các mối quan hệ giữa chúng với nhau. Trong bối cảnh này, DDD so với EF có thể xuất hiện.

Tuy nhiên, cách giải thích này còn thiếu sót và tôi thực sự khuyên bạn nên bỏ qua nó hoàn toàn.

Tóm lại : DDD và EF không loại trừ lẫn nhau, chúng thực sự không liên quan đến nhau, miễn là bạn đang thực hiện mô hình đối tượng phù hợp và không mô hình hóa dữ liệu. Các đối tượng DDD không được ở bất kỳ hình dạng hoặc hình thức nào là các tạo tác của EF. Các thực thể DDD không nên là "thực thể" của EF chẳng hạn. Bên trong một số chức năng liên quan đến kinh doanh, một thiết kế DDD có thể sử dụng EF với một số đối tượng dữ liệu có liên quan, nhưng chúng phải luôn được ẩn trong giao diện hướng hành vi liên quan đến kinh doanh.


1
EF chỉ là tiết kiệm thời gian. Theo dõi thay đổi và sự kiên trì của các tập hợp là nơi mà EF đã giúp rất nhiều. Thật không may, hiện tại không có cách nào để xác định hình dạng tổng hợp ở cấp cấu hình.
Pavel Voronin

6

Hãy đối xử với EF để biết thư viện truy cập dữ liệu chỉ được gõ mạnh hơn một chút so với ADO.NET thô. Tôi không khuyên bạn nên lập mô hình miền của mình bằng các lớp thực thể EF giống như tôi không khuyên bạn nên mô hình hóa miền bằng cách sử dụng Data set hoặc DataTable thô.

Tôi hiểu rằng EF đang được bán như một lối tắt giữa truy cập cơ sở dữ liệu và mô hình hóa miền, tuy nhiên cách tiếp cận này thực chất là thiếu sót vì nó giải quyết hai vấn đề chủ yếu không liên quan. Có những nỗ lực khác trong .NET để làm cho một lớp thực hiện một số thứ hoàn toàn không liên quan (ví dụ: Từ xa .NET) và chúng không kết thúc tốt.

Thực hiện DDD bằng các lớp POCO và không để lược đồ cơ sở dữ liệu điều khiển thiết kế của bạn. Giữ EF bên trong lớp lưu trữ / lớp lưu trữ và không để các thực thể EF bị rò rỉ ra bên ngoài.


5

Entity Framework mang UoW & Kho lưu trữ (Dbset) ra khỏi hộp

Không.

Các tóm tắt của Entity Framework được xây dựng với ORM, không phải DDD. Sự DbSettrừu tượng hóa trong bất kỳ phiên bản nào của Entity Framework không ở đâu gần với sự đơn giản của Kho lưu trữ DDD - chưa kể đến DbContextviệc phơi bày hàng trăm thứ còn hơn cả UnitOfWork.

Dưới đây là danh sách không đầy đủ các yếu tố trong bản tóm tắt của EF Core 2.1 DbSet<TEntity>mà chúng tôi không cần trong DDD:

  • Attach(TEntity) và tất cả anh chị em của nó
  • Find(Object[])
  • Update(TEntity) và tất cả anh chị em của nó
  • Thực thi IQueryable

Ngoài việc kéo theo các phụ thuộc không cần thiết với chúng, chúng còn che khuất mục đích của Kho lưu trữ thường phơi bày hành vi thu thập rất đơn giản. Cộng với sự trừu tượng bị rò rỉ là một sự cám dỗ liên tục để các nhà phát triển tự ghép đôi quá nhiều với EF và là mối đe dọa cho Tách biệt các mối quan tâm.

Điểm mấu chốt: bạn phải gói các fatties này thành các khái niệm đẹp, được sắp xếp hợp lý và đoán xem, điều đó có nghĩa là giới thiệu các lớp học thêm.

Một ví dụ tương đối hợp lý về những gì bạn có thể làm với EF và DDD (mặc dù một số quan điểm được thể hiện là gây tranh cãi): https://kalele.io/blog-posts/modeling-aggregates-with-ddd-and-entity-framework/

một số khác đang quyết định tạo thêm các lớp, thậm chí thường vi phạm SRP bằng cách tiêm DbContext vào Rễ tổng hợp

Tôi thực sự không thấy mối liên hệ giữa hai phần của câu này. Bất kể cách tiếp cận nào, có một thứ trong DDD được gọi là Dịch vụ ứng dụng và đó là nơi bạn thao túng Đơn vị công việc / Kho lưu trữ (hoặc DbContext). Không trong Rễ tổng hợp.

Mặc dù nó có thể là một cách tiếp cận hợp lệ nếu đó là một sự đánh đổi có giáo dục, xu hướng chống lưu trữ gần đây, "Entity Framework Minimalism" là ảo tưởng. Nó đổ lỗi cho các mẫu DDD cho sự ma sát xảy ra với Entity Framework khi đó thực sự là những người tạo ra EF không làm gì để làm cho khung của họ tuân thủ các thực tiễn tốt nhất. Trong khi đó, họ đang kết hợp chặt chẽ với chính khuôn khổ đó với tất cả các vấn đề về an toàn mã và khả năng bảo trì có thể xảy ra.


2

Xung đột:

mà không thực hiện một lớp kho lưu trữ khác trả về Uẩn, chúng ta thậm chí không thể> giải quyết một phần các cạm bẫy đã nói ở trên

bằng cách triển khai thêm một lớp kho lưu trữ, chúng tôi bỏ qua các tính năng tích hợp sẵn của EF (mọi Dbset đã là repo) và làm phức tạp ứng dụng

Tôi đã sử dụng một cách tiếp cận trong đó mọi Tập hợp đều có DBContext của riêng mình, chỉ ánh xạ những gì cần thiết cho Tập hợp. Tôi nghĩ rằng điều này cũng đã được mô tả bởi Julie Lerman.

Điều này hoạt động rất tốt, nhưng có thể không đủ cho các mô hình thú vị hơn, nơi bạn không muốn liên kết các khái niệm của mình với các thực thể của mình.



Có bất kỳ lợi ích nào của phương pháp DBContext Per Aggregate không? Đây có phải là cách mặc định để thực hiện DDD với EF?
Alex Herman

Không phải Julie Lerman có nghĩa là DbContext cho mỗi bối cảnh bị ràng buộc sao?
Mvision

0

Chỉ muốn chia sẻ giải pháp có thể để xem xét:

  1. tránh tham chiếu trực tiếp dự án EF trong Lớp dịch vụ

  2. tạo một lớp kho lưu trữ bổ sung (sử dụng dự án EF và trả về gốc tổng hợp)

  3. tham chiếu Lớp lưu trữ trong dự án Lớp dịch vụ

Kiến trúc :

  • Giao diện người dùng

  • Lớp điều khiển

  • Lớp dịch vụ

  • Lớp lưu trữ

  • Khuôn khổ thực

  • Dự án cốt lõi (chứa các mô hình EF)


Những cạm bẫy tôi thấy với cách tiếp cận này:

  • nếu Kho lưu trữ trả về Root tổng hợp không phải là cây mô hình EF (ví dụ: chúng tôi trả về một đối tượng được ánh xạ) - chúng tôi sẽ mất khả năng theo dõi các thay đổi của EF

  • nếu Root tổng hợp là một mô hình EF - tất cả các thuộc tính điều hướng của nó vẫn có sẵn , mặc dù chúng tôi không thể xử lý DbContext(chúng tôi không tham khảo dự án EF trong Lớp dịch vụ)

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.