Вход в систему как декоратор против внедрения зависимости - что если мне нужно войти в класс?
(Я изначально задавал этот вопрос вэтот комментарий, но Марк Симанн попросил меня создать новый вопрос.)
Я запускаю новое приложение (.NET Core, если это имеет значение), и сейчас я пытаюсь решить, как именно вести журналы.
Похоже, что общее согласие заключается в том, что ведение журнала является сквозной задачей, поэтому средство ведения журнала не должно вводиться непосредственно в класс, который должен регистрироваться.
Часто есть пример, как следующий класс, какне сделать это:
public class BadExample : IExample
{
private readonly ILogger logger;
public BadExample(ILogger logger)
{
this.logger = logger;
}
public void DoStuff()
{
try
{
// do the important stuff here
}
catch (Exception e)
{
this.logger.Error(e.ToString());
}
}
}
Вместо этого класс с бизнес-логикой не должен знать о регистраторе (SRP) и должен быть отдельный класс, который делает запись:
public class BetterExample : IExample
{
public void DoStuff()
{
// do the important stuff here
}
}
public class LoggingBetterExample : IExample
{
private readonly IExample betterExample;
private readonly ILogger logger;
public LoggingBetterExample(IExample betterExample, ILogger logger)
{
this.betterExample = betterExample;
this.logger = logger;
}
public void DoStuff()
{
try
{
this.betterExample.DoStuff();
}
catch (Exception e)
{
this.logger.Error(e.ToString());
}
}
}
Всякий раз, когдаIExample
Контейнер DI возвращает экземплярLoggingBetterExample
, который используетBetterExample
(которая содержит актуальную бизнес-логику) под капотом.
Сообщения в блогеМарк Симанн:
Инструментарий с декораторами и перехватчикамиВнедрение зависимостей - слабая связьСообщение в блоге и ТАК ответСтивен:
Между тем ... на командной стороне моей архитектурыВиндзор - вытащить временные объекты из контейнераМой вопрос:Очевидно, чтоLoggingBetterExample
Подход работает только до тех пор, пока ведение журнала может быть выполнено вне фактического класса.
(как в примере выше: поймать все исключенияBetterExample
снаружи)
Моя проблема в том, что я хотел бы занести другие вещи в класс.
Марк Симаннподозревал здесь что если кому-то нужно это сделать, возможно, рассматриваемый метод слишком много делает.
Как я уже говорил ранее, я нахожусь на этапе планирования нового приложения, поэтому у меня не так много кода для показа, но пример использования, который я сейчас думаю, выглядит примерно так:
Мое приложение будет иметь конфигурационный файл с некоторыми дополнительными значениями.
Пользователь может решить опустить необязательные значения, но это важное решение.
Поэтому я хотел бы записать предупреждение, если некоторые из дополнительных значений отсутствуют, на случай, если это произошло по ошибке.
(опускание значений совершенно нормально, поэтому я не могу просто выбросить исключение и остановиться)
Это означает, что у меня будет класс, который читает значения конфигурации и должен сделать что-то вроде этого (псевдокод):
var config = ReadConfigValues("path/to/config.file");
if (config.OptionalValue == null)
{
logger.Warn("Optional value not set!");
}
Неважно, еслиReadConfigValues
находится в этом классе или другой, я не думаю, что этот класс будет нарушать SRP.
Я знаю, что могу прочитать конфигурационный файл во внутреннем классе, но проверить значения (и записать предупреждение) в декораторе. Но проверка значения IMO - это бизнес-логика, а не инфраструктура, поэтому мне принадлежит тот же класс, где читается файл конфигурации.