.NET Разработчик
6.51K subscribers
427 photos
2 videos
14 files
2.04K links
Дневник сертифицированного .NET разработчика.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 2284. #УрокиРазработки
10 Уроков Качества Разработки ПО. Продолжение

Начало

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

Вот несколько рекомендаций:
- Код должен читаться как книга — методы упорядочены по порядку выполнения, а не по порядку видимости.
- Весь код в методе или функции должен находиться на одном уровне абстракции.
- Методы должны стараться не выходить за рамки 15 строк кода.
- Имена методов должны быть функциональными и объяснять их назначение, а не реализацию.
- Документация кода должна описывать, почему существует метод, а не как он работает.
- Встроенные комментарии допустимы, если они предоставляют дополнительный контекст.
- return либо в самом начале, либо в самом конце, но не в середине.
- Избегайте булевых параметров, используйте перечисления.
- Не вводите абстракции только ради внедрения зависимостей.
- Группируйте код по функциональности, а не по технической структуре для большей ясности.
- Обеспечьте достаточное покрытие тестами: 80% — хорошо, 90% — отлично, 95% — слишком много.
- Не тестируйте слишком подробно; тестируйте внешний интерфейс, но не детали реализации.

5. Это никогда не происходит только один раз
Вы когда-нибудь писали наспех код, а затем обнаруживали, что его используют снова и снова? Или вас просили создать прототип, который каким-то образом попадал в релиз? А как насчёт странной ошибки, которая волшебным образом разрешалась сама собой во время тестирования — только чтобы позже снова появиться в производстве?

Если вы не создаёте MVP (минимально жизнеспособный продукт), не используйте эти практики. Выделите время, чтобы заменить это одноразовое решение надлежащим долгосрочным кодом. Не соглашайтесь на ситуативные решения — будь то очистка куков, повторный запуск нестабильного теста, проблемы с разрешениями или тайм-аутами. Всегда решайте проблемы в корне. Будущий вы скажет вам спасибо.

6. Избегайте любых ручных шагов во время развёртывания
Способность команды развёртывать должным образом протестированную и версионированную программную систему на своей внутренней или облачной инфраструктуре является хорошим показателем зрелости команды. Любой ручной шаг в этом процессе (за исключением ручного запуска конвейера развёртывания) является потенциальной ответственностью и должен быть автоматизирован. Люди совершают ошибки, независимо от того, насколько они скрупулёзны.

С другой стороны, хорошо спроектированный конвейер развёртывания заботится о компиляции исходного кода, вызове любых инструментов анализа кода, запуске автоматизированных тестов, версионировании артефактов развёртывания, предоставлении инфраструктуры, обновлении схемы базы данных, развёртывании в промежуточном слоте, а затем, после подтверждения работоспособности, заменяет его на производственный слот. Всё это без необходимости сообщать разработчикам пароли производственной среды и без того, чтобы кто-либо подключался к производственной среде и вручную запускал скрипты. И если ваш руководитель не видит в этом ценности, аудит, связанный с многочисленными стандартами безопасности, которые у нас есть в настоящее время (ISO 27001, NIS и т.д.), поможет его убедить.

Окончание следует…

Источник:
https://www.dennisdoomen.com/2025/03/10-quality-lessons.html
👍14👎1
День 2285. #УрокиРазработки
10 Уроков Качества Разработки ПО. Окончание

Начало
Продолжение

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

Помимо этого, конвейер — это больше, чем просто ряд задач. Он развивается вместе с кодовой базой, может стать довольно сложным и, следовательно, должен быть простым для понимания и рефакторинга при необходимости. Слишком много компаний пытаются придерживаться конвейеров YAML, обходя ограничения, втискивая скрипты PowerShell или Bash вместе с файлами YAML — хотя есть гораздо лучшие альтернативы. Уже не говоря о необходимости перехода с одного движка сборки на другой, например, с Azure DevOps Pipeline на GitHub Actions. Можно использовать Nuke и C# Это обеспечивает доступ к возможностям навигации, рефакторинга и отладки и позволяет тестировать весь конвейер из локальной среды разработки.

8. После выпуска версии 1.0 будьте ответственны
Ваши пользователи или разработчики зависят от стабильности. Сначала выберите стратегию выпуска — будете ли вы принимать регулярные выпуски или будете выпускать новые версии только при необходимости? Чёткий план помогает согласовывать команды и устанавливать ожидания. Всегда применяйте семантическое управление версиями. Это простая система: увеличивайте основную версию при критических изменениях, второстепенную - для новых функций и версию патча для исправлений ошибок. Избегайте критических изменений, когда это возможно. Внесение серьёзных изменений может разочаровать пользователей, поэтому предоставьте чёткие исключения и альтернативы. Наконец, не забывайте о документации. Чётко документируйте свой код как для команды, так и для пользователей. Хорошо документированный код экономит время, предотвращает ошибки и способствует совместной работе.

9. Берегите историю версий
Представьте, что вы пытаетесь понять, почему кто-то увеличил таймаут для выполнения SQL-запроса до 60 секунд. Нет ничего более разочаровывающего, чем найти PR или описание коммита, в котором указано что-то вроде «Увеличен таймаут SQL». Такое описание сообщает, что было сделано, но не объясняет проблему, которую решал разработчик. Аналогично PR, содержащий один коммит, в котором смешан рефакторинг со значимыми изменениями, скорее всего, вызовет столько же разочарования.

В долго существующей кодовой базе понять, почему код ведёт себя определённым образом или написан в определённом стиле, зачастую можно только по истории изменений файла. Убедитесь, что у каждого коммита одна цель, с заголовком, объясняющим эту цель, и описанием, которое содержит обоснование изменения. Такой подход сохраняет историю изменений полезной и облегчает коллегам выполнение проверок. Просматривая коммит за коммитом, коллега может быстро понять, что все изменения в конкретном PR связаны с определённой задачей, что значительно экономит время. Просто убедитесь, что вы не сжимаете коммиты при слиянии.

10. Не бойтесь отклонять PR, если его слишком сложно просмотреть
Вас когда-нибудь просили просмотреть PR с более чем 100 файлами? Вы прокручиваете код, чувствуете себя подавленным и оставляете комментарий типа «вроде норм». Не бойтесь отклонять огромные PR. Качественный обзор кода становится невозможным при таком количестве изменений.

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

Помните, что меньше PR = лучше обзор = более качественный код.

См. также «Мастерство Пулл-Реквестов»

