Pull to refresh
38
0
Юрий Пастушенко @ypastushenko

.net разработчик, Dodo Pizza

Send message

Я, честно говоря, надеялся найти ответ на вопрос чем табличные тесты лучше, чем просто один тест в одной функции. Плюсы и минусы.

Красиво описаны выводы, но абсолютно неясно на основании чего они получены. Нужен код и описание метода.

Да, на входе стоит fluent validator, который избавляет от необходимости проверять поля, пришедшие с фронтенда.
Да, реквест mutable. Это трейдофф, на который я сознательно иду, чтобы иметь возможность обогащать его по ходу пайплайна. При этом все обогащения контролируются внутри решения и покрыты тестами, поэтому я могу доверять реквесту.
Если я меняю реквест, то тут 2 варианта:


  1. Мне нужны дополнительные данные с фронта и больше мне их взять неоткуда. В этом случае фронт, как не крути, придется менять.
  2. Мне нужны дополнительные данные, которые я могу получить, например из сервиса авторизации. Тогда я просто изменю соответствующий PipelineBehavior и хендлер даже не узнает о том, что что-то изменилось.

По поводу зависимости домена от asp.net: хендлер — это не доменный сервис, а скорее application-сервис в контексте луковой архитектуры. Он использует доменные сущности и сервисы, но не является доменным сам по себе, поэтому домен независим от asp.net.

Это в общем-то уже спор не о логике в контроллерах, а о том, правильно ли переиспользовать код. Мой подход: важно различать действительно ли это одна и та же операция или просто сейчас так случайно получилось, что реализация у двух операций совпала. Ну и на мой взгляд не нужно ничего переиспользовать на перёд: всё-равно учесть всего, что случится в будущем не получится.

Это очень правильный вопрос.
Реквест здесь — это DTO, который хранит в себе достаточно данных для обработки запроса. Эти данные могут быть получены из кук, url-параметров, body или даже из базы.
Этот объект собирается с помощью pipeline behavior'ов и приезжает в хендлер уже полностью заполненным.
Вот пример реквеста:


    [PublicAPI]
    public class Request : IRequest<Response>, IAuthorizableRequest
    {
        public SecretBuyerClaimsPrincipal SecretBuyer { get; set; }

        [FromRoute] public UUId CheckupId { get; set; }
        [FromRoute] public UUId QuestionId { get; set; }
        [FromHeader(Name = "Content-Length")] public int ContentLength { get; set; }
        [FromHeader(Name = "X-Filename")] public string FileName { get; set; }
    }

Здесь CheckupId, QuestionId, ContentLength и FileName заполняются обработчиком запросов asp.net.


В свою очередь SecretBuyerClaimsPrincipal — это реализация интерфейса IAuthorizableRequest. Это свойство заполняется хендлером авторизации.


Здесь могут быть и другие поля, которые в теории могут хоть с луны прилететь и хендлер, который будет обрабатывать реквест об этом задумываться не будет.


Таким образом реквест становится управляющим объектом. На него, при помощи интерфейсов, можно навесить множество типовых поведений, таких как например ретрай на OptimicticConcurrencyException. Здесь же ничего не мешает приделать атрибут, который будет указывать какой маршрут должен слушать этот реквест и, в этом случае, контроллеры становятся не нужны.

Handler, который принимает с фронта реквест уже и есть BL. Это, как раз, возможно из-за отказа от контроллеров.


Что касается очереди, я очень сильно топлю за то, чтобы в очередь уходили события, структура которых сделана именно под очередь. Никакие реквесты с фронта не должны туда пролезать.

Так реквест и остается в хендлере. Его единственная ответственность — это донести информацию с фронта в нужный хендлер. Если кто решит тащить реквест в очередь, то проблема как раз в том, что это ошибочное решение.

