Где долго функционирующие "сервисы" с состоянием вписываются в DDD?

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

Например, возьмем эту сущность домена, которая представляет сетевое устройство:

public class NetworkDevice {
   public IPAddress IpAddress { get; set; }
}

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

Эрик Эванс в своей знаменитой синей книге описывает, что доменная служба должна быть моделью без сохранения состояния, реализующей методы, взятые из языка ubiquitos, чтобы выполнить запрос, который объект или хранилище не может обработать сам. Но что, если служба должна быть с состоянием?

Простой пример: приложению необходимо отслеживать настроенные IP-устройства в сети, чтобы уведомить другое приложение внутри домена о событиях состояния. Если IP-устройство регистрируется внутри приложения (например, хранится в базе данных), "служба ping" получает уведомление и начинает мониторинг устройства.

public class PingMonitor : IDisposable,
   IHandle<DeviceRegisteredEvent>,
   IHandle<DeviceRemovedEvent> 
{

    public List<NetworkDevice> _devices = new List<NetworkDevice>();

    public void Handle(DeviceRegisteredEvent @event) {
        _devices.Add(@event.Device);
    }

    public void Handle(DeviceRemovedEvent @event) {
        _devices.Remove(@event.Device);
    }

    public void PingWorker() {
        foreach(var device in _devices) {
            var status = Ping(device.IpAddress);
            if(status != statusBefore)
                DomainEvents.Raise<DeviceStateEvent>(new DeviceStateEvent(device, status));
        }
    }

}

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

Теперь, что это за компоненты? Сначала я подумал, что это доменные сервисы, потому что они обслуживают определенное требование домена. Тем не менее, они не только представляют состояние, но и не представляют конкретно язык ubiquitos (задача службы ping - проверить связь с сущностью домена и сообщить о ее состоянии, однако служба ping не реализует метод, который позволил бы клиентам разрешать проверку связи). Устройство).

Это прикладные услуги? Где такие компоненты вписываются в структуру DDD?

2 ответа

Решение

Однажды я реализовал подобную функцию, надеюсь, это поможет:)

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

Ответственный за выполнение проверки отвечает:

public class CheckingBatch {
    private TransactionChecker transactionChecker;

    public void run() {
        List<Transaction> transactions = transactionsToBeChecked();
        for (Transaction transaction : transactions) {
                //publish events if the transaction needs check
                doCheck(transaction, now);                }
        } 
    }

    private List<Transaction> transactionsToBeChecked() {
         return transactionRepository.findBy(transactionChecker
            .aToBeCheckedSpec());
    }
}

Еще одна служба приложений прослушивает событие и выполняет фактическую проверку:

public class CheckTransactionServiceImpl implements CheckTransactionService {
    private TransactionChecker transactionChecker;

    @Transactional
    public void check(final TransactionNo transactionNo) {
        Transaction transaction = transactionRepository.find(transactionNo);
        CheckResult result = transactionChecker.check(transaction);
        //handle check result
    }
}

TransactionCheck - это независимая от интернет-платежей услуга домена:

public interface TransactionChecker {
/**
 * 
 * | data between online-payment provider and ours | txn STATUS | RESULT |<br>
 * | consistent | CLOSED | VALID |<br>
 * | inconsistent | CLOSED | INVALID |<br>
 * others omitted
 */
    CheckResult check(Transaction transaction);
/**
 * returns txn specification to filter to be checked ones.
 */
    ToBeCheckedSpecification aToBeCheckedSpec();
}

Как видите, и служба приложений, и служба домена теперь не сохраняют состояния.

ИМХО, Ping - это доменная служба (соотносится с TxnChecker), но монитор является своего рода службой приложений (соотносится с CheckingBatch).

В DDD длительный процесс называется Saga. Обычно это реализуется с использованием событий домена.

Вот краткое введение в тему: http://abdullin.com/journal/2010/9/26/theory-of-cqrs-command-handlers-sagas-ars-and-event-subscrip.html/

Другие вопросы по тегам