Здравствуйте, IQuerist, Вы писали:
IQ>>>Честно нет... я искренне не ожидал, что одинаковые вещи могут по разному называться и по разному оцениваться. Для меня это честно было сюрпризом. Но в мутной теме обязаны быть грязные хаки
надо лишь поискать.
IQ>·>Ничего не понял. Тема не мутная, похоже муть у тебя в голове. ServiceLocator и Ambient Context вещи не одинаковые, вообще ничего общего.
IQ>·>Ambient Context это хипстерская обёртка для обеспечения более вменяемого использования глобальных переменных.
IQ>·>А Service Locator это фактически такая мапа [serviceId -> serviceImplementation], называемая Registry. Притом сама мапа может протягиваться как через те же глобальные переменные (и даже с использованием Ambient Context), через DI, тупо через арументы метода или ещё как.
IQ>Читаем талмудъ:
IQ>https://smarly.net/dependency-injection-in-net/di-catalog/di-patterns/ambient-context
IQ>IQ>Ambient Context сходный по структуре с анти-паттерном Service Locator,
Выражения "Сходный по структуре" и "одинаковые вещи" — не одинаковые вещи, и даже не сходны по структуре. Сходность по структуре не означает, что можно ambient context в коде называть как service locator.
Почему для тебя это сюрприз — я до сих пор не понимаю. Ведь даже в этом талмуде это по-разному оценивается: Service Locator записали в анти-паттерн, а Ambient Context как паттерн.
IQ>Кстати там же про Thread Local Storage и HttpContext
А ещё там написано "Ambient Context должен быть использован только в редчайших случаях". А ты предлагаешь это как дефолтное решение.
У меня был опыт, что даже приведённый в этом талмуде пример с TimeProvider как глобальня переменная (или ambient context, что почти то же самое) дал сбой. У нас в приложении оказалось нужно два вида часов — физические для текущего запуска и логические, определяемые проигрыванием исторических событий из лога и для реализации "машины времени", применяемой для системного тестирования (а как ещё протестировать, например, что некий отчёт создаётся по пятницам?). Поэтому нам пришлось дружно заменять по всему коду статики на DI+CI.
IQ>·>Причём тут бизнес-операция? Это вообще не в тему. Смотрим что ты написал:
IQ>·>"и с десяток совершенно очевидных хелперных stateless методов типа: GetBoringItemById". Вот как такой метод может быть stateless? Как мне доводилось видеть, сигнатура такого метода типично
IQ>·>public BoringItem GetBoringItemById(long id)
IQ>·>или у тебя другие варианты?
IQ>·>Покажи как ты видишь этот метод сделать stateless. Ему как минимум нужен borrowed DbConnection и активный TransactionContext, а ещё, бывает, какой-нибудь security context и audit recorder.
IQ>GetBoringItemById не имеет состояния, состояние "DbConnection и активный TransactionContext" предоставляются ему внешними сервисами.
Они ему не предоставляются, а он их сам находит. Если бы сигнатура была
public BoringItem GetBoringItemById(long id, DbConnection db, TransactionContext tx) — вот это stateless.
Иначе у тебя получается, что любая функция на C — stateless, т.к. классов нет, все функции "статические".
IQ>Да в моем случае этот сервис глобальный (как и loggingContext). Ваш пример конечно интересен, хотя на мой взгляд никаких явных TransactionContext, security context и audit recorder и т.д. в DAL быть не должно — не тот уровень абстракции
Они все же должны быть в высокоуровневом сервисе и это имхо очевидный маркер того, что в случае GetBoringItemById DI используется неверно.
Это просто самые очевидные и понятные примеры, не придирайся к конкретным названиям. Суть в том, что такие зависимости или что-то подобное может появиться когда-то и "We still get no help if we need to add a new dependency: is it a breaking change or not?".