День 1607. #BestPractices
Правильно Используем HttpClient. Окончание
Начало
Замена именованных клиентов типизированными
Недостатком использования именованных клиентов является необходимость разрешать HttpClient, каждый раз передавая имя. Добиться того же поведения можно через типизированный клиент, вызвав AddClient<TClient>(), где TClient – сервис, в который будет внедряться HttpClient.
Замечание: «Под капотом» всё равно используется именованный клиент, имя которого совпадает с именем типа. Также это зарегистрирует MyService с временем жизни transient.
Поскольку типизированный клиент является transient-сервисом, внедрение его в singleton-сервис приведёт к его кэшированию на время существования singleton-сервиса, что помешает типизированному клиенту реагировать на изменения DNS. Если вы хотите использовать типизированный клиент в singleton-сервисе, рекомендуется использовать SocketsHttpHandler в качестве основного обработчика и настроить свойство PooledConnectionLifetime. Также, т.к. теперь SocketsHttpHandler будет управлять пулом подключений, для него можно установить бесконечное время жизни:
Согласно рекомендациям Microsoft:
- Используйте статический или singleton-экземпляр HttpClient с настроенным PooledConnectionLifetime, так как это решает проблемы как исчерпания портов, так и отслеживания изменений DNS.
- Используйте IHttpClientFactory, если вы хотите переместить конфигурацию в одно место или использовать несколько разных клиентов, настроенных для разных вариантов использования. Но помните, что клиенты должны быть недолговечными, и после создания клиента фабрика больше не может управлять им.
- Используйте типизированный клиент, если вам нужна возможность настройки IHttpClientFactory.
Источник: https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet
Правильно Используем HttpClient. Окончание
Начало
Замена именованных клиентов типизированными
Недостатком использования именованных клиентов является необходимость разрешать HttpClient, каждый раз передавая имя. Добиться того же поведения можно через типизированный клиент, вызвав AddClient<TClient>(), где TClient – сервис, в который будет внедряться HttpClient.
Замечание: «Под капотом» всё равно используется именованный клиент, имя которого совпадает с именем типа. Также это зарегистрирует MyService с временем жизни transient.
services.AddHttpClient<MyService>(В MyService внедряем HttpClient, а не фабрику:
(c) =>
{
c.BaseAddress =
new Uri("https://my.api.com");
}
);
public class MyServiceИзбегайте типизированных клиентов в синглтонах
{
private HttpClient client;
public MyService(HttpClient client)
{
_client = client;
}
public async Task<string> GetAsync()
{
return await
client.GetFromJsonAsync(…);
}
}
Поскольку типизированный клиент является transient-сервисом, внедрение его в singleton-сервис приведёт к его кэшированию на время существования singleton-сервиса, что помешает типизированному клиенту реагировать на изменения DNS. Если вы хотите использовать типизированный клиент в singleton-сервисе, рекомендуется использовать SocketsHttpHandler в качестве основного обработчика и настроить свойство PooledConnectionLifetime. Также, т.к. теперь SocketsHttpHandler будет управлять пулом подключений, для него можно установить бесконечное время жизни:
services.AddHttpClient<MyService>(Какой вариант использовать?
(c) => { … }
)
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new SocketsHttpHandler()
{
PooledConnectionLifetime
= TimeSpan.FromMinutes(15)
};
})
.SetHandlerLifetime(Timeout.InfiniteTimeSpan);
Согласно рекомендациям Microsoft:
- Используйте статический или singleton-экземпляр HttpClient с настроенным PooledConnectionLifetime, так как это решает проблемы как исчерпания портов, так и отслеживания изменений DNS.
- Используйте IHttpClientFactory, если вы хотите переместить конфигурацию в одно место или использовать несколько разных клиентов, настроенных для разных вариантов использования. Но помните, что клиенты должны быть недолговечными, и после создания клиента фабрика больше не может управлять им.
- Используйте типизированный клиент, если вам нужна возможность настройки IHttpClientFactory.
Источник: https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet
👍9
День 1733. #BestPractices #ProjectManagement
Принципы Бережливой Разработки ПО
Бережливая Разработка ПО (Lean Software Development) — это гибкая система управления проектами и разработки продуктов, основанная на принципах бережливого производства. Основное внимание уделяется обеспечению ценности для клиента путём оптимизации ресурсов, рабочих потоков и процессов. Ниже рассмотрим основные принципы бережливой разработки.
1. Устранение потерь
Эта концепция заимствована из мира бережливого производства, где она известна как «муда» (от японского бесполезность, расточительность). В разработке ПО потерями может быть что угодно: от написания ненужного кода до чрезмерных совещаний, которые не приносят никакой пользы. Цель состоит в том, чтобы оптимизировать рабочий процесс, выявляя и удаляя всё, что не помогает конечному продукту или не удовлетворяет потребностям клиента.
2. Усиленное обучение
Обучение является неотъемлемой частью разработки. Принцип усиленного обучения подчёркивает, что команда всегда должна находиться в состоянии непрерывного обучения. Будь то проверка кода, обратная связь или изучение новых материалов, этот принцип предполагает, что более информированная команда производит продукт более высокого качества. Такие практики, как предметно-ориентированное проектирование (DDD), помогают команде сосредоточиться на изучении и правильном моделировании предметной области.
3. Принятие решения как можно позже
Слишком раннее принятие решений может привести к переработке, если эти решения окажутся неправильными. Этот принцип советует отложить принятие решения до последнего ответственного момента. Это позволит команде получить максимальное количество информации и контекста перед принятием решения, тем самым снижая вероятность дорогостоящих ошибок.
4. Максимально быстрая поставка
Скорость и эффективность являются ключевыми факторами в бережливой разработке программного обеспечения. Этот принцип направлен на максимально быструю поставку функционального продукта покупателю. Речь идет не о спешке, а о поиске оптимального потока, который позволит выполнить быструю поставку без ущерба для качества. Важными показателями, которые команды могут отслеживать, чтобы определить скорость поставки готовых продуктов, являются
- время цикла (cycle time) - время, которое нужно команде, чтобы создать продукт,
- время поставки (lead time) – время между выставлением заказа клиентом и исполнением заказа.
5. Расширение возможностей команды
В рамках бережливой разработки ПО мотивированная и самостоятельная команда считается более эффективной и гибкой. Расширение прав и возможностей команды предполагает предоставление им автономии в принятии решений и ответственности за выполнение своих задач. Это создаёт чувство ответственности среди членов команды, повышая их производительность и продуктивность.
6. Обеспечение целостности
Качество не должно быть второстепенным вопросом; оно должно быть интегрировано в продукт с самого начала. Обеспечение целостности означает создание надёжной, удобной в обслуживании и адаптируемой системы с самого начала. Это требует стремления к совершенству от каждого члена команды на каждом этапе процесса разработки.
7. Оптимизация всего
Принципы бережливого производства подчеркивают важность рассмотрения процесса разработки как единого целого. Вместо того, чтобы сосредотачиваться исключительно на отдельных задачах или модулях, важно понять, как каждый элемент вписывается в общую картину. Оптимизируя всю систему, а не её части, вы можете обеспечить максимальную эффективность всего процесса.
Помните: «система, порождающая дефекты, является дефектной системой» - Джеффри Палермо. Обеспечьте качество всего процесса и выявляйте проблемы до того, как они покинут процесс.
Источник: https://ardalis.com/principles-lean-software-development/
Принципы Бережливой Разработки ПО
Бережливая Разработка ПО (Lean Software Development) — это гибкая система управления проектами и разработки продуктов, основанная на принципах бережливого производства. Основное внимание уделяется обеспечению ценности для клиента путём оптимизации ресурсов, рабочих потоков и процессов. Ниже рассмотрим основные принципы бережливой разработки.
1. Устранение потерь
Эта концепция заимствована из мира бережливого производства, где она известна как «муда» (от японского бесполезность, расточительность). В разработке ПО потерями может быть что угодно: от написания ненужного кода до чрезмерных совещаний, которые не приносят никакой пользы. Цель состоит в том, чтобы оптимизировать рабочий процесс, выявляя и удаляя всё, что не помогает конечному продукту или не удовлетворяет потребностям клиента.
2. Усиленное обучение
Обучение является неотъемлемой частью разработки. Принцип усиленного обучения подчёркивает, что команда всегда должна находиться в состоянии непрерывного обучения. Будь то проверка кода, обратная связь или изучение новых материалов, этот принцип предполагает, что более информированная команда производит продукт более высокого качества. Такие практики, как предметно-ориентированное проектирование (DDD), помогают команде сосредоточиться на изучении и правильном моделировании предметной области.
3. Принятие решения как можно позже
Слишком раннее принятие решений может привести к переработке, если эти решения окажутся неправильными. Этот принцип советует отложить принятие решения до последнего ответственного момента. Это позволит команде получить максимальное количество информации и контекста перед принятием решения, тем самым снижая вероятность дорогостоящих ошибок.
4. Максимально быстрая поставка
Скорость и эффективность являются ключевыми факторами в бережливой разработке программного обеспечения. Этот принцип направлен на максимально быструю поставку функционального продукта покупателю. Речь идет не о спешке, а о поиске оптимального потока, который позволит выполнить быструю поставку без ущерба для качества. Важными показателями, которые команды могут отслеживать, чтобы определить скорость поставки готовых продуктов, являются
- время цикла (cycle time) - время, которое нужно команде, чтобы создать продукт,
- время поставки (lead time) – время между выставлением заказа клиентом и исполнением заказа.
5. Расширение возможностей команды
В рамках бережливой разработки ПО мотивированная и самостоятельная команда считается более эффективной и гибкой. Расширение прав и возможностей команды предполагает предоставление им автономии в принятии решений и ответственности за выполнение своих задач. Это создаёт чувство ответственности среди членов команды, повышая их производительность и продуктивность.
6. Обеспечение целостности
Качество не должно быть второстепенным вопросом; оно должно быть интегрировано в продукт с самого начала. Обеспечение целостности означает создание надёжной, удобной в обслуживании и адаптируемой системы с самого начала. Это требует стремления к совершенству от каждого члена команды на каждом этапе процесса разработки.
7. Оптимизация всего
Принципы бережливого производства подчеркивают важность рассмотрения процесса разработки как единого целого. Вместо того, чтобы сосредотачиваться исключительно на отдельных задачах или модулях, важно понять, как каждый элемент вписывается в общую картину. Оптимизируя всю систему, а не её части, вы можете обеспечить максимальную эффективность всего процесса.
Помните: «система, порождающая дефекты, является дефектной системой» - Джеффри Палермо. Обеспечьте качество всего процесса и выявляйте проблемы до того, как они покинут процесс.
Источник: https://ardalis.com/principles-lean-software-development/
👍11
День 1739. #BestPractices #ProjectManagement
Раздувание Процессов: Тихий Убийца Продуктивности Разработчиков
На начальных стадиях проекта разработки команды отличаются гибкостью, быстрым принятием решений и стремлением предоставлять ценные функции. Однако по мере того, как проекты усложняются и масштабируются, многие из них становятся жертвами коварного антипаттерна: раздувания процессов.
Факторов, приводящих к этому, множество:
1. Организационная культура.
Слишком осторожная организация может создать несколько уровней бюрократии, предполагая, что чем больше формализованы процессы тем меньше риск.
2. Недостаток доверия.
Руководство, которому не хватает уверенности в возможностях разработчиков, может навязать несколько уровней утверждения и документацию.
3. Сложность масштаба.
Расширение проектов часто влечёт увеличение числа заинтересованных сторон, каждая из которых добавляет свой уровень сложности и свои процессы.
4. Устаревший багаж.
Иногда ненужные процессы задерживаются просто потому, что «так было всегда».
Последствия
1. Снижение производительности.
Разработчики часто тратят больше времени на административную работу, чем на фактическую разработку.
2. Утечка инноваций.
Бюрократия может подавить творчество и ограничить эксперименты.
3. Задержка вывода продукта на рынок.
Сложные процессы удлиняют циклы разработки.
4. Снижение морального духа.
Потеря гибкости и рутина процессов могут подорвать моральный дух команды.
Примеры раздувания процессов
1. Чрезмерные проверки кода.
Обязательное проведение нескольких уровней проверок даже для тривиальных изменений может серьёзно замедлить цикл разработки.
2. Слишком сложные системы заявок.
Сложные системы тикетов, требующие заполнения множества полей ещё до того, как задача будет одобрена, могут занять столько же времени, сколько и исполнение задачи.
3. Обязательные отчеты.
Требование подробных отчетов с описанием каждой потраченной минуты может отнять время и отвлечь внимание от фактического кодирования.
4. Чрезмерное количество совещаний
Борьба с раздуванием процессов
1. Регулярные аудиты.
Последовательно анализируйте существующие процессы для оценки их актуальности и эффективности. Это следует делать в рамках регулярных командных (и организационных) ретроспектив. Но убедитесь, что такие аудиты полезны, а не усугубляют проблему раздувания процессов!
2. Принципы бережливости и гибкости.
Примите методологии, направленные на получение максимальной отдачи при минимальных затратах на процессы. Многие agile-практики, подчёркивают важность обеспечения быстрого прохождения процесса с минимальными церемониями.
3. Поощряйте доверие и автономию.
Дайте разработчикам полномочия принимать решения без ненужных бюрократических одобрений. Ваша команда не сможет заслужить ваше доверие, если вы как менеджер первый не доверитесь ей.
4. Минимально жизнеспособный процесс.
Внедряйте только те процессы, которые абсолютно необходимы для поддержания качества и контроля. Если сомневаетесь, выбросьте. Если есть возможность сократить процессы и повысить производительность, поэкспериментируйте с этим и посмотрите, сработает ли это для вашей команды и организации.
Итого
Раздувание процессов — это тихий, но смертоносный фактор, подрывающий продуктивность разработки ПО. Распознав его симптомы и приняв упреждающие меры, команды смогут вернуть себе гибкость и дух творчества, а проекты вернуть на путь эффективности и инноваций.
Источник: https://ardalis.com/process-bloat-silent-killer-developer-productivity/
Раздувание Процессов: Тихий Убийца Продуктивности Разработчиков
На начальных стадиях проекта разработки команды отличаются гибкостью, быстрым принятием решений и стремлением предоставлять ценные функции. Однако по мере того, как проекты усложняются и масштабируются, многие из них становятся жертвами коварного антипаттерна: раздувания процессов.
Факторов, приводящих к этому, множество:
1. Организационная культура.
Слишком осторожная организация может создать несколько уровней бюрократии, предполагая, что чем больше формализованы процессы тем меньше риск.
2. Недостаток доверия.
Руководство, которому не хватает уверенности в возможностях разработчиков, может навязать несколько уровней утверждения и документацию.
3. Сложность масштаба.
Расширение проектов часто влечёт увеличение числа заинтересованных сторон, каждая из которых добавляет свой уровень сложности и свои процессы.
4. Устаревший багаж.
Иногда ненужные процессы задерживаются просто потому, что «так было всегда».
Последствия
1. Снижение производительности.
Разработчики часто тратят больше времени на административную работу, чем на фактическую разработку.
2. Утечка инноваций.
Бюрократия может подавить творчество и ограничить эксперименты.
3. Задержка вывода продукта на рынок.
Сложные процессы удлиняют циклы разработки.
4. Снижение морального духа.
Потеря гибкости и рутина процессов могут подорвать моральный дух команды.
Примеры раздувания процессов
1. Чрезмерные проверки кода.
Обязательное проведение нескольких уровней проверок даже для тривиальных изменений может серьёзно замедлить цикл разработки.
2. Слишком сложные системы заявок.
Сложные системы тикетов, требующие заполнения множества полей ещё до того, как задача будет одобрена, могут занять столько же времени, сколько и исполнение задачи.
3. Обязательные отчеты.
Требование подробных отчетов с описанием каждой потраченной минуты может отнять время и отвлечь внимание от фактического кодирования.
4. Чрезмерное количество совещаний
Борьба с раздуванием процессов
1. Регулярные аудиты.
Последовательно анализируйте существующие процессы для оценки их актуальности и эффективности. Это следует делать в рамках регулярных командных (и организационных) ретроспектив. Но убедитесь, что такие аудиты полезны, а не усугубляют проблему раздувания процессов!
2. Принципы бережливости и гибкости.
Примите методологии, направленные на получение максимальной отдачи при минимальных затратах на процессы. Многие agile-практики, подчёркивают важность обеспечения быстрого прохождения процесса с минимальными церемониями.
3. Поощряйте доверие и автономию.
Дайте разработчикам полномочия принимать решения без ненужных бюрократических одобрений. Ваша команда не сможет заслужить ваше доверие, если вы как менеджер первый не доверитесь ей.
4. Минимально жизнеспособный процесс.
Внедряйте только те процессы, которые абсолютно необходимы для поддержания качества и контроля. Если сомневаетесь, выбросьте. Если есть возможность сократить процессы и повысить производительность, поэкспериментируйте с этим и посмотрите, сработает ли это для вашей команды и организации.
Итого
Раздувание процессов — это тихий, но смертоносный фактор, подрывающий продуктивность разработки ПО. Распознав его симптомы и приняв упреждающие меры, команды смогут вернуть себе гибкость и дух творчества, а проекты вернуть на путь эффективности и инноваций.
Источник: https://ardalis.com/process-bloat-silent-killer-developer-productivity/
👍7
Что говорит enum с именем во множественном числе и атрибутом Flags о своих значениях?
#Quiz #BestPractices
#Quiz #BestPractices
Anonymous Quiz
75%
Значения могут комбинироваться как значения битового поля
8%
Значения должны быть степенью двойки
9%
Значения должны обозначать сущности во множественном числе
7%
Значения представляют взаимоисключающие варианты
👍10👎3
День 1867. #BestPractices
Избегайте Нескольких Булевых Параметров
Булевы параметры хороши, но сложно отследить, что делает каждый из них, если их несколько. Сегодня посмотрим, почему лучше избегать использования нескольких булевых параметров и как это отрефакторить.
Почему это плохо?
Посмотрим на следующий метод:
Это пример из библиотеки компонентов ImageListView. Проблема здесь в том, что два логических параметра обозначают четыре разные комбинации значений:
И в некоторой степени вы ожидаете четырёх разных вариантов поведения. Но в реализации это не так:
Разрешены только определённые комбинации. Кроме того, «сила» и «ленивость» кажутся в этом контексте противоречивыми. Трудно запомнить, что делает каждая комбинация. Можно сказать, что это в некоторой степени нарушает «принцип единой ответственности», поскольку метод выполняет несколько задач.
Другой частый пример: есть уже существующий метод, и какой-то новый метод должен расширить/изменить его поведение. Для простоты предположим, что нужна сортировка. Самый простой способ — добавить булев параметр:
Проблема здесь – понять, что происходит. И чем больше параметров, тем больше комбинаций и тем сложнее понять метод.
Рефакторинг
1. Сделать каждую комбинацию отдельным методом
Так все варианты очевидны, и вы можете использовать более выразительное имя метода. Из примера выше:
Теперь ясно, что недопустимо использовать оба параметра сразу. При этом мы возлагаем на вызывающую сторону ответственность за решение, какой метод вызывать. Клиент знает, что он хочет сделать, и может выразить это более чётко. Внутри эти методы, безусловно, могут совместно использовать большую часть кода. Кроме того, если нужно изменить поведение одного из методов, это гораздо проще сделать, поскольку между ними меньше связи.
Замечание: надо различать общедоступный API и закрытые методы. Можно иметь несколько булевых параметров в закрытых методах, но надо стараться избегать их в публичных API. Публичный API - интерфейс с внешним миром и должен быть максимально понятным.
2. Использовать перечисления с возможными вариантами
Хотя здесь показаны все возможные варианты, это не так ясно, как предыдущий подход. Все ещё возможно, что метод делает слишком много. Здесь всегда компромисс между слишком большим количеством параметров и слишком большим количеством методов.
Источник: https://steven-giesel.com/blogPost/9994b00c-8bc2-4794-ae74-80e6ee4cd5e5/avoid-multiple-boolean-parameters
Избегайте Нескольких Булевых Параметров
Булевы параметры хороши, но сложно отследить, что делает каждый из них, если их несколько. Сегодня посмотрим, почему лучше избегать использования нескольких булевых параметров и как это отрефакторить.
Почему это плохо?
Посмотрим на следующий метод:
/// <summary>
/// Refreshes the control.
/// </summary>
/// <param name="force">Forces a refresh even if the renderer is suspended.</param>
/// <param name="lazy">Refreshes the control only if a set amount of time
/// has passed since the last refresh.</param>
void Refresh(bool force, bool lazy);
Это пример из библиотеки компонентов ImageListView. Проблема здесь в том, что два логических параметра обозначают четыре разные комбинации значений:
Refresh(true, true);
Refresh(true, false);
Refresh(false, true);
Refresh(false, false);
И в некоторой степени вы ожидаете четырёх разных вариантов поведения. Но в реализации это не так:
internal void Refresh(bool force, bool lazy)
{
if (force)
base.Refresh();
else if (lazy)
{
rendererNeedsPaint = true;
lazyRefreshTimer.Start();
}
else if (CanPaint())
base.Refresh();
else
rendererNeedsPaint = true;
}
Разрешены только определённые комбинации. Кроме того, «сила» и «ленивость» кажутся в этом контексте противоречивыми. Трудно запомнить, что делает каждая комбинация. Можно сказать, что это в некоторой степени нарушает «принцип единой ответственности», поскольку метод выполняет несколько задач.
Другой частый пример: есть уже существующий метод, и какой-то новый метод должен расширить/изменить его поведение. Для простоты предположим, что нужна сортировка. Самый простой способ — добавить булев параметр:
IEnumerable<Item> GetItems(Filter f);
IEnumerable <Item> GetItems(Filter f, bool sort);
// или ещё хуже:
IEnumerable <Item> GetItems(Filter f, bool sort, bool descending);
Проблема здесь – понять, что происходит. И чем больше параметров, тем больше комбинаций и тем сложнее понять метод.
Рефакторинг
1. Сделать каждую комбинацию отдельным методом
Так все варианты очевидны, и вы можете использовать более выразительное имя метода. Из примера выше:
void Refresh();
void RefreshForce();
void RefreshLazy();
Теперь ясно, что недопустимо использовать оба параметра сразу. При этом мы возлагаем на вызывающую сторону ответственность за решение, какой метод вызывать. Клиент знает, что он хочет сделать, и может выразить это более чётко. Внутри эти методы, безусловно, могут совместно использовать большую часть кода. Кроме того, если нужно изменить поведение одного из методов, это гораздо проще сделать, поскольку между ними меньше связи.
Замечание: надо различать общедоступный API и закрытые методы. Можно иметь несколько булевых параметров в закрытых методах, но надо стараться избегать их в публичных API. Публичный API - интерфейс с внешним миром и должен быть максимально понятным.
2. Использовать перечисления с возможными вариантами
enum RefreshMode { Default, Force, Lazy }
void Refresh(RefreshMode mode);
Хотя здесь показаны все возможные варианты, это не так ясно, как предыдущий подход. Все ещё возможно, что метод делает слишком много. Здесь всегда компромисс между слишком большим количеством параметров и слишком большим количеством методов.
Источник: https://steven-giesel.com/blogPost/9994b00c-8bc2-4794-ae74-80e6ee4cd5e5/avoid-multiple-boolean-parameters
👍20
Где вы должны размещать определения переменных метода согласно принципу близости (principle of proximity)?
#Quiz #BestPractices
#Quiz #BestPractices
Anonymous Quiz
13%
Общей группой в начале метода
18%
Общей группой в начале их области видимости
4%
Группами по типу переменных
65%
Как можно ближе к месту использования
Как бы вы реализовали класс Calculator таким образом, чтобы впоследствии можно было бы добавлять другие операции по желанию?
#Quiz #BestPractices
#Quiz #BestPractices
Anonymous Quiz
17%
Передавать операции в метод Compute как выражения или делегаты
12%
Сделать класс Calculator абстрактным и наследовать классы с нужным набором операций от него
50%
Использовать паттерн Команда для инкапсуляции операций как команд
4%
Определить дополнительные операции в новом классе и внедрить его в класс Calculator
16%
Использовать паттерн Декоратор для добавления новой функциональности
👍19👎2
Какое свойство демонстрирует класс или метод, чей код тесно связан с единственной, хорошо определённой задачей?
#Quiz #BestPractices
#Quiz #BestPractices
Anonymous Quiz
25%
Сильная связанность (Tight coupling)
18%
Низкая изменчивость (Low variability)
13%
Слабая связанность (Loose coupling)
43%
Высокая связность (High cohesion)
👎22👍11
День 1947. #ЗаметкиНаПолях #BestPractices
Правильное Логирование Минимальных API в Serilog. Начало
В этой серии рассмотрим, как с максимальной пользой использовать Serilog в приложениях минимальных API ASP.NET Core 8. Серия будет состоять из 3х частей.
1. Настройка
Приложения ASP.NET Core — «всего лишь» консольные приложения. Вы можете настроить Serilog и использовать его вообще без каких-либо особенностей ASP.NET Core. Для «пустого» проекта «минимального API» файл Program.cs будет выглядеть так:
Установим Serilog и консольный приёмник (sink):
В начале Program.cs создадим пайплайн логирования и назначим его статическому свойству Log.Logger:
Теперь при запуске должно появиться сообщение «Starting up» от Serilog, а затем вывод по умолчанию от ASP.NET.
Если приложение не запускается, мы хотим перехватить все возникающие исключения, а также убедиться, что все события буферизованного журнала записаны перед завершением процесса. Добавим try/catch/finally:
Здесь мы можем использовать класс Log для записи собственных структурированных событий журнала.
Возможно, сейчас у вас возникнет соблазн добавить ещё несколько приёмников для журнала. Не торопитесь, обсудим это в следующем разделе.
Продолжение следует…
Источник: https://nblumhardt.com/2024/04/serilog-net8-0-minimal/
Правильное Логирование Минимальных API в Serilog. Начало
В этой серии рассмотрим, как с максимальной пользой использовать Serilog в приложениях минимальных API ASP.NET Core 8. Серия будет состоять из 3х частей.
1. Настройка
Приложения ASP.NET Core — «всего лишь» консольные приложения. Вы можете настроить Serilog и использовать его вообще без каких-либо особенностей ASP.NET Core. Для «пустого» проекта «минимального API» файл Program.cs будет выглядеть так:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Установим Serilog и консольный приёмник (sink):
dotnet add package Serilog
dotnet add package Serilog.Sinks.Console
В начале Program.cs создадим пайплайн логирования и назначим его статическому свойству Log.Logger:
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
Log.Information("Starting up");
// … остальной код минимального API
Теперь при запуске должно появиться сообщение «Starting up» от Serilog, а затем вывод по умолчанию от ASP.NET.
Если приложение не запускается, мы хотим перехватить все возникающие исключения, а также убедиться, что все события буферизованного журнала записаны перед завершением процесса. Добавим try/catch/finally:
using Serilog;
// … пайплайн логирования
try
{
// … код минимального API
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Unhandled exception");
return 1;
}
finally
{
await Log.CloseAndFlushAsync();
}
Здесь мы можем использовать класс Log для записи собственных структурированных событий журнала.
Возможно, сейчас у вас возникнет соблазн добавить ещё несколько приёмников для журнала. Не торопитесь, обсудим это в следующем разделе.
Продолжение следует…
Источник: https://nblumhardt.com/2024/04/serilog-net8-0-minimal/
👍5
День 1948. #ЗаметкиНаПолях #BestPractices
Правильное Логирование Минимальных API в Serilog. Продолжение
1. Настройка
2. Связываем ASP.NET Core и ILogger<T>
Это очень просто. Установим Serilog.Extensions.Hosting:
И вызовем AddSerilog():
Теперь логи приложения будут писаться в Serilog.
Если вы хотите записывать события в логи, нужно настроить место назначения: путь к файлу или URL сервера логов.
Для примера используем Seq:
Добавим его в пайплайн.
Вариант 1 – в коде, используя переменные среды:
Чтобы установить контейнер Seq, работающий по адресу http://localhost:5341, выполните:
Теперь после запуска приложения, можете перейти по адресу http://localhost:5341 в браузере и увидеть логи приложения.
Этот вариант удобен, т.к. компилятор проверит, предоставлены ли все необходимые параметры, и всё, что не изменяется во время развёртывания, может быть указано в строго типизированном C#. Он также надёжно работает при публикации приложения одним файлом.
Вариант 2 — использовать Serilog.Settings.Configuration для загрузки из appsettings.json.
Конфигурация доступна не сразу, т.е. мы не сможем отслеживать исключения, возникающие на ранних этапах запуска. Совет — не усложнять себе жизнь, упростив Program.cs до чего-то вроде:
appsettings.json будет выглядеть примерно так (Seq можно заменить другим хранилищем):
Подробнее о синтаксисе конфигурации см. здесь.
Для правильной настройки конфигурации JSON может потребоваться немного больше работы, она более хрупкая и требует немного больше тестирования.
Окончание следует…
Источник: https://nblumhardt.com/2024/04/serilog-net8-0-minimal/
Правильное Логирование Минимальных API в Serilog. Продолжение
1. Настройка
2. Связываем ASP.NET Core и ILogger<T>
Это очень просто. Установим Serilog.Extensions.Hosting:
dotnet add package Serilog.Extensions.Hosting
И вызовем AddSerilog():
…
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSerilog();
…
Теперь логи приложения будут писаться в Serilog.
Если вы хотите записывать события в логи, нужно настроить место назначения: путь к файлу или URL сервера логов.
Для примера используем Seq:
dotnet add package Serilog.Sinks.Seq
Добавим его в пайплайн.
Вариант 1 – в коде, используя переменные среды:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.Seq(
Environment.GetEnvironmentVariable("SEQ_URL")
?? "http://localhost:5341",
apiKey:
Environment.GetEnvironmentVariable("SEQ_API_KEY"))
.CreateLogger();
Чтобы установить контейнер Seq, работающий по адресу http://localhost:5341, выполните:
docker run --rm -it -e ACCEPT_EULA=y -p 5341:80 datalust/seq
Теперь после запуска приложения, можете перейти по адресу http://localhost:5341 в браузере и увидеть логи приложения.
Этот вариант удобен, т.к. компилятор проверит, предоставлены ли все необходимые параметры, и всё, что не изменяется во время развёртывания, может быть указано в строго типизированном C#. Он также надёжно работает при публикации приложения одним файлом.
Вариант 2 — использовать Serilog.Settings.Configuration для загрузки из appsettings.json.
powershell
dotnet add package Serilog.Settings.Configuration
Конфигурация доступна не сразу, т.е. мы не сможем отслеживать исключения, возникающие на ранних этапах запуска. Совет — не усложнять себе жизнь, упростив Program.cs до чего-то вроде:
using Serilog;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSerilog(lc => lc
.WriteTo.Console()
.ReadFrom.Configuration(builder.Configuration));
var app = builder.Build();
…
appsettings.json будет выглядеть примерно так (Seq можно заменить другим хранилищем):
{
"Serilog": {
"Using": ["Serilog.Sinks.Seq"],
"WriteTo": [
{
"Name": "Seq",
"Args": {
"serverUrl": "http://localhost:5341",
"apiKey": "<API key here>"
}
}
]
},
"AllowedHosts": "*"
}
Подробнее о синтаксисе конфигурации см. здесь.
Для правильной настройки конфигурации JSON может потребоваться немного больше работы, она более хрупкая и требует немного больше тестирования.
Окончание следует…
Источник: https://nblumhardt.com/2024/04/serilog-net8-0-minimal/
👍16
День 1949. #ЗаметкиНаПолях #BestPractices
Правильное Логирование Минимальных API в Serilog. Окончание
1. Настройка
2. Связываем ASP.NET Core и ILogger<T>
3. Запись веб-запросов
Приложение записывает несколько событий в журнал при обработке каждого веб-запроса. Далее рассмотрим, как объединить эту информацию в одно красиво отформатированное событие.
Классический способ сделать это — установить Serilog.AspNetCore и добавить app.UseSerilogRequestLogging() в код запуска вашего веб-приложения сразу после builder.Build(). Но если вы настраиваете всё с нуля, в долгосрочной перспективе вы получите лучший опыт, полагаясь на встроенную поддержку активности (System.Diagnostics.Activity).
Активность - это операция с началом и концом. ASP.NET Core использует активность как обёртку вокруг каждого обрабатываемого веб-запроса. Т.к. активность завершается после выполнения всего промежуточного ПО, она даёт более точную картину продолжительности запроса и конечного кода состояния, чем может предоставить промежуточное ПО UseSerilogRequestLogging(). Также активности участвуют в распределённой трассировке, поэтому вы можете просматривать входящие и исходящие запросы вашего приложения в иерархии, если выбранный вами приёмник это поддерживает.
1) Установим SerilogTracing, поддержку форматирования вывода консоли и интеграцию с ASP.NET Core:
2) В Program.cs, добавим средство форматирования с поддержкой трассировки в приёмник консоли и снизим детализацию некоторых источников журналов Microsoft.AspNetCore.*:
Здесь мы использовали Enrich (хотя это не обязательно), чтобы добавить свойство Application ко всем событиям, поскольку это помогает отслеживать в логах операции среди нескольких сервисов.
3) Сразу после этого настроим прослушиватель, который будет записывать действия ASP.NET Core в конвейер Serilog:
SerilogTracing работает со всеми приёмниками Serilog, но на данный момент только приёмники Seq, SerilogTracing.Sinks.OpenTelemetry и SerilogTracing.Sinks.Zipkin были написаны или изменены для поддержки бэкендов с функциями иерархической трассировки.
Совет: если вы используете приемник без поддержки иерархической трассировки, добавьте
Источник: https://nblumhardt.com/2024/04/serilog-net8-0-minimal/
Правильное Логирование Минимальных API в Serilog. Окончание
1. Настройка
2. Связываем ASP.NET Core и ILogger<T>
3. Запись веб-запросов
Приложение записывает несколько событий в журнал при обработке каждого веб-запроса. Далее рассмотрим, как объединить эту информацию в одно красиво отформатированное событие.
Классический способ сделать это — установить Serilog.AspNetCore и добавить app.UseSerilogRequestLogging() в код запуска вашего веб-приложения сразу после builder.Build(). Но если вы настраиваете всё с нуля, в долгосрочной перспективе вы получите лучший опыт, полагаясь на встроенную поддержку активности (System.Diagnostics.Activity).
Активность - это операция с началом и концом. ASP.NET Core использует активность как обёртку вокруг каждого обрабатываемого веб-запроса. Т.к. активность завершается после выполнения всего промежуточного ПО, она даёт более точную картину продолжительности запроса и конечного кода состояния, чем может предоставить промежуточное ПО UseSerilogRequestLogging(). Также активности участвуют в распределённой трассировке, поэтому вы можете просматривать входящие и исходящие запросы вашего приложения в иерархии, если выбранный вами приёмник это поддерживает.
1) Установим SerilogTracing, поддержку форматирования вывода консоли и интеграцию с ASP.NET Core:
dotnet add package SerilogTracing
dotnet add package SerilogTracing.Expressions
dotnet add package SerilogTracing.Instrumentation.AspNetCore
2) В Program.cs, добавим средство форматирования с поддержкой трассировки в приёмник консоли и снизим детализацию некоторых источников журналов Microsoft.AspNetCore.*:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override(
"Microsoft.AspNetCore.Hosting",
LogEventLevel.Warning)
.MinimumLevel.Override(
"Microsoft.AspNetCore.Routing",
LogEventLevel.Warning)
.Enrich.WithProperty("Application", "MyApp")
.WriteTo.Console(
Formatters.CreateConsoleTextFormatter(
theme: TemplateTheme.Code))
.WriteTo.Seq(…)
.CreateLogger();
Здесь мы использовали Enrich (хотя это не обязательно), чтобы добавить свойство Application ко всем событиям, поскольку это помогает отслеживать в логах операции среди нескольких сервисов.
3) Сразу после этого настроим прослушиватель, который будет записывать действия ASP.NET Core в конвейер Serilog:
using var listener =
new ActivityListenerConfiguration()
.Instrument.AspNetCoreRequests()
.TraceToSharedLogger();
SerilogTracing работает со всеми приёмниками Serilog, но на данный момент только приёмники Seq, SerilogTracing.Sinks.OpenTelemetry и SerilogTracing.Sinks.Zipkin были написаны или изменены для поддержки бэкендов с функциями иерархической трассировки.
Совет: если вы используете приемник без поддержки иерархической трассировки, добавьте
Enrich.WithSpanTimingMilliseconds()
, чтобы добавить свойство Elapsed для событий завершения запроса.Источник: https://nblumhardt.com/2024/04/serilog-net8-0-minimal/
👍5
Все зависимости вашего класса определены как интерфейсы. Конкретные реализации интерфейсов (зависимости) внедряются в ваш класс через конструктор. С какими функциями (свойствами и методами) этих зависимостей может работать ваш класс?
#Quiz #BestPractices
#Quiz #BestPractices
Anonymous Quiz
31%
С функциями, определёнными в любом из интерфейсов, которые реализует внедрённая зависимость
13%
Со всеми функциями конкретного типа внедрённой зависимости
53%
Только с функциями интерфейса зависимости
3%
Только с функциями класса зависимости, но не с функциями, определёнными в интерфейсе
День 2234. #BestPractices
Разбирайте, а не Валидируйте
Во многих приложениях валидация используется для определения того, соответствует ли заданная структура данных или объект определённым требованиям. Однако она не изменяет (не должна изменять) рассматриваемый объект, т.е. любое изменение в дальнейшем может сделать валидацию недействительной. Напротив, разбор (парсинг) менее структурированного объекта и создание из него более структурированного — это односторонняя операция, которая приводит к более полезным структурам данных.
Валидация
Валидация — это метод, действующий в определённый момент времени, который обычно возвращает true или false (или вместе с false - список причин, по которым он вернул false). Обычно он не имеет и не должен иметь никаких побочных эффектов, таких как мутация проверяемого объекта. Если структура данных или объект передаются между процедурами в приложении, то система, скорее всего, не сможет предполагать только на основе типа, что объект остаётся валидным по мере перемещения из одного контекста в другой. Таким образом, вы часто будете сталкиваться с проверкой, происходящей в нескольких точках в приложении даже для одного и того же экземпляра переменной или структуры.
Неизменяемые типы, конечно, помогают и могут быть проверены только один раз, а затем подразумеваться валидными, но только если проверка происходит как часть их построения. То есть типы, которые способны обеспечивать инварианты дизайна как часть их построения и которые являются неизменяемыми, могут считаться в системе валидными везде, где они появляются.
Парсинг
Процесс преобразования менее ограниченных типов в более ограниченные типов (или выдачи исключения, если это невозможно сделать) называется парсингом. Он добавляет дополнительные ограничения и, таким образом, уменьшает общий диапазон возможных значений, которые может представлять результирующий тип. Например:
Входная строка может быть относительно короткой последовательностью цифр (возможно, с префиксом -). Если это что-то другое, это всё ещё валидная строка, но это не валидный int, т.е. Parse() завершится ошибкой с исключением. Если приложению требуется числовое значение для использования в определённых методах или функциях, гораздо лучше преобразовать входную строку в целочисленное значение и затем передать его, чем передавать строку везде и каждый раз проверять, может ли она представлять целое число.
Парсеры и эту практику можно использовать совместно с неизменяемыми объектами. Принимая менее структурированные примитивные данные и разбирая их в объекты-значения, ваше ПО будет менее подвержено ошибкам, и вам придётся отслеживать меньше переменных в своей голове.
DateTime как пример
Представьте, что DateTime не существует, а приложению нужен способ представления значений даты и времени с точностью до секунды. Вы можете передать строку, которую нужно будет разобрать везде, где она используется как значение даты и/или времени. Очевидно, что в идеале вы должны выполнить операцию парсинга один раз, после чего у вас будет нестроковый тип, представляющий значение даты и времени.
Альтернативно, у вас могут быть методы со списками аргументов, такими как (int year, int month, int day, int hour, int minute, int second). Шесть целочисленных значений, каждое с отдельными допустимыми диапазонами. Можно выполнять проверку этих 6 значений в таком методе, прежде чем приступить к его фактической логике. Такая массированная проверка имеет тенденцию загромождать код и скрывать реальную работу, а также часто пропускать проверку некоторых входных данных в некоторых контекстах.
Прелесть типа DateTime в том, что разработчики могут быть уверены, что он всегда валиден. В этом смысл парсинга — создать более ограниченный тип более высокого уровня, который не требует проверки, поскольку он не может быть невалидным. Использование правильных типов вместо одержимости примитивами упростит написание правильных методов.
Источник: https://deviq.com/practices/parse-dont-validate
Разбирайте, а не Валидируйте
Во многих приложениях валидация используется для определения того, соответствует ли заданная структура данных или объект определённым требованиям. Однако она не изменяет (не должна изменять) рассматриваемый объект, т.е. любое изменение в дальнейшем может сделать валидацию недействительной. Напротив, разбор (парсинг) менее структурированного объекта и создание из него более структурированного — это односторонняя операция, которая приводит к более полезным структурам данных.
Валидация
Валидация — это метод, действующий в определённый момент времени, который обычно возвращает true или false (или вместе с false - список причин, по которым он вернул false). Обычно он не имеет и не должен иметь никаких побочных эффектов, таких как мутация проверяемого объекта. Если структура данных или объект передаются между процедурами в приложении, то система, скорее всего, не сможет предполагать только на основе типа, что объект остаётся валидным по мере перемещения из одного контекста в другой. Таким образом, вы часто будете сталкиваться с проверкой, происходящей в нескольких точках в приложении даже для одного и того же экземпляра переменной или структуры.
Неизменяемые типы, конечно, помогают и могут быть проверены только один раз, а затем подразумеваться валидными, но только если проверка происходит как часть их построения. То есть типы, которые способны обеспечивать инварианты дизайна как часть их построения и которые являются неизменяемыми, могут считаться в системе валидными везде, где они появляются.
Парсинг
Процесс преобразования менее ограниченных типов в более ограниченные типов (или выдачи исключения, если это невозможно сделать) называется парсингом. Он добавляет дополнительные ограничения и, таким образом, уменьшает общий диапазон возможных значений, которые может представлять результирующий тип. Например:
int.Parse(string input);
Входная строка может быть относительно короткой последовательностью цифр (возможно, с префиксом -). Если это что-то другое, это всё ещё валидная строка, но это не валидный int, т.е. Parse() завершится ошибкой с исключением. Если приложению требуется числовое значение для использования в определённых методах или функциях, гораздо лучше преобразовать входную строку в целочисленное значение и затем передать его, чем передавать строку везде и каждый раз проверять, может ли она представлять целое число.
Парсеры и эту практику можно использовать совместно с неизменяемыми объектами. Принимая менее структурированные примитивные данные и разбирая их в объекты-значения, ваше ПО будет менее подвержено ошибкам, и вам придётся отслеживать меньше переменных в своей голове.
DateTime как пример
Представьте, что DateTime не существует, а приложению нужен способ представления значений даты и времени с точностью до секунды. Вы можете передать строку, которую нужно будет разобрать везде, где она используется как значение даты и/или времени. Очевидно, что в идеале вы должны выполнить операцию парсинга один раз, после чего у вас будет нестроковый тип, представляющий значение даты и времени.
Альтернативно, у вас могут быть методы со списками аргументов, такими как (int year, int month, int day, int hour, int minute, int second). Шесть целочисленных значений, каждое с отдельными допустимыми диапазонами. Можно выполнять проверку этих 6 значений в таком методе, прежде чем приступить к его фактической логике. Такая массированная проверка имеет тенденцию загромождать код и скрывать реальную работу, а также часто пропускать проверку некоторых входных данных в некоторых контекстах.
Прелесть типа DateTime в том, что разработчики могут быть уверены, что он всегда валиден. В этом смысл парсинга — создать более ограниченный тип более высокого уровня, который не требует проверки, поскольку он не может быть невалидным. Использование правильных типов вместо одержимости примитивами упростит написание правильных методов.
Источник: https://deviq.com/practices/parse-dont-validate
👍21
День 2248. #BestPractices
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Начало
Как разработчики, мы часто работаем параллельно, создавая ветки для новых функций, исправляя ошибки и внося обновления. Но когда приходит время внести эти изменения в основную кодовую базу, пулл-реквесты (PR) становятся мостом между изолированной разработкой и совместной работой в команде. Каждого разочаровывает, когда PR отклоняют или отправляют на доработку. Легко можно потратить часы на функцию, а потом понять, что твоя реализация не соответствует видению команды. Однако со временем мы узнаём, что эффективные PR касаются не только самого кода. Они и про то, как мы сообщаем о наших изменениях. Рассмотрим, как создавать пулл-реквесты, которые делают процесс обзора более плавным, быстрым и эффективным для всех участников.
1. Начните с информативного заголовка
Первое впечатление имеет значение даже в мире кода. Заголовок пулл-реквеста — это наш шанс немедленно донести суть изменения. Думайте о нём как о заголовке статьи; он должен быть коротким, понятным и информативным. Вместо:
"Обновил код"
"Исправил баг"
"Изменения за вчера"
Используйте более описательные заголовки, например:
feat: Добавил OAuth2 аутентификацию для конечных точек API
fix: Устранил состояния гонки при обработке сеанса пользователя
refactor: Оптимизированы запросы к БД при поиске пользователя
Хорошо составленный заголовок помогает рецензентам понять изменение, не открывая PR. Он задает тон всему процессу обзора кода.
2. Установите контекст (не предполагайте, что все знают проблему)
Прежде чем погрузиться в код, важно предоставить контекст. Не все могут быть знакомы с конкретной проблемой, которую мы решаем, и важно объяснить, почему произошли изменения. Чёткое описание PR упрощает и ускоряет рецензирование. Вот шаблон для хорошо структурированного описания PR:
Это гарантирует, что рецензенты поймут проблему, выбранный подход и то, как проверить решение. PR без контекста может существенно замедлить процесс, поэтому всегда включайте достаточно информации, чтобы команда могла понять ваши изменения.
3. Сохраняйте PR сфокусированным
Нас всех подбивает решить сразу несколько проблем. Но это часто приводит к слишком большим PR, которые могут обескуражить рецензентов. Вместо этого пытайтесь разбить работу на более мелкие, целенаправленные PR. Каждый PR должен решать определённую задачу. Например, если мы создаём систему управления пользователями, можно разбить её на более мелкие задачи:
PR 1: feat: Добавление основной модели и миграции
PR 2: feat: Реализация конечных точек аутентификации
PR 3: feat: Добавление UI управления пользователями
PR 4: feat: Интеграция подтверждения по email
Каждый PR должен быть нацелен на одну фичу или исправление ошибки, что сделает процесс обзора проще для всех. Это ведёт к более быстрым обзорам и меньшему количеству доработок.
Окончание следует…
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Начало
Как разработчики, мы часто работаем параллельно, создавая ветки для новых функций, исправляя ошибки и внося обновления. Но когда приходит время внести эти изменения в основную кодовую базу, пулл-реквесты (PR) становятся мостом между изолированной разработкой и совместной работой в команде. Каждого разочаровывает, когда PR отклоняют или отправляют на доработку. Легко можно потратить часы на функцию, а потом понять, что твоя реализация не соответствует видению команды. Однако со временем мы узнаём, что эффективные PR касаются не только самого кода. Они и про то, как мы сообщаем о наших изменениях. Рассмотрим, как создавать пулл-реквесты, которые делают процесс обзора более плавным, быстрым и эффективным для всех участников.
1. Начните с информативного заголовка
Первое впечатление имеет значение даже в мире кода. Заголовок пулл-реквеста — это наш шанс немедленно донести суть изменения. Думайте о нём как о заголовке статьи; он должен быть коротким, понятным и информативным. Вместо:
"Обновил код"
"Исправил баг"
"Изменения за вчера"
Используйте более описательные заголовки, например:
feat: Добавил OAuth2 аутентификацию для конечных точек API
fix: Устранил состояния гонки при обработке сеанса пользователя
refactor: Оптимизированы запросы к БД при поиске пользователя
Хорошо составленный заголовок помогает рецензентам понять изменение, не открывая PR. Он задает тон всему процессу обзора кода.
2. Установите контекст (не предполагайте, что все знают проблему)
Прежде чем погрузиться в код, важно предоставить контекст. Не все могут быть знакомы с конкретной проблемой, которую мы решаем, и важно объяснить, почему произошли изменения. Чёткое описание PR упрощает и ускоряет рецензирование. Вот шаблон для хорошо структурированного описания PR:
## Проблема
Текущая система аутентификации пользователей не поддерживает вход через соцсети, что вызывает затруднения при регистрации. Мы наблюдаем 40% отказов на этапе регистрации.
Связанный тикет: AUTH-123
## Решение
Реализована аутентификация OAuth2 с Google:
- Добавлено промежуточное ПО OAuth2 для обработки аутентификации Google
- Создана новая логика сопоставления профилей пользователей
- Реализовано управление сеансами для входа через соцсети
## Технические подробности
- Использует passport-google-oauth20
- Добавлены новые поля: googleId, socialProfile
- Изменена модель пользователя для поддержки нескольких методов аутентификации
## Тестирование
1. Нажмите «Войти через Google»
2. Авторизуйте тестовое приложение
3. Проверьте успешное перенаправление на панель управления
4. Проверьте, содержит ли профиль пользователя данные Google
## Конфигурация
Требуются новые переменные среды:
- GOOGLE_CLIENT_ID
- GOOGLE_CLIENT_SECRET
- OAUTH_CALLBACK_URL
Это гарантирует, что рецензенты поймут проблему, выбранный подход и то, как проверить решение. PR без контекста может существенно замедлить процесс, поэтому всегда включайте достаточно информации, чтобы команда могла понять ваши изменения.
3. Сохраняйте PR сфокусированным
Нас всех подбивает решить сразу несколько проблем. Но это часто приводит к слишком большим PR, которые могут обескуражить рецензентов. Вместо этого пытайтесь разбить работу на более мелкие, целенаправленные PR. Каждый PR должен решать определённую задачу. Например, если мы создаём систему управления пользователями, можно разбить её на более мелкие задачи:
PR 1: feat: Добавление основной модели и миграции
PR 2: feat: Реализация конечных точек аутентификации
PR 3: feat: Добавление UI управления пользователями
PR 4: feat: Интеграция подтверждения по email
Каждый PR должен быть нацелен на одну фичу или исправление ошибки, что сделает процесс обзора проще для всех. Это ведёт к более быстрым обзорам и меньшему количеству доработок.
Окончание следует…
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
👍18👎2
День 2249. #BestPractices
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Окончание
Начало
4. Сообщения коммитов: чистота и ясность
Хорошее сообщение коммита не просто объясняет код. Оно помогает всем понять, почему было сделано изменение и как оно вписывается в общую картину.
Хорошее сообщение коммита
- предоставляет контекст: объясняет причину изменения;
- улучшает сотрудничество: будущие разработчики смогут отслеживать историю проекта и легко понимать цель каждого коммита;
- экономит время: уменьшают необходимость в дополнительных вопросах и предотвращают доработки во время процесса проверки;
Примеры плохих сообщений коммитов:
- «Исправлено»
Это расплывчато и не указывает, что исправлено или почему.
Лучше:
fix(auth): устранена ошибка входа пользователя, вызванная истекшими токенами.
- «Обновления»
Не сообщает рецензенту, что было изменено или почему обновление было необходимо.
Лучше:
chore: обновлены зависимости для исправления уязвимостей безопасности
- «Работа в процессе»
Не описывает никаких значимых изменений и предполагает, что код неполный. Также усложняет процесс проверки, так как рецензент не знает, смотрит ли он на готовую функцию или только на черновик.
Лучше:
feat(api): добавлены конечные точки аутентификации пользователя
5. Контрольный список готовности к обзору кода
Перед отправкой PR используйте следующий контрольный список, чтобы убедиться, что всё готово. Контрольный список важен, т.к.:
- Экономит время рецензентов: сводит к минимуму вероятность того, что рецензенты попросят об исправлениях, позволяя им сосредоточиться на логике кода.
- Улучшает согласованность: гарантирует, что все PR соответствуют одному стандарту, что делает процесс обзора более гладким для всех.
- Уменьшает количество повторных проверок: двойная проверка вашего кода и тестов позволяет избежать нескольких раундов обзоров.
Пример контрольного списка:
Распространённые проблемы с PR
1. В PR слишком много изменений
Разбейте задачу на более мелкие, более управляемые PR. Сначала для изменений схемы БД, затем для модификаций API, а затем — для корректировок UI. Это позволит рецензентам сосредоточиться на чём-то одном за раз.
2. Непоследовательные сообщения коммитов
Они затрудняют отслеживание изменений: одни слишком расплывчаты, другие — слишком подробные. Используйте стандартный формат сообщений коммитов и убедитесь, что все его соблюдают. Это сделает историю проекта намного более читаемой и улучшит совместную работу.
Итого
Создание эффективных PR — навык, который улучшается с практикой. Каждый PR — это возможность для обучения. Каждый комментарий, предложение или вопрос в обзоре кода помогает нам расти как разработчикам и улучшать наши методы кодирования.
Цель не просто слить наш код с основной веткой; а создать высококачественную кодовую базу, которую всем будет легко понимать и поддерживать. Уделяя особое внимание нашим PR, мы инвестируем в успех проекта и наш рост как разработчиков.
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
Мастерство Пулл-Реквестов: как Легко Пройти Обзор Кода. Окончание
Начало
4. Сообщения коммитов: чистота и ясность
Хорошее сообщение коммита не просто объясняет код. Оно помогает всем понять, почему было сделано изменение и как оно вписывается в общую картину.
Хорошее сообщение коммита
- предоставляет контекст: объясняет причину изменения;
- улучшает сотрудничество: будущие разработчики смогут отслеживать историю проекта и легко понимать цель каждого коммита;
- экономит время: уменьшают необходимость в дополнительных вопросах и предотвращают доработки во время процесса проверки;
Примеры плохих сообщений коммитов:
- «Исправлено»
Это расплывчато и не указывает, что исправлено или почему.
Лучше:
fix(auth): устранена ошибка входа пользователя, вызванная истекшими токенами.
- «Обновления»
Не сообщает рецензенту, что было изменено или почему обновление было необходимо.
Лучше:
chore: обновлены зависимости для исправления уязвимостей безопасности
- «Работа в процессе»
Не описывает никаких значимых изменений и предполагает, что код неполный. Также усложняет процесс проверки, так как рецензент не знает, смотрит ли он на готовую функцию или только на черновик.
Лучше:
feat(api): добавлены конечные точки аутентификации пользователя
5. Контрольный список готовности к обзору кода
Перед отправкой PR используйте следующий контрольный список, чтобы убедиться, что всё готово. Контрольный список важен, т.к.:
- Экономит время рецензентов: сводит к минимуму вероятность того, что рецензенты попросят об исправлениях, позволяя им сосредоточиться на логике кода.
- Улучшает согласованность: гарантирует, что все PR соответствуют одному стандарту, что делает процесс обзора более гладким для всех.
- Уменьшает количество повторных проверок: двойная проверка вашего кода и тестов позволяет избежать нескольких раундов обзоров.
Пример контрольного списка:
## Перед коммитом
- [ ] Все тесты проходят
- [ ] Нет предупреждений компилятора
- [ ] Документация обновлена
- [ ] В коммите нет приватных данных
- [ ] Ветка синхронизирована с main
- [ ] Код отвечает стилю кодирования проекта
Распространённые проблемы с PR
1. В PR слишком много изменений
Разбейте задачу на более мелкие, более управляемые PR. Сначала для изменений схемы БД, затем для модификаций API, а затем — для корректировок UI. Это позволит рецензентам сосредоточиться на чём-то одном за раз.
2. Непоследовательные сообщения коммитов
Они затрудняют отслеживание изменений: одни слишком расплывчаты, другие — слишком подробные. Используйте стандартный формат сообщений коммитов и убедитесь, что все его соблюдают. Это сделает историю проекта намного более читаемой и улучшит совместную работу.
Итого
Создание эффективных PR — навык, который улучшается с практикой. Каждый PR — это возможность для обучения. Каждый комментарий, предложение или вопрос в обзоре кода помогает нам расти как разработчикам и улучшать наши методы кодирования.
Цель не просто слить наш код с основной веткой; а создать высококачественную кодовую базу, которую всем будет легко понимать и поддерживать. Уделяя особое внимание нашим PR, мы инвестируем в успех проекта и наш рост как разработчиков.
Источник: https://dev.to/budiwidhiyanto/the-art-of-pull-requests-a-developers-guide-to-smooth-code-reviews-38bk
👍9
День 2346. #BestPractices
Пишем Хорошую Документацию. Начало
Документация часто кажется второстепенной — рутиной, которую откладывают на конец спринта или вообще пропускают. Тем не менее, любой разработчик расскажет, что одно из его самых больших разочарований - продираться через плохую, устаревшую или отсутствующую документацию. Важно не просто иметь документацию, а создать такую, которую разработчики действительно ценят и используют. Это сигнализирует о том, что создатели заботятся о людях, использующих их ПО или API.
1. Знайте свою аудиторию (глубоко)
Прежде чем написать хоть слово, поймите, для кого вы пишете. Опытные или младшие разработчики? Внутренние команды, уже знакомые с экосистемой, или внешние пользователи, впервые сталкивающиеся с продуктом?
- Техническая компетентность: адаптируйте язык и глубину объяснения. Избегайте чрезмерно упрощённых объяснений для экспертов, но не предполагайте глубоких знаний предметной области от новичков.
- Цели: чего они пытаются достичь с помощью вашего ПО/API? Они ищут краткое руководство по началу работы, устранение конкретной ошибки, понимание расширенных концепций или интеграцию с другими системами? Структурируйте документы так, чтобы они отвечали этим конкретным потребностям.
- Контекст: где они обычно ищут информацию? Подойдёт ли интерактивный UI для API или лучше статические справочные страницы?
Поставьте себя на место разработчика. Какая информация вам нужна и как бы вы хотели, чтобы она была представлена?
2. Важна структура: создайте логическую основу
Даже самый точный контент бесполезен, если разработчики не могут его найти. Логическая структура обеспечивает ментальную карту, позволяя пользователям интуитивно ориентироваться.
- Чёткая иерархия: организуйте контент логически, начиная с вводных концепций (Начало работы, Установка) и переходя к конкретике (Справочник API, Руководства, Устранение неполадок). Используйте чёткие заголовки и подзаголовки (H1, H2, H3) последовательно.
- Оглавление: хорошо структурированное, всегда видимое (на боковой панели) оглавление позволяет пользователям видеть общую компоновку и быстро переходить к нужным разделам.
- Функциональность поиска: убедитесь, что поиск эффективно индексирует контент и выделяет ключевые слова в результатах. Разработчики часто знают, что им нужно, но не знают, где это находится.
- Перекрёстные ссылки: делайте ссылки на связанные концепции, руководства и API. Если вы упоминаете конечную точку API в руководстве, давайте прямую ссылку на неё. Это создаёт сеть знаний, а не изолированные хранилища.
- Информационная архитектура: планируйте поток. Рассмотрите возможность использования устоявшихся фреймворков, таких как Diátaxis (концепции, руководства, пояснения, справочные материалы), чтобы гарантировать, что вы систематически охватываете различные потребности в обучении.
3. Содержание: ясность, краткость и примеры
Основа документации — это содержание.
- Ясность: используйте понятный, недвусмысленный язык. Избегайте жаргона, где возможно, или чётко определите понятия при их первом использовании. Предпочитайте активный залог пассивному («Функция возвращает X» вместо «X возвращается функцией»).
- Краткость: разработчики заняты. Переходите к сути. Устраняйте бессмыслицу и ненужные слова. Используйте короткие предложения и абзацы. Маркеры и нумерованные списки отлично подходят для разбиения текста и выделения ключевой информации.
- Точность: неточная документация хуже, чем её отсутствие. Установите процессы проверки и обеспечьте обновление документов вместе с изменениями кода.
- Примеры кода: многочисленные, практичные, копируемые и вставляемые примеры, которые работают из коробки (включая необходимые импорты или настройки). Объясняйте, что делает код и почему он структурирован именно так. Покажите общие случаи использования, пограничные случаи и обработку ошибок. Если ваш API/SDK поддерживает несколько языков, предоставьте примеры на каждом из них.
Продолжение следует…
Источник: https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
Пишем Хорошую Документацию. Начало
Документация часто кажется второстепенной — рутиной, которую откладывают на конец спринта или вообще пропускают. Тем не менее, любой разработчик расскажет, что одно из его самых больших разочарований - продираться через плохую, устаревшую или отсутствующую документацию. Важно не просто иметь документацию, а создать такую, которую разработчики действительно ценят и используют. Это сигнализирует о том, что создатели заботятся о людях, использующих их ПО или API.
1. Знайте свою аудиторию (глубоко)
Прежде чем написать хоть слово, поймите, для кого вы пишете. Опытные или младшие разработчики? Внутренние команды, уже знакомые с экосистемой, или внешние пользователи, впервые сталкивающиеся с продуктом?
- Техническая компетентность: адаптируйте язык и глубину объяснения. Избегайте чрезмерно упрощённых объяснений для экспертов, но не предполагайте глубоких знаний предметной области от новичков.
- Цели: чего они пытаются достичь с помощью вашего ПО/API? Они ищут краткое руководство по началу работы, устранение конкретной ошибки, понимание расширенных концепций или интеграцию с другими системами? Структурируйте документы так, чтобы они отвечали этим конкретным потребностям.
- Контекст: где они обычно ищут информацию? Подойдёт ли интерактивный UI для API или лучше статические справочные страницы?
Поставьте себя на место разработчика. Какая информация вам нужна и как бы вы хотели, чтобы она была представлена?
2. Важна структура: создайте логическую основу
Даже самый точный контент бесполезен, если разработчики не могут его найти. Логическая структура обеспечивает ментальную карту, позволяя пользователям интуитивно ориентироваться.
- Чёткая иерархия: организуйте контент логически, начиная с вводных концепций (Начало работы, Установка) и переходя к конкретике (Справочник API, Руководства, Устранение неполадок). Используйте чёткие заголовки и подзаголовки (H1, H2, H3) последовательно.
- Оглавление: хорошо структурированное, всегда видимое (на боковой панели) оглавление позволяет пользователям видеть общую компоновку и быстро переходить к нужным разделам.
- Функциональность поиска: убедитесь, что поиск эффективно индексирует контент и выделяет ключевые слова в результатах. Разработчики часто знают, что им нужно, но не знают, где это находится.
- Перекрёстные ссылки: делайте ссылки на связанные концепции, руководства и API. Если вы упоминаете конечную точку API в руководстве, давайте прямую ссылку на неё. Это создаёт сеть знаний, а не изолированные хранилища.
- Информационная архитектура: планируйте поток. Рассмотрите возможность использования устоявшихся фреймворков, таких как Diátaxis (концепции, руководства, пояснения, справочные материалы), чтобы гарантировать, что вы систематически охватываете различные потребности в обучении.
3. Содержание: ясность, краткость и примеры
Основа документации — это содержание.
- Ясность: используйте понятный, недвусмысленный язык. Избегайте жаргона, где возможно, или чётко определите понятия при их первом использовании. Предпочитайте активный залог пассивному («Функция возвращает X» вместо «X возвращается функцией»).
- Краткость: разработчики заняты. Переходите к сути. Устраняйте бессмыслицу и ненужные слова. Используйте короткие предложения и абзацы. Маркеры и нумерованные списки отлично подходят для разбиения текста и выделения ключевой информации.
- Точность: неточная документация хуже, чем её отсутствие. Установите процессы проверки и обеспечьте обновление документов вместе с изменениями кода.
- Примеры кода: многочисленные, практичные, копируемые и вставляемые примеры, которые работают из коробки (включая необходимые импорты или настройки). Объясняйте, что делает код и почему он структурирован именно так. Покажите общие случаи использования, пограничные случаи и обработку ошибок. Если ваш API/SDK поддерживает несколько языков, предоставьте примеры на каждом из них.
Продолжение следует…
Источник: https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
👍4👎2
День 2347. #BestPractices
Пишем Хорошую Документацию. Продолжение
Начало
4. Сосредоточьтесь на вариантах использования и используйте интеллектуальные инструменты для API
Разработчики не просто хотят знать, что делает конечная точка API; они хотят знать, как использовать её для решения своей проблемы. Создавайте документацию вокруг общих задач и рабочих процессов.
Специализированные фреймворки для API значительно улучшают процесс создания документации. Инструменты, разработанные специально для жизненного цикла API, могут оптимизировать как разработку, так и документирование, обеспечивая согласованность и интерактивность. Например, Apidog интегрирует проектирование API, отладку, тестирование непосредственно с созданием документации.
5. Поддерживайте точность и актуальность
Устаревшая документация подрывает доверие быстрее, чем что-либо ещё. Разработчики полагаются на правильность документов. Если они сталкиваются с несоответствиями, они полностью перестают доверять документации.
- Версионирование: чётко версионируйте документацию вместе с выпусками ПО/API. Позвольте пользователям легко переключаться между версиями.
- Документация-как-Код: относитесь к документации как к коду. Храните её в системе контроля версий (например, Git) вместе с исходным кодом, который она описывает. Это упрощает отслеживание изменений, просмотр обновлений и синхронизацию документов с выпусками кода. Интегрируйте обновления документации в свой конвейер CI/CD.
- Циклы обратной связи: упростите разработчикам возможность сообщать об ошибках или предлагать улучшения (например, кнопка «Предложить изменения», ссылающаяся на GitHub Issues или специальную форму обратной связи). Незамедлительно реагируйте на эти отзывы.
- Регулярные обзоры: запланируйте периодические обзоры документации для проверки точности, ясности и полноты.
6. Визуальная привлекательность и последовательность
Хотя суть является ключевой, представление тоже имеет значение. Красивые документы приятны и легко читаются.
- Чистый дизайн: используйте достаточно свободного пространства, читаемые шрифты и четкую визуальную иерархию. Избегайте загромождённых шаблонов.
- Единообразное форматирование: применяйте единый стиль для блоков кода, заметок, предупреждений, заголовков, ссылок и т. д. По возможности используйте руководство по стилю.
- Подсветка синтаксиса: необходима для примеров кода. Используйте чёткое и правильное выделение для соответствующих языков программирования.
- Наглядные пособия: используйте диаграммы (блок-схемы, диаграммы последовательности, диаграммы архитектуры), снимки экрана или короткие видеоролики, где они могут прояснить сложные концепции более эффективно, чем текст. Убедитесь, что визуальные материалы понятны, маркированы и актуальны.
7. Улучшите интерактивность и поисковую доступность
Выйдите за рамки статического текста:
- Интерактивные элементы: помимо пользовательского интерфейса API (например, Swagger), рассмотрите использование встроенных редакторов кода (например, CodeSandbox) или интерактивных руководств (например, Jupiter Notebooks).
- Расширенный поиск: для больших наборов документации разрешите пользователям фильтровать результаты поиска по категории, версии или разделу API.
- Виджеты "Была ли эта страница полезна?": собирайте быстрые отзывы об эффективности страницы.
Окончание следует…
Источник: https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
Пишем Хорошую Документацию. Продолжение
Начало
4. Сосредоточьтесь на вариантах использования и используйте интеллектуальные инструменты для API
Разработчики не просто хотят знать, что делает конечная точка API; они хотят знать, как использовать её для решения своей проблемы. Создавайте документацию вокруг общих задач и рабочих процессов.
Специализированные фреймворки для API значительно улучшают процесс создания документации. Инструменты, разработанные специально для жизненного цикла API, могут оптимизировать как разработку, так и документирование, обеспечивая согласованность и интерактивность. Например, Apidog интегрирует проектирование API, отладку, тестирование непосредственно с созданием документации.
5. Поддерживайте точность и актуальность
Устаревшая документация подрывает доверие быстрее, чем что-либо ещё. Разработчики полагаются на правильность документов. Если они сталкиваются с несоответствиями, они полностью перестают доверять документации.
- Версионирование: чётко версионируйте документацию вместе с выпусками ПО/API. Позвольте пользователям легко переключаться между версиями.
- Документация-как-Код: относитесь к документации как к коду. Храните её в системе контроля версий (например, Git) вместе с исходным кодом, который она описывает. Это упрощает отслеживание изменений, просмотр обновлений и синхронизацию документов с выпусками кода. Интегрируйте обновления документации в свой конвейер CI/CD.
- Циклы обратной связи: упростите разработчикам возможность сообщать об ошибках или предлагать улучшения (например, кнопка «Предложить изменения», ссылающаяся на GitHub Issues или специальную форму обратной связи). Незамедлительно реагируйте на эти отзывы.
- Регулярные обзоры: запланируйте периодические обзоры документации для проверки точности, ясности и полноты.
6. Визуальная привлекательность и последовательность
Хотя суть является ключевой, представление тоже имеет значение. Красивые документы приятны и легко читаются.
- Чистый дизайн: используйте достаточно свободного пространства, читаемые шрифты и четкую визуальную иерархию. Избегайте загромождённых шаблонов.
- Единообразное форматирование: применяйте единый стиль для блоков кода, заметок, предупреждений, заголовков, ссылок и т. д. По возможности используйте руководство по стилю.
- Подсветка синтаксиса: необходима для примеров кода. Используйте чёткое и правильное выделение для соответствующих языков программирования.
- Наглядные пособия: используйте диаграммы (блок-схемы, диаграммы последовательности, диаграммы архитектуры), снимки экрана или короткие видеоролики, где они могут прояснить сложные концепции более эффективно, чем текст. Убедитесь, что визуальные материалы понятны, маркированы и актуальны.
7. Улучшите интерактивность и поисковую доступность
Выйдите за рамки статического текста:
- Интерактивные элементы: помимо пользовательского интерфейса API (например, Swagger), рассмотрите использование встроенных редакторов кода (например, CodeSandbox) или интерактивных руководств (например, Jupiter Notebooks).
- Расширенный поиск: для больших наборов документации разрешите пользователям фильтровать результаты поиска по категории, версии или разделу API.
- Виджеты "Была ли эта страница полезна?": собирайте быстрые отзывы об эффективности страницы.
Окончание следует…
Источник: https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
👍6
День 2348. #BestPractices
Пишем Хорошую Документацию. Окончание
Начало
Продолжение
8. Используйте современные инструменты (вне зависимости от API)
Существует множество инструментов, которые помогут вам эффективно и результативно создавать документацию:
- Генераторы статических сайтов (SSG): такие инструменты, как MkDocs, Docusaurus, Hugo, Jekyll и Sphinx, являются популярным выбором. Они берут простые файлы разметки (например, Markdown) и создают профессионально выглядящие веб-сайты документации, с возможностью поиска. Они часто поставляются с темами, плагинами для поиска, поддержкой управления версиями и хорошо согласуются с подходом «Документация-как-Код».
- Платформы документации: такие сервисы, как Read the Docs, GitBook или Confluence, предлагают решения со встроенными функциями для совместной работы, управления версиями и презентации.
Выбирайте инструменты, которые соответствуют вашему рабочему процессу, размеру команды и техническим требованиям.
9. Используйте ИИ (осторожно)
Искусственный интеллект проникает в документацию. Генератор документации ИИ может стать мощным помощником, но крайне важно понимать его сильные и слабые стороны.
Потенциальные преимущества
- Генерация шаблонов: ИИ может быстро генерировать первоначальные черновики описаний функций/методов на основе комментариев или сигнатур кода (например, блоков
- Саммари: ИИ может обобщать длинные технические объяснения или сложные разделы кода.
- Проверки согласованности: ИИ может помочь выявить несоответствия в терминологии или стиле в больших наборах документации.
- Перевод: сервисы перевода на другие языки совершенствуются, хотя человеческая проверка по-прежнему необходима для технической точности.
Важные предостережения
- Точность не гарантируется: модели ИИ могут галлюцинировать или неправильно интерпретировать контекст кода. Всегда привлекайте эксперта-человека для проверки технической корректности контента, созданного ИИ.
- Отсутствие контекста: ИИ может не понимать более широкий вариант использования, потребности целевой аудитории или причины использования фрагментов кода.
- Общее повествование: текст, сгенерированный ИИ, иногда может быть скучным или не иметь конкретных идей, которые мог бы предоставить эксперт-человек.
Используйте генератор документации ИИ как инструмент для дополнения человеческих усилий, а не для их замены. Он может ускорить составление черновиков и выявить области для улучшения, но критическое мышление, техническая проверка и создание действительно полезных объяснений остаются человеческими задачами.
10. Развивайте культуру документирования
Отличная документация обычно не является продуктом одного человека, работающего в изоляции. Для этого требуются командные усилия и культурный сдвиг:
- Интеграция в рабочий процесс: сделайте документацию частью определения «готово» для новых функций или изменений API. Выделяйте на неё время во время спринтов.
- Поощряйте вклад: сделайте так, чтобы всем разработчикам (а не только преданным писателям) было легко вносить исправления и улучшения. Снизьте барьер для входа (например, простое редактирование Markdown через Git).
- Признавайте и вознаграждайте: признавайте и цените усилия, которые вложены в создание и поддержание высококачественной документации.
- Показывайте пример: если руководители групп и старшие разработчики отдают приоритет документации, другие, скорее всего, последуют их примеру.
Итого
Создание документации, которая понравится разработчикам, — непростая задача, но это чрезвычайно ценная инвестиция. Красивые документы — точные, понятные, хорошо структурированные, простые в навигации и визуально приятные — напрямую влияют на производительность разработчиков, снижают нагрузку на поддержку, улучшают адаптацию и улучшают общее восприятие вашего ПО или платформы.
Источник: https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
Пишем Хорошую Документацию. Окончание
Начало
Продолжение
8. Используйте современные инструменты (вне зависимости от API)
Существует множество инструментов, которые помогут вам эффективно и результативно создавать документацию:
- Генераторы статических сайтов (SSG): такие инструменты, как MkDocs, Docusaurus, Hugo, Jekyll и Sphinx, являются популярным выбором. Они берут простые файлы разметки (например, Markdown) и создают профессионально выглядящие веб-сайты документации, с возможностью поиска. Они часто поставляются с темами, плагинами для поиска, поддержкой управления версиями и хорошо согласуются с подходом «Документация-как-Код».
- Платформы документации: такие сервисы, как Read the Docs, GitBook или Confluence, предлагают решения со встроенными функциями для совместной работы, управления версиями и презентации.
Выбирайте инструменты, которые соответствуют вашему рабочему процессу, размеру команды и техническим требованиям.
9. Используйте ИИ (осторожно)
Искусственный интеллект проникает в документацию. Генератор документации ИИ может стать мощным помощником, но крайне важно понимать его сильные и слабые стороны.
Потенциальные преимущества
- Генерация шаблонов: ИИ может быстро генерировать первоначальные черновики описаний функций/методов на основе комментариев или сигнатур кода (например, блоков
///summary
).- Саммари: ИИ может обобщать длинные технические объяснения или сложные разделы кода.
- Проверки согласованности: ИИ может помочь выявить несоответствия в терминологии или стиле в больших наборах документации.
- Перевод: сервисы перевода на другие языки совершенствуются, хотя человеческая проверка по-прежнему необходима для технической точности.
Важные предостережения
- Точность не гарантируется: модели ИИ могут галлюцинировать или неправильно интерпретировать контекст кода. Всегда привлекайте эксперта-человека для проверки технической корректности контента, созданного ИИ.
- Отсутствие контекста: ИИ может не понимать более широкий вариант использования, потребности целевой аудитории или причины использования фрагментов кода.
- Общее повествование: текст, сгенерированный ИИ, иногда может быть скучным или не иметь конкретных идей, которые мог бы предоставить эксперт-человек.
Используйте генератор документации ИИ как инструмент для дополнения человеческих усилий, а не для их замены. Он может ускорить составление черновиков и выявить области для улучшения, но критическое мышление, техническая проверка и создание действительно полезных объяснений остаются человеческими задачами.
10. Развивайте культуру документирования
Отличная документация обычно не является продуктом одного человека, работающего в изоляции. Для этого требуются командные усилия и культурный сдвиг:
- Интеграция в рабочий процесс: сделайте документацию частью определения «готово» для новых функций или изменений API. Выделяйте на неё время во время спринтов.
- Поощряйте вклад: сделайте так, чтобы всем разработчикам (а не только преданным писателям) было легко вносить исправления и улучшения. Снизьте барьер для входа (например, простое редактирование Markdown через Git).
- Признавайте и вознаграждайте: признавайте и цените усилия, которые вложены в создание и поддержание высококачественной документации.
- Показывайте пример: если руководители групп и старшие разработчики отдают приоритет документации, другие, скорее всего, последуют их примеру.
Итого
Создание документации, которая понравится разработчикам, — непростая задача, но это чрезвычайно ценная инвестиция. Красивые документы — точные, понятные, хорошо структурированные, простые в навигации и визуально приятные — напрямую влияют на производительность разработчиков, снижают нагрузку на поддержку, улучшают адаптацию и улучшают общее восприятие вашего ПО или платформы.
Источник: https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
👍3
День 2361. #Testing #BestPractices
Лучшие Практики Интеграционного Тестирования с Testcontainers. Начало
Интеграционные тесты с Testcontainers — мощный инструмент, но их поддержка может быстро превратиться в кошмар. Сегодня рассмотрим шаблоны, которые делают тесты Testcontainers надёжными, быстрыми и простыми в поддержке.
Традиционные интеграционные тесты часто используют общие тестовые БД или БД в памяти, которые не соответствуют поведению в рабочей среде. Вам либо приходится сталкиваться с загрязнением тестов между запусками, либо жертвовать реализмом ради скорости.
Testcontainers решает эту проблему, разворачивая настоящие Docker-контейнеры для ваших зависимостей. Тесты выполняются с использованием реальных PostgreSQL, Redis или любого другого сервиса, используемого в рабочей среде. После завершения тестов контейнеры уничтожаются, каждый раз позволяя вам начинать с чистого листа.
Всё происходит через API Docker. Testcontainers управляет всем жизненным циклом: извлечение образов, запуск контейнеров, ожидание готовности и очистка. Тестовому коду нужно лишь знать, как подключиться.
1. Подготовка
Убедитесь, что у вас есть необходимые пакеты:
Пакеты TestContainers существуют для множества сервисов.
2. Создание
Вот так можно создать контейнеры для PostgreSql и Redis:
3. Использование
Чтобы запускать и останавливать контейнеры в тестах, нужно реализовать IAsyncLifetime в вашей WebApplicationFactory:
Это гарантирует готовность контейнеров до запуска тестов и их очистку после них. Т.е. отсутствие остаточного состояния Docker или состояний гонки.
Совет: закрепите версии образов (например, postgres:17), чтобы избежать сюрпризов от изменений версий зависимостей.
4. Передача конфигурации в приложение
Testcontainers назначает динамические порты. Не пишите жёсткие строки подключения в коде. Вместо этого внедряйте значения через WebApplicationFactory.ConfigureWebHost:
Здесь используется метод UseSetting для динамической передачи строк подключения. Это также позволяет избежать состояний гонки или конфликтов с другими тестами, которые могут выполняться параллельно. Это гарантирует, что тесты всегда будут подключаться к правильным портам, независимо от того, что назначает Docker.
Нет необходимости удалять сервисы из коллекции сервисов или настраивать их вручную. Просто задайте строки подключения, и ваше приложение будет использовать их автоматически.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/testcontainers-best-practices-dotnet-integration-testing
Лучшие Практики Интеграционного Тестирования с Testcontainers. Начало
Интеграционные тесты с Testcontainers — мощный инструмент, но их поддержка может быстро превратиться в кошмар. Сегодня рассмотрим шаблоны, которые делают тесты Testcontainers надёжными, быстрыми и простыми в поддержке.
Традиционные интеграционные тесты часто используют общие тестовые БД или БД в памяти, которые не соответствуют поведению в рабочей среде. Вам либо приходится сталкиваться с загрязнением тестов между запусками, либо жертвовать реализмом ради скорости.
Testcontainers решает эту проблему, разворачивая настоящие Docker-контейнеры для ваших зависимостей. Тесты выполняются с использованием реальных PostgreSQL, Redis или любого другого сервиса, используемого в рабочей среде. После завершения тестов контейнеры уничтожаются, каждый раз позволяя вам начинать с чистого листа.
Всё происходит через API Docker. Testcontainers управляет всем жизненным циклом: извлечение образов, запуск контейнеров, ожидание готовности и очистка. Тестовому коду нужно лишь знать, как подключиться.
1. Подготовка
Убедитесь, что у вас есть необходимые пакеты:
Install-Package Microsoft.AspNetCore.Mvc.Testing
Install-Package Testcontainers.PostgreSql
Install-Package Testcontainers.Redis
Пакеты TestContainers существуют для множества сервисов.
2. Создание
Вот так можно создать контейнеры для PostgreSql и Redis:
var _pg = new PostgreSqlBuilder()
.WithImage("postgres:17")
.WithDatabase("mydb")
.WithUsername("postgres")
.WithPassword("postgres")
.Build();
var _redis = new RedisBuilder()
.WithImage("redis:latest")
.Build();
3. Использование
Чтобы запускать и останавливать контейнеры в тестах, нужно реализовать IAsyncLifetime в вашей WebApplicationFactory:
public sealed class IntegrationWebAppFactory :
WebApplicationFactory<Program>, IAsyncLifetime
{
public async Task InitializeAsync()
{
await _pg.StartAsync();
await _redis.StartAsync();
// Старт других зависимостей
}
public async Task DisposeAsync()
{
await _pg.StopAsync();
await _redis.StopAsync();
// Остановка других зависимостей
}
}
Это гарантирует готовность контейнеров до запуска тестов и их очистку после них. Т.е. отсутствие остаточного состояния Docker или состояний гонки.
Совет: закрепите версии образов (например, postgres:17), чтобы избежать сюрпризов от изменений версий зависимостей.
4. Передача конфигурации в приложение
Testcontainers назначает динамические порты. Не пишите жёсткие строки подключения в коде. Вместо этого внедряйте значения через WebApplicationFactory.ConfigureWebHost:
protected override void
ConfigureWebHost(IWebHostBuilder bldr)
{
bldr.UseSetting("ConnectionStrings:Database",
_pg.GetConnectionString());
bldr.UseSetting("ConnectionStrings:Redis",
_redis.GetConnectionString());
}
Здесь используется метод UseSetting для динамической передачи строк подключения. Это также позволяет избежать состояний гонки или конфликтов с другими тестами, которые могут выполняться параллельно. Это гарантирует, что тесты всегда будут подключаться к правильным портам, независимо от того, что назначает Docker.
Нет необходимости удалять сервисы из коллекции сервисов или настраивать их вручную. Просто задайте строки подключения, и ваше приложение будет использовать их автоматически.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/testcontainers-best-practices-dotnet-integration-testing
👍12
День 2362. #Testing #BestPractices
Лучшие Практики Интеграционного Тестирования с Testcontainers. Окончание
Начало
5. Совместное использование настроек с фикстурами xUnit
Фикстура — это общий контекст для тестов, позволяющий настроить дорогостоящие ресурсы, такие как БД или брокеры сообщений, один раз и использовать их повторно в нескольких тестах. Выбор между фикстурами классов и коллекций влияет как на производительность тестов, так и на изоляцию.
Фикстура класса — один контейнер на каждый тестовый класс.
Используйте, когда тесты изменяют глобальное состояние или когда отладка тестовых взаимодействий становится затруднительной. Применяйте, когда требуется полная изоляция между тестовыми классами (это медленнее, но безопаснее).
Фикстура коллекции — один контейнер, общий для нескольких тестовых классов.
Используйте, когда тесты не изменяют общее состояние или когда вы можете надёжно выполнить очистку между тестами. Т.е. когда тестовые классы не мешают друг другу (это быстрее, но требует дисциплины).
При использовании фикстур коллекций необходимо позаботиться об очистке любого состояния, которое может сохраняться между тестами. Это может включать сброс БД, очистку кэшей или удаление тестовых данных. Если этого не сделать, тесты могут влиять друг на друга, что приведёт к нестабильным результатам.
6. Вспомогательные методы для аутентификации и очистки
Фикстура может предоставлять вспомогательные методы для упрощения написания тестов:
Эти методы могут выполнять настройку аутентификации и очистку БД, чтобы не повторять шаблонный код в каждом тесте.
7. Написание поддерживаемых интеграционных тестов
При правильной настройке инфраструктуры ваши тесты должны быть сосредоточены на бизнес-логике. Сложность контейнеров должна быть скрыта за грамотно спроектированными базовыми классами и вспомогательными методами. В тестах вы не должны заботиться о правильной имитаций Postgres или Redis, а должны тестировать реальное поведение.
Итого
Testcontainers преобразовывает интеграционное тестирование, давая вам уверенность, которую приносит тестирование с реальными зависимостями. Больше не нужно беспокоиться о том, соответствует ли поведение вашей базы в памяти поведению производственной базы, или работать с общими тестовыми средами, которые выходят из строя при запуске тестов кем-то другим.
Начните с простого: выберите один интеграционный тест, который в настоящее время использует моки или БД в памяти, и преобразуйте его для использования Testcontainers. Вы сразу заметите разницу в уверенности, когда тест пройдёт успешно. Затем постепенно расширяйте его, чтобы охватить критически важные бизнес-процессы.
Источник: https://www.milanjovanovic.tech/blog/testcontainers-best-practices-dotnet-integration-testing
Лучшие Практики Интеграционного Тестирования с Testcontainers. Окончание
Начало
5. Совместное использование настроек с фикстурами xUnit
Фикстура — это общий контекст для тестов, позволяющий настроить дорогостоящие ресурсы, такие как БД или брокеры сообщений, один раз и использовать их повторно в нескольких тестах. Выбор между фикстурами классов и коллекций влияет как на производительность тестов, так и на изоляцию.
Фикстура класса — один контейнер на каждый тестовый класс.
Используйте, когда тесты изменяют глобальное состояние или когда отладка тестовых взаимодействий становится затруднительной. Применяйте, когда требуется полная изоляция между тестовыми классами (это медленнее, но безопаснее).
public class AddItemToCartTests :
IClassFixture<IntegrationWebAppFactory>
{
private IntegrationWebAppFactory _factory;
public AddItemToCartTests(
IntegrationWebAppFactory factory)
{
_factory = factory;
}
[Fact]
public async Task ShouldFail_WhenNotEnoughQuantity()
{ … }
}
Фикстура коллекции — один контейнер, общий для нескольких тестовых классов.
Используйте, когда тесты не изменяют общее состояние или когда вы можете надёжно выполнить очистку между тестами. Т.е. когда тестовые классы не мешают друг другу (это быстрее, но требует дисциплины).
[CollectionDefinition(nameof(IntegrationCollection))]
public sealed class IntegrationCollection :
ICollectionFixture<IntegrationWebAppFactory>
{
}
// Применение
[Collection(nameof(IntegrationCollection))]
public class AddItemToCartTests :
IntegrationTestFixture
{
public AddItemToCartTests(
IntegrationWebAppFactory factory)
: base(factory) { }
[Fact]
public async Task Should_Fail_WhenNotEnoughQuantity()
{ … }
}
При использовании фикстур коллекций необходимо позаботиться об очистке любого состояния, которое может сохраняться между тестами. Это может включать сброс БД, очистку кэшей или удаление тестовых данных. Если этого не сделать, тесты могут влиять друг на друга, что приведёт к нестабильным результатам.
6. Вспомогательные методы для аутентификации и очистки
Фикстура может предоставлять вспомогательные методы для упрощения написания тестов:
public async Task<HttpClient>
CreateAuthenticatedClientAsync() { … }
protected async Task CleanupDBAsync() { … }
Эти методы могут выполнять настройку аутентификации и очистку БД, чтобы не повторять шаблонный код в каждом тесте.
7. Написание поддерживаемых интеграционных тестов
При правильной настройке инфраструктуры ваши тесты должны быть сосредоточены на бизнес-логике. Сложность контейнеров должна быть скрыта за грамотно спроектированными базовыми классами и вспомогательными методами. В тестах вы не должны заботиться о правильной имитаций Postgres или Redis, а должны тестировать реальное поведение.
Итого
Testcontainers преобразовывает интеграционное тестирование, давая вам уверенность, которую приносит тестирование с реальными зависимостями. Больше не нужно беспокоиться о том, соответствует ли поведение вашей базы в памяти поведению производственной базы, или работать с общими тестовыми средами, которые выходят из строя при запуске тестов кем-то другим.
Начните с простого: выберите один интеграционный тест, который в настоящее время использует моки или БД в памяти, и преобразуйте его для использования Testcontainers. Вы сразу заметите разницу в уверенности, когда тест пройдёт успешно. Затем постепенно расширяйте его, чтобы охватить критически важные бизнес-процессы.
Источник: https://www.milanjovanovic.tech/blog/testcontainers-best-practices-dotnet-integration-testing
👍4