Источник:
https://www.dennisdoomen.com/2025/03/10-quality-lessons.html
👍14
День 2286. #ЧтоНовенького
Новинки GitHub Copilot в Visual Studio 17.14 Preview 3
Взаимодействие с GitHub Copilot в Visual Studio постоянно обновляется, чтобы предоставить вам последние достижения в разработке с использованием ИИ. Новые функции и улучшения были недавно выпущены в Visual Studio версии 17.14 Preview 3.

1. Пошаговое руководство для начала работы
Если вы новичок в GitHub Copilot и ищете быстрый, пошаговый способ начать работу, эта функция для вас. Откройте раскрывающейся список GitHub Copilot справа вверху и выберите GitHub Copilot Walkthrough (Пошаговое руководство GitHub Copilot). Руководство откроется в новой вкладке IDE.

Оно покажет вам, как получить Copilot бесплатно, познакомит с автодополнением кода на основе ИИ, чатом Copilot, покажет, как предоставить Copilot определённый контекст вашего решения, и познакомит с возможностями редактирования нескольких файлов Copilot Edits.

2. Улучшенный доступ к моделям
Теперь стало проще, чем когда-либо, получить доступ к последним моделям, таким как Claude 3.7, из Visual Studio. Вместо необходимости настраивать параметры, теперь вы можете включить любую из доступных моделей с github.com напрямую через Visual Studio. Когда вы выбираете модель в Copilot Chat, вам будет предложено включить выбранную вами модель.

3. Сопоставление кода
То, как и куда Copilot вставляет свои предложения кода в ваш код, также получило обновление в этом выпуске с улучшениями того, что в Microsoft называют Code Mapping (Сопоставление кода).

4. Предложения следующего редактирования
Функция Next Edit Suggestions (Предложения следующего редактирования) помогает разработчикам, предоставляя контекстные предложения для редактирования последующего кода на основе предыдущих изменений. Вы нажимаете Tab, и курсор переходит в следующее место, где встречается подобный код.

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

Видео с демонстрацией новых возможностей тут.

Источник: https://devblogs.microsoft.com/visualstudio/github-copilot-highlights-in-visual-studio-17-14-preview-3-available-now/
👍9
День 2287. #ЗаметкиНаПолях
5 Основных Ошибок при Создании API. Начало

Создание API кажется простым… пока не придётся их поддерживать. Прекрасные API рушились просто из-за мелких решений, принятых на раннем этапе, — вещей, которых вы даже не замечаете, пока API не окажется под давлением реального мира. Разберём 5 самых распространённых ошибок при создании API и как вы можете избежать попадания в эти ловушки.

1. Плохая или отсутствующая проверка ввода
Ошибка: Вера в то, что клиенты всегда будут отправлять допустимые данные.
Реальность: Если вы не проверяете ввод должным образом, API становится уязвимым для ошибок, сбоев и даже угроз безопасности.
Плохо:
app.MapPost("/users", async (UserDto user) =>
{
// Подразумеваем, что имя и email
// всегда предоставляются…
var newUser = new User {
Name = user.Name,
Email = user.Email };
await db.Users.AddAsync(newUser);
await db.SaveChangesAsync();
return Results.Ok();
});

Замечание: не размещайте логику доступа к БД непосредственно в контроллерах (конечных точках).

Проблемы:
- Нет проверки на пустые поля.
- Нет проверки формата email.
- Не применяются бизнес-правила (например, минимальная/максимальная длина).

Лучше:
app.MapPost("/users", async (UserDto user) =>
{
if (string.IsNullOrWhiteSpace(user.Name) || string.IsNullOrWhiteSpace(user.Email))
return Results.BadRequest(
"Имя и email обязательны.");

if (!user.Email.Contains("@"))
return Results.BadRequest(
"Неверный формат email.");

var newUser = new User {
Name = user.Name.Trim(),
Email = user.Email.Trim() };

});

Ещё лучше – используйте FluentValidation или собственный сервис валидации, чтобы избежать замусоривания ваших конечных точек.

Почему важно:
- Защищает целостность БД.
- Упрощает отладку на стороне клиента («BadRequest» вместо «ошибки 500»).
- Уберегает бэкенд от загадочных ошибок в будущем.

2. Отсутствие версионирования API
Ошибка: Выпуск API без версий, потому что «добавим позже».
Реальность: Нужно будет изменить API. И когда вы это сделаете, вы пожалеете, что не запланировали версионирование.
Плохо:
app.MapGet("/products", () =>
{
// возврат продуктов
});

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

Лучше:
app.MapGroup("/api/v1")
.MapGet("/products", () =>
{
// возврат продуктов версии 1
});

app.MapGroup("/api/v2")
.MapGet("/products", () =>
{
// возврат продуктов версии 2
});

Или используйте .RequireHost() для разных поддоменов.

Почему важно:
- Вы можете развёртывать улучшения, не нарушая работу существующих клиентов.
- Даёт команде возможность постепенного отказа от старых клиентов.

Продолжение следует…

Источник:
https://thecodeman.net/posts/building-apis-top-5-mistakes
👍29👎1
День 2288. #ЗаметкиНаПолях
5 Основных Ошибок при Создании API. Продолжение
Начало

3. Вводящие в заблуждение или неверные коды состояния
Ошибка: Возврат 200 OK для всего — даже когда что-то не так.
Реальность: Коды состояния HTTP существуют по определенной причине: для передачи намерения.
Плохо:
return Results.Ok("User not found.");

Проблема: Клиент видит 200 OK. Но пользователя не существует. Это сбивает с толку! Теперь клиенту нужно разобрать строку сообщения, чтобы понять, что не так. Это плохая практика.
Лучше:
var user = await db.Users.FindAsync(id);
if (user is null)
return Results.NotFound(
$"Пользователь с id={id} не найден.");

return Results.Ok(user);

Используйте:
- 400 BadRequest → Плохие входные данные
- 401 Unauthorized → Необходим вход в систему
- 403 Forbidden → Доступ запрещён (нет прав)
- 404 Not Found → Ресурс не найден
- 500 Internal Server Error → Что-то сломалось на сервере.

Почему важно:
- Клиенты могут реагировать программно (повторять запрос, перенаправлять пользователя, показывать ошибку и т.д.).
- Ваш API ведёт себя как добропорядочный гражданин в Интернете.

4. Лишние данные в моделях ответа
Ошибка: Возврат целых сущностей БД или гигантских вложенных моделей.
Реальность: Клиентам обычно нужен небольшой фрагмент данных, а не вся схема вашей БД.
Плохо:
app.MapGet("/orders", async (DbContext db) =>
{
var orders = await db.Orders.ToListAsync();
return Results.Ok(orders);
});

