Tôi đã đấu tranh xung quanh một vấn đề liên quan đến DDD với Thông số kỹ thuật và tôi đã đọc nhiều vào DDD và thông số kỹ thuật và kho.Đặc điểm kỹ thuật Pattern in Domain Driven Design
Tuy nhiên, có sự cố nếu cố gắng kết hợp cả 3 trong số này mà không vi phạm thiết kế được điều khiển theo miền. Nó tóm tắt về cách áp dụng các bộ lọc với hiệu suất trong tâm trí.
Đầu tiên một vài sự kiện rõ ràng:
- Repositories để có lớp DataAccess/Cơ sở hạ tầng
- miền Models đại diện kinh doanh Logic và đi đến lớp miền
- Data Access Models đại diện Persistence lớp và đi đến Lớp Persistance/Infrastructure/DataAccess
- Logic nghiệp vụ đi tới Lớp miền
- Thông số kỹ thuật là Logic nghiệp vụ, do đó chúng cũng thuộc về lớp Miền.
- Trong tất cả các ví dụ này, một khung ORM và SQL Server được sử dụng bên trong Repository
- kiên trì mô hình có thể không bị rò rỉ vào miền Lớp
Cho đến nay, dễ dàng như vậy. Vấn đề phát sinh khi/nếu chúng tôi cố gắng áp dụng các thông số kỹ thuật cho kho lưu trữ và không phá vỡ mẫu DDD hoặc gặp sự cố về hiệu suất.
Các cách có thể áp dụng kỹ thuật:
1) cách Classic: Thông số kỹ thuật sử dụng Domain Model ở miền Lớp
Áp dụng các mẫu Đặc điểm kỹ thuật truyền thống, với một phương pháp IsSatisfiedBy
, trả lại một bool
và composite Thông số kỹ thuật để kết hợp nhiều Thông số kỹ thuật.
này chúng ta hãy giữ thông số kỹ thuật tại miền Layer, nhưng ...
- Nó có làm việc với mô hình Domain, trong khi kho sử dụng Persistence Models mà đại diện cho cấu trúc dữ liệu của lớp kiên trì. Điều này dễ sửa với việc sử dụng các người lập bản đồ như
AutoMapper
. - Tuy nhiên, vấn đề không thể giải quyết được: Tất cả các thông số kỹ thuật sẽ phải được thực hiện trong bộ nhớ. Trong một bảng/cơ sở dữ liệu lớn này có nghĩa là một tác động rất lớn nếu bạn phải lặp qua tất cả các thực chỉ để lọc ra một đáp ứng kỹ thuật của bạn
2) Thông số kỹ thuật sử dụng Persistence Mẫu
này tương tự đến 1), nhưng sử dụng Mô hình Persistence trong đặc điểm kỹ thuật. Điều này cho phép sử dụng trực tiếp Đặc điểm kỹ thuật như một phần của vị từ .Where
sẽ được dịch sang truy vấn (nghĩa là TSQL) và việc lọc sẽ được thực hiện trên bộ nhớ Persistence (tức là SQL Server).
- Trong khi điều này mang lại hiệu suất tốt, nó rõ ràng vi phạm mẫu DDD. Mô hình Persistence của chúng ta rò rỉ vào lớp Domain, làm cho Lớp Domain phụ thuộc vào Persistence Layer thay vì theo cách khác.
3) Giống như 2), nhưng làm cho thông số kỹ thuật phần của lớp Persistence
- này không hoạt động, vì miền lớp cần phải tham khảo các thông số kỹ thuật. Nó vẫn sẽ phụ thuộc vào lớp kiên trì.
- Chúng tôi sẽ có logic nghiệp vụ bên trong lớp Persistence. Mà cũng vi phạm DDD mẫu
4) Giống như 3, nhưng sử dụng trừu tượng các thông số kỹ thuật như giao diện
Chúng tôi sẽ có giao diện Đặc điểm kỹ thuật trong lớp miền của chúng tôi, triển khai cụ thể của chúng ta về kỹ thuật trong lớp Persistence. Bây giờ lớp Domain của chúng ta sẽ chỉ tương tác với các giao diện và không phụ thuộc vào lớp Persistence.
- Điều này vẫn vi phạm số 2 từ 3). Chúng tôi sẽ có logic kinh doanh trong lớp kiên trì, đó là xấu.
5) Dịch Tree Biểu hiện từ Domain Model vào Persistence Mẫu
Điều này chắc chắn giải quyết vấn đề, nhưng đó là nhiệm vụ không tầm thường nhưng nó sẽ giữ cho các thông số kỹ thuật bên trong lớp miền của chúng tôi trong khi vẫn được hưởng lợi từ SQL tối ưu, bởi vì các thông số kỹ thuật trở thành một phần của Repositories khoản ở đâu và chuyển thành TSQL
tôi đã cố gắng đi tiếp cận này và có một số vấn đề (mẫu thực hiện bên):
- Chúng tôi cần biết Cấu hình từ Trình ánh xạ (nếu chúng tôi sử dụng một) hoặc giữ hệ thống ánh xạ của riêng mình. Điều này có thể được thực hiện một phần (đọc cấu hình Mapper) với AutoMapper, nhưng các vấn đề khác tồn tại
- Có thể chấp nhận một trong những thuộc tính của Mô hình A ánh xạ tới một Thuộc tính của Mẫu B. Sẽ khó hơn nếu các loại khác nhau (ví dụ: do các loại kiên trì, ví dụ Enums được lưu dưới dạng chuỗi hoặc cặp khóa/giá trị trong một bảng khác và chúng tôi cần thực hiện chuyển đổi bên trong trình giải quyết. đây không phải là vấn đề đối với Mô hình miền -> Bản đồ mô hình Persistence
** 6) Trình tạo truy vấn như API **
Điều cuối cùng là tạo một loại API truy vấn được chuyển vào đặc tả và từ đó lớp Repository/Persistence sẽ tạo ra một cây biểu thức được chuyển tới mệnh đề .Where
và sử dụng Giao diện để khai báo tất cả các trường có thể lọc.
Tôi cũng đã thực hiện một số nỗ lực theo hướng đó nhưng không quá hài lòng về kết quả. Một cái gì đó như
public interface IQuery<T>
{
IQuery<T> Where(Expression<Func<T, T>> predicate);
}
public interface IQueryFilter<TFilter>
{
TFilter And(TFilter other);
TFilter Or(TFilter other);
TFilter Not(TFilter other);
}
public interface IQueryField<TSource, IQueryFilter>
{
IQueryFilter Equal(TSource other);
IQueryFilter GreaterThan(TSource other);
IQueryFilter Greater(TSource other);
IQueryFilter LesserThan(TSource other);
IQueryFilter Lesser(TSource other);
}
public interface IPersonQueryFilter : IQueryFilter<IPersonQueryFilter>
{
IQueryField<int, IPersonQueryFilter> ID { get; }
IQueryField<string, IPersonQueryFilter> Name { get; }
IQueryField<int, IPersonQueryFilter> Age { get; }
}
và trong đặc tả chúng tôi sẽ vượt qua một IQuery<IPersonQueryFilter> query
để các nhà xây dựng chi tiết kỹ thuật và sau đó áp dụng các kỹ thuật để nó khi sử dụng hoặc kết hợp nó.
IQuery<IGridQueryFilter> query = null;
query.Where(f => f.Name.Equal("Bob"));
Tôi không thích cách tiếp cận này nhiều, vì nó xử lý các thông số phức tạp một chút (và hoặc nếu chuỗi) và tôi không thích cách và/hoặc/không hoạt động. biểu thị cây từ "API" này.
Tôi đã tìm kiếm tuần trên Internet, đọc hàng tá bài viết về DDD và Đặc điểm kỹ thuật, nhưng chúng luôn xử lý các trường hợp đơn giản và không xem xét hiệu quả hoặc vi phạm mẫu DDD.
Làm thế nào để bạn giải quyết điều này trong một ứng dụng thế giới thực mà không làm gì trong việc lọc bộ nhớ hoặc rò rỉ Sự kiên trì vào Lớp Miền ??
Có khung công tác nào giải quyết vấn đề ở trên bằng một trong hai cách (Trình tạo truy vấn như cú pháp cây biểu thức hoặc trình dịch cây biểu thức) không?
Tôi rất vui vì tôi đã tìm thấy câu hỏi của bạn: Tôi đã có ** chính xác ** cùng một câu hỏi và cùng một mệnh đề về việc tách mô hình và mẫu đặc điểm kỹ thuật! Tôi tìm thấy [link] này (http://enterprisecraftsmanship.com/2016/04/05/having-the-domain-model-separate-from-the-persistence-model/), nơi anh chàng giải thích rằng có những mô hình riêng biệt mang lại ít tinh khiết hơn cho mô hình của bạn nhưng mang lại rất nhiều chi phí. Đối với anh ta nó không có giá trị nó. Tôi hy vọng bài viết này sẽ hữu ích :-) – Arcord
Bản trình diễn Đặc tả chung với kho lưu trữ EF chung, trong đó thông số kỹ thuật được sử dụng cho cả lọc và tải dữ liệu mong muốn: http://deviq.com/specification-pattern/ – ssmith