Технически вы можете делать то, что предлагаете: с определенной точки зрения, если вы вводите интерфейс ComplaintRepository в счет-фактуру, либо путем внедрения в конструктор, либо путем внедрения метода, вы делаете Invoice зависимым от контрактов. как хранилища, так и жалобы, и это в значительной степени разрешено.
Вы правы, когда говорите, что не можете хранить ссылку на жалобу, но вы можете вводить артефакты DDD (например, фабрики / репозитории / сущности) в операции, когда они необходимы для запуска.
Однако главный вопрос, который вы должны задать себе: действительно ли вы хотите такой уровень связи между двумя различными агрегатами? На данный момент они настолько связаны друг с другом, что в основном не могут работать без одного и другого.
Учитывая все это, вы можете оказаться в сценарии, когда жалоба может быть просто частью совокупности счетов (хотя у вашей совокупности счетов, вероятно, есть другие обязанности, и вы начнете бороться с целью "Проектировать небольшие агрегаты") , Если подумать, это то, что предлагает инвариант «Я не могу удалить счет, если на него открыта жалоба».
Если для вас все-таки нецелесообразно моделировать жалобу как часть совокупности счетов, у вас есть несколько других вариантов:
Сделайте эти агрегаты в конечном итоге непротиворечивыми: вместо того, чтобы пытаться удалить счет-фактуру «одним снимком», пометьте его как помеченный для удаления в одной операции. Эта операция запускает некое доменное событие в вашем механизме обмена сообщениями. Это событие «InvoiceFlaggedForDeletion» затем проверит наличие жалоб на счете-фактуре. Если у вас нет жалоб, вы удалите его. Если у вас есть жалобы, вы снимаете флажок удаления.
Поместите процесс удаления в доменную службу. Таким образом, Доменная служба будет координировать усилия по проверке жалоб и удалению счета, когда это необходимо. Недостатком этого подхода является то, что ваша сущность Invoice будет менее явной в своих правилах, но с точки зрения DDD это иногда приемлемый подход.