День 2554. #ЗаметкиНаПолях
Миграция Процесса Хеширования Паролей без Простоев. Окончание
Начало
В .NET 8 представлена регистрация сервисов по ключу, идеально подходящая для этого сценария. Можно зарегистрировать несколько реализаций одного и того же интерфейса и получать к ним доступ по имени.
1. Регистрация сервисов
Мы регистрируем оба сервиса хэширования, присваивая им уникальные ключи:
2. Обработка входа в систему
Теперь реализуем логику миграции. Внедряем оба сервиса, используя атрибут FromKeyedServices:
Так пароли существующих пользователей постепенно будут обновляться, используя новый алгоритм.
Префиксы алгоритмов
Стандартные алгоритмы часто включают префикс (например, Bcrypt начинается с $2a$ или $2b$). Можно использовать это для выбора алгоритма вместо попыток валидации вслепую:
Завершение миграции
После некоторого времени (обычно несколько месяцев) большинство активных учётных записей будут обновлены. Затем вы можете запустить скрипт очистки, чтобы выявить оставшиеся устаревшие хэши и заставить этих пользователей сбросить свои пароли при следующей попытке входа в систему.
На этом этапе вы можете удалить:
- Регистрацию устаревшего сервиса хэширования;
- Код проверки старого хэша.
И миграция завершена.
Источник: https://www.milanjovanovic.tech/blog/a-practical-demo-of-zero-downtime-migrations-using-password-hashing
Миграция Процесса Хеширования Паролей без Простоев. Окончание
Начало
В .NET 8 представлена регистрация сервисов по ключу, идеально подходящая для этого сценария. Можно зарегистрировать несколько реализаций одного и того же интерфейса и получать к ним доступ по имени.
1. Регистрация сервисов
Мы регистрируем оба сервиса хэширования, присваивая им уникальные ключи:
builder.Services.AddKeyedSingleton<IPasswordHasher, Pbdkf2PasswordHasher>("legacy");
builder.Services.AddKeyedSingleton<IPasswordHasher, Argon2PasswordHasher>("modern");
// (Опционально) Регистрируем новый сервис как вариант по умолчанию
builder.Services.AddSingleton<IPasswordHasher, Argon2PasswordHasher>();2. Обработка входа в систему
Теперь реализуем логику миграции. Внедряем оба сервиса, используя атрибут FromKeyedServices:
public class LoginCommandHandler(
IUserRepository userRepo,
[FromKeyedServices("modern")]
IPasswordHasher newHasher,
[FromKeyedServices("legacy")]
IPasswordHasher legacyHasher)
{
public async Task<AuthenticationResult>
Handle(LoginCommand command)
{
var user = await userRepo.GetAsync(command);
if (user is null)
return AuthenticationResult.Fail();
// 1. Пробуем новый алгоритм
if (newHasher.Verify(user.PasswordHash, command.Password))
return AuthenticationResult.Success(user);
// 2. При неудаче пробуем старый
if (legacyHasher.Verify(user.PasswordHash, command.Password))
{
// 3. МИГРАЦИЯ: вычисляем новый хэш и обновляем
var newHash = newHasher.Hash(command.Password);
user.UpdatePasswordHash(newHash);
await userRepo.SaveChangesAsync();
return AuthenticationResult.Success(user);
}
return AuthenticationResult.Fail();
}
}
Так пароли существующих пользователей постепенно будут обновляться, используя новый алгоритм.
Префиксы алгоритмов
Стандартные алгоритмы часто включают префикс (например, Bcrypt начинается с $2a$ или $2b$). Можно использовать это для выбора алгоритма вместо попыток валидации вслепую:
bool IsLegacyHash(string hash)
=> hash.StartsWith("pbkdf2$");
Завершение миграции
После некоторого времени (обычно несколько месяцев) большинство активных учётных записей будут обновлены. Затем вы можете запустить скрипт очистки, чтобы выявить оставшиеся устаревшие хэши и заставить этих пользователей сбросить свои пароли при следующей попытке входа в систему.
На этом этапе вы можете удалить:
- Регистрацию устаревшего сервиса хэширования;
- Код проверки старого хэша.
И миграция завершена.
Источник: https://www.milanjovanovic.tech/blog/a-practical-demo-of-zero-downtime-migrations-using-password-hashing
👍7
День 2555. #ЧтоНовенького
EF Core 10 Превращает PostgreSQL в Реляционно-Документную БД. Начало
Современным .NET-приложениям всё чаще требуется хранить данные, которые не помещаются в реляционные таблицы: кастомные поля для каждого клиента, изменяющиеся атрибуты продукта или данные из внешних API. До EF Core 10 обработка таких гибких данных означала неудобные костыли, столбцы с необработанным текстом JSON или разрозненные NoSQL-хранилища.
Посмотрим, как EF Core 10 представляет новый мощный способ сопоставления столбцов JSONB в PostgreSQL с помощью сложных типов. В сочетании с высокооптимизированным механизмом хранения JSONB в PostgreSQL это позволяет создавать чёткие модели гибких данных с изменяющейся схемой без ущерба для производительности или удобства запросов.
Важность JSONB
Традиционные реляционные модели перестают работать, когда вашему приложению необходимо хранить:
- Динамические или специфичные для клиента поля;
- Иерархические или вложенные атрибуты;
- Развивающиеся структуры, которые часто меняются;
- Данные внешних API или метаданные.
Здесь JSONB проявляет свои лучшие качества: вы получаете гибкость схемы, нативное индексирование, быструю обработку запросов и полные гарантии ACID — и всё это внутри реляционного механизма.
JSON или JSONB в PostgreSQL
- Хранение: JSON – текст, JSONB – двоичное дерево;
- Производительность запросов: JSON – медленно, JSONB – быстро;
- Индексы: JSON – нет, JSONB – GIN/GiST;
- Дублирующиеся ключи: JSON – сохраняются, JSONB – выигрывает последний;
- Плата за парсинг: JSON – в каждом запросе, JSONB – единожды при вставке.
Итого: всегда используйте JSONB, если только вам не нужно сохранять форматирование, тогда используйте JSON.
EF Core 10 изменяет JSON-сопоставление
До .NET 10 сопоставление JSONB требовало наличия принадлежащих сущностей, что приводило к:
- Запутанной семантике принадлежащих типов,
- Теневым первичным ключам,
- Многословной конфигурации,
- Отсутствию поддержки ExecuteUpdate.
Решение для .NET 10: Сложные типы
EF Core 10 представляет сложные типы, предоставляющие:
- Семантику типов-значений,
- Более чистую конфигурацию,
- Автоматические вложенные коллекции,
- Полноценную трансляцию LINQ в JSONB,
- Массовое обновление JSON с помощью ExecuteUpdate,
- Опциональные сложные типы (Address?).
Пример конфигурации:
Вот и всё - EF Core автоматически обрабатывает вложенные структуры.
Запросы к JSONB в EF Core 10
EF Core теперь транслирует сложные LINQ-запросы напрямую в операторы JSONB, такие как
Фильтр по атрибуту JSON:
Фильтр по вложенному числовому полю:
Запрос JSON-массивов:
Массовое обновление JSON с помощью ExecuteUpdate. EF Core 10 обеспечивает реальную поддержку массового обновления JSONB:
Сравнение производительности (10000 записей)
Загрузка+SaveChanges - 5–10с, 10000 запросов
ExecuteUpdate - 100–200мс, 1 запрос
Это значительное улучшение для счётчиков аналитики, обновлений статуса, изменений метаданных и т.д.
Окончание следует…
Источник: https://trailheadtechnology.com/ef-core-10-turns-postgresql-into-a-hybrid-relational-document-db/
EF Core 10 Превращает PostgreSQL в Реляционно-Документную БД. Начало
Современным .NET-приложениям всё чаще требуется хранить данные, которые не помещаются в реляционные таблицы: кастомные поля для каждого клиента, изменяющиеся атрибуты продукта или данные из внешних API. До EF Core 10 обработка таких гибких данных означала неудобные костыли, столбцы с необработанным текстом JSON или разрозненные NoSQL-хранилища.
Посмотрим, как EF Core 10 представляет новый мощный способ сопоставления столбцов JSONB в PostgreSQL с помощью сложных типов. В сочетании с высокооптимизированным механизмом хранения JSONB в PostgreSQL это позволяет создавать чёткие модели гибких данных с изменяющейся схемой без ущерба для производительности или удобства запросов.
Важность JSONB
Традиционные реляционные модели перестают работать, когда вашему приложению необходимо хранить:
- Динамические или специфичные для клиента поля;
- Иерархические или вложенные атрибуты;
- Развивающиеся структуры, которые часто меняются;
- Данные внешних API или метаданные.
Здесь JSONB проявляет свои лучшие качества: вы получаете гибкость схемы, нативное индексирование, быструю обработку запросов и полные гарантии ACID — и всё это внутри реляционного механизма.
JSON или JSONB в PostgreSQL
- Хранение: JSON – текст, JSONB – двоичное дерево;
- Производительность запросов: JSON – медленно, JSONB – быстро;
- Индексы: JSON – нет, JSONB – GIN/GiST;
- Дублирующиеся ключи: JSON – сохраняются, JSONB – выигрывает последний;
- Плата за парсинг: JSON – в каждом запросе, JSONB – единожды при вставке.
Итого: всегда используйте JSONB, если только вам не нужно сохранять форматирование, тогда используйте JSON.
EF Core 10 изменяет JSON-сопоставление
До .NET 10 сопоставление JSONB требовало наличия принадлежащих сущностей, что приводило к:
- Запутанной семантике принадлежащих типов,
- Теневым первичным ключам,
- Многословной конфигурации,
- Отсутствию поддержки ExecuteUpdate.
Решение для .NET 10: Сложные типы
EF Core 10 представляет сложные типы, предоставляющие:
- Семантику типов-значений,
- Более чистую конфигурацию,
- Автоматические вложенные коллекции,
- Полноценную трансляцию LINQ в JSONB,
- Массовое обновление JSON с помощью ExecuteUpdate,
- Опциональные сложные типы (Address?).
Пример конфигурации:
modelBuilder.Entity<Product>()
.ComplexProperty(p => p.Specs, b => b.ToJson());
Вот и всё - EF Core автоматически обрабатывает вложенные структуры.
Запросы к JSONB в EF Core 10
EF Core теперь транслирует сложные LINQ-запросы напрямую в операторы JSONB, такие как
->, ->>, @>.Фильтр по атрибуту JSON:
var items = await context.Products
.Where(p => p.Specs.Brand == "Apple")
.ToListAsync();
Фильтр по вложенному числовому полю:
var results = await context.Products
.Where(p => p.Specs.RAM >= 16)
.ToListAsync();
Запрос JSON-массивов:
var items = await context.Products
.Where(p => p.Specs.Features.Contains("Waterproof"))
.ToListAsync();
Массовое обновление JSON с помощью ExecuteUpdate. EF Core 10 обеспечивает реальную поддержку массового обновления JSONB:
await context.Products
.ExecuteUpdateAsync(s =>
s.SetProperty(p => p.Metadata.Views,
p => p.Metadata.Views + 1));
Сравнение производительности (10000 записей)
Загрузка+SaveChanges - 5–10с, 10000 запросов
ExecuteUpdate - 100–200мс, 1 запрос
Это значительное улучшение для счётчиков аналитики, обновлений статуса, изменений метаданных и т.д.
Окончание следует…
Источник: https://trailheadtechnology.com/ef-core-10-turns-postgresql-into-a-hybrid-relational-document-db/
👍25
День 2556. #ЧтоНовенького
EF Core 10 Превращает PostgreSQL в Реляционно-Документную БД. Окончание
Начало
Когда использовать JSONB
- Гибкая схема данных
Метаданные, настройки, определения рабочих процессов, конфигурация.
- Иерархические данные
Вложенные объекты или списки, которые плохо отображаются на реляционные таблицы.
- Часто изменяющиеся данные
Динамические поля, которые изменяются без необходимости миграции.
- Полуструктурированные или внешние данные
Полезные нагрузки веб-хуков, ответы API, интеграции.
- Снепшоты
Журналы аудита, история версий, журналы изменений.
Когда НЕ использовать JSONB
- Стабильные данные основного домена
Реляционные столбцы работают быстрее и обеспечивают соблюдение ограничений.
- Связи по внешним ключам
JSONB не может обеспечить ссылочную целостность.
- Данные с множественными объединениями (JOIN)
Объединения по реляционным полям производительнее извлечений JSON.
- Нагрузки OLTP с высокой частотой записи
Обновление JSONB перезаписывает весь документ.
Правильная индексация JSONB
Без индексации запросы к JSONB быстро деградируют.
Индекс GIN (наиболее частоиспользуемый):
Индекс-выражение для определённого поля:
Используйте GIN-индексы для запросов на вхождение и индексы-выражения для фильтрации по определённым ключам.
Разработка гибридной схемы (рекомендуемый подход)
Наиболее надёжные архитектуры сочетают реляционный и JSONB стили.
Реляционные столбцы для:
- Стабильных полей,
- Часто запрашиваемых атрибутов,
- Соединений и внешних ключей.
JSONB для:
- Необязательных полей,
- Динамических или специфичных для клиента атрибутов,
- Метаданных, настроек и рабочих процессов.
Пример модели
Это даёт вашей схеме безопасность и гибкость.
Сводка производительности
JSONB быстрее для:
- Запросов на вхождение (@>);
- Чтения целых документов;
- Запросов, избегающих нескольких объединений таблиц.
JSONB медленнее для:
- Агрегации больших наборов данных;
- Частных обновлений больших документов;
- Сложной логики объединения (JOIN);
- Запросов, требующих строгих реляционных ограничений.
Практический пример
Конфигурация EF Core:
Запрос:
Массовое обновление:
Итого
EF Core 10 наконец-то предоставляет чистый, мощный и первоклассный способ использования JSONB в PostgreSQL через сложные типы:
- Сложные типы — новый стандарт для сопоставления JSON в .NET 10;
- JSONB идеально подходит для гибких, развивающихся иерархических данных;
- ExecuteUpdate повышает производительность при обновлениях JSON;
- Используйте гибридную реляционную модель + JSONB для оптимальной архитектуры;
- JSONB — мощный инструмент, но не замена реляционному проектированию.
При разумном использовании JSONB - один из наиболее эффективных инструментов, доступных разработчикам .NET для создания современных, гибких приложений.
Источник: https://trailheadtechnology.com/ef-core-10-turns-postgresql-into-a-hybrid-relational-document-db/
EF Core 10 Превращает PostgreSQL в Реляционно-Документную БД. Окончание
Начало
Когда использовать JSONB
- Гибкая схема данных
Метаданные, настройки, определения рабочих процессов, конфигурация.
- Иерархические данные
Вложенные объекты или списки, которые плохо отображаются на реляционные таблицы.
- Часто изменяющиеся данные
Динамические поля, которые изменяются без необходимости миграции.
- Полуструктурированные или внешние данные
Полезные нагрузки веб-хуков, ответы API, интеграции.
- Снепшоты
Журналы аудита, история версий, журналы изменений.
Когда НЕ использовать JSONB
- Стабильные данные основного домена
Реляционные столбцы работают быстрее и обеспечивают соблюдение ограничений.
- Связи по внешним ключам
JSONB не может обеспечить ссылочную целостность.
- Данные с множественными объединениями (JOIN)
Объединения по реляционным полям производительнее извлечений JSON.
- Нагрузки OLTP с высокой частотой записи
Обновление JSONB перезаписывает весь документ.
Правильная индексация JSONB
Без индексации запросы к JSONB быстро деградируют.
Индекс GIN (наиболее частоиспользуемый):
CREATE INDEX idx_specs_gin ON products USING gin (specs);
Индекс-выражение для определённого поля:
CREATE INDEX idx_brand ON products ((specs ->> 'Brand'));
Используйте GIN-индексы для запросов на вхождение и индексы-выражения для фильтрации по определённым ключам.
Разработка гибридной схемы (рекомендуемый подход)
Наиболее надёжные архитектуры сочетают реляционный и JSONB стили.
Реляционные столбцы для:
- Стабильных полей,
- Часто запрашиваемых атрибутов,
- Соединений и внешних ключей.
JSONB для:
- Необязательных полей,
- Динамических или специфичных для клиента атрибутов,
- Метаданных, настроек и рабочих процессов.
Пример модели
public class Product
{
public int Id { get; set; }
public string Category { get; set; } = null!;
public decimal Price { get; set; }
public Specifications Specs { get; set; } = new();
}
Это даёт вашей схеме безопасность и гибкость.
Сводка производительности
JSONB быстрее для:
- Запросов на вхождение (@>);
- Чтения целых документов;
- Запросов, избегающих нескольких объединений таблиц.
JSONB медленнее для:
- Агрегации больших наборов данных;
- Частных обновлений больших документов;
- Сложной логики объединения (JOIN);
- Запросов, требующих строгих реляционных ограничений.
Практический пример
Конфигурация EF Core:
modelBuilder.Entity<Order>(entity =>
{
entity.ComplexProperty(o => o.Metadata, b => b.ToJson());
entity.ComplexCollection(o => o.Items, b => b.ToJson());
});
Запрос:
var orders = await context.Orders
.Where(o => o.Items.Any(i => i.UnitPrice > 100))
.ToListAsync();
Массовое обновление:
await context.Orders
.Where(o => o.Metadata.Status == "Pending")
.ExecuteUpdateAsync(s =>
s.SetProperty(p => p.Metadata.Status, "Processing"));
Итого
EF Core 10 наконец-то предоставляет чистый, мощный и первоклассный способ использования JSONB в PostgreSQL через сложные типы:
- Сложные типы — новый стандарт для сопоставления JSON в .NET 10;
- JSONB идеально подходит для гибких, развивающихся иерархических данных;
- ExecuteUpdate повышает производительность при обновлениях JSON;
- Используйте гибридную реляционную модель + JSONB для оптимальной архитектуры;
- JSONB — мощный инструмент, но не замена реляционному проектированию.
При разумном использовании JSONB - один из наиболее эффективных инструментов, доступных разработчикам .NET для создания современных, гибких приложений.
Источник: https://trailheadtechnology.com/ef-core-10-turns-postgresql-into-a-hybrid-relational-document-db/
👍10👎2
День 2557. #Карьера
Топ Советов по Повышению Продуктивности. Часть 6
Части 1, 2, 3, 4, 5
6. Алиасы команд и скрипты: автоматизируйте свою мышечную память
Быстрый тест: сколько команд вы набираете каждый день?
Для большинства разработчиков это одни и те же действия: запуск сервера разработки, запуск тестов, проверка статуса Git, и т.п. Вы набираете эти команды так часто, что они прочно засели в вашей мышечной памяти.
Секрет продуктивности: каждая повторяющаяся команда — это потраченное впустую время. Не потому, что набор текста медленный (хотя это так), а потому, что каждая команда — это точка принятия решения. «Какой тут флаг? На каком порту работает приложение?» Эти микрорешения накапливаются, превращаясь в сплошную рутину. Автоматизируйте всё, что вы делаете, более двух раз.
1. Алиасы терминала
Добавьте это в ваши .zshrc или .bashrc:
2. Функции для сложных команд
Когда алиасов недостаточно, пишите функции:
Теперь
3. Скрипты для проектов
Создайте папку
Теперь скрипт
4. Автозагрузка
Добавьте скрипт в автозагрузку ОС. В скрипт добавьте обновление ваших репозиториев, открытие браузера с багтрекером, пересборку проектов и т.п.
Дело не столько в скорости. Дело в снижении усталости от принятия решений. Когда вы исключаете микрорешения типа «Какая там была команда?», вы сохраняете умственную энергию для решения реальных проблем. Вы дольше остаётесь в состоянии потока и реже переключаетесь между задачами.
Что автоматизировать:
- Настройка и очистка среды;
- Операции с БД (сброс, заполнение, резервное копирование, восстановление);
- Рабочие процессы развёртывания;
- Генерация кода (новые компоненты, конечные точки API, тесты);
- Задачи очистки (удаление веток, очистка кэша);
- Распространённые команды отладки.
Каждый раз, когда вы вводите сложную команду во второй раз, остановитесь. Создайте алиас или скрипт. Это займет 30 секунд и принесёт дивиденды навсегда. Храните файл
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
Топ Советов по Повышению Продуктивности. Часть 6
Части 1, 2, 3, 4, 5
6. Алиасы команд и скрипты: автоматизируйте свою мышечную память
Быстрый тест: сколько команд вы набираете каждый день?
Для большинства разработчиков это одни и те же действия: запуск сервера разработки, запуск тестов, проверка статуса Git, и т.п. Вы набираете эти команды так часто, что они прочно засели в вашей мышечной памяти.
Секрет продуктивности: каждая повторяющаяся команда — это потраченное впустую время. Не потому, что набор текста медленный (хотя это так), а потому, что каждая команда — это точка принятия решения. «Какой тут флаг? На каком порту работает приложение?» Эти микрорешения накапливаются, превращаясь в сплошную рутину. Автоматизируйте всё, что вы делаете, более двух раз.
1. Алиасы терминала
Добавьте это в ваши .zshrc или .bashrc:
# Git
alias gs='git status'
alias gp='git pull'
alias gpo='git push origin'
alias gc='git commit -m'
alias gco='git checkout'
alias gb='git branch'
# Project
alias proj='cd ~/projects'
alias work='cd ~/projects/work'
alias ..='cd ..'
alias ...='cd ../..'
# Testing
alias run='dotnet run'
alias test='dotnet test'
2. Функции для сложных команд
Когда алиасов недостаточно, пишите функции:
# Новая ветка и пуш
gnb() {
git checkout -b "$1"
git push -u origin "$1"
}
# Быстрый коммит
qc() {
git add .
git commit -m "$1"
git push
}
# Создать папку и перейти в неё
mkcd() {
mkdir -p "$1"
cd "$1"
}
Теперь
gnb feature/new-auth создаст и запушит новую ветку одной командой.3. Скрипты для проектов
Создайте папку
scripts/ в проекте и добавьте частые команды:#!/bin/bash
# scripts/dev-rebuild.sh
echo "Rebuilding environment…"
dotnet clean
dotnet build
dotnet test
dotnet watch run
Теперь скрипт
./scripts/dev-setup.sh пересобирает, тестирует и запускает ваше приложение.4. Автозагрузка
Добавьте скрипт в автозагрузку ОС. В скрипт добавьте обновление ваших репозиториев, открытие браузера с багтрекером, пересборку проектов и т.п.
Дело не столько в скорости. Дело в снижении усталости от принятия решений. Когда вы исключаете микрорешения типа «Какая там была команда?», вы сохраняете умственную энергию для решения реальных проблем. Вы дольше остаётесь в состоянии потока и реже переключаетесь между задачами.
Что автоматизировать:
- Настройка и очистка среды;
- Операции с БД (сброс, заполнение, резервное копирование, восстановление);
- Рабочие процессы развёртывания;
- Генерация кода (новые компоненты, конечные точки API, тесты);
- Задачи очистки (удаление веток, очистка кэша);
- Распространённые команды отладки.
Каждый раз, когда вы вводите сложную команду во второй раз, остановитесь. Создайте алиас или скрипт. Это займет 30 секунд и принесёт дивиденды навсегда. Храните файл
.aliases в репозитории и синхронизируйте его между компьютерами. Лучшие разработчики не просто печатают быстрее — они автоматизируют всё, что не требует размышлений.Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
👍13👎1
День 2558. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
19. Глобализация и локализация
«Объясните, как реализовать глобализацию и локализацию в проекте веб-сайта ASP.NET Core MVC для поддержки нескольких языков и культур?»
Хороший ответ
Глобализация и локализация являются ключевыми факторами при разработке приложений, способных поддерживать несколько языков и культурных форматов. В ASP.NET Core это включает в себя настройку сервисов и промежуточного ПО для поддержки различных культур в целях локализации контента и форматирования данных в соответствии с предпочтениями пользователя.
Для реализации локализации в проекте веб-сайта ASP.NET Core необходимо настроить сервисы в файле Program.cs, добавив поддержку локализации для различных культур:
Далее создадим файлы ресурсов для каждого языка в каталоге
Затем внедрим IStringLocalizer в MVC-контроллеры или компоненты представления для получения локализованных строк:
Преимущества
- Гибкость и расширяемость: Лёгкое добавление поддержки дополнительных языков путем добавления новых файлов ресурсов.
- Улучшенный пользовательский опыт: Пользователи видят контент на предпочитаемом ими языке, что повышает удобство использования.
- Точность культуры: Правильно отформатированные даты, числа и валюты в соответствии с языковыми особенностями пользователя.
Эта конфигурация поддерживает не только контент, отображаемый на стороне сервера, но и может быть расширена для сценариев на стороне клиента с использованием библиотек JavaScript или вызовов API, возвращающих локализованный контент.
Часто встречающийся неправильный ответ
«Для поддержки нескольких языков в веб-приложении можно использовать перевод текста на стороне клиента, используя JavaScript или клиентскую библиотеку».
Почему это неправильно:
- Зависимость от клиентской стороны: Этот подход предполагает чрезмерно упрощённый метод, полагаясь исключительно на перевод на стороне клиента, что может привести к несоответствиям и не обрабатывает рендеринг на стороне сервера или форматирование данных (например, дат и чисел) должным образом.
- Игнорирование возможностей ASP.NET Core: Подход игнорирует встроенную поддержку локализации в ASP.NET Core, которая разработана для интеграции с серверной архитектурой, обеспечивая согласованное сохранение настроек локализации во всём приложении.
- Игнорирование доступности и SEO: Локализация на стороне сервера имеет решающее значение для доступности и поисковой оптимизации - областей, которые рендеринг на стороне клиента не может в полной мере учитывать.
Обычно эта ошибка возникает из-за недостаточного понимания инструментов и конфигураций, предоставляемых ASP.NET Core для обработки локализации и глобализации как на стороне клиента, так и на стороне сервера.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
19. Глобализация и локализация
«Объясните, как реализовать глобализацию и локализацию в проекте веб-сайта ASP.NET Core MVC для поддержки нескольких языков и культур?»
Хороший ответ
Глобализация и локализация являются ключевыми факторами при разработке приложений, способных поддерживать несколько языков и культурных форматов. В ASP.NET Core это включает в себя настройку сервисов и промежуточного ПО для поддержки различных культур в целях локализации контента и форматирования данных в соответствии с предпочтениями пользователя.
Для реализации локализации в проекте веб-сайта ASP.NET Core необходимо настроить сервисы в файле Program.cs, добавив поддержку локализации для различных культур:
// Чтобы использовать RequestCulture
using Microsoft.AspNetCore.Localization;
var builder = WebApplication.CreateBuilder(args);
// Добавляем сервисы локализации
builder.Services.AddLocalization(options =>
options.ResourcesPath = "Resources");
// Настраиваем поддерживаемые культуры
string[] cultures = ["en-US", "fr-FR", "ru-RU"];
builder.Services
.Configure<RequestLocalizationOptions>(opts =>
{
opts.DefaultRequestCulture =
new RequestCulture("ru-RU ");
opts.SupportedCultures = cultures;
opts.SupportedUICultures = cultures;
});
var app = builder.Build();
app.UseRequestLocalization();
app.MapGet("/", (IStringLocalizer<Program> localizer) =>
localizer["WelcomeMessage"]);
app.Run();
Далее создадим файлы ресурсов для каждого языка в каталоге
Resources, назвав их <ClassName>.<Culture>.resx, например, Program.en-US.resx, Program.ru-RU.resx.Затем внедрим IStringLocalizer в MVC-контроллеры или компоненты представления для получения локализованных строк:
public class HomeController : Controller
{
private readonly
IStringLocalizer<HomeController> _localizer;
public HomeController(
IStringLocalizer<HomeController> localizer)
{
_localizer = localizer;
}
public IActionResult Index()
{
ViewData["Message"] = _localizer["HomePageWelcome"];
return View();
}
}
Преимущества
- Гибкость и расширяемость: Лёгкое добавление поддержки дополнительных языков путем добавления новых файлов ресурсов.
- Улучшенный пользовательский опыт: Пользователи видят контент на предпочитаемом ими языке, что повышает удобство использования.
- Точность культуры: Правильно отформатированные даты, числа и валюты в соответствии с языковыми особенностями пользователя.
Эта конфигурация поддерживает не только контент, отображаемый на стороне сервера, но и может быть расширена для сценариев на стороне клиента с использованием библиотек JavaScript или вызовов API, возвращающих локализованный контент.
Часто встречающийся неправильный ответ
«Для поддержки нескольких языков в веб-приложении можно использовать перевод текста на стороне клиента, используя JavaScript или клиентскую библиотеку».
Почему это неправильно:
- Зависимость от клиентской стороны: Этот подход предполагает чрезмерно упрощённый метод, полагаясь исключительно на перевод на стороне клиента, что может привести к несоответствиям и не обрабатывает рендеринг на стороне сервера или форматирование данных (например, дат и чисел) должным образом.
- Игнорирование возможностей ASP.NET Core: Подход игнорирует встроенную поддержку локализации в ASP.NET Core, которая разработана для интеграции с серверной архитектурой, обеспечивая согласованное сохранение настроек локализации во всём приложении.
- Игнорирование доступности и SEO: Локализация на стороне сервера имеет решающее значение для доступности и поисковой оптимизации - областей, которые рендеринг на стороне клиента не может в полной мере учитывать.
Обычно эта ошибка возникает из-за недостаточного понимания инструментов и конфигураций, предоставляемых ASP.NET Core для обработки локализации и глобализации как на стороне клиента, так и на стороне сервера.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍3👎1
День 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
👍17
День 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
👍13
👍29👎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
👍3
День 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
👍15
Если вы уровня мидл+, сколько времени у вас занимает программирование?
Anonymous Poll
28%
Строго "с 9 до 5", в свободное время занимаюсь другим
13%
Работаю сверхурочно, если не успеваю
29%
Работа и иногда изучаю что-то новое
11%
Регулярно занимаюсь сторонними проектами "для души"
9%
Помимо работы заставляю себя заниматься, чтобы "не отстать" от коллег
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/
👍11
День 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/
👍3
День 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
👎6👍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
👍4👎3