Как создать домен Событие, когда я не хочу делиться фактической моделью домена - PullRequest
0 голосов
/ 27 февраля 2020

Я пытаюсь реализовать DDD в моем небольшом проекте, но не могу понять, как вызвать событие домена в следующем случае.

Домен аккаунта

public class Account : BaseEntity
{
    public string PhoneNumber { get; set; }

    public int OTP { get; set; }

    public Account()
    {
    }

    public Account(string phoneNumber, short otp)
    {
        this.PhoneNumber = phoneNumber;
        this.OTP = otp;
        CreatedDate = DateTime.Now;
        RowKey = Guid.NewGuid().ToString();
        PartitionKey = phoneNumber;
    }
}

Сервис аккаунта

public async Task<bool> GenerateOTP(string phoneNumber)
    {
        if (phoneNumber.Length != 10)
            throw new ArgumentException(ApplicationConstraint.InvalidNumber);

        var otp = Convert.ToInt16(new Random().Next(1000, 9999));
        var account = new Account(phoneNumber, otp);
        await this.accountRepository.AddEntity(account);
        return true;
    }

Хранилище аккаунта Azure Таблица хранения - это моя база данных

public virtual async Task AddEntity(TEntity entity)
    {
        TableOperation insertOperation = TableOperation.Insert(entity);
        await table.ExecuteAsync(insertOperation);
    }

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

1 Ответ

1 голос
/ 27 февраля 2020

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

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

---- Редактировать ----

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

  1. Публикация сразу после сохранения не является ошибкой. Это простой способ сделать это, и (если вы применяете методологию, основанную на событиях), вы можете сделать это общим образом c для всех ваших сущностей, минимальная работа. Тем не менее, вы должны быть осторожны с ошибками. В частности, проблема заключается в том, что если вы сначала сохраните сущность перед публикацией события, а затем произойдет сбой процесса по какой-либо причине, событие может быть пропущено, поэтому более поздние рабочие процессы не будут запущены. Если вы сделаете обратное (publi sh затем сохраните), вы рискуете дважды опубликовать событие. В этом случае у вас есть два варианта:

    1. Если вы храните-затем-публикуете sh: просто примите (действительно редкую) возможность не публиковать событие. Это то, что вам нужно, чтобы поговорить с бизнесом, и вы можете минимизировать серьезность, зарегистрировав событие, прежде чем пытаться сохранить сущность.
    2. Если вы опубликуете sh -then-store: (вам понадобится чтобы сделать это, если стоимость исправления каких-либо проблем ad-ho c слишком велика), вы можете решить эту проблему, попросив своих потребителей проверить идентификатор входящего сообщения, если они когда-либо обрабатывали его ранее, и отклонить его, если они это сделали ИЛИ сделать процесс идемпотентным (если это возможно), что означает, что выполнение процесса дважды не является проблемой
  2. Использование источников событий. На мой взгляд, это не сложно, но очевидно, что это сложная задача, если это простое приложение, и хотя оно не сложно, требует значительного объема чтения, если вы не знакомы с ним. Если это нетривиальное приложение, источник событий может очень помочь, потому что наблюдатели могут просто наблюдать за событиями в буфере и реагировать на это (поэтому не нужно явно публиковать sh изменения).

  3. Добавьте событие в отдельную таблицу в той же транзакции, где вы храните сущность, и используйте реализацию исходящих шаблонов (опубликуйте sh эти события из отдельной службы, отметив их как опубликованные, как только они были опубликованы). Честно говоря, шаблон, показанный на этом, немного упрощен c, и здесь есть много хитрых и небольших сложностей, поэтому предпочитайте использовать существующий, если сможете найти.

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

...