День 2559. #ЗаметкиНаПолях
Когда для Моделирования Объектов не Обойтись без Методов Расширения
Иногда "обычный" подход к моделированию сущности достигает своего предела, и приходится прибегать к методам расширения.
Проблема
Есть фронтенд-часть, которая позволяет частично обновлять сущность. Представьте, что в JIRA вы можете обновлять заголовок, автора и так далее в одном пользовательском интерфейсе. Для этого не нужен отдельный DTO для каждого варианта использования, достаточно одного DTO, который позволял бы частично обновлять сущность.
Во фронтенде (TypeScript/Angular):
Который используется в DTO:
На бэкэнде это позволяет сделать так:
Затем в методе обновления:
Это работает. Но что, если мы добавим propFour с обнуляемым типом:
Но в UpdateModel мы хотели бы иметь (потому что в случае обновления значение обязательно):
Теперь, если мы попытаемся выполнить:
Мы получим:
Argument type 'int?' is not assignable to parameter type 'int' (Тип аргумента 'int?' не может быть присвоен параметру типа 'int')
Решение
Проблема в том, что мы не можем легко переопределить возможность присвоения значения null в методе GetValueOrDefault. Здесь помогут методы расширения:
Теперь:
работает, как ожидалось.
Источник: https://steven-giesel.com/blogPost/7f6e2ade-b5b9-4de6-a060-281e45b2448e/sometimes-you-just-need-extensions-methods-to-model-your-stuff
Когда для Моделирования Объектов не Обойтись без Методов Расширения
Иногда "обычный" подход к моделированию сущности достигает своего предела, и приходится прибегать к методам расширения.
Проблема
Есть фронтенд-часть, которая позволяет частично обновлять сущность. Представьте, что в JIRA вы можете обновлять заголовок, автора и так далее в одном пользовательском интерфейсе. Для этого не нужен отдельный DTO для каждого варианта использования, достаточно одного DTO, который позволял бы частично обновлять сущность.
Во фронтенде (TypeScript/Angular):
export type Optional<T> = {
hasValue: boolean;
value: T;
};Который используется в DTO:
export type UpdateModel = {
propOne: Optional<number | null>;
propTwo: Optional<string | null>;
propThree: Optional<string>;
};На бэкэнде это позволяет сделать так:
/// <summary>
/// Структура, представляющая необязательное значение
/// </summary>
public readonly record struct
Optional<T>(bool HasValue, T Value)
{
/// <summary>
/// Возвращает значение, если оно есть, либо значение по умолчанию.
/// </summary>
public T GetValueOrDefault(T current)
=> HasValue ? Value : current;
}
Затем в методе обновления:
public void
UpdateEntity(UpdateModel model)
{
PropOne = model.PropOne
.GetValueOrDefault(entity.PropOne);
PropTwo = model.PropTwo
.GetValueOrDefault(entity.PropTwo);
PropThree = model.PropThree
.GetValueOrDefault(entity.PropThree);
}
Это работает. Но что, если мы добавим propFour с обнуляемым типом:
public int? PropFour { get; set; }Но в UpdateModel мы хотели бы иметь (потому что в случае обновления значение обязательно):
public Optional<int> PropFour { get; set; }Теперь, если мы попытаемся выполнить:
PropFour = model.PropFour
.GetValueOrDefault(entity.PropFour);
Мы получим:
Argument type 'int?' is not assignable to parameter type 'int' (Тип аргумента 'int?' не может быть присвоен параметру типа 'int')
Решение
Проблема в том, что мы не можем легко переопределить возможность присвоения значения null в методе GetValueOrDefault. Здесь помогут методы расширения:
public static class OptionalExtensions
{
/// <summary>
/// Возвращает значение, если оно есть, либо значение по умолчанию
/// </summary>
public static T? GetValueOrDefault<T>(
this Optional<T> opt,
T? value) where T : struct
=> opt.HasValue ? opt.Value : value;
}
Теперь:
PropFour = model.PropFour
.GetValueOrDefault(entity.PropFour);
работает, как ожидалось.
Источник: https://steven-giesel.com/blogPost/7f6e2ade-b5b9-4de6-a060-281e45b2448e/sometimes-you-just-need-extensions-methods-to-model-your-stuff
День 2560. #ЧтоНовенького
Microsoft Выпустили превью 3 OData .NET (ODL) 9.0.0
Microsoft выпустили OData .NET (ODL) 9.0.0 превью 3, последнюю предварительную версию клиентских и основных библиотек OData .NET, продолжая работу по модернизации библиотеки. Эта превью версия фокусируется на более безопасном поведении по умолчанию и более тесном соответствии спецификации OData.
Для контекста, текущий стабильный релиз основных библиотек OData .NET (например, Microsoft.OData.Core) остаётся на уровне 8.4.x в NuGet, при этом версия 8.4.3 является последней стабильной из этой серии. Она реализует поддержку OData v4/v4.01 и по-прежнему широко используется в производственной среде, в то время как релизы 9.x всё ещё находятся в предварительной версии.
В превью 3 поведение улучшено на основе отзывов разработчиков и в соответствии со спецификациями OData.
1. Выполнение запросов Action теперь использует семантику SingleOrDefault() для ссылок, допускающих значение null, что уменьшает количество неожиданных исключений для распространенных ответов с null, сохраняя при этом строгие проверки на недопустимые значения.
2. Удалены устаревшие конструкторы сериализации, привязанные к ISerializable, что устраняет предупреждения сборки в современных SDK.
3. Решено отказаться от старой концепции CsdlTarget и объявить устаревшими методы доступа к типам возвращаемых значений в пользу новых интерфейсов EDM.
4. Устаревшие API, связанные со свойством типа возвращаемого значения (ReturnType) в IEdmOperation, также полностью заменены новой абстракцией IEdmOperationReturn.
В совокупности эти изменения отражают стремление к совместимости с .NET 8/9/10 во время выполнения, использование более простых алгоритмов выделения памяти (например, добавление перегрузок для поиска с помощью ReadOnlySpan<char>) и опору на встроенные API платформы.
Ключевое изменение в поведении версии превью 3 — принудительная десериализация в типы-структуры для нетипизированных значений (больше нет переключателей ReadUntypedAsString), что приводит поведение во время выполнения в большее соответствие с официальным форматом OData JSON. Кроме того, для нетипизированных числовых значений теперь по умолчанию определяются определённые числовые типы CLR с флагом совместимости для устаревших результатов (числа десериализуются в тип decimal).
Переход со стабильной версии 8.x на предварительную версию 9.x пакетов NuGet следует рассматривать как ломающее изменение: разработчикам необходимо пересмотреть обработку обнуляемых возвращаемых значений, ожидаемые нетипизированные формы JSON и любые зависимости от удалённых устаревших API. Поскольку релизы 9.x всё ещё находятся в предварительной версии, их не рекомендуется использовать в производственной среде без тщательного тестирования.
Экосистема OData продолжает развиваться. Например, пакеты ASP.NET Core OData независимо перешли в собственную серию 9.x+ (включая стабильные релизы, такие как Microsoft.AspNetCore.OData 9.4.x), что свидетельствует о параллельном развитии стеков OData на стороне сервиса и клиента.
Разработчики, заинтересованные в предоставлении отзывов или отслеживании планов развития, могут следить за репозиторием OData/odata.net на GitHub и официальным блогом OData, где публикуются анонсы предварительной версии, рекомендации по миграции и информация о планах по выпуску стабильной версии 9.0.
Источник: https://www.infoq.com/news/2026/01/odata-net-preview-9/
Microsoft Выпустили превью 3 OData .NET (ODL) 9.0.0
Microsoft выпустили OData .NET (ODL) 9.0.0 превью 3, последнюю предварительную версию клиентских и основных библиотек OData .NET, продолжая работу по модернизации библиотеки. Эта превью версия фокусируется на более безопасном поведении по умолчанию и более тесном соответствии спецификации OData.
Для контекста, текущий стабильный релиз основных библиотек OData .NET (например, Microsoft.OData.Core) остаётся на уровне 8.4.x в NuGet, при этом версия 8.4.3 является последней стабильной из этой серии. Она реализует поддержку OData v4/v4.01 и по-прежнему широко используется в производственной среде, в то время как релизы 9.x всё ещё находятся в предварительной версии.
В превью 3 поведение улучшено на основе отзывов разработчиков и в соответствии со спецификациями OData.
1. Выполнение запросов Action теперь использует семантику SingleOrDefault() для ссылок, допускающих значение null, что уменьшает количество неожиданных исключений для распространенных ответов с null, сохраняя при этом строгие проверки на недопустимые значения.
2. Удалены устаревшие конструкторы сериализации, привязанные к ISerializable, что устраняет предупреждения сборки в современных SDK.
3. Решено отказаться от старой концепции CsdlTarget и объявить устаревшими методы доступа к типам возвращаемых значений в пользу новых интерфейсов EDM.
4. Устаревшие API, связанные со свойством типа возвращаемого значения (ReturnType) в IEdmOperation, также полностью заменены новой абстракцией IEdmOperationReturn.
В совокупности эти изменения отражают стремление к совместимости с .NET 8/9/10 во время выполнения, использование более простых алгоритмов выделения памяти (например, добавление перегрузок для поиска с помощью ReadOnlySpan<char>) и опору на встроенные API платформы.
Ключевое изменение в поведении версии превью 3 — принудительная десериализация в типы-структуры для нетипизированных значений (больше нет переключателей ReadUntypedAsString), что приводит поведение во время выполнения в большее соответствие с официальным форматом OData JSON. Кроме того, для нетипизированных числовых значений теперь по умолчанию определяются определённые числовые типы CLR с флагом совместимости для устаревших результатов (числа десериализуются в тип decimal).
Переход со стабильной версии 8.x на предварительную версию 9.x пакетов NuGet следует рассматривать как ломающее изменение: разработчикам необходимо пересмотреть обработку обнуляемых возвращаемых значений, ожидаемые нетипизированные формы JSON и любые зависимости от удалённых устаревших API. Поскольку релизы 9.x всё ещё находятся в предварительной версии, их не рекомендуется использовать в производственной среде без тщательного тестирования.
Экосистема OData продолжает развиваться. Например, пакеты ASP.NET Core OData независимо перешли в собственную серию 9.x+ (включая стабильные релизы, такие как Microsoft.AspNetCore.OData 9.4.x), что свидетельствует о параллельном развитии стеков OData на стороне сервиса и клиента.
Разработчики, заинтересованные в предоставлении отзывов или отслеживании планов развития, могут следить за репозиторием OData/odata.net на GitHub и официальным блогом OData, где публикуются анонсы предварительной версии, рекомендации по миграции и информация о планах по выпуску стабильной версии 9.0.
Источник: https://www.infoq.com/news/2026/01/odata-net-preview-9/
День 2561. #ЗаметкиНаПолях
Контейнеризация .NET-приложений без Dockerfile. Начало
Контейнеры стали стандартом для развёртывания современных приложений. Но если вы когда-либо писали Dockerfile, вы знаете, насколько это может быть утомительно. Нужно понимать многоэтапные сборки, выбирать правильные базовые образы, настраивать правильные порты и помнить о копировании файлов в правильном порядке. Но в принципе, без Dockerfile можно обойтись.
Начиная с .NET 7, SDK имеет встроенную поддержку публикации приложения непосредственно в образ контейнера с помощью команды dotnet publish.
Традиционный подход: Dockerfile
Сначала посмотрим, что мы заменяем. Типичный многоэтапный Dockerfile для .NET-приложения выглядит так:
Это работает, но требует обучения и дополнительных затрат на обслуживание:
- нужно вручную обновлять теги базового образа;
- неправильный порядок копирования приводит к повреждению кэша сборки;
- каждому проекту нужен похожий Dockerfile;
- переключение контекста: вы пишете Docker DSL, а не код .NET.
Подход с использованием .NET SDK устраняет все это.
Включение публикации в контейнер
Если вы работаете на .NET 10, не нужно делать ничего особенного для включения публикации в контейнер. Это будет работать для приложений ASP.NET Core, фоновых сервисов и консольных приложений. Можно публиковать напрямую в образ контейнера:
И всё. SDK .NET выполнит следующие действия:
- соберёт приложение;
- выберет подходящий базовый образ;
- создаст образ контейнера с опубликованным результатом;
- загрузит его в ваш локальный OCI-совместимый демон (наиболее популярный вариант — Docker, но он также работает с Podman).
SDK предоставляет разумные значения по умолчанию, но часто будет требоваться настроить образ. Далее рассмотрим наиболее распространённые настройки.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/containerize-your-dotnet-applications-without-a-dockerfile
Контейнеризация .NET-приложений без Dockerfile. Начало
Контейнеры стали стандартом для развёртывания современных приложений. Но если вы когда-либо писали Dockerfile, вы знаете, насколько это может быть утомительно. Нужно понимать многоэтапные сборки, выбирать правильные базовые образы, настраивать правильные порты и помнить о копировании файлов в правильном порядке. Но в принципе, без Dockerfile можно обойтись.
Начиная с .NET 7, SDK имеет встроенную поддержку публикации приложения непосредственно в образ контейнера с помощью команды dotnet publish.
Традиционный подход: Dockerfile
Сначала посмотрим, что мы заменяем. Типичный многоэтапный Dockerfile для .NET-приложения выглядит так:
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["src/MyApi/MyApi.csproj", "src/MyApi/"]
RUN dotnet restore "src/MyApi/MyApi.csproj"
COPY . .
WORKDIR "/src/src/MyApi"
RUN dotnet build "MyApi.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "MyApi.csproj" -c $BUILD_CONFIGURATION -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApi.dll"]
Это работает, но требует обучения и дополнительных затрат на обслуживание:
- нужно вручную обновлять теги базового образа;
- неправильный порядок копирования приводит к повреждению кэша сборки;
- каждому проекту нужен похожий Dockerfile;
- переключение контекста: вы пишете Docker DSL, а не код .NET.
Подход с использованием .NET SDK устраняет все это.
Включение публикации в контейнер
Если вы работаете на .NET 10, не нужно делать ничего особенного для включения публикации в контейнер. Это будет работать для приложений ASP.NET Core, фоновых сервисов и консольных приложений. Можно публиковать напрямую в образ контейнера:
dotnet publish --os linux --arch x64 /t:PublishContainer
И всё. SDK .NET выполнит следующие действия:
- соберёт приложение;
- выберет подходящий базовый образ;
- создаст образ контейнера с опубликованным результатом;
- загрузит его в ваш локальный OCI-совместимый демон (наиболее популярный вариант — Docker, но он также работает с Podman).
SDK предоставляет разумные значения по умолчанию, но часто будет требоваться настроить образ. Далее рассмотрим наиболее распространённые настройки.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/containerize-your-dotnet-applications-without-a-dockerfile
👍19
День 2562. #ЗаметкиНаПолях
Контейнеризация .NET-приложений без Dockerfile. Окончание
Начало
Настройка образа контейнера
Здесь рассмотрим наиболее распространённые настройки. Более полный список параметров см. в официальной документации.
Задание имени и тега образа
Свойство ContainerRepository задает имя образа (репозитория). Свойство ContainerImageTags задает один или несколько тегов (разделённых точками с запятой). Если нужен один тег, можно использовать ContainerImageTag:
Начиная с .NET 8 и далее, если тег не указан, по умолчанию используется последний вариант.
Выбор другого базового образа
По умолчанию SDK использует следующие базовые образы:
- mcr.microsoft.com/dotnet/runtime-deps – для self-contained приложений;
- mcr.microsoft.com/dotnet/aspnet – для приложений ASP.NET Core;
- mcr.microsoft.com/dotnet/runtime – для других случаев.
Вы можете использовать образ меньшего размера или другой образ:
Это также можно сделать, установив ContainerFamily в значение alpine, а остальное определится автоматически.
Настройка портов
Для веб-приложений по умолчанию используются открытые порты 8080 и 8081 для HTTP и HTTPS. Они определяются из переменных среды ASP.NET Core (ASPNETCORE_URLS, ASPNETCORE_HTTP_PORT, ASPNETCORE_HTTPS_PORT). Атрибут Type может быть tcp или udp:
Публикация в реестр контейнеров
Локальная публикация полезна для разработки, но для развёртывания потребуется отправить изменения в реестр. Вы можете указать целевой реестр во время публикации.
Вот пример публикации в реестр контейнеров GitHub:
Аутентификация: SDK использует ваши локальные учетные данные Docker. Убедитесь, что вы вошли в систему с помощью команды
Когда Dockerfile всё же нужен
Поддержка контейнеров в SDK мощная, но она не охватывает все сценарии. Dockerfile понадобится для:
- Установки системных зависимостей: если приложению нужны нативные библиотеки (например, libgdiplus для обработки изображений);
- Сложных многоэтапных сборок: нужно запускать кастомные шаги сборки;
- Компонентов, не относящихся к .NET: контейнеру нужны дополнительные сервисы или инструменты.
Но для большинства веб-API и фоновых сервисов SDK-подхода достаточно.
Источник: https://www.milanjovanovic.tech/blog/containerize-your-dotnet-applications-without-a-dockerfile
Контейнеризация .NET-приложений без Dockerfile. Окончание
Начало
Настройка образа контейнера
Здесь рассмотрим наиболее распространённые настройки. Более полный список параметров см. в официальной документации.
Задание имени и тега образа
Свойство ContainerRepository задает имя образа (репозитория). Свойство ContainerImageTags задает один или несколько тегов (разделённых точками с запятой). Если нужен один тег, можно использовать ContainerImageTag:
<PropertyGroup>
<ContainerRepository>ghcr.io/USERNAME/REPOSITORY</ContainerRepository>
<ContainerImageTags>1.0.0;latest</ContainerImageTags>
</PropertyGroup>
Начиная с .NET 8 и далее, если тег не указан, по умолчанию используется последний вариант.
Выбор другого базового образа
По умолчанию SDK использует следующие базовые образы:
- mcr.microsoft.com/dotnet/runtime-deps – для self-contained приложений;
- mcr.microsoft.com/dotnet/aspnet – для приложений ASP.NET Core;
- mcr.microsoft.com/dotnet/runtime – для других случаев.
Вы можете использовать образ меньшего размера или другой образ:
xml
<PropertyGroup>
<!-- Используем образ на основе Alpine, меньшего размера -->
<ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:10.0-alpine</ContainerBaseImage>
</PropertyGroup>
Это также можно сделать, установив ContainerFamily в значение alpine, а остальное определится автоматически.
Настройка портов
Для веб-приложений по умолчанию используются открытые порты 8080 и 8081 для HTTP и HTTPS. Они определяются из переменных среды ASP.NET Core (ASPNETCORE_URLS, ASPNETCORE_HTTP_PORT, ASPNETCORE_HTTPS_PORT). Атрибут Type может быть tcp или udp:
<PropertyGroup>
<ContainerPort Include="8080" Type="tcp" />
<ContainerPort Include="8081" Type="tcp" />
</PropertyGroup>
Публикация в реестр контейнеров
Локальная публикация полезна для разработки, но для развёртывания потребуется отправить изменения в реестр. Вы можете указать целевой реестр во время публикации.
Вот пример публикации в реестр контейнеров GitHub:
dotnet publish --os linux --arch x64 /t:PublishContainer /p:ContainerRegistry=ghcr.io
Аутентификация: SDK использует ваши локальные учетные данные Docker. Убедитесь, что вы вошли в систему с помощью команды
docker login перед публикацией в удалённый реестр.Когда Dockerfile всё же нужен
Поддержка контейнеров в SDK мощная, но она не охватывает все сценарии. Dockerfile понадобится для:
- Установки системных зависимостей: если приложению нужны нативные библиотеки (например, libgdiplus для обработки изображений);
- Сложных многоэтапных сборок: нужно запускать кастомные шаги сборки;
- Компонентов, не относящихся к .NET: контейнеру нужны дополнительные сервисы или инструменты.
Но для большинства веб-API и фоновых сервисов SDK-подхода достаточно.
Источник: https://www.milanjovanovic.tech/blog/containerize-your-dotnet-applications-without-a-dockerfile
👍10
День 2563. #ЗаметкиНаПолях
Планирование Задач с Coravel
Coravel — легковесная библиотека с открытым кодом, которая добавляет в .NET-приложения планирование фоновых задач, постановку в очередь, кэширование, отправку почты и трансляцию событий — и всё это без необходимости в отдельной инфраструктуре.
Основные преимущества:
- Не требуется база данных или брокер сообщений;
- Идеально подходит для небольших и средних приложений;
- Полная интеграция с внедрением зависимостей ASP.NET Core;
- Чистый и читаемый синтаксис.
Посмотрим, что вы можете сделать с Coravel.
Планирование задач
Создаём задачу:
Регистрируем:
Планируем:
Также можно использовать:
-
-
-
-
Очередь фоновых задач
Можно избежать блокировки основного потока для таких задач, как отправка email или обработка файлов.
Создаём вызываемую задачу:
Ставим в очередь:
Работает только в памяти: задачи теряются при перезапуске приложения. Идеально подходит для некритичных задач.
Трансляция событий
Система событий Coravel обеспечивает независимую связь между сервисами в одном приложении.
Определяем событие:
Создаём наблюдателя:
Используем:
Рассылка писем с Razor-шаблонами
Определяем шаблон:
Отправляем:
Поддерживает отрисовку представлений из библиотек классов Razor или файлов .cshtml.
Простое кэширование
Встроенное кэширование в памяти для хранения часто используемых данных.
Хранение и извлечение из кэша:
Не требует дополнительной настройки.
Итого
Coravel доказывает, что мощная фоновая обработка задач в .NET не обязательно должна быть сложной. Он позволяет сосредоточиться на бизнес-логике, а не на инфраструктуре, предоставляя все необходимое для быстрого создания отзывчивых и поддерживаемых приложений.
Источник: https://thecodeman.net/posts/job-scheduling-with-coravel
Планирование Задач с Coravel
Coravel — легковесная библиотека с открытым кодом, которая добавляет в .NET-приложения планирование фоновых задач, постановку в очередь, кэширование, отправку почты и трансляцию событий — и всё это без необходимости в отдельной инфраструктуре.
Основные преимущества:
- Не требуется база данных или брокер сообщений;
- Идеально подходит для небольших и средних приложений;
- Полная интеграция с внедрением зависимостей ASP.NET Core;
- Чистый и читаемый синтаксис.
Посмотрим, что вы можете сделать с Coravel.
Планирование задач
Создаём задачу:
public class DailyReportJob : IInvocable
{
public Task Invoke()
{
// Отправляем ежедневный отчёт…
return Task.CompletedTask;
}
}
Регистрируем:
builder.Services.AddScheduler();
builder.Services.AddTransient<DailyReportJob>();
Планируем:
app.Services.UseScheduler(sch =>
{
sch
.Schedule<DailyReportJob>()
.DailyAtHour(6); // Каждый день в 6 утра
});
Также можно использовать:
-
.Hourly()-
.EveryMinute()-
.Weekly()-
.Cron("/5 *") для большего контроляОчередь фоновых задач
Можно избежать блокировки основного потока для таких задач, как отправка email или обработка файлов.
Создаём вызываемую задачу:
public class ProcessWebhook : IInvocable
{
public Task Invoke()
{
// Фоновая задача…
return Task.CompletedTask;
}
}
Ставим в очередь:
var dispatcher =
app.Services.GetService<IDispatcher>();
await dispatcher.EnqueueAsync<ProcessWebhook>();
Работает только в памяти: задачи теряются при перезапуске приложения. Идеально подходит для некритичных задач.
Трансляция событий
Система событий Coravel обеспечивает независимую связь между сервисами в одном приложении.
Определяем событие:
public record OrderPlacedEvent(int OrderId);
Создаём наблюдателя:
public class SendThankYouEmail :
IListener<OrderPlacedEvent>
{
public Task HandleAsync(OrderPlacedEvent e)
{
// Отправляем email о заказе e.OrderId…
return Task.CompletedTask;
}
}
Используем:
await dispatcher
.BroadcastAsync(new OrderPlacedEvent(123));
Рассылка писем с Razor-шаблонами
Определяем шаблон:
public class WelcomeMailable : Mailable<User>
{
public override void Build()
{
To(Model.Email)
.Subject("Добро пожаловать!")
.View("Emails.Welcome", Model);
}
}
Отправляем:
await mailer
.SendAsync(new WelcomeMailable(user));
Поддерживает отрисовку представлений из библиотек классов Razor или файлов .cshtml.
Простое кэширование
Встроенное кэширование в памяти для хранения часто используемых данных.
Хранение и извлечение из кэша:
var data = cache.GetOrAdd("top-products",
() => {
return FetchTopProducts();
},
TimeSpan.FromMinutes(15));
Не требует дополнительной настройки.
Итого
Coravel доказывает, что мощная фоновая обработка задач в .NET не обязательно должна быть сложной. Он позволяет сосредоточиться на бизнес-логике, а не на инфраструктуре, предоставляя все необходимое для быстрого создания отзывчивых и поддерживаемых приложений.
Источник: https://thecodeman.net/posts/job-scheduling-with-coravel
👍7
День 2564. #Карьера
Топ Советов по Повышению Продуктивности. Часть 7
Части 1, 2, 3, 4, 5, 6
7. Сила документированных дейликов
Да, слова «документация» и «дейлик» в одном предложении вызывают у разработчиков ПТСР. Но речь не о новых митингах или бюрократии — речь о создании механизма, который вносит ясность и делает день более продуктивным.
Каждое утро, прежде чем писать код, потратьте 5 минут на написание короткой заметки:
1. Что я выпустил вчера (или в последний рабочий день);
2. Что я выпускаю сегодня;
3. Что меня блокирует.
Ни строгого формата, ни сложных шаблонов. Просто 3 пункта в документе на ваш выбор.
Почему это работает?
1. Вносит ясность до того, как она понадобится. Прежде чем погрузиться в код, вы спрашиваете себя: «Чего я пытаюсь достичь сегодня?» Это предотвращает невероятно распространённую проблему, когда вы весь день усердно работаете, но не над тем, над чем нужно.
2. Создаёт чувство ответственности перед самим собой. Когда вы пишете: «Сегодня я внедряю аутентификацию пользователей», вы берёте на себя обязательство. Не перед руководителем (хотя он, возможно, оценит), а перед собой. Вы превращаете расплывчатые намерения в конкретные планы.
3. Выявляет закономерности, которые иначе не увидишь. Через неделю вы просмотрите свои записи и заметите:
- «Меня уже три дня блокирует одна и та же проблема с API — надо сообщить об этом руководству».
- «Я постоянно хочу писать тесты, но никогда этого не делаю — нужно изменить подход».
- «Я выпускаю больше продукта, когда определяю конкретные, небольшие задачи, а не расплывчатые большие».
Эти выводы незаметны, когда каждый день сливается с предыдущим. Записанные, они выявляют закономерности.
Это делает реальные дейлики быстрее и эффективнее. Когда команда проводит дейлик (виртуальный или очный), не приходится лихорадочно вспоминать, что вы делали. Вы просто читаете записи. Совещания становятся короче. Команда получает пользу от этого ритуала, а не относится к нему как к формальности. Это создаёт «хлебные крошки» для переключения контекста. Неожиданное совещание? Нет проблем — ваши заметки точно покажут, где вы были и чем занимались. Потом вы мгновенно возобновите работу, вместо того чтобы тратить 20 минут на попытки вспомнить, над чем работали.
Уровень выше
- Еженедельные обзоры: Каждую пятницу просматривайте заметки за неделю. Отмечайте достижения. Выявляйте повторяющиеся препятствия. Планируйте следующую неделю, основываясь на том, что реально произошло, а не на том, на что вы надеялись.
- Оценка эффективности: Когда приходит время ежегодной оценки, у вас есть лог, чего вы добились. Месяцы документированной работы, организованные по дням. Больше не нужно ломать голову, вспоминая, что вы делали во втором квартале.
- Отладка производительности: Плохая неделя? Посмотрите заметки. Вы слишком часто переключались между задачами? Взяли слишком много задач? Постоянно сталкивались с препятствиями? Заметки позволят провести диагностику.
- Коммуникационный рычаг: Менеджер спрашивает, как дела? Отправьте ему заметки за последние 3 дня. Он получит полную информацию за 30 секунд.
Это не рутинная работа. Это время для стратегического мышления. Эти 5 минут утром — это время, когда вы становитесь архитектором своего дня.
Распространённые возражения
- «Нет времени». У вас точно найдётся 5 минут.
- «Мои дни слишком непредсказуемы». Именно поэтому вам это нужно. Когда наступает хаос, заметки служат вам опорой. Вы можете сознательно отклониться от своего плана, вместо того чтобы случайно сбиться с курса.
- «Я никогда не буду их пересматривать». Возможно. Но лог дел — это бонус; главное — планирование.
Начните завтра
Прежде чем открыть IDE, откройте документ. Напишите три пункта. Сделайте это ритуалом, таким же автоматическим, как утренний кофе. Разработчики, которые кажутся суперорганизованными, всегда знают, над чем работают и стабильно выпускают продукты - не сверхлюди. Они просто выработали небольшие привычки, которые приводят к большой ясности. Это одна из них.
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
Топ Советов по Повышению Продуктивности. Часть 7
Части 1, 2, 3, 4, 5, 6
7. Сила документированных дейликов
Да, слова «документация» и «дейлик» в одном предложении вызывают у разработчиков ПТСР. Но речь не о новых митингах или бюрократии — речь о создании механизма, который вносит ясность и делает день более продуктивным.
Каждое утро, прежде чем писать код, потратьте 5 минут на написание короткой заметки:
1. Что я выпустил вчера (или в последний рабочий день);
2. Что я выпускаю сегодня;
3. Что меня блокирует.
Ни строгого формата, ни сложных шаблонов. Просто 3 пункта в документе на ваш выбор.
Почему это работает?
1. Вносит ясность до того, как она понадобится. Прежде чем погрузиться в код, вы спрашиваете себя: «Чего я пытаюсь достичь сегодня?» Это предотвращает невероятно распространённую проблему, когда вы весь день усердно работаете, но не над тем, над чем нужно.
2. Создаёт чувство ответственности перед самим собой. Когда вы пишете: «Сегодня я внедряю аутентификацию пользователей», вы берёте на себя обязательство. Не перед руководителем (хотя он, возможно, оценит), а перед собой. Вы превращаете расплывчатые намерения в конкретные планы.
3. Выявляет закономерности, которые иначе не увидишь. Через неделю вы просмотрите свои записи и заметите:
- «Меня уже три дня блокирует одна и та же проблема с API — надо сообщить об этом руководству».
- «Я постоянно хочу писать тесты, но никогда этого не делаю — нужно изменить подход».
- «Я выпускаю больше продукта, когда определяю конкретные, небольшие задачи, а не расплывчатые большие».
Эти выводы незаметны, когда каждый день сливается с предыдущим. Записанные, они выявляют закономерности.
Это делает реальные дейлики быстрее и эффективнее. Когда команда проводит дейлик (виртуальный или очный), не приходится лихорадочно вспоминать, что вы делали. Вы просто читаете записи. Совещания становятся короче. Команда получает пользу от этого ритуала, а не относится к нему как к формальности. Это создаёт «хлебные крошки» для переключения контекста. Неожиданное совещание? Нет проблем — ваши заметки точно покажут, где вы были и чем занимались. Потом вы мгновенно возобновите работу, вместо того чтобы тратить 20 минут на попытки вспомнить, над чем работали.
Уровень выше
- Еженедельные обзоры: Каждую пятницу просматривайте заметки за неделю. Отмечайте достижения. Выявляйте повторяющиеся препятствия. Планируйте следующую неделю, основываясь на том, что реально произошло, а не на том, на что вы надеялись.
- Оценка эффективности: Когда приходит время ежегодной оценки, у вас есть лог, чего вы добились. Месяцы документированной работы, организованные по дням. Больше не нужно ломать голову, вспоминая, что вы делали во втором квартале.
- Отладка производительности: Плохая неделя? Посмотрите заметки. Вы слишком часто переключались между задачами? Взяли слишком много задач? Постоянно сталкивались с препятствиями? Заметки позволят провести диагностику.
- Коммуникационный рычаг: Менеджер спрашивает, как дела? Отправьте ему заметки за последние 3 дня. Он получит полную информацию за 30 секунд.
Это не рутинная работа. Это время для стратегического мышления. Эти 5 минут утром — это время, когда вы становитесь архитектором своего дня.
Распространённые возражения
- «Нет времени». У вас точно найдётся 5 минут.
- «Мои дни слишком непредсказуемы». Именно поэтому вам это нужно. Когда наступает хаос, заметки служат вам опорой. Вы можете сознательно отклониться от своего плана, вместо того чтобы случайно сбиться с курса.
- «Я никогда не буду их пересматривать». Возможно. Но лог дел — это бонус; главное — планирование.
Начните завтра
Прежде чем открыть IDE, откройте документ. Напишите три пункта. Сделайте это ритуалом, таким же автоматическим, как утренний кофе. Разработчики, которые кажутся суперорганизованными, всегда знают, над чем работают и стабильно выпускают продукты - не сверхлюди. Они просто выработали небольшие привычки, которые приводят к большой ясности. Это одна из них.
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
👍15
👍30👎9
День 2565. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
21. Обработка исключений
«Расскажите о способах обработки исключений в .NET и опишите, как бы вы реализовали её в реальном приложении? С какими типами исключений вы можете столкнуться и как бы вы их обрабатывали».
Хороший ответ
Обработка исключений имеет решающее значение для создания отказоустойчивых приложений, способных корректно обрабатывать ошибки во время выполнения и поддерживать надёжный UI. Она включает использование блоков try, catch, finally и throw для корректной обработки ошибок, возникающих во время выполнения.
Блок
Блок
Блок
Выражение
В реальном приложении можно структурировать обработку исключений таким образом, чтобы она обрабатывала как системные исключения (например, IOException, NullReferenceException), так и исключения, специфичные для приложения (например, InvalidOperationException).
Например, при чтении файла следует обрабатывать IOException, чтобы перехватывать проблемы, связанные с доступом к файлу, при этом использовать логические проверки для генерации и перехвата InvalidOperationException, если формат файла не соответствует ожиданиям.
Важно логировать исключения для целей устранения неполадок и аудита, и предоставлять пользователю понятные сообщения об ошибке.
Часто встречающийся плохой ответ
«В .NET, когда нужно обрабатывать ошибки, я использую блоки try-catch вокруг почти всего кода, чтобы убедиться, что любая ошибка будет перехвачена. Исключения я перехватываю с помощью общего блока `catch (Exception ex)` и логирую или иногда просто игнорирую ошибку, если она не критична. Так я гарантирую, что все исключения будут обработаны».
Почему это неправильно
- Чрезмерное использование блоков try-catch: заключение больших блоков кода в структуры try-catch — плохая практика. Это затрудняет чтение и понимание кода, может скрывать ошибки, перехватывая исключения, которые следует обрабатывать более целенаправленно или позволять им распространяться вверх по стеку вызовов.
- Перехват всех исключений: Использование
- Игнорирование исключений: Игнорирование исключений без какой-либо логики обработки, даже логирования, противоречит цели обработки исключений, которая заключается в адекватном реагировании на ошибки, а не просто в их подавлении. Это может привести к тому, что проблемы останутся незамеченными и нерешёнными, что повлияет на стабильность и надёжность приложения.
Эта ошибка отражает фундаментальное непонимание цели и стратегической реализации обработки исключений. Обработка исключений должна быть точной и направленной на поддержание целостности приложения и предоставление содержательной обратной связи или вариантов восстановления там, где это применимо.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
21. Обработка исключений
«Расскажите о способах обработки исключений в .NET и опишите, как бы вы реализовали её в реальном приложении? С какими типами исключений вы можете столкнуться и как бы вы их обрабатывали».
Хороший ответ
Обработка исключений имеет решающее значение для создания отказоустойчивых приложений, способных корректно обрабатывать ошибки во время выполнения и поддерживать надёжный UI. Она включает использование блоков try, catch, finally и throw для корректной обработки ошибок, возникающих во время выполнения.
Блок
try содержит код, который потенциально может вызвать исключение.Блок
catch перехватывает исключения, выброшенные из блока try. Он может быть специфичным для типа исключения, чтобы обрабатывать различные сценарии ошибок. Кроме того, можно применять фильтры исключений для более тонкой обработки.Блок
finally выполняет код после блоков try и catch независимо от того, было ли выброшено исключение; часто используется для очистки ресурсов.Выражение
throw используется для повторного выбрасывания или распространения исключения вверх по стеку вызовов после того, как оно было перехвачено. Обычно, когда ошибку необходимо обработать на более высоком уровне.В реальном приложении можно структурировать обработку исключений таким образом, чтобы она обрабатывала как системные исключения (например, IOException, NullReferenceException), так и исключения, специфичные для приложения (например, InvalidOperationException).
Например, при чтении файла следует обрабатывать IOException, чтобы перехватывать проблемы, связанные с доступом к файлу, при этом использовать логические проверки для генерации и перехвата InvalidOperationException, если формат файла не соответствует ожиданиям.
Важно логировать исключения для целей устранения неполадок и аудита, и предоставлять пользователю понятные сообщения об ошибке.
Часто встречающийся плохой ответ
«В .NET, когда нужно обрабатывать ошибки, я использую блоки try-catch вокруг почти всего кода, чтобы убедиться, что любая ошибка будет перехвачена. Исключения я перехватываю с помощью общего блока `catch (Exception ex)` и логирую или иногда просто игнорирую ошибку, если она не критична. Так я гарантирую, что все исключения будут обработаны».
Почему это неправильно
- Чрезмерное использование блоков try-catch: заключение больших блоков кода в структуры try-catch — плохая практика. Это затрудняет чтение и понимание кода, может скрывать ошибки, перехватывая исключения, которые следует обрабатывать более целенаправленно или позволять им распространяться вверх по стеку вызовов.
- Перехват всех исключений: Использование
catch (Exception ex) обычно считается плохой практикой. Это мешает обрабатывать конкретные исключения соответствующим контексту способом и может привести к перехвату исключений, которые не следует обрабатывать (например, OutOfMemoryException или StackOverflowException), потенциально маскируя серьёзные ошибки, которые следует обрабатывать по-другому.- Игнорирование исключений: Игнорирование исключений без какой-либо логики обработки, даже логирования, противоречит цели обработки исключений, которая заключается в адекватном реагировании на ошибки, а не просто в их подавлении. Это может привести к тому, что проблемы останутся незамеченными и нерешёнными, что повлияет на стабильность и надёжность приложения.
Эта ошибка отражает фундаментальное непонимание цели и стратегической реализации обработки исключений. Обработка исключений должна быть точной и направленной на поддержание целостности приложения и предоставление содержательной обратной связи или вариантов восстановления там, где это применимо.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍4
День 2566. #Карьера
Перестал Писать Код по Выходным, и Карьера Пошла в Гору.
Автор оригинала: NorthernDev
Знаете это чувство? Субботнее утро. Вы пьёте кофе, может быть, собираетесь прогуляться или поиграть в видеоигру. Но где-то в глубине души тихий голосок:
- «Надо бы поработать над тем пэт-проектом».
- «Все говорят про TUnit? Надо бы его попробовать».
- «Настоящие разработчики программируют для удовольствия».
Технологическая индустрия внушила нам ложь: страсть равна количеству отработанных часов. Если ты не будешь усердно работать по выходным, тебя обгонит кто-то моложе, голоднее и готовый спать под столом.
Я верил в это. Годами писал код по 50 часов на работе и ещё 15 часов по выходным, создавая наполовину готовые приложения, которыми никто не пользовался. Я не становился лучше, как разработчик. Я просто уставал. По понедельникам мой код был неряшливым, я впустую просиживал митинги и ненавидел открывать IDE.
Поэтому около года назад я сделал нечто ужасное. Я остановился и установил правило: ноутбук закрывается в пятницу в 17:00 и не открывается до 9:00 понедельника. Никаких исключений. Никаких «просто проверяю PR». Я думал, что потеряю навык, отстану от остальных.
Вот что произошло на самом деле.
1. Моё подсознание начало решать проблемы.
Раньше, когда я натыкался на стену в пятницу, я бился об неё все выходные. Теперь я просто ухожу. Иду в поход. Встречаюсь с друзьями. И почти каждое воскресенье вечером, «в душе», решение просто приходит мне в голову. Я решаю сложные проблемы быстрее в понедельник утром за 30 минут, чем раньше за 8 часов утомительного программирования в выходные.
2. Я стал лучше, как коллега (и получил повышение).
Оказывается, быть старшим разработчиком — это не только скорость написания кода. Это также коммуникабельность, терпение и лидерские качества. Когда я не нахожусь постоянно на грани выгорания, со мной приятнее работать. Я лучше слушал на архитектурных совещаниях. Люди стали больше доверять моему мнению, потому что я перестал быть на автопилоте.
3. Я заново открыл для себя радость программирования.
Расстояние укрепляет чувства. Избавившись от программирования на два дня, я теперь с нетерпением жду понедельника. Да, некоторые скажут: «Но я люблю программировать по выходным!» Если это так, продолжайте.
Я также знаю, что начинающим разработчикам часто приходится работать сверхурочно, чтобы восполнить пробелы в знаниях на ранних этапах. Мне тоже приходилось. Но если вы разработчик среднего или старшего уровня и чувствуете, что тонете в культуре постоянной спешки, пусть это станет для вас разрешением остановиться.
Вы не машина для написания кода. Вы человек, который решает проблемы с помощью кода. Машинам не нужен отдых. Людям нужен. Кем из них вы хотите быть?
Пишите в комментариях: Обязательна ли «страсть» для того, чтобы выжить в этой индустрии? Или разработка — это просто хорошо оплачиваемая работа, позволяющая нам наслаждаться жизнью?
Источник: https://dev.to/the_nortern_dev/unpopular-opinion-i-stopped-coding-on-weekends-and-my-career-got-better-3el
Перестал Писать Код по Выходным, и Карьера Пошла в Гору.
Автор оригинала: NorthernDev
Знаете это чувство? Субботнее утро. Вы пьёте кофе, может быть, собираетесь прогуляться или поиграть в видеоигру. Но где-то в глубине души тихий голосок:
- «Надо бы поработать над тем пэт-проектом».
- «Все говорят про TUnit? Надо бы его попробовать».
- «Настоящие разработчики программируют для удовольствия».
Технологическая индустрия внушила нам ложь: страсть равна количеству отработанных часов. Если ты не будешь усердно работать по выходным, тебя обгонит кто-то моложе, голоднее и готовый спать под столом.
Я верил в это. Годами писал код по 50 часов на работе и ещё 15 часов по выходным, создавая наполовину готовые приложения, которыми никто не пользовался. Я не становился лучше, как разработчик. Я просто уставал. По понедельникам мой код был неряшливым, я впустую просиживал митинги и ненавидел открывать IDE.
Поэтому около года назад я сделал нечто ужасное. Я остановился и установил правило: ноутбук закрывается в пятницу в 17:00 и не открывается до 9:00 понедельника. Никаких исключений. Никаких «просто проверяю PR». Я думал, что потеряю навык, отстану от остальных.
Вот что произошло на самом деле.
1. Моё подсознание начало решать проблемы.
Раньше, когда я натыкался на стену в пятницу, я бился об неё все выходные. Теперь я просто ухожу. Иду в поход. Встречаюсь с друзьями. И почти каждое воскресенье вечером, «в душе», решение просто приходит мне в голову. Я решаю сложные проблемы быстрее в понедельник утром за 30 минут, чем раньше за 8 часов утомительного программирования в выходные.
2. Я стал лучше, как коллега (и получил повышение).
Оказывается, быть старшим разработчиком — это не только скорость написания кода. Это также коммуникабельность, терпение и лидерские качества. Когда я не нахожусь постоянно на грани выгорания, со мной приятнее работать. Я лучше слушал на архитектурных совещаниях. Люди стали больше доверять моему мнению, потому что я перестал быть на автопилоте.
3. Я заново открыл для себя радость программирования.
Расстояние укрепляет чувства. Избавившись от программирования на два дня, я теперь с нетерпением жду понедельника. Да, некоторые скажут: «Но я люблю программировать по выходным!» Если это так, продолжайте.
Я также знаю, что начинающим разработчикам часто приходится работать сверхурочно, чтобы восполнить пробелы в знаниях на ранних этапах. Мне тоже приходилось. Но если вы разработчик среднего или старшего уровня и чувствуете, что тонете в культуре постоянной спешки, пусть это станет для вас разрешением остановиться.
Вы не машина для написания кода. Вы человек, который решает проблемы с помощью кода. Машинам не нужен отдых. Людям нужен. Кем из них вы хотите быть?
Пишите в комментариях: Обязательна ли «страсть» для того, чтобы выжить в этой индустрии? Или разработка — это просто хорошо оплачиваемая работа, позволяющая нам наслаждаться жизнью?
Источник: https://dev.to/the_nortern_dev/unpopular-opinion-i-stopped-coding-on-weekends-and-my-career-got-better-3el
👍17
Если вы уровня мидл+, сколько времени у вас занимает программирование?
Anonymous Poll
28%
Строго "с 9 до 5", в свободное время занимаюсь другим
13%
Работаю сверхурочно, если не успеваю
30%
Работа и иногда изучаю что-то новое
11%
Регулярно занимаюсь сторонними проектами "для души"
10%
Помимо работы заставляю себя заниматься, чтобы "не отстать" от коллег
8%
Пашу без выходных с перерывами только на сон
👎15👍6
День 2567. #ЗаметкиНаПолях
Метод HTTP PATCH: Частичные Обновления в REST API. Начало
HTTP PATCH применяет частичные изменения к ресурсу. Он решает распространённую задачу проектирования API: обновление определённых полей без замены всего ресурса. Рассмотрим метод PATCH, чем он отличается от PUT и POST, и как эффективно реализовать запросы PATCH.
Пример: Обновление роли пользователя
Сервер обновляет только поле роли, оставляя остальные поля неизменными.
PATCH, PUT или POST
PATCH
Цель: частичное обновление;
Отправляемые данные: только изменяемые поля;
Идемпотентность: не является идемпотентным, но часто запросы PATCH разрабатываются с учётом возможности их идемпотентности;
Использование: обновление отдельных полей ресурса;
Результат: обновляются только отправленные поля.
PUT
Цель: полная замена;
Отправляемые данные: ресурс целиком;
Идемпотентность: да;
Использование: замена всего ресурса;
Результат: заменяется ресурс целиком.
POST
Цель: замена или действие;
Отправляемые данные: новый ресурс;
Идемпотентность: нет;
Использование: создание нового ресурса или действие над ресурсом;
Результат: отправленные поля заменяются, не отправленные устанавливаются в значения по умолчанию.
Когда не использовать
1. Нужно заменить весь ресурс (используйте PUT).
2. Обновления неидемпотентны (рассмотрите POST).
3. Контракт API требует полной проверки всех полей при каждом обновлении.
4. Ресурса не существует (верните 404 и используйте POST для его создания).
Форматы запросов
1. JSON Merge-patch
Отправляет JSON-объект, содержащий только поля для обновления:
Этот подход прост и интуитивно понятен, но может быть неоднозначным для вложенных объектов и значений NULL.
2. JSON Patch
JSON Patch (RFC 6902) обеспечивает точный контроль с помощью массива операций:
Доступные операции:
- add – добавление нового поля или элемента массива;
- remove – удаление поля;
- replace – обновление существующего поля;
- move – перемещение значения в новое место;
- copy – копирование значения в новое место;
- test – проверка значения перед применением операции.
Стандартные ответы метода PATCH
Успешные ответы:
- 200 OK — обновление успешно, возвращается обновлённый ресурс;
- 204 No Content - обновление успешно, но тело ответа отсутствует;
- 202 Accepted - обновление принято для асинхронной обработки.
Ответы с ошибкой:
- 400 Bad Request - неверный формат или данные;
- 401 Unauthorized - требуется аутентификация;
- 403 Forbidden - недостаточные права доступа;
- 404 Not Found - ресурса не существует;
- 409 Conflict - обновление конфликтует с текущим состоянием ресурса;
- 422 Unprocessable Entity - валидный JSON, но семантически некорректный.
Понимание идемпотентности PATCH
Идемпотентность означает, что многократное применение одного и того же запроса дает тот же результат, что и однократное применение. Это свойство имеет решающее значение для безопасной обработки повторных попыток в сети. PATCH по своей природе не является идемпотентным, но многие API разрабатывают запросы PATCH таким образом, чтобы они вели себя идемпотентно для обеспечения надёжности и безопасных повторных попыток.
Пример идемпотентного PATCH:
Многократная отправка этого запроса приводит к одному и тому же итоговому состоянию ресурса.
Пример неидемпотентного PATCH:
Каждый запрос вычитает 5 единиц инвентаря, приводя к различным итоговым состояниям ресурса.
Окончание следует…
Источник: https://blog.postman.com/http-patch-method/
Метод HTTP PATCH: Частичные Обновления в REST API. Начало
HTTP PATCH применяет частичные изменения к ресурсу. Он решает распространённую задачу проектирования API: обновление определённых полей без замены всего ресурса. Рассмотрим метод PATCH, чем он отличается от PUT и POST, и как эффективно реализовать запросы PATCH.
Пример: Обновление роли пользователя
PATCH /api/users/12345 HTTP/1.1
Content-Type: application/json
{
"role": "Senior Developer"
}
Сервер обновляет только поле роли, оставляя остальные поля неизменными.
PATCH, PUT или POST
PATCH
Цель: частичное обновление;
Отправляемые данные: только изменяемые поля;
Идемпотентность: не является идемпотентным, но часто запросы PATCH разрабатываются с учётом возможности их идемпотентности;
Использование: обновление отдельных полей ресурса;
Результат: обновляются только отправленные поля.
PUT
Цель: полная замена;
Отправляемые данные: ресурс целиком;
Идемпотентность: да;
Использование: замена всего ресурса;
Результат: заменяется ресурс целиком.
POST
Цель: замена или действие;
Отправляемые данные: новый ресурс;
Идемпотентность: нет;
Использование: создание нового ресурса или действие над ресурсом;
Результат: отправленные поля заменяются, не отправленные устанавливаются в значения по умолчанию.
Когда не использовать
1. Нужно заменить весь ресурс (используйте PUT).
2. Обновления неидемпотентны (рассмотрите POST).
3. Контракт API требует полной проверки всех полей при каждом обновлении.
4. Ресурса не существует (верните 404 и используйте POST для его создания).
Форматы запросов
1. JSON Merge-patch
Отправляет JSON-объект, содержащий только поля для обновления:
PATCH /api/users/12345
Content-Type: application/merge-patch+json
{
"email": "updated@example.com",
"role": "Manager"
}
Этот подход прост и интуитивно понятен, но может быть неоднозначным для вложенных объектов и значений NULL.
2. JSON Patch
JSON Patch (RFC 6902) обеспечивает точный контроль с помощью массива операций:
PATCH /api/users/12345
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/email", "value": "new@example.com" },
{ "op": "add", "path": "/phone", "value": "+1-555-0123" },
{ "op": "remove", "path": "/temporary_field" }
]
Доступные операции:
- add – добавление нового поля или элемента массива;
- remove – удаление поля;
- replace – обновление существующего поля;
- move – перемещение значения в новое место;
- copy – копирование значения в новое место;
- test – проверка значения перед применением операции.
Стандартные ответы метода PATCH
Успешные ответы:
- 200 OK — обновление успешно, возвращается обновлённый ресурс;
- 204 No Content - обновление успешно, но тело ответа отсутствует;
- 202 Accepted - обновление принято для асинхронной обработки.
Ответы с ошибкой:
- 400 Bad Request - неверный формат или данные;
- 401 Unauthorized - требуется аутентификация;
- 403 Forbidden - недостаточные права доступа;
- 404 Not Found - ресурса не существует;
- 409 Conflict - обновление конфликтует с текущим состоянием ресурса;
- 422 Unprocessable Entity - валидный JSON, но семантически некорректный.
Понимание идемпотентности PATCH
Идемпотентность означает, что многократное применение одного и того же запроса дает тот же результат, что и однократное применение. Это свойство имеет решающее значение для безопасной обработки повторных попыток в сети. PATCH по своей природе не является идемпотентным, но многие API разрабатывают запросы PATCH таким образом, чтобы они вели себя идемпотентно для обеспечения надёжности и безопасных повторных попыток.
Пример идемпотентного PATCH:
PATCH /api/users/12345
{
"email": "consistent@example.com"
}
Многократная отправка этого запроса приводит к одному и тому же итоговому состоянию ресурса.
Пример неидемпотентного PATCH:
PATCH /api/products/789
{
"inventory_adjustment": -5
}
Каждый запрос вычитает 5 единиц инвентаря, приводя к различным итоговым состояниям ресурса.
Окончание следует…
Источник: https://blog.postman.com/http-patch-method/
👍12
День 2568. #ЗаметкиНаПолях
Метод HTTP PATCH: Частичные Обновления в REST API. Окончание
Начало
Лучшие практики реализации запросов PATCH
1. Делайте запросы идемпотентными
Используйте абсолютные значения в запросах PATCH вместо относительных. Для операций, требующих относительных обновлений, используйте запрос POST, инициирующий действие над ресурсом вместо модифицирующего ресурс запроса PATCH.
2. Документируйте модифицируемые поля
Чётко укажите, какие поля можно изменять, а какие нельзя.
Поля, допускающие изменения:
- email (string, valid email format)
- role (string: "user", "admin", "manager")
- preferences (object)
Защищённые поля (не подлежат изменению):
- id, created_at, username
3. Проверка перед применением изменений
Сначала проверьте все поля и применяйте обновления только в том случае, если все проверки пройдены успешно.
4. Явно обрабатывайте NULL
Разделяйте пропущенные поля (оставьте их без изменений) и явно заданные значения NULL (очищайте поле).
5. Возвращайте обновлённый ресурс
После успешного выполнения PATCH возвращайте полный обновлённый ресурс, чтобы клиенты могли подтвердить изменения.
Безопасность PATCH
Поскольку PATCH изменяет существующие данные, необходимы строгие меры безопасности.
1. Требуйте аутентификацию и авторизацию
Всегда проверяйте личность вызывающего пользователя и убедитесь, что его права доступа действительны. Убедитесь, что пользователи могут изменять только те ресурсы, которыми они владеют или на редактирование которых у них есть разрешение.
2. Ограничивайте доступ к конфиденциальным полям
Никогда не позволяйте PATCH изменять поля, управляемые системой или критически важные для безопасности, такие как id, created_at, password_hash или флаги разрешений.
3. Проверяйте все входные данные
Обрабатывайте данные PATCH как любые пользовательские входные данные. Проверяйте типы, форматы и диапазоны, чтобы предотвратить атаки внедрения и повреждение данных.
4. Используйте HTTPS
Запросы PATCH часто содержат конфиденциальные данные. Всегда используйте HTTPS для шифрования данных при передаче.
5. Примените ограничения запросов
Предотвратите злоупотребления, ограничив количество запросов PATCH на пользователя или IP-адрес.
Распространённые ошибки
1. Обработка запросов PATCH как PUT
Не требуйте все поля в запросе PATCH. Отправляйте только то, что нужно изменить.
2. Создание ресурсов с помощью PATCH вместо POST
Возвращайте 404 Not Found при попытке изменить несуществующие ресурсы с помощью PATCH. Используйте POST для создания ресурсов.
3. Разрешение обновлений неизменяемых полей
Защитите управляемые системой поля от изменения с помощью чётких правил проверки.
4. Игнорирование зависимостей между связанными полями
Некоторые поля зависят от других. Проверяйте эти связи перед применением изменений.
5. Пропуск защиты транспортного уровня
Даже при надлежащей аутентификации всегда используйте HTTPS для шифрования запросов PATCH и защиты конфиденциальных данных.
Итого
Метод HTTP PATCH в основном используется для указания того, какие изменения должны быть внесены в ресурс без повторной отправки всего его состояния. Когда запросы PATCH чётко определены по области действия, проверены заранее и разработаны таким образом, чтобы вести себя предсказуемо, они уменьшают случайную потерю данных и упрощают развитие API с течением времени. При таком использовании PATCH становится мощным инструментом для создания масштабируемых API без нарушения работы клиентов.
Источник: https://blog.postman.com/http-patch-method/
Метод HTTP PATCH: Частичные Обновления в REST API. Окончание
Начало
Лучшие практики реализации запросов PATCH
1. Делайте запросы идемпотентными
Используйте абсолютные значения в запросах PATCH вместо относительных. Для операций, требующих относительных обновлений, используйте запрос POST, инициирующий действие над ресурсом вместо модифицирующего ресурс запроса PATCH.
2. Документируйте модифицируемые поля
Чётко укажите, какие поля можно изменять, а какие нельзя.
PATCH /api/users/{id}Поля, допускающие изменения:
- email (string, valid email format)
- role (string: "user", "admin", "manager")
- preferences (object)
Защищённые поля (не подлежат изменению):
- id, created_at, username
3. Проверка перед применением изменений
Сначала проверьте все поля и применяйте обновления только в том случае, если все проверки пройдены успешно.
4. Явно обрабатывайте NULL
Разделяйте пропущенные поля (оставьте их без изменений) и явно заданные значения NULL (очищайте поле).
5. Возвращайте обновлённый ресурс
После успешного выполнения PATCH возвращайте полный обновлённый ресурс, чтобы клиенты могли подтвердить изменения.
Безопасность PATCH
Поскольку PATCH изменяет существующие данные, необходимы строгие меры безопасности.
1. Требуйте аутентификацию и авторизацию
Всегда проверяйте личность вызывающего пользователя и убедитесь, что его права доступа действительны. Убедитесь, что пользователи могут изменять только те ресурсы, которыми они владеют или на редактирование которых у них есть разрешение.
2. Ограничивайте доступ к конфиденциальным полям
Никогда не позволяйте PATCH изменять поля, управляемые системой или критически важные для безопасности, такие как id, created_at, password_hash или флаги разрешений.
3. Проверяйте все входные данные
Обрабатывайте данные PATCH как любые пользовательские входные данные. Проверяйте типы, форматы и диапазоны, чтобы предотвратить атаки внедрения и повреждение данных.
4. Используйте HTTPS
Запросы PATCH часто содержат конфиденциальные данные. Всегда используйте HTTPS для шифрования данных при передаче.
5. Примените ограничения запросов
Предотвратите злоупотребления, ограничив количество запросов PATCH на пользователя или IP-адрес.
Распространённые ошибки
1. Обработка запросов PATCH как PUT
Не требуйте все поля в запросе PATCH. Отправляйте только то, что нужно изменить.
2. Создание ресурсов с помощью PATCH вместо POST
Возвращайте 404 Not Found при попытке изменить несуществующие ресурсы с помощью PATCH. Используйте POST для создания ресурсов.
3. Разрешение обновлений неизменяемых полей
Защитите управляемые системой поля от изменения с помощью чётких правил проверки.
4. Игнорирование зависимостей между связанными полями
Некоторые поля зависят от других. Проверяйте эти связи перед применением изменений.
5. Пропуск защиты транспортного уровня
Даже при надлежащей аутентификации всегда используйте HTTPS для шифрования запросов PATCH и защиты конфиденциальных данных.
Итого
Метод HTTP PATCH в основном используется для указания того, какие изменения должны быть внесены в ресурс без повторной отправки всего его состояния. Когда запросы PATCH чётко определены по области действия, проверены заранее и разработаны таким образом, чтобы вести себя предсказуемо, они уменьшают случайную потерю данных и упрощают развитие API с течением времени. При таком использовании PATCH становится мощным инструментом для создания масштабируемых API без нарушения работы клиентов.
Источник: https://blog.postman.com/http-patch-method/
👍4
День 2569. #ЗаметкиНаПолях #AI
Руководство по Эффективному Промпт-Инжинирингу. Начало
Промпт-инжиниринг — это процесс разработки инструкций, которые направляют языковые модели ИИ на получение желаемых результатов. На первый взгляд, это может показаться простым. Мы говорим ИИ, что хотим, и он это выполняет. Однако любой, кто работал с такими моделями, быстро обнаруживает, что написание эффективных подсказок сложнее, чем кажется.
Простота начала работы в промпт-инжиниринге может вводить в заблуждение. Любой может написать подсказку, но не каждый может написать такую, которая будет стабильно давать качественные результаты. Представьте это как разницу между умением общаться и умением эффективно общаться. Начать легко, но для достижения мастерства необходимы практика, эксперименты и понимание того, как модели обрабатывают информацию.
Рассмотрим основные методы и лучшие практики промпт-инжиниринга. Изучим различные подходы, от простых инструкций без контекста до сложных логических рассуждений.
Что делает промпт хорошим
Промпт обычно состоит из нескольких компонентов:
- Описание задачи - объясняет, что мы хотим, чтобы модель делала, включая любую роль или образ, который мы хотим, чтобы она приняла.
- Контекст - предоставляет необходимую справочную информацию. Примеры демонстрируют желаемое поведение или формат.
- Конкретный вопрос, на который нужно ответить, или действие, которое нужно выполнить.
Большинство API для моделей позволяют разделять промпты на системные и пользовательские:
- Системные обычно содержат описания задач и инструкции по роли, определяющей поведение модели на протяжении всего разговора.
- Пользовательские содержат саму задачу или вопрос.
Например, если мы создаём чат-бота, который помогает покупателям понимать информацию о недвижимости, системный промпт может указывать модели действовать как опытный агент по недвижимости, а пользовательский будет содержать конкретный вопрос о недвижимости.
Ясность — ключевой фактор эффективного промпта. Так же, как чёткая коммуникация помогает людям понять, что им нужно, конкретные и недвусмысленные инструкции помогают моделям ИИ генерировать соответствующие ответы. Мы должны точно объяснить, чего хотим, определить любые системы оценки или форматы, которые ожидаем, и исключить предположения о том, что модель уже может знать.
Контекст имеет не меньшее значение. Предоставление релевантной информации помогает моделям работать лучше и уменьшает количество ошибок. Если мы хотим, чтобы модель отвечала на вопросы о научной статье, включение этой статьи в контекст значительно улучшит качество ответов. Без достаточного контекста модель вынуждена полагаться на свои внутренние знания, которые могут быть устаревшими или неверными.
Как модели обрабатывают промпты
Обучение в контексте — способность модели обучаться новым моделям поведения на примерах, предоставленных в самом промпте, без необходимости обновления весов модели. Когда мы показываем модели примеры выполнения задачи, она может адаптировать свои ответы в соответствии с продемонстрированным нами шаблоном.
Модели, как правило, лучше понимают инструкции в начале и конце подсказок, чем в середине. Т.е. наиболее важную информацию следует размещать в стратегически важных местах промпта.
Количество необходимых примеров зависит как от возможностей модели, так и от сложности задачи. Более мощные модели, как правило, требуют меньшего количества примеров для понимания того, что нам нужно. Для более простых задач мощным моделям может вообще не понадобиться ни одного примера. Однако для приложений, специфичных для конкретной области, или сложных требований к форматированию предоставление нескольких примеров может существенно изменить ситуацию.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/a-guide-to-effective-prompt-engineering
Руководство по Эффективному Промпт-Инжинирингу. Начало
Промпт-инжиниринг — это процесс разработки инструкций, которые направляют языковые модели ИИ на получение желаемых результатов. На первый взгляд, это может показаться простым. Мы говорим ИИ, что хотим, и он это выполняет. Однако любой, кто работал с такими моделями, быстро обнаруживает, что написание эффективных подсказок сложнее, чем кажется.
Простота начала работы в промпт-инжиниринге может вводить в заблуждение. Любой может написать подсказку, но не каждый может написать такую, которая будет стабильно давать качественные результаты. Представьте это как разницу между умением общаться и умением эффективно общаться. Начать легко, но для достижения мастерства необходимы практика, эксперименты и понимание того, как модели обрабатывают информацию.
Рассмотрим основные методы и лучшие практики промпт-инжиниринга. Изучим различные подходы, от простых инструкций без контекста до сложных логических рассуждений.
Что делает промпт хорошим
Промпт обычно состоит из нескольких компонентов:
- Описание задачи - объясняет, что мы хотим, чтобы модель делала, включая любую роль или образ, который мы хотим, чтобы она приняла.
- Контекст - предоставляет необходимую справочную информацию. Примеры демонстрируют желаемое поведение или формат.
- Конкретный вопрос, на который нужно ответить, или действие, которое нужно выполнить.
Большинство API для моделей позволяют разделять промпты на системные и пользовательские:
- Системные обычно содержат описания задач и инструкции по роли, определяющей поведение модели на протяжении всего разговора.
- Пользовательские содержат саму задачу или вопрос.
Например, если мы создаём чат-бота, который помогает покупателям понимать информацию о недвижимости, системный промпт может указывать модели действовать как опытный агент по недвижимости, а пользовательский будет содержать конкретный вопрос о недвижимости.
Ясность — ключевой фактор эффективного промпта. Так же, как чёткая коммуникация помогает людям понять, что им нужно, конкретные и недвусмысленные инструкции помогают моделям ИИ генерировать соответствующие ответы. Мы должны точно объяснить, чего хотим, определить любые системы оценки или форматы, которые ожидаем, и исключить предположения о том, что модель уже может знать.
Контекст имеет не меньшее значение. Предоставление релевантной информации помогает моделям работать лучше и уменьшает количество ошибок. Если мы хотим, чтобы модель отвечала на вопросы о научной статье, включение этой статьи в контекст значительно улучшит качество ответов. Без достаточного контекста модель вынуждена полагаться на свои внутренние знания, которые могут быть устаревшими или неверными.
Как модели обрабатывают промпты
Обучение в контексте — способность модели обучаться новым моделям поведения на примерах, предоставленных в самом промпте, без необходимости обновления весов модели. Когда мы показываем модели примеры выполнения задачи, она может адаптировать свои ответы в соответствии с продемонстрированным нами шаблоном.
Модели, как правило, лучше понимают инструкции в начале и конце подсказок, чем в середине. Т.е. наиболее важную информацию следует размещать в стратегически важных местах промпта.
Количество необходимых примеров зависит как от возможностей модели, так и от сложности задачи. Более мощные модели, как правило, требуют меньшего количества примеров для понимания того, что нам нужно. Для более простых задач мощным моделям может вообще не понадобиться ни одного примера. Однако для приложений, специфичных для конкретной области, или сложных требований к форматированию предоставление нескольких примеров может существенно изменить ситуацию.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/a-guide-to-effective-prompt-engineering
👎7👍2
День 2570. #ЗаметкиНаПолях #AI
Руководство по Эффективному Промпт-Инжинирингу. Продолжение
Начало
Основные техники
1. Без примеров (Zero-Shot)
Описываем, что хотим получить, и модель пытается выполнить запрос на основе своих знаний. Подходит для простых задач, где желаемый результат ясен из самих инструкций: «Переведи текст на французский» или «Кратко изложи содержание этой статьи».
Преимущество: меньше токенов, промпт проще писать и поддерживать.
Недостаток: когда требуется определённое форматирование или поведение, промпта без примеров может быть недостаточно.
Лучшие практики:
- Максимально чёткое описание желаемого результата;
- Ясное указание формата вывода, любых ограничений или требований;
2. С примерами (Few-Shot)
Подходит, когда требуется определённый формат или когда желаемое поведение сложно определить из одних только инструкций.
Большее примеров - лучше производительность, но мы ограничены длиной контекста и соображениями стоимости. Обычно 3-5 примеров обеспечивают хороший баланс.
При форматировании примеров можно экономить токены, выбирая эффективные структуры. Например, «пицца -> съедобный» использует меньше токенов, чем «Вход: пицца, Выход: съедобный», сообщая при этом ту же информацию.
3. Цепочка рассуждений (Chain-of-Though, CoT)
Предполагает явное указание модели пошагово обдумывать получение ответа. Способствует систематическому решению проблем и значительно улучшает производительность в сложных задачах на рассуждение.
Простейшая реализация — добавление к промпту фраз типа «объясни свои рассуждения». Так модель методично решает задачу, демонстрируя процесс рассуждения, прежде чем прийти к выводу.
CoT часто улучшает производительность модели в различных тестах, особенно для математических задач, логических головоломок и задач на многошаговое рассуждение. Также помогает уменьшить количество ошибок, поскольку модель должна обосновывать свои ответы явными шагами рассуждения.
Можно указать точные шаги, которые мы хотим, чтобы модель выполнила, или предоставить примеры, демонстрирующие процесс рассуждения.
Недостаток: увеличение времени ответа и стоимости. Модель генерирует больше токенов по мере обработки рассуждений. Для сложных задач, где точность имеет решающее значение, этот компромисс обычно оправдан.
4. Ролевой
Назначает модели определённую роль или область знаний. Так мы влияем на точку зрения и стиль ответов. Особенно эффективно в приложениях для обслуживания клиентов, образовательном контенте, творческом письме и любых сценариях, где контекст или уровень квалификации имеют значение. Модель может корректировать словарный запас, уровень детализации и подход в зависимости от назначенной роли.
Следует быть максимально подробными в описании роли и любых соответствующих характеристик. Чем конкретнее, тем лучше модель сможет «сыграть эту роль».
5. Цепочка промптов и декомпозиция
Предполагает разбиение сложных задач на более мелкие, управляемые подзадачи, со своим промптом на каждую.
Например, чат-бот службы поддержки клиентов. Процесс ответа на запрос клиента можно разделить на:
- Классификацию намерения запроса: нужна ли клиенту помощь с выставлением счетов, техническая поддержка, управление учётной записью или общая информация.
- Генерацию соответствующего ответа: отдельный этап для генерации фактического ответа на основе намерения.
Недостаток: увеличение воспринимаемой пользователями задержки. Однако для сложных приложений улучшенная надёжность и удобство сопровождения часто перевешивают этот недостаток.
Окончание следует…
Источник: https://blog.bytebytego.com/p/a-guide-to-effective-prompt-engineering
Руководство по Эффективному Промпт-Инжинирингу. Продолжение
Начало
Основные техники
1. Без примеров (Zero-Shot)
Описываем, что хотим получить, и модель пытается выполнить запрос на основе своих знаний. Подходит для простых задач, где желаемый результат ясен из самих инструкций: «Переведи текст на французский» или «Кратко изложи содержание этой статьи».
Преимущество: меньше токенов, промпт проще писать и поддерживать.
Недостаток: когда требуется определённое форматирование или поведение, промпта без примеров может быть недостаточно.
Лучшие практики:
- Максимально чёткое описание желаемого результата;
- Ясное указание формата вывода, любых ограничений или требований;
2. С примерами (Few-Shot)
Подходит, когда требуется определённый формат или когда желаемое поведение сложно определить из одних только инструкций.
Большее примеров - лучше производительность, но мы ограничены длиной контекста и соображениями стоимости. Обычно 3-5 примеров обеспечивают хороший баланс.
При форматировании примеров можно экономить токены, выбирая эффективные структуры. Например, «пицца -> съедобный» использует меньше токенов, чем «Вход: пицца, Выход: съедобный», сообщая при этом ту же информацию.
3. Цепочка рассуждений (Chain-of-Though, CoT)
Предполагает явное указание модели пошагово обдумывать получение ответа. Способствует систематическому решению проблем и значительно улучшает производительность в сложных задачах на рассуждение.
Простейшая реализация — добавление к промпту фраз типа «объясни свои рассуждения». Так модель методично решает задачу, демонстрируя процесс рассуждения, прежде чем прийти к выводу.
CoT часто улучшает производительность модели в различных тестах, особенно для математических задач, логических головоломок и задач на многошаговое рассуждение. Также помогает уменьшить количество ошибок, поскольку модель должна обосновывать свои ответы явными шагами рассуждения.
Можно указать точные шаги, которые мы хотим, чтобы модель выполнила, или предоставить примеры, демонстрирующие процесс рассуждения.
Недостаток: увеличение времени ответа и стоимости. Модель генерирует больше токенов по мере обработки рассуждений. Для сложных задач, где точность имеет решающее значение, этот компромисс обычно оправдан.
4. Ролевой
Назначает модели определённую роль или область знаний. Так мы влияем на точку зрения и стиль ответов. Особенно эффективно в приложениях для обслуживания клиентов, образовательном контенте, творческом письме и любых сценариях, где контекст или уровень квалификации имеют значение. Модель может корректировать словарный запас, уровень детализации и подход в зависимости от назначенной роли.
Следует быть максимально подробными в описании роли и любых соответствующих характеристик. Чем конкретнее, тем лучше модель сможет «сыграть эту роль».
5. Цепочка промптов и декомпозиция
Предполагает разбиение сложных задач на более мелкие, управляемые подзадачи, со своим промптом на каждую.
Например, чат-бот службы поддержки клиентов. Процесс ответа на запрос клиента можно разделить на:
- Классификацию намерения запроса: нужна ли клиенту помощь с выставлением счетов, техническая поддержка, управление учётной записью или общая информация.
- Генерацию соответствующего ответа: отдельный этап для генерации фактического ответа на основе намерения.
Недостаток: увеличение воспринимаемой пользователями задержки. Однако для сложных приложений улучшенная надёжность и удобство сопровождения часто перевешивают этот недостаток.
Окончание следует…
Источник: https://blog.bytebytego.com/p/a-guide-to-effective-prompt-engineering
👍5👎5
День 2571. #ЗаметкиНаПолях #AI
Руководство по Эффективному Промпт-Инжинирингу. Окончание
Начало https://news.1rj.ru/str/NetDeveloperDiary/3089
Продолжение https://news.1rj.ru/str/NetDeveloperDiary/3090
Рекомендации по написанию эффективных промптов
1. Будьте ясны и конкретны: нужно устранить любую неопределённость относительно того, что мы хотим, чтобы модель сделала. Чтобы модель оценила эссе, нужно указать шкалу оценок. Допускаются ли дробные оценки? Что должна делать модель, если она не уверена в оценке?
2. Предоставьте достаточный контекст: контекст помогает моделям генерировать точные и релевантные ответы. Чтобы получить ответы на вопросы о документе, включение его в промпт крайне важно. Без него модель может полагаться только на свои обучающие данные, что может привести к устаревшей или неверной информации.
3. Укажите формат вывода: краткий ответ или подробное объяснение? JSON, маркированный список или абзац текста? Включать ли преамбулы или сразу переходить к сути?
4. Стратегически используйте примеры: их следует приводить, когда желаемый формат или поведение не очевидны из одних только инструкций.
5. Итерация и экспериментирование: разработка промптов — итеративный процесс. Начните с базового промпта, проанализируйте результаты и дорабатывайте промпт на основе полученных знаний.
6. Версионирование промптов: так вы сможете отслеживать изменения во времени. Использование согласованных данных оценки позволяет объективно сравнивать различные варианты промптов. Тестирование промптов следует проводить не только изолированно, но и в контексте всей системы, чтобы гарантировать, что улучшения в одной области не создадут проблем в другой.
Распространённые ошибки
1. Излишняя расплывчатость: предположение, что модель понимает наше намерение без явного объяснения. Такие промпты оставляют слишком много места для интерпретации. Модель сделает свой выбор, который может не совпадать с тем, чего мы на самом деле хотим.
2. Чрезмерное усложнение заданий: слишком сложные задания с избыточными инструкциями, большим количеством примеров или сложной логикой могут запутать модель, а не помочь ей. Стремитесь к самому простому заданию, которое достигает цели. Если задание без примеров работает хорошо, нет необходимости добавлять примеры.
3. Игнорирование формата вывода: может вызвать проблемы, особенно когда выходные данные модели передаются в другие системы. Если нужны структурированные данные, но мы не запрашиваем их явно, модель может сгенерировать неструктурированный текст, требующий дополнительной обработки или очистки. Это усложняет работу приложения и создаёт потенциальные точки отказа.
4. Недостаточное тестирование: один успешный результат не означает надёжность запроса. Необходимо тестировать запросы с различными входными данными, включая крайние случаи и необычные сценарии. То, что работает в типичных случаях, может дать сбой, если входные данные немного отличаются или неожиданны. Создание небольшого оценочного набора данных и систематическое тестирование помогают выявлять слабые места до того, как они станут проблемами в производственной среде.
Итого
Эффективная разработка промптов сочетает в себе чёткую коммуникацию, стратегическое использование примеров и систематическое экспериментирование.
Ключевые принципы остаются неизменными для различных моделей и приложений:
- Будьте конкретны и ясны в своих инструкциях.
- Предоставьте достаточный контекст для работы модели.
- Укажите необходимый формат выходных данных.
- Используйте примеры, когда они приносят пользу, и вносите изменения на основе полученных результатов.
Источник: https://blog.bytebytego.com/p/a-guide-to-effective-prompt-engineering
Руководство по Эффективному Промпт-Инжинирингу. Окончание
Начало https://news.1rj.ru/str/NetDeveloperDiary/3089
Продолжение https://news.1rj.ru/str/NetDeveloperDiary/3090
Рекомендации по написанию эффективных промптов
1. Будьте ясны и конкретны: нужно устранить любую неопределённость относительно того, что мы хотим, чтобы модель сделала. Чтобы модель оценила эссе, нужно указать шкалу оценок. Допускаются ли дробные оценки? Что должна делать модель, если она не уверена в оценке?
2. Предоставьте достаточный контекст: контекст помогает моделям генерировать точные и релевантные ответы. Чтобы получить ответы на вопросы о документе, включение его в промпт крайне важно. Без него модель может полагаться только на свои обучающие данные, что может привести к устаревшей или неверной информации.
3. Укажите формат вывода: краткий ответ или подробное объяснение? JSON, маркированный список или абзац текста? Включать ли преамбулы или сразу переходить к сути?
4. Стратегически используйте примеры: их следует приводить, когда желаемый формат или поведение не очевидны из одних только инструкций.
5. Итерация и экспериментирование: разработка промптов — итеративный процесс. Начните с базового промпта, проанализируйте результаты и дорабатывайте промпт на основе полученных знаний.
6. Версионирование промптов: так вы сможете отслеживать изменения во времени. Использование согласованных данных оценки позволяет объективно сравнивать различные варианты промптов. Тестирование промптов следует проводить не только изолированно, но и в контексте всей системы, чтобы гарантировать, что улучшения в одной области не создадут проблем в другой.
Распространённые ошибки
1. Излишняя расплывчатость: предположение, что модель понимает наше намерение без явного объяснения. Такие промпты оставляют слишком много места для интерпретации. Модель сделает свой выбор, который может не совпадать с тем, чего мы на самом деле хотим.
2. Чрезмерное усложнение заданий: слишком сложные задания с избыточными инструкциями, большим количеством примеров или сложной логикой могут запутать модель, а не помочь ей. Стремитесь к самому простому заданию, которое достигает цели. Если задание без примеров работает хорошо, нет необходимости добавлять примеры.
3. Игнорирование формата вывода: может вызвать проблемы, особенно когда выходные данные модели передаются в другие системы. Если нужны структурированные данные, но мы не запрашиваем их явно, модель может сгенерировать неструктурированный текст, требующий дополнительной обработки или очистки. Это усложняет работу приложения и создаёт потенциальные точки отказа.
4. Недостаточное тестирование: один успешный результат не означает надёжность запроса. Необходимо тестировать запросы с различными входными данными, включая крайние случаи и необычные сценарии. То, что работает в типичных случаях, может дать сбой, если входные данные немного отличаются или неожиданны. Создание небольшого оценочного набора данных и систематическое тестирование помогают выявлять слабые места до того, как они станут проблемами в производственной среде.
Итого
Эффективная разработка промптов сочетает в себе чёткую коммуникацию, стратегическое использование примеров и систематическое экспериментирование.
Ключевые принципы остаются неизменными для различных моделей и приложений:
- Будьте конкретны и ясны в своих инструкциях.
- Предоставьте достаточный контекст для работы модели.
- Укажите необходимый формат выходных данных.
- Используйте примеры, когда они приносят пользу, и вносите изменения на основе полученных результатов.
Источник: https://blog.bytebytego.com/p/a-guide-to-effective-prompt-engineering
👎7👍3
День 2572. #Карьера
Топ Советов по Повышению Продуктивности. Часть 8
Части 1, 2, 3, 4, 5, 6, 7
8. Освойте IDE как музыкальный инструмент
Неприятная правда: большинство разработчиков используют IDE, как будто играют на пианино двумя пальцами. Музыка звучит, но по сравнению с тем, кто в совершенстве овладел инструментом, разница колоссальная.
IDE — ваш основной интерфейс для работы с кодом. Каждое действие — открытие файлов, навигация по коду, рефакторинг, запуск тестов — либо происходит плавно на автомате, либо неуклюже серией кликов. Разница накапливается, превращаясь в часы в неделю, а затем в недели в год. Разница в продуктивности новичка и эксперта в IDE - 2-3 раза.
Уровень 1: Освойте основные сочетания клавиш
Перестаньте использовать мышь для навигации. Серьёзно. Мышь плохо предназначена редактирования и поиска кода. Вот старый, но всё ещё актуальный пост о сочетаниях клавиш в Visual Studio.
Челлендж: в течение недели каждый раз, когда вы тянетесь к мышке, делайте паузу. Спросите себя: «Есть ли для этого сочетание клавиш?» Найдите его. Используйте. Через неделю многие действия станут автоматическими.
Уровень 2: Шаблоны для повторяющегося кода
Вы пишете одни и те же шаблоны кода снова и снова. Перестаньте набирать их посимвольно. VS автоматически добавит шаблон кода при нажатии Tab после набора ключевых слов: for, foreach, switch, try, ctor (конструктор), prop (свойство) и т.п. Создайте шаблоны для наиболее используемых вами фрагментов кода.
Уровень 3: Функции IDE, которые вы, скорее всего, не используете
Инструменты рефакторинга: не переименовывайте вручную функцию и её 47 повторений. Позвольте IDE сделать это безопасно, в том числе и в разных файлах (
Множественный курсор - освойте это. Научитесь:
- Устанавливать курсоры на нескольких строках;
- Добавлять курсоры выше/ниже текущей строки;
- Выделять все вхождения в файле.
Изучите горячие клавиши для навигации по коду:
- Переход к соответствующей скобке;
- Переход между изменениями;
- Переход к предыдущей/следующей позиции курсора (как назад/вперёд в браузере);
- Переход по ошибкам/предупреждениям;
- Закладки и навигация по ним.
Интеграция с Git: перестаньте переключаться на терминал для каждой операции Git. Научитесь добавлять фрагменты кода в индекс, просматривать различия, разрешать конфликты и создавать коммиты прямо в IDE. Одних только инструментов визуального сравнения изменений достаточно, чтобы их освоить.
Уровень 4: Оптимизация рабочего пространства и UI
Разумное разделение редакторов: не открывайте только один файл за раз. Разделите экран, чтобы видеть:
- Файл реализации слева, файл теста справа;
- Код компонента сверху, стили снизу;
- Маршрут API сверху, модель базы данных снизу.
Используйте группировки и управление вкладками:
- Закрепляйте часто используемые файлы, чтобы они не закрывались;
- Используйте вертикальное или горизонтальное разделение в зависимости от файлов;
- Научитесь переключаться между вкладками без использования мыши (Ctrl+Tab).
Создавайте настройки для конкретного рабочего пространства: разные проекты имеют разные потребности. Настройте для проекта:
- Правила форматирования кода;
- Пользовательские шаблоны кода
- Задачи сборки;
- Конфигурации отладки.
Уровень 5: Расширения и плагины, которые действительно важны
Не устанавливайте множество расширений, которые замедляют IDE. Используйте только действительно нужные. Перед установкой расширения проверьте, есть ли в IDE эта функциональность. Многие функции, ради которых люди устанавливают расширения, уже есть в IDE, если вы знаете, где искать.
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
Топ Советов по Повышению Продуктивности. Часть 8
Части 1, 2, 3, 4, 5, 6, 7
8. Освойте IDE как музыкальный инструмент
Неприятная правда: большинство разработчиков используют IDE, как будто играют на пианино двумя пальцами. Музыка звучит, но по сравнению с тем, кто в совершенстве овладел инструментом, разница колоссальная.
IDE — ваш основной интерфейс для работы с кодом. Каждое действие — открытие файлов, навигация по коду, рефакторинг, запуск тестов — либо происходит плавно на автомате, либо неуклюже серией кликов. Разница накапливается, превращаясь в часы в неделю, а затем в недели в год. Разница в продуктивности новичка и эксперта в IDE - 2-3 раза.
Уровень 1: Освойте основные сочетания клавиш
Перестаньте использовать мышь для навигации. Серьёзно. Мышь плохо предназначена редактирования и поиска кода. Вот старый, но всё ещё актуальный пост о сочетаниях клавиш в Visual Studio.
Челлендж: в течение недели каждый раз, когда вы тянетесь к мышке, делайте паузу. Спросите себя: «Есть ли для этого сочетание клавиш?» Найдите его. Используйте. Через неделю многие действия станут автоматическими.
Уровень 2: Шаблоны для повторяющегося кода
Вы пишете одни и те же шаблоны кода снова и снова. Перестаньте набирать их посимвольно. VS автоматически добавит шаблон кода при нажатии Tab после набора ключевых слов: for, foreach, switch, try, ctor (конструктор), prop (свойство) и т.п. Создайте шаблоны для наиболее используемых вами фрагментов кода.
Уровень 3: Функции IDE, которые вы, скорее всего, не используете
Инструменты рефакторинга: не переименовывайте вручную функцию и её 47 повторений. Позвольте IDE сделать это безопасно, в том числе и в разных файлах (
Ctrl + R,R). То же самое относится к «Извлечь метод», «Извлечь переменную» и т.п.Множественный курсор - освойте это. Научитесь:
- Устанавливать курсоры на нескольких строках;
- Добавлять курсоры выше/ниже текущей строки;
- Выделять все вхождения в файле.
Изучите горячие клавиши для навигации по коду:
- Переход к соответствующей скобке;
- Переход между изменениями;
- Переход к предыдущей/следующей позиции курсора (как назад/вперёд в браузере);
- Переход по ошибкам/предупреждениям;
- Закладки и навигация по ним.
Интеграция с Git: перестаньте переключаться на терминал для каждой операции Git. Научитесь добавлять фрагменты кода в индекс, просматривать различия, разрешать конфликты и создавать коммиты прямо в IDE. Одних только инструментов визуального сравнения изменений достаточно, чтобы их освоить.
Уровень 4: Оптимизация рабочего пространства и UI
Разумное разделение редакторов: не открывайте только один файл за раз. Разделите экран, чтобы видеть:
- Файл реализации слева, файл теста справа;
- Код компонента сверху, стили снизу;
- Маршрут API сверху, модель базы данных снизу.
Используйте группировки и управление вкладками:
- Закрепляйте часто используемые файлы, чтобы они не закрывались;
- Используйте вертикальное или горизонтальное разделение в зависимости от файлов;
- Научитесь переключаться между вкладками без использования мыши (Ctrl+Tab).
Создавайте настройки для конкретного рабочего пространства: разные проекты имеют разные потребности. Настройте для проекта:
- Правила форматирования кода;
- Пользовательские шаблоны кода
- Задачи сборки;
- Конфигурации отладки.
Уровень 5: Расширения и плагины, которые действительно важны
Не устанавливайте множество расширений, которые замедляют IDE. Используйте только действительно нужные. Перед установкой расширения проверьте, есть ли в IDE эта функциональность. Многие функции, ради которых люди устанавливают расширения, уже есть в IDE, если вы знаете, где искать.
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
👍8
День 2573. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
22. Стратегии ветвления в Git
«Опишите стратегию ветвления Git, которую вы использовали в своих проектах, и как она помогает эффективно управлять циклами разработки и выпуска?»
Хороший ответ
Одна из эффективных стратегий ветвления Git — стратегия Git Flow. Согласно этой стратегии, работа организуется вокруг двух ветвей с бесконечным временем жизни:
- главная ветка (main), в которой исходный код HEAD всегда отражает состояние, готовое к использованию в продакшене.
- ветка develop служит интеграционной ветвью для новых функций. Она всегда отражает состояние с последними внесёнными изменениями для следующего релиза.
Дополнительные ветки, используемые в Git Flow:
- Ветки функций (Feature branches) – ответвляются от develop и сливаются обратно в develop. Каждая feature-ветка используется для разработки новой функции для будущего релиза. Обычно они создаются для каждой новой функции.
- Ветки релизов (Release branches) - ответвляются от develop и сливаются в develop и main. Используются для подготовки к новому релизу. Позволяют вносить незначительные исправления ошибок и подготавливать метаданные для релиза (номер версии, дату сборки и т.д.).
- Ветки исправлений (Hotfix branches) - ответвляются от main и сливаются в develop и main. Используются для быстрого обновления производственных релизов.
Такой структурированный подход позволяет одновременно осуществлять множество видов разработки, не мешая друг другу, поддерживает параллельную разработку функций, подготовку к будущим релизам и оперативное устранение проблем, влияющих на производственную среду.
Вот как можно использовать эту стратегию на практике:
Эта стратегия особенно полезна для поддержания контроля над разработкой и релизами, обеспечивая надёжную доставку ПО.
Часто встречающийся плохой ответ
«Мы использовали одну ветку для всего, потому что это проще и легче в управлении. После тестирования кода мы делали коммиты напрямую в ветку main, не усложняя систему несколькими ветками.»
Почему это неправильно:
- Риск нестабильности: коммиты напрямую в main увеличивают риск внедрения нестабильного кода в продакшн. Это может привести к серьёзным проблемам с развёртыванием и эксплуатацией.
- Отсутствие изоляции для новых функций: такой подход игнорирует преимущества изоляции новой работы по разработке в ветках функций, что минимизирует влияние на основную кодовую базу и другую текущую работу.
- Неэффективность в обработке релизов и исправлений: без выделенных веток для релизов и исправлений становится сложно управлять различными версиями и исправлять проблемы, не влияя на основной рабочий процесс разработки.
Обычно эта ошибка возникает из-за недостатка опыта работы с совместными проектами значительной сложности или непонимания важности структурированных рабочих процессов для поддержания качества и стабильности кода. Такой подход может привести к значительным проблемам масштабирования процесса разработки и управления несколькими одновременными инициативами.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
22. Стратегии ветвления в Git
«Опишите стратегию ветвления Git, которую вы использовали в своих проектах, и как она помогает эффективно управлять циклами разработки и выпуска?»
Хороший ответ
Одна из эффективных стратегий ветвления Git — стратегия Git Flow. Согласно этой стратегии, работа организуется вокруг двух ветвей с бесконечным временем жизни:
- главная ветка (main), в которой исходный код HEAD всегда отражает состояние, готовое к использованию в продакшене.
- ветка develop служит интеграционной ветвью для новых функций. Она всегда отражает состояние с последними внесёнными изменениями для следующего релиза.
Дополнительные ветки, используемые в Git Flow:
- Ветки функций (Feature branches) – ответвляются от develop и сливаются обратно в develop. Каждая feature-ветка используется для разработки новой функции для будущего релиза. Обычно они создаются для каждой новой функции.
- Ветки релизов (Release branches) - ответвляются от develop и сливаются в develop и main. Используются для подготовки к новому релизу. Позволяют вносить незначительные исправления ошибок и подготавливать метаданные для релиза (номер версии, дату сборки и т.д.).
- Ветки исправлений (Hotfix branches) - ответвляются от main и сливаются в develop и main. Используются для быстрого обновления производственных релизов.
Такой структурированный подход позволяет одновременно осуществлять множество видов разработки, не мешая друг другу, поддерживает параллельную разработку функций, подготовку к будущим релизам и оперативное устранение проблем, влияющих на производственную среду.
Вот как можно использовать эту стратегию на практике:
# Создание ветки для функции
git checkout -b feature/new-cool-feature develop
# Завершение работы над функцией и слияние
git checkout develop
git merge feature/new-cool-feature
git branch -d feature/new-cool-feature
# Подготовка релиза
git checkout -b release/1.2.0 develop
#Специфичная для релиза метаинформация
git checkout master
git merge release/1.2.0
git tag -a 1.2.0
# Патч бага в продакшене
git checkout -b hotfix/urgent-fix master
#Исправление бага
git checkout master
git merge hotfix/urgent-fix
git tag -a 1.2.1
git checkout develop
git merge hotfix/urgent-fix
git branch -d hotfix/urgent-fix
Эта стратегия особенно полезна для поддержания контроля над разработкой и релизами, обеспечивая надёжную доставку ПО.
Часто встречающийся плохой ответ
«Мы использовали одну ветку для всего, потому что это проще и легче в управлении. После тестирования кода мы делали коммиты напрямую в ветку main, не усложняя систему несколькими ветками.»
Почему это неправильно:
- Риск нестабильности: коммиты напрямую в main увеличивают риск внедрения нестабильного кода в продакшн. Это может привести к серьёзным проблемам с развёртыванием и эксплуатацией.
- Отсутствие изоляции для новых функций: такой подход игнорирует преимущества изоляции новой работы по разработке в ветках функций, что минимизирует влияние на основную кодовую базу и другую текущую работу.
- Неэффективность в обработке релизов и исправлений: без выделенных веток для релизов и исправлений становится сложно управлять различными версиями и исправлять проблемы, не влияя на основной рабочий процесс разработки.
Обычно эта ошибка возникает из-за недостатка опыта работы с совместными проектами значительной сложности или непонимания важности структурированных рабочих процессов для поддержания качества и стабильности кода. Такой подход может привести к значительным проблемам масштабирования процесса разработки и управления несколькими одновременными инициативами.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍10
День 2574. #ЧтоНовенького #DotNet11
Асинхронность в Рантайме в превью 1 .NET 11. Начало
В .NET 11 превью 1 появилась революционная функция: асинхронные операции в среде выполнения. Вместо того чтобы заставлять компилятор C# переписывать методы async/await в конечные автоматы, сама среда выполнения .NET теперь будет рассматривать асинхронные методы как нативную концепцию. Рассмотрим, что это такое, почему это важно и как вы можете поэкспериментировать с ними.
Проблема с текущей реализацией
С тех пор, как в C# 5 были введены async/await, компилятор был единственным ответственным за работу асинхронных операций. Когда вы пишете асинхронный метод, компилятор C# переписывает его в конечный автомат — сгенерированную структуру, реализующую IAsyncStateMachine, которая отслеживает прогресс метода в точках приостановки.
Недостатки
1. Накладные расходы на конечный автомат
Каждый асинхронный метод генерирует структуру конечного автомата с полями для каждой локальной переменной, которая «переходит через await». Когда метод не завершается синхронно, эта структура помещается в кучу.
2. Неудобство для отладчика
Сгенерированный код конечного автомата затрудняет пошаговое выполнение асинхронных методов. Трассировка стека показывает синтетические методы MoveNext вместо исходных имён методов.
3. Слепые зоны профилировщика
Инструменты анализа производительности с трудом правильно распределяют время между точками приостановки асинхронных операций, поскольку среда выполнения не знает асинхронной семантики — она видит только обычные вызовы методов.
4. Упущенные возможности оптимизации
Т.к. среда выполнения не понимает паттерн асинхронности, она не может оптимизировать цепочки асинхронных вызовов. Каждый вызов await приводит к полному циклу приостановки/возобновления, даже если среда выполнения теоретически могла бы оптимизировать передачу управления.
Что такое асинхронность в среде выполнения?
Асинхронность в среде выполнения переносит понятие асинхронных методов из компилятора в саму среду выполнения .NET. Вместо того чтобы компилятор генерировал сложный конечный автомат, он генерирует более простой IL-код, аннотированный
- Приостановление и возобновление: среда выполнения управляет сохранением и восстановлением состояния метода в точках приостановки, устраняя необходимость в структурах конечного автомата, генерируемых компилятором.
- Поднятие локальных переменных: «Поднимаются» (сохраняются при переходе через await) только те переменные, которые фактически существуют между точками приостановки, и среда выполнения обрабатывает это напрямую.
- Оптимизированные асинхронные вызовы: когда один асинхронный метод среды выполнения вызывает другой, среда выполнения может оптимизировать передачу, потенциально полностью избегая аллокаций экземпляров Task в цепочках асинхронных вызовов.
Как работает новая модель?
В модели асинхронности в среде выполнения асинхронные методы используют AsyncHelpers для выражения приостановки:
Когда компилятор C# генерирует асинхронный IL-код, вместо построения полного конечного автомата он создает вызов
Окончание следует…
Источник: https://laurentkempe.com/2026/02/14/exploring-net-11-preview-1-runtime-async-a-dive-into-the-future-of-async-in-net/
Асинхронность в Рантайме в превью 1 .NET 11. Начало
В .NET 11 превью 1 появилась революционная функция: асинхронные операции в среде выполнения. Вместо того чтобы заставлять компилятор C# переписывать методы async/await в конечные автоматы, сама среда выполнения .NET теперь будет рассматривать асинхронные методы как нативную концепцию. Рассмотрим, что это такое, почему это важно и как вы можете поэкспериментировать с ними.
Проблема с текущей реализацией
С тех пор, как в C# 5 были введены async/await, компилятор был единственным ответственным за работу асинхронных операций. Когда вы пишете асинхронный метод, компилятор C# переписывает его в конечный автомат — сгенерированную структуру, реализующую IAsyncStateMachine, которая отслеживает прогресс метода в точках приостановки.
Недостатки
1. Накладные расходы на конечный автомат
Каждый асинхронный метод генерирует структуру конечного автомата с полями для каждой локальной переменной, которая «переходит через await». Когда метод не завершается синхронно, эта структура помещается в кучу.
2. Неудобство для отладчика
Сгенерированный код конечного автомата затрудняет пошаговое выполнение асинхронных методов. Трассировка стека показывает синтетические методы MoveNext вместо исходных имён методов.
3. Слепые зоны профилировщика
Инструменты анализа производительности с трудом правильно распределяют время между точками приостановки асинхронных операций, поскольку среда выполнения не знает асинхронной семантики — она видит только обычные вызовы методов.
4. Упущенные возможности оптимизации
Т.к. среда выполнения не понимает паттерн асинхронности, она не может оптимизировать цепочки асинхронных вызовов. Каждый вызов await приводит к полному циклу приостановки/возобновления, даже если среда выполнения теоретически могла бы оптимизировать передачу управления.
Что такое асинхронность в среде выполнения?
Асинхронность в среде выполнения переносит понятие асинхронных методов из компилятора в саму среду выполнения .NET. Вместо того чтобы компилятор генерировал сложный конечный автомат, он генерирует более простой IL-код, аннотированный
[MethodImpl(MethodImplOptions.Async)]. Затем среда выполнения берёт на себя ответственность за:- Приостановление и возобновление: среда выполнения управляет сохранением и восстановлением состояния метода в точках приостановки, устраняя необходимость в структурах конечного автомата, генерируемых компилятором.
- Поднятие локальных переменных: «Поднимаются» (сохраняются при переходе через await) только те переменные, которые фактически существуют между точками приостановки, и среда выполнения обрабатывает это напрямую.
- Оптимизированные асинхронные вызовы: когда один асинхронный метод среды выполнения вызывает другой, среда выполнения может оптимизировать передачу, потенциально полностью избегая аллокаций экземпляров Task в цепочках асинхронных вызовов.
Как работает новая модель?
В модели асинхронности в среде выполнения асинхронные методы используют AsyncHelpers для выражения приостановки:
namespace System.Runtime.CompilerServices
{
public static class AsyncHelpers
{
[MethodImpl(MethodImplOptions.Async)]
public static void Await(Task task);
[MethodImpl(MethodImplOptions.Async)]
public static void Await(ValueTask task);
…
}
}
Когда компилятор C# генерирует асинхронный IL-код, вместо построения полного конечного автомата он создает вызов
AsyncHelpers.Await(…). Среда выполнения перехватывает этот вызов, и, если задача ещё не завершена, приостанавливает выполнение метода, сохраняя только необходимое состояние, и возобновляет его позже, когда результат станет доступен.Окончание следует…
Источник: https://laurentkempe.com/2026/02/14/exploring-net-11-preview-1-runtime-async-a-dive-into-the-future-of-async-in-net/
2👍35
День 2575. #ЧтоНовенького #DotNet11
Асинхронность в Рантайме в превью 1 .NET 11. Окончание
Начало
Что изменилось в .NET 11 Preview 1
Асинхронность в Рантайме была доступна в виде экспериментальной функции в .NET 10, но требовала установки флагов в переменных среды. В .NET 11 превью 1:
- Поддержка CoreCLR включена по умолчанию
Больше не нужно устанавливать
- Нативная поддержка AOT
Превью 1 включает базовую нативную поддержку AOT для асинхронных методов во время выполнения. Т.е. код, скомпилированный с
Как попробовать?
1. Установите целевую платформу на .NET 11:
2. Включите функции предварительного просмотра и асинхронную компиляцию в файле .csproj:
3. Пишите код, как обычно:
При включенных асинхронных операциях в среде выполнения компилятор C# генерирует более простой IL-код без полноценного конечного автомата. Среда выполнения обрабатывает приостановку и возобновление выполнения нативно. Ваш исходный код при этом не меняется — улучшение заключается исключительно в способе компиляции и выполнения кода. Вот пример низкоуровневого кода C# для .NET 11:
Сгенерированный IL-код также значительно проще. Для сравнения, конечный автомат, генерируемый в .NET 10.
Что дальше?
В рамках задачи по асинхронной обработке в среде выполнения для .NET 11 осталось реализовать:
- Перекомпиляцию библиотек
Компиляция библиотек System.* и ASP.NET Core с поддержкой асинхронной обработки во время выполнения позволит добиться повышения производительности на уровне всей платформы.
- Улучшения диагностики
Улучшенное форматирование и вывод трассировки стека для асинхронных методов во время выполнения.
- Тестирование
Включение асинхронной компиляции во время выполнения для модульных тестов и библиотек во всей экосистеме.
После перекомпиляции и поставки основных библиотек с включенной асинхронной обработкой в среде выполнения, все преимущества в производительности — уменьшение выделений памяти, меньший размер состояния и оптимизированные цепочки асинхронных вызовов — должны стать измеримыми в реальных приложениях, таких как ASP.NET Core.
Источник: https://laurentkempe.com/2026/02/14/exploring-net-11-preview-1-runtime-async-a-dive-into-the-future-of-async-in-net/
Асинхронность в Рантайме в превью 1 .NET 11. Окончание
Начало
Что изменилось в .NET 11 Preview 1
Асинхронность в Рантайме была доступна в виде экспериментальной функции в .NET 10, но требовала установки флагов в переменных среды. В .NET 11 превью 1:
- Поддержка CoreCLR включена по умолчанию
Больше не нужно устанавливать
DOTNET_RuntimeAsync=1. Среда выполнения готова к выполнению асинхронных методов сразу после установки.- Нативная поддержка AOT
Превью 1 включает базовую нативную поддержку AOT для асинхронных методов во время выполнения. Т.е. код, скомпилированный с
runtime-async=on, теперь может быть предкомпилирован, включая поддержку продолжений и инфраструктуру для диагностики.Как попробовать?
1. Установите целевую платформу на .NET 11:
<TargetFramework>net11.0</TargetFramework>
2. Включите функции предварительного просмотра и асинхронную компиляцию в файле .csproj:
<PropertyGroup>
<EnablePreviewFeatures>true</EnablePreviewFeatures>
<Features>$(Features);runtime-async=on</Features>
</PropertyGroup>
3. Пишите код, как обычно:
async Task<string> FetchDataAsync(
HttpClient client, string url)
{
var resp = await client.GetAsync(url);
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync();
}
При включенных асинхронных операциях в среде выполнения компилятор C# генерирует более простой IL-код без полноценного конечного автомата. Среда выполнения обрабатывает приостановку и возобновление выполнения нативно. Ваш исходный код при этом не меняется — улучшение заключается исключительно в способе компиляции и выполнения кода. Вот пример низкоуровневого кода C# для .NET 11:
[NullableContext(1)]
[CompilerGenerated]
[MethodImpl(MethodImplOptions.Async)]
internal static Task<string> <<Main>$>g__FetchDataAsync|0_0(HttpClient client, string url)
{
HttpResponseMessage httpResponseMessage = AsyncHelpers.Await<HttpResponseMessage>(client.GetAsync(url));
httpResponseMessage.EnsureSuccessStatusCode();
return (Task<string>) AsyncHelpers.Await<string>(httpResponseMessage.Content.ReadAsStringAsync());
}
Сгенерированный IL-код также значительно проще. Для сравнения, конечный автомат, генерируемый в .NET 10.
Что дальше?
В рамках задачи по асинхронной обработке в среде выполнения для .NET 11 осталось реализовать:
- Перекомпиляцию библиотек
Компиляция библиотек System.* и ASP.NET Core с поддержкой асинхронной обработки во время выполнения позволит добиться повышения производительности на уровне всей платформы.
- Улучшения диагностики
Улучшенное форматирование и вывод трассировки стека для асинхронных методов во время выполнения.
- Тестирование
Включение асинхронной компиляции во время выполнения для модульных тестов и библиотек во всей экосистеме.
После перекомпиляции и поставки основных библиотек с включенной асинхронной обработкой в среде выполнения, все преимущества в производительности — уменьшение выделений памяти, меньший размер состояния и оптимизированные цепочки асинхронных вызовов — должны стать измеримыми в реальных приложениях, таких как ASP.NET Core.
Источник: https://laurentkempe.com/2026/02/14/exploring-net-11-preview-1-runtime-async-a-dive-into-the-future-of-async-in-net/
👍21
День 2576. #МоиИнструменты #PostgresTips
Инструменты Оптимизации Запросов в PostgreSQL. Часть 1
Каждый инженер сталкивался с ситуацией, когда запрос, который должен выполняться за секунды, выполняется 20 минут. Панель мониторинга выдает ошибку тайм-аута. И вы застреваете, глядя на SQL-запрос, гадая, что пошло не так. Проблема не всегда очевидна. Без правильных инструментов оптимизация — это гадание. Эти инструменты помогут обеспечить кратное повышение производительности запросов. Также они показывают, почему запросы выполняются медленно и как именно это исправить.
Замечание: анализ инструментов основан на обширном тестировании в Snowflake, BigQuery, Postgres и Redshift по состоянию на февраль 2025 года. Улучшения производительности — это реальные измерения на производственных нагрузках, а не синтетические бенчмарки.
1. pgBadger (PostgreSQL Query Analyzer)
Что даёт: понимание, что на самом деле происходит в Postgres, не утопая в логах.
Зачем нужен:
Логи запросов PostgreSQL полны, но нечитаемы. Тысячи строк показывают время выполнения, планы и ошибки — но нет чёткого представления о том, что именно снижает производительность.
pgBadger преобразует чистые логи PostgreSQL в полезные HTML-отчеты, показывающие:
- Самые медленные запросы (с фактическим временем выполнения);
- Наиболее часто выполняемые запросы (цели оптимизации с высоким уровнем влияния);
- Запросы, вызывающие ошибки;
- Анализ ожидания блокировок;
- Использование временных файлов;
- Паттерны соединений.
До pgBadger (чистые логи):
И так 50 тысяч строк. Не понятно, какие запросы важны.
С pgBadger (создание отчёта из логов):
Создаёт красивый HTML-отчет, показывающий:
- 10 самых медленных запросов;
- Варианты быстрых решений.
Когда использовать
- Использование PostgreSQL в продакшене;
- Проблемы с производительностью, но неясно, в каких запросах;
- Необходим ретроспективный анализ паттернов запросов;
- Желание показать значимость оптимизации.
Когда отказаться
- Не производственная среда (есть альтернативы);
- Отладка отдельных запросов (используйте EXPLAIN);
- Необходим мониторинг в реальном времени (pgBadger - это пакетный анализ).
Скрытая функция
Инкрементальная генерация отчетов вместо обработки всего лога:
- Анализирует только новые записи лога;
- В 100 раз быстрее для ежедневных отчётов;
- Идеальна для автоматического мониторинга.
Недостаток
Использование памяти pgBadger’ом возрастает с ростом размера лога.
Для больших логов (>10Гб) используйте сэмплинг:
Источник: https://medium.com/@reliabledataengineering/15-sql-optimization-tools-that-make-queries-10x-faster-8629ac451d97
Инструменты Оптимизации Запросов в PostgreSQL. Часть 1
Каждый инженер сталкивался с ситуацией, когда запрос, который должен выполняться за секунды, выполняется 20 минут. Панель мониторинга выдает ошибку тайм-аута. И вы застреваете, глядя на SQL-запрос, гадая, что пошло не так. Проблема не всегда очевидна. Без правильных инструментов оптимизация — это гадание. Эти инструменты помогут обеспечить кратное повышение производительности запросов. Также они показывают, почему запросы выполняются медленно и как именно это исправить.
Замечание: анализ инструментов основан на обширном тестировании в Snowflake, BigQuery, Postgres и Redshift по состоянию на февраль 2025 года. Улучшения производительности — это реальные измерения на производственных нагрузках, а не синтетические бенчмарки.
1. pgBadger (PostgreSQL Query Analyzer)
Что даёт: понимание, что на самом деле происходит в Postgres, не утопая в логах.
Зачем нужен:
Логи запросов PostgreSQL полны, но нечитаемы. Тысячи строк показывают время выполнения, планы и ошибки — но нет чёткого представления о том, что именно снижает производительность.
pgBadger преобразует чистые логи PostgreSQL в полезные HTML-отчеты, показывающие:
- Самые медленные запросы (с фактическим временем выполнения);
- Наиболее часто выполняемые запросы (цели оптимизации с высоким уровнем влияния);
- Запросы, вызывающие ошибки;
- Анализ ожидания блокировок;
- Использование временных файлов;
- Паттерны соединений.
До pgBadger (чистые логи):
2025-02-07 14:23:11 UTC [12345]: LOG: duration: 45231.234 ms statement: SELECT...
2025-02-07 14:23:56 UTC [12346]: LOG: duration: 123.456 ms statement: SELECT...
И так 50 тысяч строк. Не понятно, какие запросы важны.
С pgBadger (создание отчёта из логов):
pgbadger /var/log/postgresql/postgresql-*.log -o report.html
Создаёт красивый HTML-отчет, показывающий:
- 10 самых медленных запросов;
- Варианты быстрых решений.
Когда использовать
- Использование PostgreSQL в продакшене;
- Проблемы с производительностью, но неясно, в каких запросах;
- Необходим ретроспективный анализ паттернов запросов;
- Желание показать значимость оптимизации.
Когда отказаться
- Не производственная среда (есть альтернативы);
- Отладка отдельных запросов (используйте EXPLAIN);
- Необходим мониторинг в реальном времени (pgBadger - это пакетный анализ).
Скрытая функция
Инкрементальная генерация отчетов вместо обработки всего лога:
pgbadger --last-parsed /var/log/last_parsed.log \
/var/log/postgresql/postgresql-*.log \
-o incremental-report.html
- Анализирует только новые записи лога;
- В 100 раз быстрее для ежедневных отчётов;
- Идеальна для автоматического мониторинга.
Недостаток
Использование памяти pgBadger’ом возрастает с ростом размера лога.
Для больших логов (>10Гб) используйте сэмплинг:
# Анализируем 10% логов
pgbadger --sample 10 large_logfile.log
# Делим на временные отрезки
pgbadger --begin "2025-02-07 00:00:00" \
--end "2025-02-07 23:59:59" \
postgresql.log
Источник: https://medium.com/@reliabledataengineering/15-sql-optimization-tools-that-make-queries-10x-faster-8629ac451d97
👍8