2

Я разрабатываю приложение, используя asp.net mvc, NHibernate и DDD. У меня есть уровень сервиса, который используется контроллерами моего приложения. Все используют Unity для инъекций зависимостей (ISessionFactory в репозиториях, хранилищах в сервисах и службах в контроллерах) и отлично работает.Service Layer повторяют мои репозитории

Но, очень часто мне нужен метод в обслуживании, чтобы получить только объект в моем хранилище, как это (в классе обслуживания):

public class ProductService { 

    private readonly IUnitOfWork _uow; 
    private readonly IProductRepository _productRepository; 

    public ProductService(IUnitOfWork unitOfWork, IProductRepository productRepository) { 
     this._uow = unitOfWork; 
     this._productRepository = productRepository; 
    } 

    /* this method should be exists in DDD ??? It's very common */ 
    public Domain.Product Get(long key) { 
     return _productRepository.Get(key); 
    } 

    /* other common method... is correct by DDD ? */ 
    public bool Delete(long key) { 
     usign (var tx = _uow.BeginTransaction()) { 
     try 
     { 
      _productRepository.Delete(key); 
      tx.Commit(); 
      return true; 
     } catch { 
      tx.RollBack(); 
      return false; 
     }   
     } 
    } 

    /* ... others methods ... */ 

} 

Этот код является правильным ДДД? Для каждого класса службы у меня есть репозиторий, и для каждого класса службы мне нужен метод «Получить» для объекта?

Спасибо, ребята

Приветствие

ответ

1

Это выглядит правильно с моей точки зрения. Мне действительно не нравилось повторять имена методов службы и репозитория много раз в моем проекте MVC asp.net, поэтому я пошел на общий подход/шаблон репозитория. Это означает, что мне действительно нужен только один или два метода Get() в моем репозитории для извлечения моих объектов. Это возможно для меня, потому что я использую Entity Framework, и у меня есть метод get() моего репозитория, возвращающий IQueryable. Тогда я могу просто сделать следующее:

Product product = from p in _productRepository.Get() where p.Id == Id select p; 

Вы, вероятно, может повторить это в NHibernate с помощью LINQ -> NHibernate.


Edit: Это работает для DDD, потому что это по-прежнему позволяет мне поменять мои DAL/хранилища, пока библиотека данных я использую (NHibernate, EF, и т.д ..) поддерживает IQueryable.

Я не уверен, как сделать общий репозиторий без IQueryable, но вы можете использовать функции делегатов/лямбда для его включения.


Edit2: И только в случае, если я не ответил на ваш вопрос правильно, если вы спрашиваете, вы должны вызвать метод вашего репозитория Get() из сервиса, то да, это правильно DDD дизайн также. Причина в том, что сервисный уровень должен обрабатывать всю вашу бизнес-логику, поэтому он точно определяет, как и какие данные извлекать (например, вы хотите, чтобы он был в алфавитном порядке, неупорядочен и т. Д.). Это также означает, что он может выполнять проверку после загрузки, если необходимо, или проверки перед удалением и/или сохранением.

Это означает, что сервисный уровень не заботится точно о том, как эти данные сохраняются и извлекаются, а только решает, какие данные хранятся и извлекаются. Затем он вызывает репозиторий для правильной обработки запроса и получения/хранения данных в том виде, в котором сообщает ему служебный уровень. Таким образом, у вас есть правильное разделение проблем.

9

Ваш продуктУслуги не выглядят так, как следует Принципы проектирования, основанные на домене. Если я правильно ее понимаю, это часть уровня приложения между презентацией и доменом. Если это так, методы ProductService должны иметь деловое значение в отношении продуктов.

Давайте поговорим об удалении продуктов. Это так же просто, как выполнить удаление в базе данных (NHibernate или что-то еще?) Я думаю, что это не так. Как насчет заказов, которые ссылаются на продукт, который будет удален? И так далее. Btw, Udi Dahan написал great article об удалении сущностей.

В самом деле, если ваше приложение настолько просто, что службы действительно реплицируют ваши репозитории и содержат только операции с CRUD, вы, вероятно, не должны делать DDD, отбрасываете свои репозитории и позволяете службам работать с объектами (что было бы просто контейнеры данных в этом случае).

С другой стороны, если существует сложное поведение (например, с обработкой «удаленных» продуктов), есть точка в пути DDD, и я решительно выступаю за это.

PS. Несмотря на то, что подход (DDD или нет) вы в конечном итоге возьмете, я бы посоветовал вам использовать некоторые аспекты ориентированного программирования для обработки транзакций и связанных с исключениями вещей. В результате вы получите множество методов, таких как DeleteProduct с тем же кодом обработки и обработки исключений.