Проблемы:
- Утечка внутренней структуры БД.
- Может случайно раскрыть конфиденциальные поля.
- Большая нагрузка на трафик = медленный API.

Лучше:
app.MapGet("/orders", async (DbContext db) =>
{
var orders = await db.Orders
.Select(o => new
{
o.Id,
o.CustomerName,
o.TotalAmount,
o.OrderDate
})
.ToListAsync();

return Results.Ok(orders);
});

Почему важно:
- Вы контролируете, какие именно данные покидают ваш сервер.
- Меньше и быстрее ответы = более довольные пользователи и лучше SEO.
- Меньше риска безопасности, если ваша модель изменится позже.

Окончание следует…

Источник:
https://thecodeman.net/posts/building-apis-top-5-mistakes
👍16👎1
День 2289. #ЗаметкиНаПолях
5 Основных Ошибок при Создании API. Окончание

Начало
Продолжение

5. Отсутствие централизованной обработки ошибок
Ошибка: Хаотичное использование блоков try-catch по всему коду или, что ещё хуже оставление исключений необработанными.
Реальность: Нужно одно место для аккуратной обработки непредвиденных ошибок.
Плохо:
try
{
var user = await db.Users.FindAsync(id);
return Results.Ok(user);
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}

Проблемы:
- Дублирование кода.
- Несогласованные ответы с ошибками.
- Трудности с правильным логированием.

Лучше (использование промежуточного ПО обработки ошибок):
app.UseExceptionHandler(app =>
{
app.Run(async ctx =>
{
ctx.Response.StatusCode = 500;
ctx.Response.ContentType = "application/json";
await ctx.Response.WriteAsJsonAsync(new
{
Error = "Что-то пошло не так."
});
});
});

Ещё лучше – использование ProblemDetails (application/problem+json) в .NET 9 автоматически через ответ Problem().

Почему важно:
- Более чистый код.
- Стандартные сообщения об ошибках для всех клиентов.
- Простота подключения логирования (Serilog, OpenTelemetry, и т.п.).

Кроме того:
Не рекомендуется использовать исключения в качестве основного способа обработки ошибок. Вместо этого, если вы создаёте новые API сегодня, рассмотрите шаблон Result (например, Result, OneOf и т.д.). Так вы явно возвращаете результаты успеха/неудачи, вообще не полагаясь на исключения. Исключения должны использоваться для действительно неожиданных случаев, а не для обычных ошибок проверки. Тем не менее, если ваш проект (или ваша команда) уже использует исключения, лучшим решением будет централизовать их обработку.

Вот простая обработка ошибок в стиле Result:
public record Result<T>(
bool IsSuccess,
T? Value,
string? ErrorMessage
);

app.MapGet("/users/{id}",
async (Guid id, DbContext db) =>
{
var user = await db.Users.FindAsync(id);
if (user is null)
return Results.NotFound(
new Result<User>(
false,
null,
"Пользователь не найден"));

return Results.Ok(
new Result<User>(true, user, null));
});


Итого
API — это не просто «передача данных туда и обратно».
API — это контракты.
API — это обещания.
Когда вы создаёте API с хорошей проверкой входных данных, управлением версиями, обработкой ошибок и продуманными ответами — вы даёте обещание своим клиентам (и себе в будущем), что ваша система будет надёжной и предсказуемой. Даже небольшие улучшения в API сейчас могут сэкономить десятки часов позже.

Источник: https://thecodeman.net/posts/building-apis-top-5-mistakes
👍14
День 2290. #ЧтоНовенького
Поддержка Валидации в Минимальных API

В превью 3 .NET 10 доступна поддержка валидации в минимальных API. Эта функция позволяет вам требовать валидацию данных, отправляемых на конечные точки API. Когда валидация включена, среда выполнения ASP.NET Core выполнит любые проверки, определённые для параметров запроса, заголовка и маршрута, а также для тела запроса. Валидации можно определить с помощью атрибутов из пространства имён System.ComponentModel.DataAnnotations.

Разработчики также могут добавлять кастомную валидацию с помощью:
- создания пользовательских реализаций ValidationAttribute (для валидации отдельных свойств);
- реализации интерфейса IValidatableObject для сложной логики проверки (задействующей несколько свойств модели).
Если валидация не проходит, среда выполнения возвращает ответ 400 Bad Request с подробностями ошибок валидации.

Чтобы включить встроенную поддержку валидации для минимальных API, вызовите метод расширения AddValidation, чтобы зарегистрировать требуемые сервисы в контейнере зависимостей приложения:
builder.Services.AddValidation();

Вам также нужно установить свойство InterceptorsNamespaces в файле проекта следующим образом:
<PropertyGroup>
<!-- Включаем генерацию перехватчиков для атрибутов валидации -->
<InterceptorsNamespaces>$(InterceptorsNamespaces);Microsoft.AspNetCore.Http.Validation.Generated</InterceptorsNamespaces>
</PropertyGroup>

Реализация автоматически обнаруживает типы, которые определены в обработчиках минимальных API или базовые типы типов, определённых в обработчиках минимальных API. Валидация выполняется для этих типов с помощью фильтра, добавляемого к каждой конечной точке.
Таким образом, используется генерация исходного кода для добавления перехватчиков, что очень эффективно. Но всё-таки, надеюсь, что к релизу добавление этого магического кода будет не обязательно.

Валидация может быть отключена для определённых конечных точек с помощью метода расширения DisableValidation:
app.MapPost("/products",
([EvenNumber(ErrorMessage = "ID должен быть чётным")]
int productId,
[Required] string name)
=> TypedResults.Ok(productId))
.DisableValidation();


Атрибуты валидации могут добавляться как к отдельным параметрам конечной точки, так и к свойствам модели (если класс модели является параметром конечной точки).

Источник: https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview3/aspnetcore.md#validation-support-in-minimal-apis
👍4
День 2291. #TipsAndTricks
Скрипт PowerShell для Переименования Проектов .NET
Переименовать проект .NET — утомительное занятие. Вам придётся переименовать файлы и папки, а также заменить содержимое в файлах, например пространство имён или путь в файлах .sln.

Следующий скрипт PowerShell, переименует файлы и папки и заменит содержимое в файлах:
$ErrorActionPreference = "Stop"

$rootFolder = Resolve-Path -Path "."
$oldName = "SampleRazorPages"
$newName = "SampleWebApp"

# Переименовываем файлы и папки
foreach ($item in Get-ChildItem -LiteralPath $rootFolder -Recurse | Sort-Object -Property FullName -Descending) {
$itemNewName = $item.Name.Replace($oldName, $newName)
if ($item.Name -ne $itemNewName) {
Rename-Item -LiteralPath $item.FullName -NewName $itemNewName
}
}

# Заменяем содержимое в файлах
foreach ($item in Get-ChildItem $rootFolder -Recurse -Include "*.cmd", "*.cs", "*.csproj", "*.json", "*.md", "*.proj", "*.props", "*.ps1", "*.sln", "*.slnx", "*.targets", "*.txt", "*.vb", "*.vbproj", "*.xaml", "*.xml", "*.xproj", "*.yml", "*.yaml") {
$content = Get-Content -LiteralPath $item.FullName
if ($content) {
$newContent = $content.Replace($oldName, $newName)
Set-Content -LiteralPath $item.FullName -Value $newContent
}
}


Источник: https://www.meziantou.net/powershell-script-to-rename-dotnet-projects.htm
👍26
День 2292. #SystemDesign101
Объяснение Модели OSI
Как данные передаются по сети? Зачем нам нужно так много уровней в модели OSI (Open Systems Interconnection)?

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

Шаг 1: Когда устройство A отправляет данные устройству B по сети через протокол HTTP, сначала добавляется заголовок HTTP на прикладном уровне.

Шаг 2: Затем к данным добавляется заголовок TCP или UDP. Они инкапсулируются в сегменты TCP на транспортном уровне. Заголовок содержит порт источника, порт назначения и порядковый номер.

Шаг 3: Сегменты инкапсулируются с заголовком IP на сетевом уровне. Заголовок IP содержит IP-адреса источника/получателя.

Шаг 4: Добавляется заголовок MAC на канальном уровне с MAC-адресами источника/получателя.

Шаг 5: Инкапсулированные фреймы отправляются на физический уровень и передаются по сети в двоичном формате.

Шаги 6–10: Когда устройство B получает двоичные данные из сети, оно выполняет процесс деинкапсуляции, который является обратным процессу инкапсуляции. Заголовки удаляются слой за слоем, и в итоге устройство B может прочитать данные.

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

Источник: https://github.com/ByteByteGoHq/system-design-101
👍11
День 2293. #УрокиРазработки
Уроки 50 Лет Разработки ПО


Совершенствование процессов
Цель совершенствования процесса разработки (Software Process Improvement, SPI) — снизить стоимость разработки и сопровождения ПО. Это средство достижения превосходных бизнес-результатов, что бы ни подразумевалось под ними: ускорение доставки продуктов, уменьшение количества переделок, лучшее удовлетворение потребностей клиентов, снижение затрат на поддержку и т.п. Что-то должно измениться в работе команды, чтобы данная цель стала достижимой. Это изменение и есть SPI. Каждый ретроспективный обзор, чтобы извлечь уроки и улучшить работу в следующий раз, закладывает основу для совершенствования процессов. Каждая новая техника, делающая проект более эффективным и действенным, совершенствует процесс.

Не бойтесь процессов
Для некоторых слово «процесс» имеет негативный оттенок. Иногда люди не осознают, что у них уже есть процесс разработки ПО, даже если он плохо определён или не задокументирован. Некоторые опасаются, что необходимость следовать процедурам будет ограничивать их, подавлять творческий потенциал или замедлит проект. Конечно, можно упорно применять неподходящие процессы, не добавляя ценности и не допуская изменений в проектах и людях. Но это не обязательно! Когда всё работает правильно, организации добиваются успеха благодаря процессам, а не вопреки им. Разумные и подходящие процессы помогают добиваться успеха постоянно. Процесс и творчество совместимы.

Несмотря на концептуальную простоту, SPI — сложная задача. Нелегко заставить людей признать наличие недостатков в их нынешних методах работы. Любая проектная работа сложна, и как же уговорить команды тратить время на выявление и устранение недостатков? Изменить культуру организации непросто, однако SPI предполагает изменение культуры наряду с изменениями в технических и управленческих методах.

Как возвести SPI в привычку
Многие программы SPI не дают эффективных и устойчивых результатов. Новые модные инициативы по изменениям вводятся с помпой, но потом тихо исчезают без объявления и анализа причин. Организация отказывается от приложенных усилий и позже пробует что-то другое. Обычно вы можете совершить только две неудачные попытки стратегического совершенствования, прежде чем люди решат, что организация несерьёзно относится к изменениям. После двух неудач мало кто всерьёз отнесётся к следующей инициативе по изменению.

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

Если в организации нет настоятельной необходимости соблюдать определённый стандарт, например в целях сертификации, то приемлема любая система разработки, будь то устоявшаяся модель, вроде Agile или какая-то своя. Но если рассматривать SPI просто как очередную причуду руководства, то большинство работников постараются просто пережить её, пытаясь выполнять свою настоящую работу, несмотря на отвлекающие факторы. Это не способствует успеху изменений.

Первые шаги
1. Каких бизнес-результатов вы ещё не достигли, для чего могло бы потребоваться SPI?
2. Увенчались ли успехом прошлые инициативы SPI? Какие действия окупились: устоявшаяся модель совершенствования или доморощенные подходы?
3. Определите любые недостатки или проблемы в работе организации, устранив которые можно улучшить процессы.
4. Как каждая проблема влияет на способность успешно выявлять, разрабатывать и внедрять SPI?
5. Попробуйте определить основные причины, провоцирующие или усугубляющие каждую проблему.

Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 6.
👍4👎3
День 2294. #ЧтоНовенького
Поддержка Server-Sent Events (SSE)
ASP.NET Core теперь поддерживает возврат результата ServerSentEvents с помощью API TypedResults.ServerSentEvents. Эта функция поддерживается как в минимальных API, так и в приложениях на основе контроллеров.

События Server-Sent (SSE) — это технология push-уведомлений со стороны сервера, которая позволяет серверу отправлять поток сообщений о событиях клиенту в рамках одного HTTP-соединения. В .NET сообщения о событиях представлены как объекты SseItem<T>, которые могут содержать тип события, идентификатор и полезные данные типа T.

Класс TypedResults включает новый статический метод ServerSentEvents для возврата результата ServerSentEvents. Первым параметром этого метода является IAsyncEnumerable<SseItem<T>>, который представляет собой поток сообщений о событиях, отправляемых клиенту.

