Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Это из цикла "Проблемный шаблон 'репозиторий'". Нет чёткого и удовлетворяющего всем решения.
- Попробую написать вкратце.
- 1. Некоторый плюют на всё и экспозят (от слова expose) наружу IQueryable из контракта репозитория:
- interface IRepository<T> {
- IQueryable<T> Query();
- }
- Здесь проблема в том, что бизнес-логика (БЛ) может оказаться размазанной по всему проекту.
- В качестве маскирования размазанности иногда выносят БЛ в методы расширения для IQueryable.
- public static IQueryable<Customer> WhereIsActive(this IQueryable<Customer> q){
- return q.Where(c => c.Orders.Any() && c.LastLogonDate.Days < 365);
- }
- В принципе, можно и в отдельные правила в отдельном классе выносить:
- class CustomerBL {
- Expression<Func<Customer, bool>> IsActive = c => c.Orders.Any() && c.LastLogonDate.Days < 365;
- }
- 2. Можно выносить методы прямо в контракт репозитория:
- interface ICustomerRepository : IRepository<Customer> {
- GetActive();
- }
- Здесь проблема в том, что у вас может быть over9000 методов в вашем репозитории.
- Это очень напрягает. Тяжело поддерживать и ответственность размазанна.
- 3. Паттерн Спецификация
- interface ISpecification<T> {
- bool IsSatisfied(T entity);
- }
- interface IRepository<T> {
- IReadOnlyList<T> GetAll(IReadOnlyList<ISpecification<T>> specs);
- }
- class IsActiveSpecification : ISpecification<Customer>{
- public bool IsSatisfied(Customer c) {
- return c.Orders.Any() && c.LastLogonDate.Days < 365);
- }
- }
- 4. DDD. Выносите вашу БЛ в модель
- public class Customer {
- public DateTime LastLogonDate { get; protected set; }
- public IReadOnlyList<Order> Orders { get; protected set; }
- public bool IsActive() {
- return c.Orders.Any() && c.LastLogonDate.Days < 365);
- }
- }
- 5. Посмотрите в сторону CQRS, MessagePattern/"Pub/Sub"
- Можно комбинировать с предыдущими пунктами. Сложнее, но гибче.
- Позволит избавиться от проблем в пункте 2 (но, естественно, наплодит другие).
- public class ActiveCustomersQuery {
- }
- public class CustomerQueryHandler {
- public IReadOnlyList<Customer> Handle<ActiveCustomersQuery>(ActiveCustomersQuery query){
- return _repository.Where(x => x.IsActive());
- }
- }
- Как я уже сказал, Pub/Sub можно использовать и без DDD.
- 6. Почитайте блоги Александра Бындю (http://blog.byndyu.ru/), Сергея Теплякова (http://sergeyteplyakov.blogspot.ru/) и Максима Аршинова (https://habrahabr.ru/users/marshinov/topics/)
- У них много статей про эту проблему.
Advertisement
Add Comment
Please, Sign In to add comment