Comments 13
Snake Case в тестах прям глаза режет. Это же шарпы https://www.dofactory.com/csharp-coding-standards
я его использую только для наименования тестов. Так из названия тестов хорошо видно, что именно тест тестирует - привык🤷♂️
Нижнее подчёркивание действительно принято использовать в именах тестов, но чаще всего им отделяют три компонента названия: объект тестирования (например метод), сценарий и ожидаемое поведение, например:
[Fact]
public void Add_SingleNumber_ReturnsSameNumber()
{
var stringCalculator = new StringCalculator();
var actual = stringCalculator.Add("0");
Assert.Equal(0, actual);
}Взято отсюда https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices#follow-test-naming-standards
а не лучше вот так? : settingsProvider.Setup(x => x.Get(It.IsAny<string>())).Returns(0);
Хорошая статья, но режет глаз наследование ImageCacheMiddlewareForTesting для тестов. ASP.NET Core middleware поддерживает Constructor Injection — можно просто инжектить ISettingsProvider напрямую, без виртуальных методов и наследников. Тогда и тесты станут чище, и продакшен-код не придётся менять ради тестирования. А в остальном — подход через middleware годный, спасибо!
спасибо за совет, попробую. Если правильно помню, что-то не завелось через constructor injection именно в middlewares. Это первое, что я пробую обычно, т.к. самый простой и наиболее логичный путь. Для ViewComponents напр. construction injwction завелся, а для middlewares почему-то нет. Но я пробовал это на более ранних версиях MVC Core - тогда нашел рабочий вариант с HttpContext.RequestServices.GetService<T>() и так его и использую с тех пор. Вообщем посмотрю, спасибо👍
Я не люблю смешивать функциональные и нефункциональные аспекты, поэтому буду использовать третий вариант с промежуточным слоем.
Не совсем понятен этот тезис. У вас контроллер и есть то место, которое целиком и полностью отвечает только за http запросы. То,что делается одним атрибутом (вариант 1) или вариант 2 с возможностью читать срок жизни кэша из настроек, вы размазали в избыточные строки кода. Кроме того, ваш промежуточный слой сейчас кэширует вообще все ответы, а это значит что его нужно доработать, добавив в код if условия и, вероятно, связность с нужным контроллером, чтобы понимать нужно кэшировать или нет.
Upd. Увидел, что эту связность вы запихнули вообще в самое неподходящее место - в use. Код стал плохо поддерживаемый.
>Не совсем понятен этот тезис. У вас контроллер и есть то место, которое целиком и полностью отвечает только за http запросы.
При чем здесь http запросы? Я писал про смешивание функциональных и нефункциональных аспектов внутри контроллера. Функциональные аспекты - то что относится к основной деятельности контроллера (в данном случае, работа с картинками - операции с их созданием, удалением, масштабированием и др), нефункциональные - обвязка вокруг функциональных (логирование, кеширование, обработка транзакций и др).
> Кроме того, ваш промежуточный слой сейчас кэширует вообще все ответы, а это значит что его нужно доработать, добавив в код if условия и, вероятно, связность с нужным контроллером, чтобы понимать нужно кэшировать или нет.
все ответы из action-а под названием View, чего и нужно было добиться
> Upd. Увидел, что эту связность вы запихнули вообще в самое неподходящее место - в use. Код стал плохо поддерживаемый.
по-моему, это наиболее подходящее место для подобных вещей, чтобы оставить код контроллера "чистым". Согласен, что с таким подходом, глядя на action View, сразу сложно сказать, что его результат кэшируется - у себя я решил это добавлением однострочного комментария над action-ом. Но если вам этот подход не нравится, можете использовать другие - для этого я их и упомянул
Вы видимо неправильно понимаете границы ответственности работы контроллеров в ASP. То, что вы пишите "в данном случае, работа с картинками - операции с их созданием, удалением, масштабированием и др" - это, извините меня, ответственность не котроллера, а доменного слоя. Контроллер - это порт из терминологии про луковую\ортодоксальную архитектуру, и никакую бизнес логику содержать не может. Про токний\ходой контроллер и про его потомка в виде minimal API слышали же? Представим, что завтра у вас появляется новый канал связи с клиентами: шина, web socket, gRPC и т.д. Вы операции работы с файлами все будете туда копировать? Контроллер отвечает за полный цикл взаимодействия между доменной логикой и её потребителями, в том числе и за управление кэшированием, т.к. это нефункциональные требования канала.
>>нефункциональные - обвязка вокруг функциональных (логирование, кеширование, обработка транзакций и др).
О как интересно. По вашему, в сервис нельзя инжектить (вы же надеюсь против DI ничего не имеете?) ILogger и потом его там вызывать, ведь это же нефункциональные возможности, а не бизнес логика?
А авторизацию (подчёркиваю, авторизацию) вы как делаете у себя, раз у вас неприязнь к атрибутам?
А такие нефункциональные требования как "система должна отвечать не более чем за 3 секунды" - это обвязка над чем? У вас какое-то свое вольное трактование требований.
>>все ответы из action-а под названием View, чего и нужно было добиться
А если, а точнее когда, мне нужно будет сделать разные правила кэширования, например, видео на 1 неделю, изображения на 20 дней, а аватары пользователей - вообще не кэшировать, вы это как делать будете в своем одном месте управления "аспектом кэширования"? Ну понятно, наставите if'ов. А потом у вас и тесты будут структурированы не по доменной зоне, а по аспектной. Сомнительно, ну ок, если вам так нравится.
>>Но если вам этот подход не нравится
Вот вы себя архитектором назвали, статью написали, а рассуждаете, как будто мы пришли на выставку посредственного искусства, в терминах нравится не нравится. В инженерии нет такого понятия. Мы должны делать поддерживаемые и масштабируемые решения с минимальными затратами на эту самую поддержку в будущем. Ваш код получает излишнюю цикломатическую и ментальную сложность, что скажется на его поддержке в будущем.
И при этом, ладно бы, придумали что-то новое, но нет, отказались от общепринятых решений в пользу костылей. Или вы наверное хотите сказать, что архитекторы из майкрософт, которые дали нам такие возможности, дураки и ошибаются, а вы... А вы распространяете вредные советы, надеюсь жуны (кои еще остались) и обучающие датасеты ИИ не возьмут в серьёз ваше решение.
Вы видимо неправильно понимаете границы ответственности работы контроллеров в ASP. То, что вы пишите "в данном случае, работа с картинками - операции с их созданием, удалением, масштабированием и др" - это, извините меня, ответственность не котроллера, а доменного слоя
во первых, полноценный доменный слой не всегда нужен: частно достаточно внутри вызвать метод соответствующего репозитория (про паттерн репозиторий же слышали? Как встречный вопрос по DI :) ). Во-вторых, в моей статье ни о каких шинах, web socketах, gRPC и т.д речь не идет. Не надо натягивать сову на глобус.
По вашему, в сервис нельзя инжектить
где про это говорится в статье?
ILogger и потом его там вызывать, ведь это же нефункциональные возможности, а не бизнес логика?
волне себе можно, я так и делаю, когда других возможностей нет. Да смешивание, да не нравится, но приходится делать. Там, где можно избежать прямого использования ILogger, стараюсь избегать. Мир - это не черное и белое
А авторизацию (подчёркиваю, авторизацию) вы как делаете у себя, раз у вас неприязнь к атрибутам?
авторизацию делаю аттрибутами - там это вполне оправдано (см. предыдущий ответ)
А такие нефункциональные требования как "система должна отвечать не более чем за 3 секунды" - это обвязка над чем?
требование к производительности, именно что нефункциональное
А если, а точнее когда, мне нужно будет сделать разные правила кэширования, например, видео на 1 неделю, изображения на 20 дней
опять попытка натянуть сову на глобус
Ваш код получает излишнюю цикломатическую и ментальную сложность, что скажется на его поддержке в будущем.
по-моему, наоборот - сложность увеличивается если смешивать все аспекты в одну кучу
Последний абзац комментировать не буду, неконструктивно.
Кешируем отдачу картинок в .NET MVC Core