В следующем примере показано, как использовать API TypedResults.ServerSentEvents для возврата клиенту потока событий сердечного ритма в виде объектов JSON:
app.MapGet("/json-item", 
(CancellationToken ct) =>
{
async IAsyncEnumerable<HeartRateEvent>
GetHeartRate(
[EnumeratorCancellation]
CancellationToken token)
{
while (!token.IsCancellationRequested)
{
var hr = Random.Shared.Next(60, 100);
yield return HeartRateEvent.Create(hr);
await Task.Delay(2000, token);
}
}

return TypedResults.ServerSentEvents(
GetHeartRate(ct),
eventType: "heartRate");
});


Подробнее Server-Sent Events разобрал Ник Чапсас в своём видео.

Источник: https://github.com/dotnet/core/blob/main/release-notes/10.0/preview/preview3/aspnetcore.md#support-for-server-sent-events-sse
👍28
День 2295. #Карьера
Как Расставлять Приоритеты Задач, Когда Всё Кажется Срочным. Начало

У всех нас были дни, когда список задач состоял из одних «срочных» запросов. Менеджеру по продукту нужна эта функция вчера. В производстве только что появились три критических ошибки. Технический долг, который вы откладывали, наконец стал причиной проблем. И от вас ожидают, что вы будете справляться со всем этим одновременно. С правильной структурой и инструментами расстановки приоритетов вы можете прорваться через хаос и сосредоточиться на том, что действительно важно.

Почему это важно?
Эффективная расстановка приоритетов — это не только работа быстрее, но и работа умнее. Для разработчиков правильная расстановка приоритетов задач:
- Уменьшает переключение контекста, которое, как показывают исследования, может снизить производительность до 40%.
- Гарантирует устранение критических ошибок и проблем безопасности до того, как они повлияют на пользователей.
- Согласует работу по разработке с целями и сроками бизнеса.
- Снижает стресс и предотвращает выгорание.
- Создаёт возможность работы «в потоке», когда получается лучший код.

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

Эффективные методики определения приоритетов задач разработки
Следующие проверенные методики могут помочь вам определить, что заслуживает вашего внимания в первую очередь.

1. Матрица Эйзенхауэра: срочное и важное
Матрица Эйзенхауэра делит задачи на четыре квадранта в зависимости от их срочности и важности.
- Срочно и важно: критические ошибки, уязвимости безопасности, сбои в производстве. Делайте это немедленно.
- Важно, но не срочно: рефакторинг кода, документирование, изучение новых навыков. Запланируйте время для этого.
- Срочно, но не важно: всяческие встречи, письма, обновления статуса. Делегируйте, если возможно.
- Не срочно и не важно: прочие отвлекающие факторы. Полностью исключите это.

Для разработчиков эта методика особенно ценна, поскольку помогает различать действительно чрезвычайные ситуации (например, нарушения безопасности) и задачи, которые просто кажутся срочными, но могут подождать (например, запрос на функцию, который «абсолютно необходимо сделать на этой неделе»).

2. Метод ABCDE
Разработан Брайаном Трейси и предлагает простой подход к расстановке приоритетов:
- A: Высокоприоритетные, срочные задачи со значительными последствиями, если не будут выполнены.
- B: Важные задачи, но менее срочные, чем A, со средними последствиями.
- C: Низкоприоритетные с небольшими или нулевыми последствиями.
- D: Задачи, которые можно делегировать другим.
- E: Задачи, которые можно полностью исключить.
Всегда сначала беритесь за задачи «A», так как они требуют немедленных действий и существенно влияют на ваши долгосрочные цели и сроки.

3. Метод MoSCoW
Особенно полезный для agile команд. Классифицирует задачи следующим образом:
- Обязательно (Must have): критические требования, которые должны быть выполнены для успеха проекта.
- Хорошо бы (Should have): важные функции, которые добавляют значительную ценность, но не являются абсолютно необходимыми.
- Можно бы (Could have): функции, которые улучшат продукт, но могут быть отложены.
- Необязательно (Won’t have): функции, которые не будут реализованы в текущей итерации.
Эта структура особенно хорошо работает при расстановке приоритетов в пользовательских историях и требованиях на основе их важности для общего пользовательского опыта.

Продолжение следует…

Источник:
https://dev.to/teamcamp/how-to-prioritize-tasks-when-everything-feels-urgent-a-developers-guide-3d6o
👍12
День 2296. #Карьера
Как Расставлять Приоритеты Задач, Когда Всё Кажется Срочным. Продолжение

Начало

Практические шаги
1. Соберите и перечислите все задачи

Прежде чем вы сможете эффективно расставить приоритеты, необходимо иметь представление обо всём, что нужно сделать. Составьте полный список задач, включая:
- Назначенные тикеты и отчёты об ошибках;
- Запросы функций;
- Обзоры кода;
- Элементы технического долга;
- Необходимость документации;
- Встречи и административная работа.
Используйте инструмент управления проектами, чтобы централизовать эту информацию, а не держать её разбросанной по электронным письмам, сообщениям в мессенджерах и листочкам на рабочем столе.

2. Оцените истинную срочность и кажущуюся срочность
Не всё, что помечено как «срочное», на самом деле срочно. Задайте эти вопросы, чтобы определить фактическую срочность задачи:
- Что произойдет, если это не будет сделано сегодня? На этой неделе?
- Кто пострадает, если эта задача будет отложена?
- Блокирует ли это других членов команды или элементы критического пути?
- Существуют ли жёсткие сроки, обусловленные внешними факторами (например, запуск продукта)?
Часто вы обнаружите, что многие «срочные» запросы могут подождать без существенных последствий.

3. Примените методику приоритетов
Выберите одну из методик, обсуждавшихся ранее, и классифицируйте каждую задачу соответствующим образом. Будьте честны и реалистичны в отношении того, к какому классу относятся задачи — не позволяйте всему скатываться в категорию «срочно и важно».

4. Сосредоточьтесь на одной задаче за раз
Многозадачность — миф, особенно для разработчиков. Переключение контекста между задачами написания кода особенно затратно с когнитивной точки зрения. Как только вы определили самую приоритетную задачу:
- Закройте ненужные вкладки и приложения;
- Блокируйте отвлекающие факторы (email, телефон, мессенджеры и т.д.);
- Установите таймер для сосредоточенной работы («помидорный график» хорошо подходит многим разработчикам);
- Работайте над этой единственной задачей до её завершения или до тех пор, пока не достигнете логической точки остановки.

5. Сообщите приоритеты и установите ожидания
Когда вы не можете сделать всё сразу (а вы не можете), становится важным чёткое общение:
- Сообщите заинтересованным сторонам о ваших текущих приоритетах и о том, почему вы расположили задачи в определённом порядке;
- Укажите реалистичные сроки для менее приоритетных задач;
- При необходимости обсудите сроки;
- Будьте прозрачны в отношении ограничений ваших физических способностей.
Большинство разумных членов команды поймут решения по расстановке приоритетов, если вы чётко объясните свои доводы.

Инструменты
Правильные инструменты могут значительно упростить процесс.

1. Платформы управления проектами
Предоставляют централизованное рабочее пространство для визуализации, организации и расстановки приоритетов задач. Некоторые платформы, такие как Teamcamp помогают отслеживать и анализировать время. Такие инструменты помогут вам:
- Определить, какие задачи постоянно занимают больше времени, чем ожидалось;
- Распознать закономерности в вашей производительности;
- Делать более точные оценки для будущей работы;
- Обосновывать решения по расстановке приоритетов с помощью данных.

2. Инструменты автоматизации
Автоматизируя повторяющиеся задачи, вы освобождаете умственное пространство и время для важной работы:
- Настройте конвейеры CI/CD для автоматизации тестирования и развёртывания;
- Создайте скрипты для распространённых шаблонов кода;
- Используйте чат-ботов для рутинных коммуникаций;
- Внедрите автоматизированные проверки кода.
Каждая задача, которую вы автоматизируете, — это на одну задачу меньше, в конкуренции за ваше внимание.

Окончание следует…

Источник:
https://dev.to/teamcamp/how-to-prioritize-tasks-when-everything-feels-urgent-a-developers-guide-3d6o
👍5
День 2297. #Карьера
Как Расставлять Приоритеты Задач, Когда Всё Кажется Срочным. Окончание

Начало
Продолжение

Стратегии приоритизации для разработчиков
1. Метод Айви Ли

- В конце каждого рабочего дня записывайте 6 самых важных задач на завтра.
- Расположите эти задачи в порядке важности.
- Когда вы начнёте работу на следующий день, сосредоточьтесь исключительно на первой задаче, пока она не будет завершена.
- Переходите к следующей задаче только после завершения предыдущей.
- Перемещайте все незавершённые задачи в список на завтра.
- Повторяйте ежедневно.

2. Блокировка времени для работы «в потоке»
Разработчикам нужно непрерывное время для сложных задач. Попробуйте этот подход:
- Определите 2–3 самые приоритетные задачи на день.
- Выделите 90–120-минутные отрезки в графике для сосредоточенной работы над этими задачами.
- Установите статус «Не беспокоить» на эти периоды.
- Сгруппируйте встречи и административную работу в другие временные блоки.
- Оставляйте буферное время между блоками для непредвиденных проблем.

3. Правило 1–3–5
Помогает поддерживать реалистичные ожидания относительно того, что вы можете сделать за день. Планируйте выполнение:
- 1 большой задачи;
- 3 средних задач;
- 5 небольших задач.
Этот подход признаёт, что не все задачи требуют одинакового количества времени или умственной энергии, что помогает вам создать более сбалансированный и достижимый ежедневный план.

4. Когда сказать «нет» (и как это сделать)
Иногда лучшая стратегия расстановки приоритетов — научиться говорить «нет» новым задачам, когда вы по уши в работе. Это может быть особенно сложно для разработчиков, но это важно для поддержания фокуса и качества.

Когда поступает новый «срочный» запрос:
- Оцените, как он соотносится с текущими приоритетами.
- Если он действительно более важен, объясните, какая текущая задача будет отложена в результате.
- Если он менее важен, объясните свои текущие приоритеты и когда вы могли бы разумно взяться за новую задачу.
- Предложите альтернативы (Может ли кто-то другой справиться с этим? Можно ли это упростить? Можно ли отодвинуть срок?)
Помните: говорить «да» каждый раз тоже невыгодно, поэтому говорить «нет» новой работе означает, что вы заботитесь о том, чтобы качественно выполнять ту работу, которая действительно важна.

Итого
Эффективная расстановка приоритетов — это не разовое упражнение, а постоянная практика. Чтобы построить устойчивую систему:
- Ежедневно пересматривайте приоритеты: тратьте 10 минут каждое утро на оценку того, что заслуживает внимания сегодня.
- Проводите еженедельное планирование: тратьте 30 минут в начале каждой недели на то, чтобы согласовать свои задачи с более широкими целями.
- Обдумывайте и корректируйте: в конце каждой недели оценивайте, что сработало, а что нет в вашем подходе к расстановке приоритетов.

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

Источник: https://dev.to/teamcamp/how-to-prioritize-tasks-when-everything-feels-urgent-a-developers-guide-3d6o
👍2👎2
День 2298. #TipsAndTricks
Очистка Кэшей NuGet

NuGet может кэшировать множество пакетов и других вещей с течением времени. Сегодня рассмотрим, как очистить большинство из этого.

Вы можете посмотреть используемые кэши и их местонахождения, выполнив следующую команду:
dotnet nuget locals all --list

Вывод будет примерно таким:
http-cache: C:\Users\sbenz\AppData\Local\NuGet\v3-cache
global-packages: C:\Users\sbenz\.nuget\packages\
temp: C:\Users\sbenz\AppData\Local\Temp\NuGetScratch
plugins-cache: C:\Users\sbenz\AppData\Local\NuGet\plugins-cache

Со временем там накапливается гигантский объём данных. У меня http-cache больше 2ГБ, а global-packages больше 20ГБ. Если у вас достаточно места, можете оставить всё как есть. Это просто кэшированные данные, которые на самом деле безвредны (кроме занятого места).

Кэш NuGet-пакетов
Папка global-packages — это то место, куда dotnet restore помещает все пакеты пользователя. Поэтому неважно, в каком репозитории вы находитесь, он всегда загружает каждый пакет (конечно, включая все зависимости, которые требуются пакету) в эту папку. Преимущество в том, что, если только это не nodejs и npm, у вас будет супербыстрое восстановление для пакетов, которые уже загружены и не являются локальными для вашего репозитория.

Чтобы удалить кэш (что приведёт к повторной загрузке требуемых пакетов), вы можете либо очистить содержимое папки, либо просто вызвать:
dotnet nuget locals global-packages --clear


Кэш Http
То же самое относится к http-cache. По сути, он хранит метаданные в пакетов (например, в каких версиях они существуют в NuGet), но также, похоже, содержит некоторые бинарные файлы. В любом случае, если вы хотите удалить это:
dotnet nuget locals http-cache --clear


Временные данные
Папка temp хранит временные файлы. Очистить её можно так:
dotnet nuget locals temp --clear


Удалить всё
Следующая команда удалит все кэшированные данные NuGet:
dotnet nuget locals all --clear


После этого, при создании нового приложения, все данные NuGet будут скачаны заново из интернета. Но это также уберёт всё ненужное!

Источник: https://steven-giesel.com/blogPost/ef7e9271-3b8d-4658-988f-b48bbd11e320/clearing-nuget-caches
👍26
День 2299. #Оффтоп
Доброй субботы, дорогие подписчики. Давно не рекомендовал вам познавательных видосиков. Я обожаю истории про историю (извините за тавтологию) развития компьютеров и программирования. И сегодня порекомендую вам одну из таких ламповых – в прямом смысле – историй.

Как появились первые диоды и триоды? Почему алгебру логики называют булевой? Как «считают» компьютеры на самом нижнем уровне? Сколько энергии потреблял первый ЭНИАК?

Об этом и не только в видео с канала Veritasium. Приятного просмотра.

https://youtu.be/FU_YFpfDqqA
(видео с переводом на русский здесь)

А для тех, кому захочется ещё больше углубиться в историю и узнать про аналоговые компьютеры, вот видео в двух частях: часть 1, часть 2 (видео с переводом на русский: часть 1, часть 2).
👍13
День 2300. #УрокиРазработки
Уроки 50 Лет Разработки ПО

Урок 51. Остерегайтесь «менеджмента по Businessweek». Начало

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

Руководитель может прочитать о многообещающей, но, возможно, чересчур разрекламированной методологии и настаивать на немедленном принятии её в организации. Этот феномен называют «менеджмент по Businessweek». Либо разработчик, посетив конференцию, узнаёт о новом способе решения своих задач и торопится попробовать его. Стремление к совершенствованию похвально, но вы должны направить эту энергию в правильное русло и оценить, насколько хорошо потенциальное решение соответствует вашей культуре, прежде чем принять его.

За прошедшие годы люди изобрели бесчисленное множество парадигм, методологий и систем управления разработкой ПО:
- анализ и проектирование структурированных систем;
- объектно-ориентированное программирование;
- информационная инженерия;
- быстрая разработка приложений;
- спиральная модель;
- разработка через тестирование;
- рациональный унифицированный процесс;
- DevOps.

Методология Agile-разработки во многих её вариациях (экстремальное программирование, адаптивная разработка, разработка на основе функциональности, Scrum, Lean, Kanban, Scaled Agile Framework и др.) ещё один пример стремления к идеальным решениям.

Увы, как учит дядюшка Брукс, «серебряной пули не существует». Все вышеперечисленные подходы имеют свои достоинства и недостатки и должны применяться к соответствующим задачам правильно подготовленными командами и руководителями. В качестве примера далее рассмотрим некий новый подход к разработке ПО под названием «Метод Х».

Сначала проблема, потом решение
В статьях и книгах, написанных изобретателями и первыми последователями «Метода Х», восхвалялись его преимущества. Некоторые компании выбрали «Метод Х», желая создавать продукты, которые лучше удовлетворяют потребности клиентов. Хотите быстрее доставлять полезное ПО? (А кто не хочет?) «Метод Х» поможет в этом. Хотите уменьшить количество дефектов, раздражающих клиентов и отнимающих у команды время на доработку? (Опять же, кто не хочет?) «Метод Х» придёт на помощь! В этом суть совершенствования процессов: постановка целей, выявление препятствий и выбор методов, которые, по вашему мнению, могут помочь их устранить.

Однако прежде, чем выбрать какой-либо новый подход к разработке, спросите себя: «Что мешает нам добиться таких же результатов, которые он обещает, уже сегодня?» Если вы хотите быстрее доставлять продукты, что вам мешает? Если цель — уменьшить количество дефектов, то почему сегодня их много? И т.п. Т.е., если «Метод Х» является решением проблем, в чём их причина?

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

Предположим, вы хотите поставлять программные продукты, хорошо удовлетворяющие потребности клиентов. Вы прочитали, что в командах, применяющих «Метод Х», есть роль под названием «гуру», который отвечает за то, чтобы продукт достиг желаемого результата. «Отлично! — думаете вы. — Гуру позаботится о том, чтобы мы создали правильный продукт. Клиенты будут счастливы». Проблема решена? Может быть, но, прежде чем изменять процессы, ваша команда должна понять, почему ваши продукты не вызывают восторга у клиентов уже сейчас.

Окончание следует…

Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍9
День 2301. #УрокиРазработки
Уроки 50 Лет Разработки ПО

Урок 51. Остерегайтесь «менеджмента по Businessweek». Окончание

Начало

Анализ первопричин — это процесс размышлений, когда несколько раз задаётся вопрос «почему?», пока вы не доберётесь до проблем, на которые можно воздействовать с помощью тщательно подобранных действий по улучшению. Первая найденная причина может не оказывать прямого влияния и не быть первопричиной. Следовательно, её устранение не решит проблему. Вам нужно спросить «почему?» еще раз или два, чтобы убедиться, что вы добрались до основания дерева анализа.

На рисунке выше показан фрагмент диаграммы «Рыбий скелет» (диаграмма Исикавы) — удобного способа анализа первопричин. Ваша цель — выпускать продукты, лучше удовлетворяющие потребности клиентов. Напишите эту цель вдоль длинной горизонтальной линии. Это представляет вашу основную проблему. Затем спросите команду: «Почему мы не удовлетворяем потребности наших клиентов?» Один из возможных ответов: команда не получает адекватной информации о требованиях от конечных пользователей — обычная ситуация. Запишите эту причину вдоль диагональной линии, отходящей от формулировки цели. Хорошо, но решение проблемы требует более глубокого понимания. Поэтому далее вы спрашиваете: «Почему мы не получаем такой информации?» Один из членов группы говорит: «Мы пытались поговорить с реальными пользователями, но их руководители говорят, что они слишком заняты, чтобы работать с командой разработчиков». Кто-то ещё жалуется, что представители клиента, работающие с командой, не имеют полного представления о реальных потребностях конечных пользователей. Напишите эти причины второго уровня вдоль горизонтальных линий, отходящих от диагональной линии родительской проблемы.

Кто-то отмечает, что разработчики задают представителям клиента неправильные вопросы: «Почему задаются неправильные вопросы?» Причин может быть несколько, в том числе отсутствие образования или интереса у разработчиков к работе с требованиями. Возможно, бизнес-анализ не является основным навыком команды или в команде нет подготовленного бизнес-аналитика. Каждая причина записывается вдоль новой диагональной линии, соединяющейся с родительской.

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

Постановка диагноза ведёт к излечению
Дальше стоит перейти к поиску практических решений для устранения этих первопричин. Возможно, вы решите, что добавление бизнес-аналитика в команду более ценно, чем принятие «Метода Х» с его «гуру». Или вам нужна комбинация этих двух методов. Вы не узнаете этого, пока не продумаете всё до конца.

Вот несколько хороших вопросов, которые следует задать себе:
- Потребуется ли команде обучение, инструменты или консультации, чтобы начать работу и двигаться вперед?
- Принесёт ли решение выгоду по сравнению с вложениями?
- Какое культурное влияние окажет переход к новым методам на вашу команду, клиентов и их организации?
- Насколько крутой может быть кривая обучения?

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

Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍10
День 2302. #ЧтоНовенького #TipsAndTricks
Используем Расширения C# 14 для Парсинга Enum

Расширения ещё только в планах для C# 14, а умельцы уже предлагают интересные варианты их использования.

В .NET многие типы предоставляют статический метод Parse для преобразования строк в соответствующие им типы. Например:
int.Parse("123");
double.Parse("123.45");
DateTime.Parse("2023-01-01");
IPAddress.Parse("192.168.0.1");

В перечислениях используется обобщённый метод Enum.Parse:
Enum.Parse<MyEnum>("Value1");

А вот это не сработает:
MyEnum.Parse("Value1");


Было бы более интуитивно понятно, если бы перечисления поддерживали метод Parse напрямую. С помощью C# 14 и его новой функции членов-расширений мы можем этого добиться.

Следующий код демонстрирует, как добавить методы Parse и TryParse к перечислениям с использованием расширений C# 14:
static class EnumExtensions
{
extension<T>(T _) where T : struct, Enum
{
public static T Parse(string value)
=> Enum.Parse<T>(value);

public static T Parse(string value, bool ignoreCase)
=> Enum.Parse<T>(value, ignoreCase);

public static T Parse(ReadOnlySpan<char> value)
=> Enum.Parse<T>(value);

public static T Parse(
ReadOnlySpan<char> value,
bool ignoreCase)
=> Enum.Parse<T>(value, ignoreCase);

public static bool TryParse(
[NotNullWhen(true)] string? value,
out T result)
=> Enum.TryParse(value, out result);

public static bool TryParse(
[NotNullWhen(true)] string? value,
bool ignoreCase,
out T result)
=> Enum.TryParse(value, ignoreCase, out result);

public static bool TryParse(
ReadOnlySpan<char> value,
out T result)
=> Enum.TryParse(value, out result);

public static bool TryParse(
ReadOnlySpan<char> value,
bool ignoreCase,
out T result)
=> Enum.TryParse(value, ignoreCase, out result);
}
}


Теперь мы можем использовать методы Parse/TryParse для самого типа enum, так же как мы это делаем для других типов:
MyEnum.Parse("Value1");

if (MyEnum.TryParse("Value1", out var result))
{
//…
}


Источник: https://www.meziantou.net/use-csharp-14-extensions-to-simplify-enum-parsing.htm
👍35
День 2303. #ЗаметкиНаПолях
AsyncEnumerable в C#: Важность Атрибута EnumeratorCancellation

Сегодня рассмотрим IAsyncEnumerable<T> и почему атрибут EnumeratorCancellation для параметра CancellationToken имеет решающее значение для написания надёжного отменяемого асинхронного кода.

IAsyncEnumerable<T> — это асинхронный аналог IEnumerable<T> (см. подробнее про создание и потребление асинхронных потоков).

IAsyncEnumerable<T> позволяет:
- Выполнять асинхронные операции во время итерации последовательности;
- Выдавать результаты по мере их появления;
- Обрабатывать отмену.

Необходимость отмены
Поддержка отмены в асинхронных операциях нужна в следующих сценариях:
- Пользователь уходит с веб-страницы, которая извлекает данные;
- Операция поиска занимает слишком много времени, и пользователь отменяет её;
- Сервис завершает работу во время выполнения операций.
Без надлежащей поддержки отмены ресурсы могут быть потрачены впустую, а приложения могут перестать отвечать или произойдёт утечка ресурсов.

Атрибут EnumeratorCancellation
При применении к параметру CancellationToken в методе асинхронного итератора этот атрибут сообщает компилятору о необходимости передать этот токен методу GetAsyncEnumerator, когда итератор используется через await foreach. Вот простой пример:
public async IAsyncEnumerable<int> 
GenerateNumbersAsync(
int count,
[EnumeratorCancellation]
CancellationToken ct = default)
{
for (int i = 0; i < count; i++)
{
// Проверяем отмену
ct.ThrowIfCancellationRequested();

// Симулируем асинхронную работу
await Task.Delay(100, ct);

yield return i;
}
}


Использование метода через вызов WithCancellation:
CancellationTokenSource cts = new();
await foreach (var item in
GenerateNumbersAsync(10)
.WithCancellation(cts.Token))
{
Console.WriteLine(item);
}

Без атрибута EnumeratorCancellation существует разрыв между токеном отмены, переданным в метод асинхронного итератора, и токеном, переданным в GetAsyncEnumerator при потреблении перечисляемого объекта. Атрибут EnumeratorCancellation гарантирует, что этот токен попадёт в метод асинхронного итератора, позволяя вам реагировать на запросы отмены от потребителя.

Чтобы помочь вам избежать этой ошибки, компилятор выдает предупреждение CS8425 в качестве напоминания о правильной реализации отмены в ваших методах асинхронного итератора:
CS8425: Async-iterator method 'MyMethod' has parameters that are declared with 'CancellationToken' but are not decorated with the 'EnumeratorCancellation' attribute, and will not be passed the cancellation token from 'WithCancellation' method calls
CS8425: Метод асинхронного итератора 'MyMethod' имеет параметры, объявленные с 'CancellationToken', но не декорированные атрибутом 'EnumeratorCancellation', и ему не будет передан токен отмены из вызовов метода 'WithCancellation'.


Предупреждение возникает, когда вы определяете метод асинхронного итератора, который возвращает IAsyncEnumerable<T> и включает параметр CancellationToken, но вы не декорировали этот параметр атрибутом [EnumeratorCancellation].

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

Итого
При работе с асинхронными потоками:
- Используйте атрибут EnumeratorCancellation для параметров токена отмены;
- Регулярно проверяйте отмену;
- Распространяйте токен на внутренние операции;
- Обратите внимание на предупреждение компилятора CS8425, поскольку оно указывает на потенциальную проблему отмены.

Источник: https://bartwullems.blogspot.com/2025/04/asyncenumerable-in-c-importance-of.html
👍18