2016-07-12 3 views
0

У меня есть встроенный корень счета-фактуры, который в какой-то момент может быть отправлен на учетную внешнюю веб-службу и отмечен как отправленный путем сохранения некоторого идентификатора/номера, полученного из этой службы.DDD Доменные службы

Каков правильный способ сделать это в DDD?

Вот мои идеи:

Первый apprroach:

Иметь счета AggregateRoot с функцией SendToAccounting, и ввести домен службы/интерфейс, который будет отправлять счета-фактуры к бухгалтерскому учету, и получить некоторые «идентификатор/код»в бухгалтерскую программу и установить AccountingSoftwareId свойство

Invoice.SendToAccounting(IInvoiceDomain service) 
{ 
    var accountingSoftwareID = service.getAccountingSoftwareId(this); 
    this.AccountingSoftwareId = accountingSoftwareId; 
} 

///Implementation in the application service 
    var invoice = _invoiceRepository.GetInvoiceById(id); 
    invoice.SendToAccounting(someDomainService); 
    _invoiceRepository.Update(invoice); 
    _unitOfWork.Save(); 

Второй подход:

Похожие, как первый подход, но обслуживание домена должен быть ответственным за сохраняющихся так:

var invoice = _invoiceRepository.GetInvoiceById(id); 
///unit of work save will be called inside this function 
invoice.SendToAccounting(someDomainService); 

Третий approcach:

обслуживание домена будет полностью rensponsible инкапсулировать такое поведение

///Code inside domain service 
public void SendInvoiceToAccounting(int invoiceId) 
{ 
    var invoice = _invoiceRepository.GetInvoiceById(invoiceId); 
    string invoiceAccountingId = _accountingService.GetAccountingSoftwareId(invoice); 
    invoice.SetAsSentToAccounting(invoiceAccountingId); 
    _invoiceRepository.Update(invoice); 
    _unitOfWork.Save(); 
} 
+0

Я не совсем понимаю, к чему относится процесс отправки в учет - что это? – tomliversidge

+0

как вы справитесь с сбоем при вызове внешней службы? – tomliversidge

+0

Что такое учетная запись, используемая для агрегирования счетов-фактур? – tomliversidge

ответ

1

Какой правильный способ сделать это в DDD?

Ваш первый подход ближе всего. Подпись в вашей службе домена должна принимать состояние как аргументы, а не сам агрегатный корень.

Invoice.SendToAccounting(IInvoiceDomain service) 
{ 
    var accountingSoftwareID = service.getAccountingSoftwareId(this.Id, ...); 
    this.AccountingSoftwareId = accountingSoftwareId; 
} 

Все аргументов, переданные должна быть типами значений - сервис домена не должен быть в состоянии изменить состояние агрегата путем манипулирования его копии аргументов, и это, конечно, не должно быть в состоянии работать другие команды в совокупности.

В обзоре кода я бы отказался от второго подхода, который вы предлагаете; с точки зрения модели домена интерфейс службы домена должен предоставлять только запросы, а не команды (в смысле CQS).

В обзоре кода я бы полностью отказался от третьего подхода - сеттеры на агрегатах - это запах кода; все дело в том, чтобы инкапсулировать состояние правилами для его обновления.

НО

дизайн несколько настораживает, что вы делаете пишет в двух разных местах в одной и той же сделки. На счастливом пути это не очень важно, но что вы должны делать, если команда, запущенная в бухгалтерском сервисе, преуспевает, но сохранение обновленного счета-фактуры не удается?

Предполагая, что распределенные транзакции не привлекательны, вы можете ознакомиться с тем, что Уди Дахан может сказать о reliable messaging.

0

Моя первая мысль была «не выставлять счета за счет учета?» :)

вариант 1 - это то, что я использовал в прошлом, когда мои объекты домена имеют поведение.

Мне не нравится вариант 2, так как для счета-фактуры требуется частная ссылка на репозиторий.

Более общее наблюдение заключается в том, что здесь не очень много поведения в этом домене - кажется, это просто установка идентификатора. Вариант 3, похоже, фиксирует это. Я задаюсь вопросом, если служба приложения будет достаточно и просто координировать следующие действия

  1. Загрузите счет
  2. Получить AccountingId
  3. Сохранить его на фактуре

что довольно много вариант 3 выше. Однако у меня возникнет соблазн пройти в хранилище и службу, но это действительно более функциональный стиль - выше будет работать и с частными полями.

0

Учет BC должен всегда возвращать тот же отчетSoftwareId для данного invoiceId.

Если в первом раунде вызов выполняется на BC бухгалтерии, но обновление счета-фактуры терпит неудачу, у вас есть состояние t1 в учетной записи BC и состояние t0 в счете-фактуре BC. Когда вы повторите команду, он выполнит тот же вызов и вернет тот же идентификатор, и если обновление будет успешным, вы будете в состоянии t1 в каждом BC. В худшем случае, даже если команда должна быть разрешена вручную, результирующий идентификатор учетной записи всегда будет одинаковым для данного идентификатора счета.

Таким образом, чтобы разрешить идентификатор учета для конкретного счета-фактуры, вы можете напрямую запросить учетную запись BC.

Смежные вопросы