Channel: .NET Разработчик
День 2237. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 44. Высокое качество естественным образом ведет к повышению продуктивности. Окончание
Начало
Стоимость качества
На решение проблемы уходит больше времени и денег, чем на её предотвращение. Плохо выполненная работа доставляет хлопоты всем, кто находится далее в цепочке рабочего процесса, и имеет неприятные побочные последствия, такие как:
- накопление технического долга, из-за которого становится все труднее улучшать продукт;
- упущенные возможности и задержки в других проектах из-за того, что разработчики отвлекаются на переделки;
- перебои в обслуживании клиентов и последующие отчёты о проблемах, потеря доверия и, возможно, судебные иски;
- гарантийные претензии, возвраты и недовольные клиенты.
Под стоимостью качества понимается общая цена, которую компания платит за поставку продукции и услуг приемлемого качества. Стоимость качества складывается из:
1. Предотвращения дефектов
Планирование качества, обучение, мероприятия по совершенствованию процессов, анализ первопричин.
2. Оценки качества
Оценка рабочих продуктов и процессов на предмет проблем с качеством.
3. Внутренних отказов
Анализ отказов и доработка для устранения проблем перед выпуском продукта.
4. Внешних отказов
Анализ отказов и доработка для устранения проблем после доставки; работа с претензиями клиентов, исправление и замена продукции.
Экономия на затратах по предотвращению дефектов и оценке качества приводит к стремительному росту стоимости отказов. Помимо затрат времени и средств на доработку, внешние отказы могут привести к негативным последствиям для бизнеса, таким как снижение эффективности и уход клиентов к конкурентам. Существует множество страшных историй о компаниях, понесших огромные убытки и потерявших доверие общественности в результате сбоев в ПО.
Для организаций, занимающихся разработкой, полезно подсчитать свои общие затраты на качество и понять, как эти суммы распределяются между разными видами деятельности по обеспечению качества. Для этого необходимо собрать и проанализировать данные, как расходуются средства на обеспечение качества. Такие данные позволят организации выбирать, на что именно потратить свои деньги.
Например, узнав, какой процент бюджета уходит на разработку нового ПО, а какой — на предотвращение дефектов, оценку качества, внутренние и внешние отказы, вы сможете уделить больше сил обеспечению качества с максимальной для себя выгодой. Такой анализ показывает, что вложения организации в предотвращение и раннее обнаружение дефектов окупаются.
Обычные человеческие ошибки и некоторые доработки неизбежны. Доработка может увеличить ценность продукта, но только если делает его более функциональным, эффективным, надёжным или удобным в использовании. Руководители компании могут согласиться с неизбежностью некоторых доработок в качестве приемлемого компромисса между скоростью и небольшими первоначальными затратами. Это деловое решение хорошо выглядит в бухгалтерских книгах, но может привести к более дорогостоящим проблемам в будущем. Методы, описанные в конце урока 43, тоже сокращают затраты на доработку и тем самым снижают общие затраты организации на обеспечение качества и повышение продуктивности.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 6.
Уроки 50 Лет Разработки ПО
Урок 44. Высокое качество естественным образом ведет к повышению продуктивности. Окончание
Начало
Стоимость качества
На решение проблемы уходит больше времени и денег, чем на её предотвращение. Плохо выполненная работа доставляет хлопоты всем, кто находится далее в цепочке рабочего процесса, и имеет неприятные побочные последствия, такие как:
- накопление технического долга, из-за которого становится все труднее улучшать продукт;
- упущенные возможности и задержки в других проектах из-за того, что разработчики отвлекаются на переделки;
- перебои в обслуживании клиентов и последующие отчёты о проблемах, потеря доверия и, возможно, судебные иски;
- гарантийные претензии, возвраты и недовольные клиенты.
Под стоимостью качества понимается общая цена, которую компания платит за поставку продукции и услуг приемлемого качества. Стоимость качества складывается из:
1. Предотвращения дефектов
Планирование качества, обучение, мероприятия по совершенствованию процессов, анализ первопричин.
2. Оценки качества
Оценка рабочих продуктов и процессов на предмет проблем с качеством.
3. Внутренних отказов
Анализ отказов и доработка для устранения проблем перед выпуском продукта.
4. Внешних отказов
Анализ отказов и доработка для устранения проблем после доставки; работа с претензиями клиентов, исправление и замена продукции.
Экономия на затратах по предотвращению дефектов и оценке качества приводит к стремительному росту стоимости отказов. Помимо затрат времени и средств на доработку, внешние отказы могут привести к негативным последствиям для бизнеса, таким как снижение эффективности и уход клиентов к конкурентам. Существует множество страшных историй о компаниях, понесших огромные убытки и потерявших доверие общественности в результате сбоев в ПО.
Для организаций, занимающихся разработкой, полезно подсчитать свои общие затраты на качество и понять, как эти суммы распределяются между разными видами деятельности по обеспечению качества. Для этого необходимо собрать и проанализировать данные, как расходуются средства на обеспечение качества. Такие данные позволят организации выбирать, на что именно потратить свои деньги.
Например, узнав, какой процент бюджета уходит на разработку нового ПО, а какой — на предотвращение дефектов, оценку качества, внутренние и внешние отказы, вы сможете уделить больше сил обеспечению качества с максимальной для себя выгодой. Такой анализ показывает, что вложения организации в предотвращение и раннее обнаружение дефектов окупаются.
Обычные человеческие ошибки и некоторые доработки неизбежны. Доработка может увеличить ценность продукта, но только если делает его более функциональным, эффективным, надёжным или удобным в использовании. Руководители компании могут согласиться с неизбежностью некоторых доработок в качестве приемлемого компромисса между скоростью и небольшими первоначальными затратами. Это деловое решение хорошо выглядит в бухгалтерских книгах, но может привести к более дорогостоящим проблемам в будущем. Методы, описанные в конце урока 43, тоже сокращают затраты на доработку и тем самым снижают общие затраты организации на обеспечение качества и повышение продуктивности.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 6.
👍6
День 2236. #ЧтоНовенького #NET10
System.Linq.Async Стал Частью .NET 10
IAsyncEnumerable — интерфейс, который был представлен во времена netcoreapp3.1. Хотя он и похож на IEnumerable (пусть и асинхронный), он никогда не имел таких возможностей, как его синхронный аналог. До .NET 10. Теперь у нас есть некоторое соответствие функций между ними.
Что такое IAsyncEnumerable?
Представьте, что у вас есть коллекция чего-то. В IEnumerable<T> это может быть Enumerable.Range(0, 10_000), что сгенерирует 10000 элементов. Но что, если генерация каждого элемента асинхронна?
Task<IEnumerable<T>> нам поможет? Не совсем. Придётся сначала ждать генерации всех элементов, а потом их обрабатывать.
А как насчет IEnumerable<Task<T>>? Семантика намекает, что у нас есть коллекция, в которой каждый элемент должен быть ожидаем. Но вам придётся заботиться о каждом элементе самостоятельно. Т.е. метод возвращает перечисление из задач, а вам решать, как обрабатывать эти задачи. Вот тут и поможет IAsyncEnumerable. По сути он похож на IEnumerable<Task<T>>, но упрощает обработку результатов. См. подробнее про асинхронные коллекции.
AsyncEnumerable
AsyncEnumerable, как и его синхронная версия Enumerable, определяет все полезные расширения (вроде Select, Where и т. д.) для типа IAsyncEnumerable. Поэтому вы можете написать такой код:
Или:
Т.е. материализующая часть имеет суффикс Async. В целом, это может помочь более широкому использованию IAsyncEnumerable, хотя он в любом случае остаётся довольно нишевым. Вот оригинальное предложение на GitHub. А полный список изменений тут.
System.Linq.Async
Этот API не новый, а взят отсюда. API доступен через NuGet-пакет System.Linq.Async. Хотя пакет по-прежнему действует для всего ниже .NET 10, нет смысла использовать его начиная с 10й версии. Поэтому пакет можно полностью удалить. API, судя по всему, идентичен. Если у вас этот пакет используется в качестве транзитивной зависимости, можно исключить библиотеку вот так:
Источник: https://steven-giesel.com/blogPost/e40aaedc-9e56-491f-9fe5-3bb0b162ae94/systemlinqasync-is-part-of-net-10-linq-for-iasyncenumerable
System.Linq.Async Стал Частью .NET 10
IAsyncEnumerable — интерфейс, который был представлен во времена netcoreapp3.1. Хотя он и похож на IEnumerable (пусть и асинхронный), он никогда не имел таких возможностей, как его синхронный аналог. До .NET 10. Теперь у нас есть некоторое соответствие функций между ними.
Что такое IAsyncEnumerable?
Представьте, что у вас есть коллекция чего-то. В IEnumerable<T> это может быть Enumerable.Range(0, 10_000), что сгенерирует 10000 элементов. Но что, если генерация каждого элемента асинхронна?
Task<IEnumerable<T>> нам поможет? Не совсем. Придётся сначала ждать генерации всех элементов, а потом их обрабатывать.
А как насчет IEnumerable<Task<T>>? Семантика намекает, что у нас есть коллекция, в которой каждый элемент должен быть ожидаем. Но вам придётся заботиться о каждом элементе самостоятельно. Т.е. метод возвращает перечисление из задач, а вам решать, как обрабатывать эти задачи. Вот тут и поможет IAsyncEnumerable. По сути он похож на IEnumerable<Task<T>>, но упрощает обработку результатов. См. подробнее про асинхронные коллекции.
AsyncEnumerable
AsyncEnumerable, как и его синхронная версия Enumerable, определяет все полезные расширения (вроде Select, Where и т. д.) для типа IAsyncEnumerable. Поэтому вы можете написать такой код:
IAsyncEnumerable<MyObject> items = GetItems();
var filtered = await items
.Where(x => x.IsEnabled)
.ToListAsync(cancellationToken: token);
Или:
var avg = await items
.Select(s => s.SomeNumber)
.AverageAsync(cancellationToken);
Т.е. материализующая часть имеет суффикс Async. В целом, это может помочь более широкому использованию IAsyncEnumerable, хотя он в любом случае остаётся довольно нишевым. Вот оригинальное предложение на GitHub. А полный список изменений тут.
System.Linq.Async
Этот API не новый, а взят отсюда. API доступен через NuGet-пакет System.Linq.Async. Хотя пакет по-прежнему действует для всего ниже .NET 10, нет смысла использовать его начиная с 10й версии. Поэтому пакет можно полностью удалить. API, судя по всему, идентичен. Если у вас этот пакет используется в качестве транзитивной зависимости, можно исключить библиотеку вот так:
<PackageReference Include="System.Linq.Async" Version="6.0.1">
<ExcludeAssets>all</ExcludeAssets>
</PackageReference>
Источник: https://steven-giesel.com/blogPost/e40aaedc-9e56-491f-9fe5-3bb0b162ae94/systemlinqasync-is-part-of-net-10-linq-for-iasyncenumerable
👍25
День 2239. #Книги
«Kubernetes для разработчиков» (Деннис У. — СПб.: Питер, 2025).
Прочитал подаренную издательством «Питер» книгу про Kubernetes.
Могу сказать, что это прекрасное пособие для тех, кто хочет ознакомиться с технологией. При этом книга подойдёт даже совсем новичкам, потому что начинается с самых основ контейнеризации, создания «Hello World» в докере, постепенно увеличивая сложность. Добавляется простенький веб-сервис, разворачивается в кубере, добавляются реплики, сервисы, проверки жизнеспособности, автомасштабирование, балансировщики, и т.д., и т.п. При этом всё с подробными разборами примеров. Я лично не выполнял все примеры (тем более, что они на Python – хотя это нисколько не мешает, код не сложный). Но для закрепления материала, конечно, полезнее будет всё потыкать на практике.
Ещё хотел бы отметить качество перевода. Поскольку я сам участвовал в переводах книг, то обращаю на это внимание. Так вот, здесь перевод один из лучших, которые я встречал. Это, конечно, вопрос вкуса, но на мой взгляд соблюли хороший баланс между переводом терминов на русский язык, которые можно легко перевести (nodes – узлы, deployment – развёртывание и т.п.), при этом оставив то, что сложно переводится, как есть (поды или Stateful-приложения), не уходя в излишнюю «литературность» перевода. Сервисы названы сервисами, а не службами! Единственное, что немножко «резануло глаз» - это «продуктивная среда» (отсюда и недавний опрос), но к этому быстро привыкаешь. Так что спасибо научному редактору перевода, Алексею Патрину (кстати, C#-разработчику), за работу.
В общем, книга не сделает вас спецом по Kubernetes, но получить довольно неплохую базу по технологии поможет. Советую.
Ещё раз спасибо за подарок издательству «Питер». Присылайте что-нибудь ещё 😊
«Kubernetes для разработчиков» (Деннис У. — СПб.: Питер, 2025).
Прочитал подаренную издательством «Питер» книгу про Kubernetes.
Могу сказать, что это прекрасное пособие для тех, кто хочет ознакомиться с технологией. При этом книга подойдёт даже совсем новичкам, потому что начинается с самых основ контейнеризации, создания «Hello World» в докере, постепенно увеличивая сложность. Добавляется простенький веб-сервис, разворачивается в кубере, добавляются реплики, сервисы, проверки жизнеспособности, автомасштабирование, балансировщики, и т.д., и т.п. При этом всё с подробными разборами примеров. Я лично не выполнял все примеры (тем более, что они на Python – хотя это нисколько не мешает, код не сложный). Но для закрепления материала, конечно, полезнее будет всё потыкать на практике.
Ещё хотел бы отметить качество перевода. Поскольку я сам участвовал в переводах книг, то обращаю на это внимание. Так вот, здесь перевод один из лучших, которые я встречал. Это, конечно, вопрос вкуса, но на мой взгляд соблюли хороший баланс между переводом терминов на русский язык, которые можно легко перевести (nodes – узлы, deployment – развёртывание и т.п.), при этом оставив то, что сложно переводится, как есть (поды или Stateful-приложения), не уходя в излишнюю «литературность» перевода. Сервисы названы сервисами, а не службами! Единственное, что немножко «резануло глаз» - это «продуктивная среда» (отсюда и недавний опрос), но к этому быстро привыкаешь. Так что спасибо научному редактору перевода, Алексею Патрину (кстати, C#-разработчику), за работу.
В общем, книга не сделает вас спецом по Kubernetes, но получить довольно неплохую базу по технологии поможет. Советую.
Ещё раз спасибо за подарок издательству «Питер». Присылайте что-нибудь ещё 😊
👍45
День 2241. #ЗаметкиНаПолях
Выполнение Очистки в BackgroundService
Есть что-то немного странное в шаблоне Worker Service в .NET.
Создадим новый проект Worker Service с помощью:
Класс Worker использует BackgroundService в качестве базового класса. Worker имеет метод ExecuteAsync(…), который вызывается при запуске сервиса и принимает CancellationToken. В ExecuteAsync(…) есть цикл while, который проверяет, отменён ли CancellationToken. Если да, цикл завершается, и всё, что находится за пределами цикла, должно быть выполнено. В цикле есть вызов Task.Delay(1000, stopToken), который задерживается на 1 секунду и также принимает токен отмены.
Если Worker делает мало работы, задержка во время каждой итерации цикла велика по сравнению со временем, которое занимает фактическая работа. И отмена, скорее всего, произойдет во время периода задержки. Если CancellationToken отменяется во время задержки, Task.Delay(…) должен выбросить TaskCanceledException.
Но этого не происходит. Метод ExecuteAsync(…) прекращает работу, но исключение не выбрасывается. Код за пределами цикла while не выполняется. Это означает, что любой код очистки, который я хочу запустить при отмене BackgroundService, скорее всего, не будет выполнен, т.к. отмена обычно происходит во время задержки. Это странно.
Если запустить аналогичное консольное приложение, Task.Delay(…) выбросит TaskCanceledException, и мы получим исключение.
Получим:
Но фоновый процесс не выбрасывает исключения!
Решение
Обернём Task.Delay(1000, stopsToken) в try…catch, перехватывая TaskCanceledException:
Если вы используете Task.Delay(1000) без токена отмены, код дождётся окончания задержки, прежде чем выходить из while, но любой код после выполнится.
Также можно попробовать:
Они тоже не прервут работу и выполнят код после задержки.
Источник: https://nodogmablog.bryanhogan.net/2025/02/doing-some-cleanup-in-a-canceled-background-service/
Выполнение Очистки в BackgroundService
Есть что-то немного странное в шаблоне Worker Service в .NET.
Создадим новый проект Worker Service с помощью:
dotnet new worker -n MyWorker
Класс Worker использует BackgroundService в качестве базового класса. Worker имеет метод ExecuteAsync(…), который вызывается при запуске сервиса и принимает CancellationToken. В ExecuteAsync(…) есть цикл while, который проверяет, отменён ли CancellationToken. Если да, цикл завершается, и всё, что находится за пределами цикла, должно быть выполнено. В цикле есть вызов Task.Delay(1000, stopToken), который задерживается на 1 секунду и также принимает токен отмены.
Если Worker делает мало работы, задержка во время каждой итерации цикла велика по сравнению со временем, которое занимает фактическая работа. И отмена, скорее всего, произойдет во время периода задержки. Если CancellationToken отменяется во время задержки, Task.Delay(…) должен выбросить TaskCanceledException.
Но этого не происходит. Метод ExecuteAsync(…) прекращает работу, но исключение не выбрасывается. Код за пределами цикла while не выполняется. Это означает, что любой код очистки, который я хочу запустить при отмене BackgroundService, скорее всего, не будет выполнен, т.к. отмена обычно происходит во время задержки. Это странно.
Если запустить аналогичное консольное приложение, Task.Delay(…) выбросит TaskCanceledException, и мы получим исключение.
var cts = new CancellationTokenSource(3000);
var stopToken = cts.Token;
int count = 0;
while (!stopToken.IsCancellationRequested)
{
Console.WriteLine($"{++count} - {DateTime.Now:HH:mm:ss}");
await Task.Delay(1000, stopToken);
}
Console.WriteLine("Exiting");
Получим:
1 - 01:23:45
2 - 01:23:46
3 - 01:23:47
Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
…
Но фоновый процесс не выбрасывает исключения!
Решение
Обернём Task.Delay(1000, stopsToken) в try…catch, перехватывая TaskCanceledException:
protected override async Task
ExecuteAsync(CancellationToken stopToken)
{
while (!stopToken.IsCancellationRequested)
{
Console.WriteLine($"До: {DateTime.Now:HH:mm:ss}");
try
{
await Task.Delay(1000, stopToken);
}
catch (TaskCanceledException)
{
Console.WriteLine($"Отмена в Task.Delay.");
break;
}
Console.WriteLine($"После: {DateTime.Now:HH:mm:ss}");
}
Console.WriteLine("Очистка");
}
Если вы используете Task.Delay(1000) без токена отмены, код дождётся окончания задержки, прежде чем выходить из while, но любой код после выполнится.
Также можно попробовать:
await Task.Delay(1000, stopToken)
.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
// или
await Task.Delay(1000, stopToken)
.ContinueWith(t => { return t.Exception == default;});
Они тоже не прервут работу и выполнят код после задержки.
Источник: https://nodogmablog.bryanhogan.net/2025/02/doing-some-cleanup-in-a-canceled-background-service/
👍8👎1
День 2242. #Карьера
Собеседования и Рынок .NET в РФ
Походил я тут ради интереса в последнее время по собеседованиям. Уже выкладывал задачу на код ревью от Озона. Сегодня хочу порассуждать о собеседованиях и в принципе о состоянии найма в ИТ.
В предыдущий раз я собеседовался аж в 2021 году. Хочу отметить, что если тогда все по классике спрашивали Рихтера, async-await и ленивое выполнение в LINQ, то сейчас этого очень мало. Почти везде (а я был на 4х техсобесах в разных компаниях), жёстко гоняют по «кабанчику». Распределённые системы, очереди сообщений, репликации и точки отказа. Надо, конечно, как советуют многие, ходить для профилактики на собеседования хотя бы раз в полгода-год, а то упускаешь, что сегодня в тренде. «Кабанчика» пришлось перечитать, т.к. многое оттуда забыл.
Ещё хотелось бы отметить довольно странную работу HR отделов компаний (исключая крупные, вроде Т-банка, Озона или Контура). 60% на присланное резюме просто не реагируют никак (хотя оно отправлялось напрямую по указанному в вакансии контакту), либо ограничиваются «я передам резюме руководству и вернусь с обратной связью». Дальше, как в меме: «С обратной связью, конечно, никто возвращаться не собирался». Они просто пропадают. Неужели сложно коротко ответить, типа «Вы нам не подходите». Не понимаю.
Из остальных 40% интересно, что некоторые HR умудряются так пропадать даже после созвона. Остальные всё-таки отвечают, и удавалось продолжить диалог и получить либо отказ, либо согласие общаться дальше. В большинстве случаев проходит 3 этапа собеседований:
- знакомство с HR (30 минут – час),
- техническое собеседование (1,5-2,5 часа),
- общение с командой/техлидом об условиях работы (1,5-2 часа).
В этом плане хотел бы отметить работу отдела найма в Контуре. После того, как я отправил резюме, HR довольно быстро ответила и прислала список вопросов для первого знакомства: почему ищу работу? какие ожидания по ЗП? чего жду от нового места? какой есть опыт с тем и с этим? был ли опыт управления командой? и т.п.
Я ответил на вопросы, и буквально в течение 10 минут HR вернулась с фидбеком. Для сравнения, иногда диалоги с HR других компаний шли по 1 сообщению в 1-2 дня. Приходилось перечитывать переписку, чтоб вспомнить, кто это и из какой компании. В общем, HR Контура ответила, что ЗП определят по итогам тех. интервью. Но, т.к. у меня не было такого и такого опыта, спросила, соглашусь ли я на ЗП на 10% меньше? Но сразу же упомянула, что в компании до двух раз в год пересматривают зарплаты, и в случае удачного старта можно выйти на желаемый уровень довольно быстро. А также перечислила другие преимущества работы в компании. Т.е. не просто отказала из-за завышенных требований, не заявила, что «можем дать только столько-то», а дала мотивированное объяснение. По-моему, прекрасный ответ.
Далее был созвон с HR (другой), поболтали о компании и о моём опыте. Кстати, совет. Будьте готовы ответить на вопросы типа «Что вы считаете своими большими достижениями в карьере?» и «Какие у вас были провалы?». Понятно, что и то, и другое, случается у каждого, но, чтоб не было неожиданностью, и чтоб не ляпнуть от волнения что-нибудь ненужное, стоит подготовить ответы заранее.
Техническое интервью тоже вполне достойное. Сначала дали код на обзор. Но тут, в отличие от Озона, не было очевидных ляпов в коде. Упор сделали на алгоритмы, оценку сложности и возможные улучшения. Разбирали, кстати, самописную реализацию StringBuilder. А после тоже погоняли по моему опыту, по «кабанчику» и попросили нарисовать и объяснить архитектуру небольшого сервиса: куда поместить сервис, какой будет API, где и как хранить данные, что, когда, куда будет передаваться. После этого также вернулись с подробным фидбеком: в чём были сильные стороны, где есть «зоны роста», причём с перечнем литературы, которую надо почитать (да, «кабанчик» там тоже был).
В общем, Контур оставил прекрасное впечатление в плане работы с кандидатами. Всем бы так.
Пишите в комментарии ваши истории о поиске работы.
Автору лучшей истории пришлю книгу по Kubernetes (мне из "Питера" случайно вторую прислали, разрешили подарить).
Собеседования и Рынок .NET в РФ
Походил я тут ради интереса в последнее время по собеседованиям. Уже выкладывал задачу на код ревью от Озона. Сегодня хочу порассуждать о собеседованиях и в принципе о состоянии найма в ИТ.
В предыдущий раз я собеседовался аж в 2021 году. Хочу отметить, что если тогда все по классике спрашивали Рихтера, async-await и ленивое выполнение в LINQ, то сейчас этого очень мало. Почти везде (а я был на 4х техсобесах в разных компаниях), жёстко гоняют по «кабанчику». Распределённые системы, очереди сообщений, репликации и точки отказа. Надо, конечно, как советуют многие, ходить для профилактики на собеседования хотя бы раз в полгода-год, а то упускаешь, что сегодня в тренде. «Кабанчика» пришлось перечитать, т.к. многое оттуда забыл.
Ещё хотелось бы отметить довольно странную работу HR отделов компаний (исключая крупные, вроде Т-банка, Озона или Контура). 60% на присланное резюме просто не реагируют никак (хотя оно отправлялось напрямую по указанному в вакансии контакту), либо ограничиваются «я передам резюме руководству и вернусь с обратной связью». Дальше, как в меме: «С обратной связью, конечно, никто возвращаться не собирался». Они просто пропадают. Неужели сложно коротко ответить, типа «Вы нам не подходите». Не понимаю.
Из остальных 40% интересно, что некоторые HR умудряются так пропадать даже после созвона. Остальные всё-таки отвечают, и удавалось продолжить диалог и получить либо отказ, либо согласие общаться дальше. В большинстве случаев проходит 3 этапа собеседований:
- знакомство с HR (30 минут – час),
- техническое собеседование (1,5-2,5 часа),
- общение с командой/техлидом об условиях работы (1,5-2 часа).
В этом плане хотел бы отметить работу отдела найма в Контуре. После того, как я отправил резюме, HR довольно быстро ответила и прислала список вопросов для первого знакомства: почему ищу работу? какие ожидания по ЗП? чего жду от нового места? какой есть опыт с тем и с этим? был ли опыт управления командой? и т.п.
Я ответил на вопросы, и буквально в течение 10 минут HR вернулась с фидбеком. Для сравнения, иногда диалоги с HR других компаний шли по 1 сообщению в 1-2 дня. Приходилось перечитывать переписку, чтоб вспомнить, кто это и из какой компании. В общем, HR Контура ответила, что ЗП определят по итогам тех. интервью. Но, т.к. у меня не было такого и такого опыта, спросила, соглашусь ли я на ЗП на 10% меньше? Но сразу же упомянула, что в компании до двух раз в год пересматривают зарплаты, и в случае удачного старта можно выйти на желаемый уровень довольно быстро. А также перечислила другие преимущества работы в компании. Т.е. не просто отказала из-за завышенных требований, не заявила, что «можем дать только столько-то», а дала мотивированное объяснение. По-моему, прекрасный ответ.
Далее был созвон с HR (другой), поболтали о компании и о моём опыте. Кстати, совет. Будьте готовы ответить на вопросы типа «Что вы считаете своими большими достижениями в карьере?» и «Какие у вас были провалы?». Понятно, что и то, и другое, случается у каждого, но, чтоб не было неожиданностью, и чтоб не ляпнуть от волнения что-нибудь ненужное, стоит подготовить ответы заранее.
Техническое интервью тоже вполне достойное. Сначала дали код на обзор. Но тут, в отличие от Озона, не было очевидных ляпов в коде. Упор сделали на алгоритмы, оценку сложности и возможные улучшения. Разбирали, кстати, самописную реализацию StringBuilder. А после тоже погоняли по моему опыту, по «кабанчику» и попросили нарисовать и объяснить архитектуру небольшого сервиса: куда поместить сервис, какой будет API, где и как хранить данные, что, когда, куда будет передаваться. После этого также вернулись с подробным фидбеком: в чём были сильные стороны, где есть «зоны роста», причём с перечнем литературы, которую надо почитать (да, «кабанчик» там тоже был).
В общем, Контур оставил прекрасное впечатление в плане работы с кандидатами. Всем бы так.
Пишите в комментарии ваши истории о поиске работы.
Автору лучшей истории пришлю книгу по Kubernetes (мне из "Питера" случайно вторую прислали, разрешили подарить).
👍52👎2
День 2243. #ЗаметкиНаПолях
Статические Лямбда-Функции не Являются Статическими Методами
Начиная с C# 9.0, вы можете использовать модификатор static в лямбда-функциях. Например, вы можете написать следующий код:
Когда вы используете модификатор static в лямбда-функции, компилятор гарантирует, что не будет захвата переменных из охватывающей области видимости. Это позволяет компилятору генерировать лучший код. Он может кэшировать лямбда-функцию и повторно использовать её в нескольких вызовах. Это может повысить производительность в некоторых сценариях. Однако код, сгенерированный компилятором, одинаков, независимо от того, используете ли вы модификатор static или нет.
Если вы посмотрите на сгенерированный код, вы увидите, что лямбда-функция не является статическим методом. Это метод экземпляра.
Почему компилятор генерирует метод экземпляра вместо статического метода? Причина кроется в том, как работают делегаты. Делегаты используют соглашение о вызове экземпляра, то есть они ожидают вызова методов экземпляра. Когда лямбда-функция преобразуется в делегат, компилятор генерирует метод экземпляра, соответствующий этому соглашению. Если бы лямбда была статическим методом, компилятору пришлось бы использовать костыли для перестановки аргументов, что может негативно повлиять на производительность.
Источник: https://www.meziantou.net/static-lambda-functions-are-not-static-methods.htm
Статические Лямбда-Функции не Являются Статическими Методами
Начиная с C# 9.0, вы можете использовать модификатор static в лямбда-функциях. Например, вы можете написать следующий код:
enumerable.Select(static x => x * 2);
Когда вы используете модификатор static в лямбда-функции, компилятор гарантирует, что не будет захвата переменных из охватывающей области видимости. Это позволяет компилятору генерировать лучший код. Он может кэшировать лямбда-функцию и повторно использовать её в нескольких вызовах. Это может повысить производительность в некоторых сценариях. Однако код, сгенерированный компилятором, одинаков, независимо от того, используете ли вы модификатор static или нет.
Если вы посмотрите на сгенерированный код, вы увидите, что лямбда-функция не является статическим методом. Это метод экземпляра.
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static Func<int, int> <>9__0_0;
// This method is not static
internal int <<Main>$>b__0_0(int i)
{
return i + 1;
}
}
Почему компилятор генерирует метод экземпляра вместо статического метода? Причина кроется в том, как работают делегаты. Делегаты используют соглашение о вызове экземпляра, то есть они ожидают вызова методов экземпляра. Когда лямбда-функция преобразуется в делегат, компилятор генерирует метод экземпляра, соответствующий этому соглашению. Если бы лямбда была статическим методом, компилятору пришлось бы использовать костыли для перестановки аргументов, что может негативно повлиять на производительность.
Источник: https://www.meziantou.net/static-lambda-functions-are-not-static-methods.htm
👍24
День 2244. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 45. У организаций никогда нет времени, чтобы правильно создать ПО, но они находят ресурсы, чтобы исправить его позже
Это великая тайна бизнеса ПО. Многие проектные группы работают в условиях нереалистичного графика и ограниченного бюджета, что вынуждает их экономить на качестве. В результате часто появляется продукт, который необходимо долго и дорого приводить в порядок или даже отказываться от него. Однако каким-то образом организация находит время, деньги и людей для доработки или замены.
Почему не сразу?
Очевидно, если система настолько необходима и актуальна, что руководство оказывает сильное давление на работников, требуя ускорить её развёртывание, то стоит создавать её должным образом. Когда у команды разработчиков нет времени, квалифицированного персонала, надлежащих процессов или инструментов для правильного выполнения работы, им неизбежно придётся переделывать хотя бы часть работы. Ранее мы обсудили, что такая доработка влечет снижение продуктивности.
К сожалению, многие не понимают, насколько важно потратить дополнительное время на разработку изначально правильного ПО, а не на его доработку позже. Время, необходимое для применения эффективных методов обеспечения качества, таких как обзоры кода, тестирование или технические экспертные оценки, часто не закладывается в график. В результате люди начинают проводить такие оценки, только осознав их важность. А даже если они запланированы, оказывается, что у людей нет времени на них. Отказ от экспертных оценок и других методов обеспечения качества означает не отсутствие дефектов, а то, что кто-то найдёт их позже, когда последствия будут более серьёзными.
Масштабные неудачи чаще всего являются результатом плохого управления, а не технических проблем. Недооценка объёмов работ в сочетании с нереалистичной надеждой на то, что разработчики смогут работать быстрее, чем в прошлом, приводит к отставанию от графика и снижению качества. И простые разработчики, и руководители должны предусматривать время и действия, необходимые для достижения успеха, чтобы избежать потенциально огромных затрат времени и денег.
Достижение баланса
Почти все технические специалисты хотят добросовестно трудиться и предоставлять высококачественные продукты и услуги. Иногда это желание вступает в противоречие с внешними факторами, такими как смехотворно короткие сроки, продиктованные руководством, или правила, установленные руководящими органами. Специалисты-практики не всегда знают о бизнес-мотивах или причинах такого давления. Качество и целостность тоже должны быть частью обсуждения, когда команда обдумывает, что можно сделать, чтобы уложиться в сроки, достичь бизнес-целей и реализовать правильную и надёжную функциональность.
Как и у многих, у меня тоже не всё получается идеально, но я стараюсь сразу сделать свою работу хорошо, чтобы избежать финансовых потерь, затрат времени, позора и потенциальных юридических последствий, связанных с необходимостью переделывать всё заново. Если для этого потребуется больше времени, пусть будет так. Выигрыш в долгосрочной перспективе стоит первоначальных инвестиций.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 6.
Уроки 50 Лет Разработки ПО
Урок 45. У организаций никогда нет времени, чтобы правильно создать ПО, но они находят ресурсы, чтобы исправить его позже
Это великая тайна бизнеса ПО. Многие проектные группы работают в условиях нереалистичного графика и ограниченного бюджета, что вынуждает их экономить на качестве. В результате часто появляется продукт, который необходимо долго и дорого приводить в порядок или даже отказываться от него. Однако каким-то образом организация находит время, деньги и людей для доработки или замены.
Почему не сразу?
Очевидно, если система настолько необходима и актуальна, что руководство оказывает сильное давление на работников, требуя ускорить её развёртывание, то стоит создавать её должным образом. Когда у команды разработчиков нет времени, квалифицированного персонала, надлежащих процессов или инструментов для правильного выполнения работы, им неизбежно придётся переделывать хотя бы часть работы. Ранее мы обсудили, что такая доработка влечет снижение продуктивности.
К сожалению, многие не понимают, насколько важно потратить дополнительное время на разработку изначально правильного ПО, а не на его доработку позже. Время, необходимое для применения эффективных методов обеспечения качества, таких как обзоры кода, тестирование или технические экспертные оценки, часто не закладывается в график. В результате люди начинают проводить такие оценки, только осознав их важность. А даже если они запланированы, оказывается, что у людей нет времени на них. Отказ от экспертных оценок и других методов обеспечения качества означает не отсутствие дефектов, а то, что кто-то найдёт их позже, когда последствия будут более серьёзными.
Масштабные неудачи чаще всего являются результатом плохого управления, а не технических проблем. Недооценка объёмов работ в сочетании с нереалистичной надеждой на то, что разработчики смогут работать быстрее, чем в прошлом, приводит к отставанию от графика и снижению качества. И простые разработчики, и руководители должны предусматривать время и действия, необходимые для достижения успеха, чтобы избежать потенциально огромных затрат времени и денег.
Достижение баланса
Почти все технические специалисты хотят добросовестно трудиться и предоставлять высококачественные продукты и услуги. Иногда это желание вступает в противоречие с внешними факторами, такими как смехотворно короткие сроки, продиктованные руководством, или правила, установленные руководящими органами. Специалисты-практики не всегда знают о бизнес-мотивах или причинах такого давления. Качество и целостность тоже должны быть частью обсуждения, когда команда обдумывает, что можно сделать, чтобы уложиться в сроки, достичь бизнес-целей и реализовать правильную и надёжную функциональность.
Как и у многих, у меня тоже не всё получается идеально, но я стараюсь сразу сделать свою работу хорошо, чтобы избежать финансовых потерь, затрат времени, позора и потенциальных юридических последствий, связанных с необходимостью переделывать всё заново. Если для этого потребуется больше времени, пусть будет так. Выигрыш в долгосрочной перспективе стоит первоначальных инвестиций.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 6.
👍13👎1
День 2245. #ЧтоНовенького
Новые Функции Visual Studio 17.14
Очередная порция интересных новинок в новой версии Visual Studio.
1. Генерация саммари с помощью ИИ
Если в настройках включена автоматическая генерация саммари, вы можете просто ввести ///, и Copilot автоматически заполнит описание метода и параметров на основе содержимого метода. Вы можете принять эти предложения с помощью Tab, как и обычные автодополнения кода Copilot. См. картинку 1.
Чтобы включить эту функцию, перейдите в Tools > Options > Text Editor > C# > Advanced (Инструменты > Параметры > Текстовый Редактор > C# > Дополнительно) и в блоке Comments (Комментарии) отметьте Generate XML documentation comments for /// (Генерировать комментарии XML документации для ///).
2. Поиск Функций IDE с помощью GitHub Copilot
VS упрощает доступ к чату GitHub Copilot из поиска функций (
Этот инструмент интерпретирует семантическое значение вашего запроса, учитывает вашу версию Visual Studio и даёт точные ответы. Например, ввод «prettify file» в традиционном поиске может не найти опцию «format document». Однако Copilot понимает намерение вашего запроса и может подсказать правильную настройку со всей необходимой информацией. См. картинку 2.
3. Улучшения Обзоров Кода в Пул-Реквестах
Просмотр комментариев к пул-реквестам уже был добавлен в VS некоторое время назад. Теперь вы сможете добавлять комментарии непосредственно в IDE прямо в нужном месте кода.
Чтобы использовать эту функцию комментирования, убедитесь, что вы включили флаги функции: Tools > Options > Preview Features > Pull Request Comments (Инструменты > Опции > Предварительный Просмотр Функций > Комментарии к Пул-реквестам) и Tools > Options > Preview Features > Pull Request Add Comment (Инструменты > Опции > Предварительный Просмотр Функций > Добавление Комментариев к Пул-реквестам).
После этого выберите любую ветку с активным пул-реквестом и нажмите Show Comments in Files (Показывать комментарии в файлах) в окне Git Changes, чтобы активировать комментарии к пул-реквесту в редакторе. Тогда в редакторе кода слева от каждой строки будет появляться значок Add comment (Добавить комментарий) или значок комментария в месте, где он был оставлен.
Значки комментариев будут отображаться только в файлах, которые являются частью пул-реквеста. Комментарии можно добавлять только к строкам, окружающим и включающим изменения.
Подробности в этом видео.
Источники:
- https://devblogs.microsoft.com/visualstudio/introducing-automatic-documentation-comment-generation-in-visual-studio/
- https://devblogs.microsoft.com/visualstudio/find-the-ide-features-you-need-with-github-copilot-and-search/
- https://devblogs.microsoft.com/visualstudio/enhance-pull-request-reviews-with-in-depth-feedback/
Новые Функции Visual Studio 17.14
Очередная порция интересных новинок в новой версии Visual Studio.
1. Генерация саммари с помощью ИИ
Если в настройках включена автоматическая генерация саммари, вы можете просто ввести ///, и Copilot автоматически заполнит описание метода и параметров на основе содержимого метода. Вы можете принять эти предложения с помощью Tab, как и обычные автодополнения кода Copilot. См. картинку 1.
Чтобы включить эту функцию, перейдите в Tools > Options > Text Editor > C# > Advanced (Инструменты > Параметры > Текстовый Редактор > C# > Дополнительно) и в блоке Comments (Комментарии) отметьте Generate XML documentation comments for /// (Генерировать комментарии XML документации для ///).
2. Поиск Функций IDE с помощью GitHub Copilot
VS упрощает доступ к чату GitHub Copilot из поиска функций (
Ctrl+Q
). Теперь нажатие кнопки Ask Copilot (Спросить Copilot) отправит запрос в чат GitHub Copilot, и вы получите подробный ответ.Этот инструмент интерпретирует семантическое значение вашего запроса, учитывает вашу версию Visual Studio и даёт точные ответы. Например, ввод «prettify file» в традиционном поиске может не найти опцию «format document». Однако Copilot понимает намерение вашего запроса и может подсказать правильную настройку со всей необходимой информацией. См. картинку 2.
3. Улучшения Обзоров Кода в Пул-Реквестах
Просмотр комментариев к пул-реквестам уже был добавлен в VS некоторое время назад. Теперь вы сможете добавлять комментарии непосредственно в IDE прямо в нужном месте кода.
Чтобы использовать эту функцию комментирования, убедитесь, что вы включили флаги функции: Tools > Options > Preview Features > Pull Request Comments (Инструменты > Опции > Предварительный Просмотр Функций > Комментарии к Пул-реквестам) и Tools > Options > Preview Features > Pull Request Add Comment (Инструменты > Опции > Предварительный Просмотр Функций > Добавление Комментариев к Пул-реквестам).
После этого выберите любую ветку с активным пул-реквестом и нажмите Show Comments in Files (Показывать комментарии в файлах) в окне Git Changes, чтобы активировать комментарии к пул-реквесту в редакторе. Тогда в редакторе кода слева от каждой строки будет появляться значок Add comment (Добавить комментарий) или значок комментария в месте, где он был оставлен.
Значки комментариев будут отображаться только в файлах, которые являются частью пул-реквеста. Комментарии можно добавлять только к строкам, окружающим и включающим изменения.
Подробности в этом видео.
Источники:
- https://devblogs.microsoft.com/visualstudio/introducing-automatic-documentation-comment-generation-in-visual-studio/
- https://devblogs.microsoft.com/visualstudio/find-the-ide-features-you-need-with-github-copilot-and-search/
- https://devblogs.microsoft.com/visualstudio/enhance-pull-request-reviews-with-in-depth-feedback/
👍11
День 2246. #ЗаметкиНаПолях
Не Смешивайте CQRS и MediatR. Начало
Экосистема .NET постепенно приравняла CQRS к использованию MediatR. Развеем некоторые распространённые заблуждения и выделим преимущества каждого шаблона.
CQRS в чистом виде
CQRS — это паттерн, разделяющий операции чтения и записи в приложении. Он предполагает, что модели, используемые для чтения данных, должны отличаться от моделей, используемых для записи. Никаких конкретных деталей реализации, никаких предписанных библиотек, просто архитектурный принцип.
Он возник из понимания того, что во многих приложениях, особенно в сложных доменах, требования к чтению и записи данных принципиально различаются. Операции чтения часто требуют объединения данных из нескольких источников или представления их в определённых форматах для UI. Операции записи должны обеспечивать соблюдение бизнес-правил, поддерживать согласованность и управлять состоянием домена.
Такое разделение даёт несколько преимуществ:
1. Оптимизированные модели чтения и записи для их конкретных целей.
2. Упрощённое обслуживание, поскольку проблемы чтения и записи независимы.
3. Расширенные возможности масштабирования для операций чтения и записи.
4. Более чёткая граница между логикой предметной области и потребностями представления.
MediatR
MediatR — это реализация шаблона посредника. Его основная цель — уменьшить прямые зависимости между компонентами, предоставляя единую точку связи. Вместо того, чтобы компоненты знали друг о друге, используется посредник, который их соединяет.
MediatR предоставляет несколько функций:
1. Внутрипроцессный обмен сообщениями между компонентами.
2. Поведения конвейера (pipeline behaviors) для сквозных проблем.
3. Обработка уведомлений (по модели публикация/подписка).
Косвенность, которую вводит MediatR, является его наиболее критикуемым аспектом. Она может усложнить отслеживание кода, особенно для новичков. Однако можно решить эту проблему, определив запросы в том же файле, что и обработчики.
Почему они часто появляются вместе?
Частое сочетание CQRS и MediatR не беспричинно. Модель запроса/ответа MediatR хорошо согласуется с разделением команд/запросов в CQRS. Команды и запросы могут быть реализованы как запросы MediatR, с обработчиками, содержащими фактическую логику реализации.
Вот пример команды в MediatR:
CQRS с MediatR предлагает несколько преимуществ:
1. Согласованная обработка как команд, так и запросов.
2. Поведения конвейера для регистрации, проверки и обработки ошибок.
3. Чёткое разделение проблем с помощью классов обработчиков.
4. Упрощённое тестирование с помощью изоляции обработчиков.
Однако это удобство достигается ценой дополнительной абстракции и сложности. Нам нужно определить классы запросов/ответов и их обработчики, написать код для отправки запросов и т.д. Это может быть излишним для простых приложений.
Вопрос не в том, является ли этот компромисс универсально хорошим или универсально плохим, а в том, подходит ли это для вашего конкретного контекста.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/stop-conflating-cqrs-and-mediatr
Не Смешивайте CQRS и MediatR. Начало
Экосистема .NET постепенно приравняла CQRS к использованию MediatR. Развеем некоторые распространённые заблуждения и выделим преимущества каждого шаблона.
CQRS в чистом виде
CQRS — это паттерн, разделяющий операции чтения и записи в приложении. Он предполагает, что модели, используемые для чтения данных, должны отличаться от моделей, используемых для записи. Никаких конкретных деталей реализации, никаких предписанных библиотек, просто архитектурный принцип.
Он возник из понимания того, что во многих приложениях, особенно в сложных доменах, требования к чтению и записи данных принципиально различаются. Операции чтения часто требуют объединения данных из нескольких источников или представления их в определённых форматах для UI. Операции записи должны обеспечивать соблюдение бизнес-правил, поддерживать согласованность и управлять состоянием домена.
Такое разделение даёт несколько преимуществ:
1. Оптимизированные модели чтения и записи для их конкретных целей.
2. Упрощённое обслуживание, поскольку проблемы чтения и записи независимы.
3. Расширенные возможности масштабирования для операций чтения и записи.
4. Более чёткая граница между логикой предметной области и потребностями представления.
MediatR
MediatR — это реализация шаблона посредника. Его основная цель — уменьшить прямые зависимости между компонентами, предоставляя единую точку связи. Вместо того, чтобы компоненты знали друг о друге, используется посредник, который их соединяет.
MediatR предоставляет несколько функций:
1. Внутрипроцессный обмен сообщениями между компонентами.
2. Поведения конвейера (pipeline behaviors) для сквозных проблем.
3. Обработка уведомлений (по модели публикация/подписка).
Косвенность, которую вводит MediatR, является его наиболее критикуемым аспектом. Она может усложнить отслеживание кода, особенно для новичков. Однако можно решить эту проблему, определив запросы в том же файле, что и обработчики.
Почему они часто появляются вместе?
Частое сочетание CQRS и MediatR не беспричинно. Модель запроса/ответа MediatR хорошо согласуется с разделением команд/запросов в CQRS. Команды и запросы могут быть реализованы как запросы MediatR, с обработчиками, содержащими фактическую логику реализации.
Вот пример команды в MediatR:
public record CreateHabit(string Name, string? Description, int Priority) : IRequest<HabitDto>;
public sealed class CreateHabitHandler(
ApplicationDbContext dbContext,
IValidator<CreateHabit> validator)
: IRequestHandler<CreateHabit, HabitDto>
{
public async Task<HabitDto> Handle(
CreateHabit request, CancellationToken ct)
{
await validator
.ValidateAndThrowAsync(request);
var habit = request.ToEntity();
dbContext.Habits.Add(habit);
await dbContext.SaveChangesAsync(ct);
return habit.ToDto();
}
}
CQRS с MediatR предлагает несколько преимуществ:
1. Согласованная обработка как команд, так и запросов.
2. Поведения конвейера для регистрации, проверки и обработки ошибок.
3. Чёткое разделение проблем с помощью классов обработчиков.
4. Упрощённое тестирование с помощью изоляции обработчиков.
Однако это удобство достигается ценой дополнительной абстракции и сложности. Нам нужно определить классы запросов/ответов и их обработчики, написать код для отправки запросов и т.д. Это может быть излишним для простых приложений.
Вопрос не в том, является ли этот компромисс универсально хорошим или универсально плохим, а в том, подходит ли это для вашего конкретного контекста.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/stop-conflating-cqrs-and-mediatr
👍24👎1
День 2247. #ЗаметкиНаПолях
Не Смешивайте CQRS и MediatR. Окончание
Начало
CQRS без MediatR
CQRS можно реализовать так же легко и без MediatR. Вы можете определить команды и запросы как простые интерфейсы:
Теперь реализуем обработчики:
и зарегистрируем их в DI-контейнере
Наконец, используем обработчик в контроллере:
В чем разница между этим подходом и подходом c MediatR?
Этот подход обеспечивает такое же разделение задач, но без косвенности. Он прямой, явный и часто достаточный для многих приложений.
Однако ему не хватает некоторых удобств, которые предлагает MediatR, таких как поведение конвейера и автоматическая регистрация обработчиков. Вам также необходимо внедрять обработчики в контроллеры, что может быть обременительным для более крупных приложений.
Итого
CQRS и MediatR — это отдельные инструменты, которые решают разные проблемы. Хотя они могут хорошо работать вместе, воспринимать их как нечто неделимое вредно. CQRS разделяет задачи чтения и записи, в то время как MediatR разделяет компоненты через посредника.
Важно понимание того, что предлагает каждый шаблон, и принятии обоснованных решений на основе вашего конкретного контекста. Иногда вам нужны оба, иногда только один, а иногда ни один. В этом суть продуманной архитектуры: выбор правильных инструментов для ваших конкретных потребностей.
Источник: https://www.milanjovanovic.tech/blog/stop-conflating-cqrs-and-mediatr
Не Смешивайте CQRS и MediatR. Окончание
Начало
CQRS без MediatR
CQRS можно реализовать так же легко и без MediatR. Вы можете определить команды и запросы как простые интерфейсы:
public interface ICommandHandler<in TCommand, TResult>
{
Task<TResult> Handle(
TCommand command, CancellationToken ct = default);
}
// аналогично для IQueryHandler
Теперь реализуем обработчики:
public record CreateOrderCommand(
string CustomerId, List<OrderItem> Items)
: ICommand<CreateOrderResult>;
public class CreateOrderCommandHandler :
ICommandHandler<CreateOrderCommand, CreateOrderResult>
{
public async Task<CreateOrderResult> Handle(
CreateOrderCommand command,
CancellationToken ct = default)
{
// реализация
}
}
и зарегистрируем их в DI-контейнере
builder.Services
.AddScoped<ICommandHandler<CreateOrderCommand, CreateOrderResult>, CreateOrderCommandHandler>();
Наконец, используем обработчик в контроллере:
[ApiController]
[Route("orders")]
public class OrdersController : ControllerBase
{
[HttpPost]
public async Task<ActionResult<CreateOrderResult>>
CreateOrder(
CreateOrderCommand command,
ICommandHandler<CreateOrderCommand, CreateOrderResult> handler)
{
var result = await handler.Handle(command);
return Ok(result);
}
}
В чем разница между этим подходом и подходом c MediatR?
Этот подход обеспечивает такое же разделение задач, но без косвенности. Он прямой, явный и часто достаточный для многих приложений.
Однако ему не хватает некоторых удобств, которые предлагает MediatR, таких как поведение конвейера и автоматическая регистрация обработчиков. Вам также необходимо внедрять обработчики в контроллеры, что может быть обременительным для более крупных приложений.
Итого
CQRS и MediatR — это отдельные инструменты, которые решают разные проблемы. Хотя они могут хорошо работать вместе, воспринимать их как нечто неделимое вредно. CQRS разделяет задачи чтения и записи, в то время как MediatR разделяет компоненты через посредника.
Важно понимание того, что предлагает каждый шаблон, и принятии обоснованных решений на основе вашего конкретного контекста. Иногда вам нужны оба, иногда только один, а иногда ни один. В этом суть продуманной архитектуры: выбор правильных инструментов для ваших конкретных потребностей.
Источник: https://www.milanjovanovic.tech/blog/stop-conflating-cqrs-and-mediatr
👍20👎1
День 2248. #BestPractices
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Начало
Как разработчики, мы часто работаем параллельно, создавая ветки для новых функций, исправляя ошибки и внося обновления. Но когда приходит время внести эти изменения в основную кодовую базу, пулл-реквесты (PR) становятся мостом между изолированной разработкой и совместной работой в команде. Каждого разочаровывает, когда PR отклоняют или отправляют на доработку. Легко можно потратить часы на функцию, а потом понять, что твоя реализация не соответствует видению команды. Однако со временем мы узнаём, что эффективные PR касаются не только самого кода. Они и про то, как мы сообщаем о наших изменениях. Рассмотрим, как создавать пулл-реквесты, которые делают процесс обзора более плавным, быстрым и эффективным для всех участников.
1. Начните с информативного заголовка
Первое впечатление имеет значение даже в мире кода. Заголовок пулл-реквеста — это наш шанс немедленно донести суть изменения. Думайте о нём как о заголовке статьи; он должен быть коротким, понятным и информативным. Вместо:
"Обновил код"
"Исправил баг"
"Изменения за вчера"
Используйте более описательные заголовки, например:
feat: Добавил OAuth2 аутентификацию для конечных точек API
fix: Устранил состояния гонки при обработке сеанса пользователя
refactor: Оптимизированы запросы к БД при поиске пользователя
Хорошо составленный заголовок помогает рецензентам понять изменение, не открывая PR. Он задает тон всему процессу обзора кода.
2. Установите контекст (не предполагайте, что все знают проблему)
Прежде чем погрузиться в код, важно предоставить контекст. Не все могут быть знакомы с конкретной проблемой, которую мы решаем, и важно объяснить, почему произошли изменения. Чёткое описание PR упрощает и ускоряет рецензирование. Вот шаблон для хорошо структурированного описания PR:
Это гарантирует, что рецензенты поймут проблему, выбранный подход и то, как проверить решение. PR без контекста может существенно замедлить процесс, поэтому всегда включайте достаточно информации, чтобы команда могла понять ваши изменения.
3. Сохраняйте PR сфокусированным
Нас всех подбивает решить сразу несколько проблем. Но это часто приводит к слишком большим PR, которые могут обескуражить рецензентов. Вместо этого пытайтесь разбить работу на более мелкие, целенаправленные PR. Каждый PR должен решать определённую задачу. Например, если мы создаём систему управления пользователями, можно разбить её на более мелкие задачи:
PR 1: feat: Добавление основной модели и миграции
PR 2: feat: Реализация конечных точек аутентификации
PR 3: feat: Добавление UI управления пользователями
PR 4: feat: Интеграция подтверждения по email
Каждый PR должен быть нацелен на одну фичу или исправление ошибки, что сделает процесс обзора проще для всех. Это ведёт к более быстрым обзорам и меньшему количеству доработок.
Окончание следует…
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Начало
Как разработчики, мы часто работаем параллельно, создавая ветки для новых функций, исправляя ошибки и внося обновления. Но когда приходит время внести эти изменения в основную кодовую базу, пулл-реквесты (PR) становятся мостом между изолированной разработкой и совместной работой в команде. Каждого разочаровывает, когда PR отклоняют или отправляют на доработку. Легко можно потратить часы на функцию, а потом понять, что твоя реализация не соответствует видению команды. Однако со временем мы узнаём, что эффективные PR касаются не только самого кода. Они и про то, как мы сообщаем о наших изменениях. Рассмотрим, как создавать пулл-реквесты, которые делают процесс обзора более плавным, быстрым и эффективным для всех участников.
1. Начните с информативного заголовка
Первое впечатление имеет значение даже в мире кода. Заголовок пулл-реквеста — это наш шанс немедленно донести суть изменения. Думайте о нём как о заголовке статьи; он должен быть коротким, понятным и информативным. Вместо:
"Обновил код"
"Исправил баг"
"Изменения за вчера"
Используйте более описательные заголовки, например:
feat: Добавил OAuth2 аутентификацию для конечных точек API
fix: Устранил состояния гонки при обработке сеанса пользователя
refactor: Оптимизированы запросы к БД при поиске пользователя
Хорошо составленный заголовок помогает рецензентам понять изменение, не открывая PR. Он задает тон всему процессу обзора кода.
2. Установите контекст (не предполагайте, что все знают проблему)
Прежде чем погрузиться в код, важно предоставить контекст. Не все могут быть знакомы с конкретной проблемой, которую мы решаем, и важно объяснить, почему произошли изменения. Чёткое описание PR упрощает и ускоряет рецензирование. Вот шаблон для хорошо структурированного описания PR:
## Проблема
Текущая система аутентификации пользователей не поддерживает вход через соцсети, что вызывает затруднения при регистрации. Мы наблюдаем 40% отказов на этапе регистрации.
Связанный тикет: AUTH-123
## Решение
Реализована аутентификация OAuth2 с Google:
- Добавлено промежуточное ПО OAuth2 для обработки аутентификации Google
- Создана новая логика сопоставления профилей пользователей
- Реализовано управление сеансами для входа через соцсети
## Технические подробности
- Использует passport-google-oauth20
- Добавлены новые поля: googleId, socialProfile
- Изменена модель пользователя для поддержки нескольких методов аутентификации
## Тестирование
1. Нажмите «Войти через Google»
2. Авторизуйте тестовое приложение
3. Проверьте успешное перенаправление на панель управления
4. Проверьте, содержит ли профиль пользователя данные Google
## Конфигурация
Требуются новые переменные среды:
- GOOGLE_CLIENT_ID
- GOOGLE_CLIENT_SECRET
- OAUTH_CALLBACK_URL
Это гарантирует, что рецензенты поймут проблему, выбранный подход и то, как проверить решение. PR без контекста может существенно замедлить процесс, поэтому всегда включайте достаточно информации, чтобы команда могла понять ваши изменения.
3. Сохраняйте PR сфокусированным
Нас всех подбивает решить сразу несколько проблем. Но это часто приводит к слишком большим PR, которые могут обескуражить рецензентов. Вместо этого пытайтесь разбить работу на более мелкие, целенаправленные PR. Каждый PR должен решать определённую задачу. Например, если мы создаём систему управления пользователями, можно разбить её на более мелкие задачи:
PR 1: feat: Добавление основной модели и миграции
PR 2: feat: Реализация конечных точек аутентификации
PR 3: feat: Добавление UI управления пользователями
PR 4: feat: Интеграция подтверждения по email
Каждый PR должен быть нацелен на одну фичу или исправление ошибки, что сделает процесс обзора проще для всех. Это ведёт к более быстрым обзорам и меньшему количеству доработок.
Окончание следует…
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
👍18👎2
День 2249. #BestPractices
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Окончание
Начало
4. Сообщения коммитов: чистота и ясность
Хорошее сообщение коммита не просто объясняет код. Оно помогает всем понять, почему было сделано изменение и как оно вписывается в общую картину.
Хорошее сообщение коммита
- предоставляет контекст: объясняет причину изменения;
- улучшает сотрудничество: будущие разработчики смогут отслеживать историю проекта и легко понимать цель каждого коммита;
- экономит время: уменьшают необходимость в дополнительных вопросах и предотвращают доработки во время процесса проверки;
Примеры плохих сообщений коммитов:
- «Исправлено»
Это расплывчато и не указывает, что исправлено или почему.
Лучше:
fix(auth): устранена ошибка входа пользователя, вызванная истекшими токенами.
- «Обновления»
Не сообщает рецензенту, что было изменено или почему обновление было необходимо.
Лучше:
chore: обновлены зависимости для исправления уязвимостей безопасности
- «Работа в процессе»
Не описывает никаких значимых изменений и предполагает, что код неполный. Также усложняет процесс проверки, так как рецензент не знает, смотрит ли он на готовую функцию или только на черновик.
Лучше:
feat(api): добавлены конечные точки аутентификации пользователя
5. Контрольный список готовности к обзору кода
Перед отправкой PR используйте следующий контрольный список, чтобы убедиться, что всё готово. Контрольный список важен, т.к.:
- Экономит время рецензентов: сводит к минимуму вероятность того, что рецензенты попросят об исправлениях, позволяя им сосредоточиться на логике кода.
- Улучшает согласованность: гарантирует, что все PR соответствуют одному стандарту, что делает процесс обзора более гладким для всех.
- Уменьшает количество повторных проверок: двойная проверка вашего кода и тестов позволяет избежать нескольких раундов обзоров.
Пример контрольного списка:
Распространённые проблемы с PR
1. В PR слишком много изменений
Разбейте задачу на более мелкие, более управляемые PR. Сначала для изменений схемы БД, затем для модификаций API, а затем — для корректировок UI. Это позволит рецензентам сосредоточиться на чём-то одном за раз.
2. Непоследовательные сообщения коммитов
Они затрудняют отслеживание изменений: одни слишком расплывчаты, другие — слишком подробные. Используйте стандартный формат сообщений коммитов и убедитесь, что все его соблюдают. Это сделает историю проекта намного более читаемой и улучшит совместную работу.
Итого
Создание эффективных PR — навык, который улучшается с практикой. Каждый PR — это возможность для обучения. Каждый комментарий, предложение или вопрос в обзоре кода помогает нам расти как разработчикам и улучшать наши методы кодирования.
Цель не просто слить наш код с основной веткой; а создать высококачественную кодовую базу, которую всем будет легко понимать и поддерживать. Уделяя особое внимание нашим PR, мы инвестируем в успех проекта и наш рост как разработчиков.
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Окончание
Начало
4. Сообщения коммитов: чистота и ясность
Хорошее сообщение коммита не просто объясняет код. Оно помогает всем понять, почему было сделано изменение и как оно вписывается в общую картину.
Хорошее сообщение коммита
- предоставляет контекст: объясняет причину изменения;
- улучшает сотрудничество: будущие разработчики смогут отслеживать историю проекта и легко понимать цель каждого коммита;
- экономит время: уменьшают необходимость в дополнительных вопросах и предотвращают доработки во время процесса проверки;
Примеры плохих сообщений коммитов:
- «Исправлено»
Это расплывчато и не указывает, что исправлено или почему.
Лучше:
fix(auth): устранена ошибка входа пользователя, вызванная истекшими токенами.
- «Обновления»
Не сообщает рецензенту, что было изменено или почему обновление было необходимо.
Лучше:
chore: обновлены зависимости для исправления уязвимостей безопасности
- «Работа в процессе»
Не описывает никаких значимых изменений и предполагает, что код неполный. Также усложняет процесс проверки, так как рецензент не знает, смотрит ли он на готовую функцию или только на черновик.
Лучше:
feat(api): добавлены конечные точки аутентификации пользователя
5. Контрольный список готовности к обзору кода
Перед отправкой PR используйте следующий контрольный список, чтобы убедиться, что всё готово. Контрольный список важен, т.к.:
- Экономит время рецензентов: сводит к минимуму вероятность того, что рецензенты попросят об исправлениях, позволяя им сосредоточиться на логике кода.
- Улучшает согласованность: гарантирует, что все PR соответствуют одному стандарту, что делает процесс обзора более гладким для всех.
- Уменьшает количество повторных проверок: двойная проверка вашего кода и тестов позволяет избежать нескольких раундов обзоров.
Пример контрольного списка:
## Перед коммитом
- [ ] Все тесты проходят
- [ ] Нет предупреждений компилятора
- [ ] Документация обновлена
- [ ] В коммите нет приватных данных
- [ ] Ветка синхронизирована с main
- [ ] Код отвечает стилю кодирования проекта
Распространённые проблемы с PR
1. В PR слишком много изменений
Разбейте задачу на более мелкие, более управляемые PR. Сначала для изменений схемы БД, затем для модификаций API, а затем — для корректировок UI. Это позволит рецензентам сосредоточиться на чём-то одном за раз.
2. Непоследовательные сообщения коммитов
Они затрудняют отслеживание изменений: одни слишком расплывчаты, другие — слишком подробные. Используйте стандартный формат сообщений коммитов и убедитесь, что все его соблюдают. Это сделает историю проекта намного более читаемой и улучшит совместную работу.
Итого
Создание эффективных PR — навык, который улучшается с практикой. Каждый PR — это возможность для обучения. Каждый комментарий, предложение или вопрос в обзоре кода помогает нам расти как разработчикам и улучшать наши методы кодирования.
Цель не просто слить наш код с основной веткой; а создать высококачественную кодовую базу, которую всем будет легко понимать и поддерживать. Уделяя особое внимание нашим PR, мы инвестируем в успех проекта и наш рост как разработчиков.
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
👍9
День 2250. #SystemDesign101
Начинаю серию постов про System Design. Это будут небольшие шпаргалки, описывающие ту или иную технологию. Надеюсь, вам понравится.
1. Виды коммуникаций API
Архитектурные стили определяют, как различные компоненты системы взаимодействуют друг с другом. В результате они обеспечивают эффективность, надёжность и простоту интеграции с другими системами, предоставляя стандартный подход к проектированию и созданию API. Вот наиболее часто используемые стили:
SOAP
- Зрелый, всеобъемлющий, на основе XML;
- Лучше всего подходит для корпоративных приложений.
RESTful
- Популярный, простые в реализации методы HTTP;
- Идеально подходит для веб-сервисов.
GraphQL
- Язык запросов, запрашивает только нужные данные;
- Снижает сетевые издержки, ускоряет ответы.
gRPC
- Современный, высокопроизводительный;
- Подходит для архитектур микросервисов.
WebSocket
- Двунаправленные, постоянные соединения в реальном времени;
- Идеально подходит для обмена данными с малой задержкой.
Webhook
- Управляемый событиями, использует обратные вызовы HTTP, асинхронный;
- Уведомляет системы о событиях.
Источник: https://github.com/ByteByteGoHq/system-design-101
Начинаю серию постов про System Design. Это будут небольшие шпаргалки, описывающие ту или иную технологию. Надеюсь, вам понравится.
1. Виды коммуникаций API
Архитектурные стили определяют, как различные компоненты системы взаимодействуют друг с другом. В результате они обеспечивают эффективность, надёжность и простоту интеграции с другими системами, предоставляя стандартный подход к проектированию и созданию API. Вот наиболее часто используемые стили:
SOAP
- Зрелый, всеобъемлющий, на основе XML;
- Лучше всего подходит для корпоративных приложений.
RESTful
- Популярный, простые в реализации методы HTTP;
- Идеально подходит для веб-сервисов.
GraphQL
- Язык запросов, запрашивает только нужные данные;
- Снижает сетевые издержки, ускоряет ответы.
gRPC
- Современный, высокопроизводительный;
- Подходит для архитектур микросервисов.
WebSocket
- Двунаправленные, постоянные соединения в реальном времени;
- Идеально подходит для обмена данными с малой задержкой.
Webhook
- Управляемый событиями, использует обратные вызовы HTTP, асинхронный;
- Уведомляет системы о событиях.
Источник: https://github.com/ByteByteGoHq/system-design-101
👍29👎1
День 2251. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 46. Помните, что разница между плохим и хорошим может быть малозаметной
Во многих случаях разницу между качественным и некачественным продуктом определяют небольшой дополнительный анализ, опрос, проверка или тестирование. Это не обычные ошибки, которые время от времени совершают все, а проблемы, возникающие из-за поспешности, небрежности или невнимания к деталям.
Чтобы избежать малозаметных разрывов между плохим и хорошим, часто нужно лишь немного подумать, прежде чем продолжать. Все мы встречали множество программных продуктов с ошибками, которые должны были быть обнаружены во время тестирования, или с плохим дизайном, по которому было видно, что пользовательскому опыту не уделили должного внимания. Например, сайт сообщает, что у вас есть непрочитанное уведомление. Но при нажатии на значок уведомления появляется сообщение: «У вас нет сообщений». Или форма на сайте, которая из-за ошибки в Javascript не проходит валидацию, и клиент не может её отправить. Подобные дефекты мелкие, но очень раздражают и заставляют задуматься: «А что, если во всём остальном эта компания тоже работает спустя рукава»?
Вот некоторые категории проблем, ухудшающих качество ПО, которых разработчики могут избежать:
1. Предположения
Бизнес-аналитик может ошибиться в своих предположениях или записать предположение, сделанное клиентами, но затем забыть проверить, насколько оно верно.
2. Идеи решения
Клиенты часто предлагают бизнес-аналитикам свои идеи решения вместо требований. Если бизнес-аналитик не заглянет за пределы предложенного решения, чтобы понять реальную потребность, то может взяться за решение неправильной задачи или выбрать неадекватное решение, которое придётся исправлять позже.
3. Регрессионное тестирование
Если не выполнить регрессионное тестирование после быстрого изменения кода, то можно пропустить ошибку в изменённом коде. Даже небольшое изменение может неожиданно сломать что-то ещё.
4. Обработка исключений
Разработчики могут настолько сосредоточиться на «счастливом пути» в ожидаемом поведении системы, что могут забыть о распространённых ошибках. Отсутствующие, ошибочные или неправильно отформатированные данные могут привести к неожиданным результатам или даже сбою системы.
5. Воздействие изменений
Иногда люди внедряют изменения, не задумываясь о том, как они повлияют на другие части системы или сопутствующие продукты. Изменение одного аспекта поведения системы может привести к нарушению взаимодействия с пользователем, если аналогичная функциональность, имеющаяся в других местах, не будет изменена соответствующим образом.
Качество не бесплатно в смысле стоимости. Предотвращение, обнаружение и исправление дефектов требуют дополнительных ресурсов. Тем не менее устранение малозаметных разрывов между плохим и хорошим обязательно окупится, так как вам не придётся тратить ещё больше ресурсов на устранение проблем.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 6.
Уроки 50 Лет Разработки ПО
Урок 46. Помните, что разница между плохим и хорошим может быть малозаметной
Во многих случаях разницу между качественным и некачественным продуктом определяют небольшой дополнительный анализ, опрос, проверка или тестирование. Это не обычные ошибки, которые время от времени совершают все, а проблемы, возникающие из-за поспешности, небрежности или невнимания к деталям.
Чтобы избежать малозаметных разрывов между плохим и хорошим, часто нужно лишь немного подумать, прежде чем продолжать. Все мы встречали множество программных продуктов с ошибками, которые должны были быть обнаружены во время тестирования, или с плохим дизайном, по которому было видно, что пользовательскому опыту не уделили должного внимания. Например, сайт сообщает, что у вас есть непрочитанное уведомление. Но при нажатии на значок уведомления появляется сообщение: «У вас нет сообщений». Или форма на сайте, которая из-за ошибки в Javascript не проходит валидацию, и клиент не может её отправить. Подобные дефекты мелкие, но очень раздражают и заставляют задуматься: «А что, если во всём остальном эта компания тоже работает спустя рукава»?
Вот некоторые категории проблем, ухудшающих качество ПО, которых разработчики могут избежать:
1. Предположения
Бизнес-аналитик может ошибиться в своих предположениях или записать предположение, сделанное клиентами, но затем забыть проверить, насколько оно верно.
2. Идеи решения
Клиенты часто предлагают бизнес-аналитикам свои идеи решения вместо требований. Если бизнес-аналитик не заглянет за пределы предложенного решения, чтобы понять реальную потребность, то может взяться за решение неправильной задачи или выбрать неадекватное решение, которое придётся исправлять позже.
3. Регрессионное тестирование
Если не выполнить регрессионное тестирование после быстрого изменения кода, то можно пропустить ошибку в изменённом коде. Даже небольшое изменение может неожиданно сломать что-то ещё.
4. Обработка исключений
Разработчики могут настолько сосредоточиться на «счастливом пути» в ожидаемом поведении системы, что могут забыть о распространённых ошибках. Отсутствующие, ошибочные или неправильно отформатированные данные могут привести к неожиданным результатам или даже сбою системы.
5. Воздействие изменений
Иногда люди внедряют изменения, не задумываясь о том, как они повлияют на другие части системы или сопутствующие продукты. Изменение одного аспекта поведения системы может привести к нарушению взаимодействия с пользователем, если аналогичная функциональность, имеющаяся в других местах, не будет изменена соответствующим образом.
Качество не бесплатно в смысле стоимости. Предотвращение, обнаружение и исправление дефектов требуют дополнительных ресурсов. Тем не менее устранение малозаметных разрывов между плохим и хорошим обязательно окупится, так как вам не придётся тратить ещё больше ресурсов на устранение проблем.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 6.
👍5👎1
День 2252. #ЗаметкиНаПолях
Пример Сопоставления по Шаблону
Сегодня поделюсь с вами фрагментом кода от Жеральда Барре (aka Meziantou), в котором используется сопоставление по шаблону, а также метод SplitAny, использующий SearchValues<char>.
В примере ниже приведён простой сопоставитель версий, который проверяет, удовлетворяет ли версия (version) ограничениям (constraints). Ограничения — это строка, которая может содержать несколько ограничений, разделённых
Источник: https://www.meziantou.net/nice-example-of-csharp-list-pattern-matching.htm
Пример Сопоставления по Шаблону
Сегодня поделюсь с вами фрагментом кода от Жеральда Барре (aka Meziantou), в котором используется сопоставление по шаблону, а также метод SplitAny, использующий SearchValues<char>.
В примере ниже приведён простой сопоставитель версий, который проверяет, удовлетворяет ли версия (version) ограничениям (constraints). Ограничения — это строка, которая может содержать несколько ограничений, разделённых
,
или ;
. Каждое ограничение может быть одной версией или диапазоном версий. В свою очередь, диапазон может выглядеть как >1.0.0
, >=1.0.0
, <1.0.0
, <=1.0.0
, =1.0.0
, или 1.0.0
.using System.Buffers;
var version = "1.5.0";
var constraints = ">=1.0.0,<2.0.0";
Console.WriteLine(
VersionMatcher.IsValid(version, constraints));
class VersionMatcher
{
private static readonly SearchValues<char>
SplitChars = SearchValues.Create([',', ';']);
public static bool IsValid(
ReadOnlySpan<char> version,
ReadOnlySpan<char> constraints)
{
var parsed = Version.Parse(version);
foreach (var partRange in
constraints.SplitAny(SplitChars))
{
var part = constraints[partRange].Trim();
if (part.IsEmpty)
continue;
var satisfy = part switch
{
['=', .. var r] => parsed == Version.Parse(r),
['<', '=', .. var r] => parsed <= Version.Parse(r),
['<', .. var r] => parsed < Version.Parse(r),
['>', '=', .. var r] => parsed >= Version.Parse(r),
['>', .. var r] => parsed > Version.Parse(r),
_ => parsed == Version.Parse(part),
};
if (!satisfy)
return false;
}
return true;
}
}
Источник: https://www.meziantou.net/nice-example-of-csharp-list-pattern-matching.htm
👍10👎2
День 2253. #ЧтоНовенького #NET10
Новинки Превью 2 ASP.NET Core 10
В последнем выпуске ASP.NET Core 10 Preview 2 представлены несколько улучшений в Blazor, в создании документации OpenAPI и в инструментах разработчика. Большинство изменений присланы контрибьюторами и основаны на обратной связи от разработчиков.
1. Переработана навигация в Blazor
При использовании NavigateTo для навигации по той же странице (например, при изменении только строки запроса) браузер больше не будет принудительно прокручивать страницу вверх. В предыдущих версиях разработчикам приходилось вручную обходить это поведение.
Компонент NavLink теперь по умолчанию игнорирует строки запроса и фрагменты (часть URL после #) при сопоставлении с помощью NavLinkMatch.All. Это означает, что ссылка будет активна, даже если строки запроса или фрагменты в URL изменятся. В AppContext есть переключатель, который позволит вернуться к предыдущему поведению, если вам это необходимо. Для кастомного поведения сопоставления NavLink теперь предоставляет переопределяемый метод ShouldMatch.
Визуализация повторного подключения, когда клиент теряет WebSocket-соединение с сервером, обновилась в шаблоне проекта, и представляет новый компонент ReconnectModal, который разделяет CSS и JavaScript для более строгого соответствия политике безопасности контента (CSP). Настраиваемое событие components-reconnect-state-changed обеспечивает более детальный контроль над состояниями подключения, включая новую фазу retrying (повторной попытки).
2. Изменения в OpenAPI
Разработчики API получат встроенную поддержку для автоматического преобразования описаний <summary> в исходном коде в документы OpenAPI. Для этого нужно добавить в файл проекта следующую строку:
Тогда во время компиляции генератор исходного кода соберёт комментарии и создаст документ OpenAPI. Однако в конечных точках минимальных API придётся использовать именованные методы, а не лямбды, чтобы использовать эту функцию. Например, вместо
использовать вызов метода
и определить метод Hello с описанием
3. Прочие изменения
При использовании атрибута
Здесь при отсутствии значения в форме DueDate будет установлено в null.
Новые метрики аутентификации для панели управления Aspire отслеживают события входа/выхода и попытки авторизации, а телеметрия продолжительности запроса помогает выявлять узкие места производительности.
Источники:
- https://www.infoq.com/news/2025/03/aspnet-core-10-preview2
- https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview2/aspnetcore.md
Новинки Превью 2 ASP.NET Core 10
В последнем выпуске ASP.NET Core 10 Preview 2 представлены несколько улучшений в Blazor, в создании документации OpenAPI и в инструментах разработчика. Большинство изменений присланы контрибьюторами и основаны на обратной связи от разработчиков.
1. Переработана навигация в Blazor
При использовании NavigateTo для навигации по той же странице (например, при изменении только строки запроса) браузер больше не будет принудительно прокручивать страницу вверх. В предыдущих версиях разработчикам приходилось вручную обходить это поведение.
Компонент NavLink теперь по умолчанию игнорирует строки запроса и фрагменты (часть URL после #) при сопоставлении с помощью NavLinkMatch.All. Это означает, что ссылка будет активна, даже если строки запроса или фрагменты в URL изменятся. В AppContext есть переключатель, который позволит вернуться к предыдущему поведению, если вам это необходимо. Для кастомного поведения сопоставления NavLink теперь предоставляет переопределяемый метод ShouldMatch.
Визуализация повторного подключения, когда клиент теряет WebSocket-соединение с сервером, обновилась в шаблоне проекта, и представляет новый компонент ReconnectModal, который разделяет CSS и JavaScript для более строгого соответствия политике безопасности контента (CSP). Настраиваемое событие components-reconnect-state-changed обеспечивает более детальный контроль над состояниями подключения, включая новую фазу retrying (повторной попытки).
2. Изменения в OpenAPI
Разработчики API получат встроенную поддержку для автоматического преобразования описаний <summary> в исходном коде в документы OpenAPI. Для этого нужно добавить в файл проекта следующую строку:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
Тогда во время компиляции генератор исходного кода соберёт комментарии и создаст документ OpenAPI. Однако в конечных точках минимальных API придётся использовать именованные методы, а не лямбды, чтобы использовать эту функцию. Например, вместо
app.MapGet("/hello",
(string name) =>$"Hello, {name}!");
использовать вызов метода
app.MapGet("/hello", Hello);
и определить метод Hello с описанием
static partial class Program
{
/// <summary>
/// Отправляет приветствие.
/// </summary>
/// …
public static string Hello(string name)
{
return $"Hello, {name}!";
}
}
3. Прочие изменения
При использовании атрибута
[FromForm]
со сложным объектом в минимальных API пустые строки в теле формы теперь преобразуются в null, а не вызывают ошибку парсинга. Это поведение соответствует логике обработки форм, не принимающих сложные объекты, в минимальных API:app.MapPost("/todo", ([FromForm] Todo todo)
=> TypedResults.Ok(todo));
public record Todo(int Id, DateOnly? DueDate,
string Title, bool Completed);
Здесь при отсутствии значения в форме DueDate будет установлено в null.
Новые метрики аутентификации для панели управления Aspire отслеживают события входа/выхода и попытки авторизации, а телеметрия продолжительности запроса помогает выявлять узкие места производительности.
Источники:
- https://www.infoq.com/news/2025/03/aspnet-core-10-preview2
- https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview2/aspnetcore.md
👍15
День 2254. #SystemDesign101
REST API или GraphQL
REST
➕ Использует стандартные методы HTTP, такие как GET, POST, PUT, DELETE для операций CRUD.
➕ Хорошо работает, когда вам нужны простые, единообразные интерфейсы между отдельными сервисами/приложениями.
➕ Стратегии кэширования просты в реализации.
➖ Может потребоваться несколько циклов для сбора связанных данных из отдельных конечных точек.
GraphQL
➕ Предоставляет клиентам единую конечную точку для запроса именно тех данных, которые им нужны.
➕ Клиенты указывают требуемые поля во вложенных запросах, и сервер возвращает данные, содержащие только эти поля.
➕ Поддерживает мутации для изменения данных и подписки для уведомлений в реальном времени.
➕ Отлично подходит для агрегации данных из нескольких источников и хорошо работает с быстро меняющимися требованиями к внешнему интерфейсу.
➖ Переносит сложность на сторону клиента и может допускать опасные запросы, если не защищён должным образом.
➖ Стратегии кэширования могут быть сложнее, чем REST.
Выбор между REST и GraphQL зависит от конкретных требований приложения и команды разработчиков. GraphQL хорошо подходит для сложных или часто меняющихся потребностей интерфейса, в то время как REST подходит для приложений, где предпочтительны простые и последовательные контракты.
Ни один из подходов не является панацеей. Тщательная оценка требований и компромиссов важна для выбора правильного стиля. И REST, и GraphQL являются допустимыми вариантами для раскрытия данных и поддержки современных приложений.
Источник: https://github.com/ByteByteGoHq/system-design-101
REST API или GraphQL
REST
➕ Использует стандартные методы HTTP, такие как GET, POST, PUT, DELETE для операций CRUD.
➕ Хорошо работает, когда вам нужны простые, единообразные интерфейсы между отдельными сервисами/приложениями.
➕ Стратегии кэширования просты в реализации.
➖ Может потребоваться несколько циклов для сбора связанных данных из отдельных конечных точек.
GraphQL
➕ Предоставляет клиентам единую конечную точку для запроса именно тех данных, которые им нужны.
➕ Клиенты указывают требуемые поля во вложенных запросах, и сервер возвращает данные, содержащие только эти поля.
➕ Поддерживает мутации для изменения данных и подписки для уведомлений в реальном времени.
➕ Отлично подходит для агрегации данных из нескольких источников и хорошо работает с быстро меняющимися требованиями к внешнему интерфейсу.
➖ Переносит сложность на сторону клиента и может допускать опасные запросы, если не защищён должным образом.
➖ Стратегии кэширования могут быть сложнее, чем REST.
Выбор между REST и GraphQL зависит от конкретных требований приложения и команды разработчиков. GraphQL хорошо подходит для сложных или часто меняющихся потребностей интерфейса, в то время как REST подходит для приложений, где предпочтительны простые и последовательные контракты.
Ни один из подходов не является панацеей. Тщательная оценка требований и компромиссов важна для выбора правильного стиля. И REST, и GraphQL являются допустимыми вариантами для раскрытия данных и поддержки современных приложений.
Источник: https://github.com/ByteByteGoHq/system-design-101
👍15
HTML Embed Code: