• Анализ корреляций биржевых фондов за первую половину 2020
    0
    Красиво описаны выводы, но абсолютно неясно на основании чего они получены. Нужен код и описание метода.
  • А почему мы не пишем код в контроллерах?
    0

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


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

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

  • А почему мы не пишем код в контроллерах?
    0

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

  • А почему мы не пишем код в контроллерах?
    +1

    Это очень правильный вопрос.
    Реквест здесь — это 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. Здесь же ничего не мешает приделать атрибут, который будет указывать какой маршрут должен слушать этот реквест и, в этом случае, контроллеры становятся не нужны.

  • А почему мы не пишем код в контроллерах?
    0

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


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

  • А почему мы не пишем код в контроллерах?
    0

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

  • А почему мы не пишем код в контроллерах?
    +1

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

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

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

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

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

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


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

    Уже есть WebAssembly.

  • Теория и практика стандартизации Docker-сервисов
    0

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

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

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

    Я привык считать полезностью теста то, насколько он облегчает разработку. По опыту, тест, который падает на каждый чих не очень полезен, т.к. при его падении непонятно что конкретно сломалось.
  • Метаморфоза тестирования redux-saga
    +1
    Философский вопрос. Я бы сказал, что не прекрасно, т.к. даже в интеграционных тестах нужно стремиться к сфокусированности. Если мы от неё отказываемся, то для этого должна быть веская причина, например низкая скорость выполнения теста. В нашем случае тест хоть и не быстрый, но еще не настолько медленный, чтобы мы не могли написать отдельный тест на каждый из кейсов.
  • Метаморфоза тестирования redux-saga
    +1
    Хорошее замечание. Я сам об этом думал, когда делал пример. Он, действительно, получился не очень удачным, но проверять промежуточный результат я бы не стал, т.к. в этом случае нарушится требование сфокусированности теста — у теста появится вторая причина для падения.
    Здесь два dispatch подряд можно интерпретировать как то, что мы хотим проверить, что событие click() никак не изменит то, что в итоге в стейт будет просуното то, что вернётся в последнем событии.
  • Будь как Мунк, или пару слов о техническом долге
    +4
    Статья скорее о масштабе проблем и об усилиях, которые потребовалось вложить для приведения системы в порядок.
  • Волшебная фея для юнит-тестов: DSL в C#
    0
    Да, рекорды это круто. Скорее бы хотя бы в работу взяли)
  • Волшебная фея для юнит-тестов: DSL в C#
    0
    1. Не понял, почему не помогает? Ордер — это, кстати, не мок, а тестовые данные.


    2. Конкретно здесь Testable нужен только для того, чтобы завернуть в себя ассёрты на моках и создание самих моков. Protected методов тут нет.



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

  • Волшебная фея для юнит-тестов: DSL в C#
    0

    Можно ли накосячить при написании DSL? Да, разумеется.
    Можно ли накосячить в сложном сетапе юнит-теста? Да, разумеется.
    Разница только в том, что в первом случае косяк придется править только в одном месте, а во втором во всех тестах, использующих этот сетап.


    По поводу того, что проверяется только вызов метода: это называется "тест на поведение". О том, что следует писать тесты на состояние, а не на поведение я упоминал в статье.


    Ну и в целом, если юнит-тесты проходят, это еще далеко не значит, что у вас всё хорошо. Зато если они падают, значит всё точно плохо :)

  • Волшебная фея для юнит-тестов: DSL в C#
    0
    У нас в команде тоже нет консенсуса по этому вопросу) В статье оно приведено для ознакомления. Кому-то нравится, кому-то нет.
  • Волшебная фея для юнит-тестов: DSL в C#
    0
    1. Это не так.
    2. То, что удобно использовать при разработке бизнес-логики не обязано быть удобным для тестов и DSL как раз помогает сгладить это несоответствие.
    3. Мы стараемся писать комментарии только в самых крайних случаях. А использовать BDD фреймворки в юнит-тестах мне представляется оверхедом посильнее DSL.
    4. Дебаг любого теста со сложным сетапом не самое приятное занятие. Согласен, DSL явно не поможет его упростить, но и не сильно усложнит.
  • Волшебная фея для юнит-тестов: DSL в C#
    0

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

  • Волшебная фея для юнит-тестов: DSL в C#
    0
    Я думаю, тут нет однозначного ответа использовать или нет. Я считаю, что использование билдеров несёт больше плюсов чем минусов. Более того, с минусами сам ни разу не сталкивался. Возможно у вас другой опыт и это интересно.
    Расскажите плз, как вам мешала необходимость изучения структуры билдеров?
  • Волшебная фея для юнит-тестов: DSL в C#
    0
    Да, так и надо. Всё, кроме extension'ов студия и райдер смогут создать.
  • Волшебная фея для юнит-тестов: DSL в C#
    +1
    Справедливое замечание. Спасибо, поправил.
  • Наш первый обед вместе: почему и как мы проводим тестовый день
    0
    Кроме парной работы, есть еще одна причина: мы постепенно переводим наше решение на .net core и переходим на маки. Студия, к сожалению, работать на маках пока не умеет(
  • Redux — пересмотр логики reducer'a и actions
    0

    Подход интересный, но константы всё-равно нужны. Экшены же как-то надо диспэтчить.

  • Про одного парня
    0

    Очень напоминает книгу "Проект феникс" про дев опс.


    Статья хорошая. Как бывшему одинэснику было интересно узнать об упущенных возможностях)

  • Асинхронный рассинхрон: антипаттерны в работе с async/await в .NET
    0
    Да, что-то я погорячился. Вспомнил про примеры с наносекундами и решил, что оверхед не растет с ростом времени запроса.
  • Асинхронный рассинхрон: антипаттерны в работе с async/await в .NET
    0
    В соседней команде как раз недавно его впилили. Пока наблюдают)
  • Асинхронный рассинхрон: антипаттерны в работе с async/await в .NET
    0
    Спасибо за советы. У нас сейчас как раз висит задачка на профилирование одно из сервисов. Попробуем сделать с PerfView.
  • Асинхронный рассинхрон: антипаттерны в работе с async/await в .NET
    0
    Очень зависит от библиотеки. Например, коннектору к базе данных вполне стоит быть полностью асинхронным.
  • Асинхронный рассинхрон: антипаттерны в работе с async/await в .NET
    +2
    10 милисекунд — это где-то на три-четыре порядка больше, чем время, уходящее на создание асинхронщины. В этом случае можно вообще не волноваться.
  • Асинхронный рассинхрон: антипаттерны в работе с async/await в .NET
    +1
    Вообще вы, конечно правы в том, что async — это не панацея, и переводить решение на async просто потому что так сейчас модно, скорее всего не стоит. Однако, если ASP.NET решение упирается в пул потоков стоит наряду с увеличением пула рассмотреть вариант, при котором на hot path все вызовы будут полностью асинхронными.

    Кроме того, набирают популярность managed решения, в которых у юзеров нет доступа к размеру пула потоков.

    Я бы смотрел на async/await в ASP.NET так: микрософт предложил нам легкий способ работы с асинхронным кодом, который позволяет малой кровью подготовиться к хайлоаду «из коробки». По началу, он был кривой и косой, но уже в ASP.NET Core с ним стало вполне приятно работать и почти все известные проблемы убрали.

    Кстати, поделитесь опытом: как вы с помощью PerfView пришли к выводу, что при использовании async/await сильный оверхед?

    И еще вопрос:
    Если же они работают медленно (>100мс) — на сервер никакой серьёзной нагрузки всё равно не создать

    Можете пояснить: почему не создать?