Отличная статья. У меня тоже возникают подобные мысли, но они больше о том, что контроллеры — это пережиток прошлого. Они были актуальны, когда мы писали с использованием MVC, а на сегодняшний день большие проекты это скорее отдельный бандл с фронтом и API например на ASP.NET. То есть вьюх больше нет, модель — это детали реализации, но контроллеры мы продолжаем фанатично использовать.
Но некоторое время назад мы стали переходить на Mediatr и писать однострочные контроллеры, которые вызывают всегда один и тот же метод mediator.Send(request) и в этот момент вопрос "А нужны ли нам контроллеры?" заиграл новыми красками. Такой вопрос появился ещё, как минимум, у одного человека, который сделал библиотеку https://smithgeek.com/announcing-voyager/. Она позволяет писать код для каждого обработчика в отдельном файле и управлять роутингом с помощью атрибутов для Реквеста, а не для метода контроллера.
По факту, люди использующие медиатр уже и так управляют пайплайном обработки путём навешивания на реквест атрибутов и интерфейсов, Voyager же перекладывает на реквест ещё и роутинг и контроллеры становятся не нужны.

Да, я как раз про это.
Видимо сказывается многозначность термина «Поток» в русском языке) Он может означать и thread и asynchronous flow.
При переводе большой системы в multitennant это, конечно вполне оправданное решение. Но при всех его плюсах, также очевидны и минусы.
Вы бы стали его использовать при проектировании multitennant-системы с нуля или всё же воспользовались бы идентификатором теннанта?
Александр, спасибо за статью. Хотелось бы кое-что прояснить для себя:
1. Не беспокоитесь ли вы, что с ростом количества клиентов у вас будут проблемы с администрированием N баз данных?
2. Как вы шерите общие справочники, актуальные одновременно для всех тенантов?
3. Что такое «монолитные сервисы» и чем они отличаются от микросервисов в вашей интерпретации?
4. Вам не мешает жесткая привязка тенанта к потоку при выполнении асинхронного метода контроллера для http-запроса? Ведь при выполнении асинхронной операции неизвестно в каком потоке будет выполнен continuation после await.
Причем здесь open-source движение? Причем здесь MySQL, Postgree и Google? Здесь на одной из сторон в абсолютно хозяйственном споре выступает гэбня! Причём дело касается реально самой уважаемой в айтишном мире российской разработки. Даже сам Яндекс не может похвастаться таким успехом в мире как NGINX. И вы пишете «Рамблер, не надо трогать open-source»…
Что там вообще в голове-то у вас? Рамблер, конечно мерзотнейше себя ведёт, спору нет, но без поддержки ОБЭПа и прочей братии, он бы даже влезать в эту заранее проигрышную историю не стал.
Похоже, что после принятия закона о значимых российских айти-компаниях вы выдохнули и считаете, что за вами уже не придут и можно расслабится… ну флаг вам в руки…

Спасибо, хорошая справочная подборка.
Только, насколько я знаю cte есть только в sql server, а 4 практически эквивалентно 3.

Спасибо за уточнение. Убрал этот пункт. Фактическая ошибка.
Если я правильно понял вашу статью, всё что предлагают «товарищи» это как бы делать всё то что делает TCP, только программным способом.

Не совсем. QUIC ещё должен решить проблему «head-of-line blocking» и предоставить лёгкий способ поддержания соединения при изменении IP-адреса клиента.

В связи с этим такой вопрос, как вы думаете не связано ли это «движение» с заблаговременной подготовкой ко встрече 5G ???


Не думаю, что у меня достаточно компетенций, чтобы уверенно отвечать на этот вопрос. Могу только сказать, что тесты производительности для gQUIC в случае работы через смартфон по мобильной сети, показывают, что gQUIC в этом случае имеет меньший отрыв от  TCP, чем при использовании десктопного компьютера и кабельного интернета. Да, тут больше важна производительность смартфона, но всё-равно, думаю, что развитие мобильных сетей в меньшей степени оказывает влияние на развитие QUIC, чем упоротость создателей и желание решить указанные выше проблемы :)
Насколько я знаю, нет. Он только про замену js.

Уже есть WebAssembly.

Спасибо, интересная статья.
Кто у вас накатывает миграции БД во время деплоя? Если это делает CI система, то где она берет кренделя для подключения к базе?

Олеся, отдельное спасибо за плейлист)
Сфокусированность теста обратно пропорциональна его полезности. Т.е., набор несфокусированных тестов всегда строго лучше, чем эквивалентный набор сфокусированных, т.к. отловит строго большее количество ошибок.

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

Я привык считать полезностью теста то, насколько он облегчает разработку. По опыту, тест, который падает на каждый чих не очень полезен, т.к. при его падении непонятно что конкретно сломалось.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Works in
Date of birth
Registered
Activity