Опции для МОК автоматическое проводное соединение в доменном управляемом дизайне

В моем последнем приложении ASP.NET MVC 2 я пытался осуществить понятие Доменного управляемого дизайна (DDD), Единственного принципа ответственности (SRP), Инверсии управления (IoC) и Разработки через тестирование (TDD). Как пример архитектуры я следовал за "Луковой Архитектурой Jeffery Palermo", на которой подробно останавливаются значительно в ASP.NET MVC 2 в Действии.

Onion Architecture Diagram

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

Как пример: каждый доменный объект, который нуждается в способности послать электронное письмо, должен зависеть от IEmailService интерфейс. От моего чтения лучшая практика для раскрытия этой зависимости должна была бы использовать инжекцию конструктора. В моем уровне UI я выполняю подобную инжекцию для реализаций интерфейса репозитория с помощью StructureMapControllerFactory из ASP.NET MVC Contrib.

То, где я смущен, - то, что лучший механизм для автопроводного соединения инжекции необходимых сервисов в доменные объекты? Доменные объекты должны даже быть введены этот путь? Как я пошел бы об использовании IEmailService если я не ввожу его в доменные объекты?

Дополнительные вопросы о Переполнении стека, которые являются большим DDD, SRP, МОК, ссылками TDD:

7
задан Community 23 May 2017 в 12:30
поделиться

1 ответ

Если я не понимаю ваши намерения и вместо этого я предпочитаю сосредоточиться на семантике, я собираюсь проанализировать это утверждение. «В качестве примера: каждый объект домена, которому требуется возможность отправлять электронная почта должна зависеть от интерфейса IEmailService ".

Я бы сказал, что это само по себе крайнее бастардирование DDD. Зачем доменной сущности когда-либо нужно зависеть от почтовой службы? ИМО, этого не должно быть. Этому нет оправдания.

Однако существуют бизнес-операции, связанные с доменной сущностью, которые потребуют отправки электронных писем. У вас должна быть ваша зависимость IEmailService , содержащаяся здесь в этом классе, а не в сущности домена.Этот класс, скорее всего, попадет под одно из нескольких почти синонимичных имен: Модель, Сервис или Контроллер, в зависимости от того, на какой архитектуре / уровне вы находитесь.

На этом этапе ваша StructureMapControllerFactory будет правильно автоматически подключать все, что будет использовать IEmailService .

Хотя я, возможно, немного преувеличиваю, это довольно стандартная практика, когда объекты домена являются POCO или почти POCO (чтобы избежать нарушения SRP), однако часто SRP нарушается в объектах домена для сериализации и проверки. Решение о нарушении SRP для этих типов сквозных проблем является скорее личным убеждением, чем «правильным» или «неправильным» решением.

В качестве последнего ответа, если ваш вопрос касается части кода, которая действительно работает в автономном сервисе, будь то веб или ОС, и как связать зависимости от этого, обычным решением будет взять на себя сервис на базовом уровне и примените к нему IOC таким же образом, как StructureMapControllerFactory в MVC. Как этого добиться, будет полностью зависеть от инфраструктуры, с которой вы работаете.

Ответ:

Допустим, у вас есть IOrderConfirmService , у которого есть метод EmailOrderConfirmation (Order order) . В результате вы получите что-то вроде этого:

public class MyOrderConfirmService : IOrderConfirmService
{    
    private readonly IEmailService _mailer;

    public MyOrderConfirmService(IEmailService mailer)
    {        
        _mailer = mailer;        
    }

    public void EmailOrderConfirmation(Order order)
    {        
        var msg = ConvertOrderToMessage(order); //good extension method candidite
        _mailer.Send(msg);        
    }    
}

Тогда у вас будет класс OrderController , который будет выглядеть примерно так:

public class OrderController : Controller
{    
    private readonly IOrderConfirmService _service;

    public OrderController(IOrderConfirmService service)
    {        
        _service= service;        
    }

    public ActionResult Confirm()
    {      
            _service.EmailOrderConfirmation(some order);

            return View();
    }    
}

StrucutreMap по своей сути построит всю вашу архитектурную цепочку, если вы правильно используете инъекцию конструктора. .Это фундаментальное различие между сильной связью и инверсией управления. Поэтому, когда StructureMapFactory приступает к созданию вашего контроллера, первое, что он увидит, это то, что ему нужен IOrderConfirmService. На этом этапе он проверит, может ли он подключить IOrderConfirmService напрямую, чего он не может, потому что ему нужен IEmailService. Таким образом, он проверит, может ли он подключить IEmailService, и для аргументации скажет, что может. Итак, на этом этапе он создаст EmailService, который затем создаст MyOrderConfirmService и подключит EmailService, а затем, наконец, создаст OrderController и подключит MyOrderConfirmService. Отсюда и термин «инверсия управления». StructureMap сначала создаст EmailService во всей цепочке зависимостей и завершит работу с Контроллером. В жестко связанной настройке все будет наоборот, когда сначала будет построен Контроллер, который должен будет создать бизнес-сервис, а затем создать сервис электронной почты. Плотно соединенная конструкция очень хрупкая по сравнению с IOC.

4
ответ дан 7 December 2019 в 14:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: