Где вы должны размещать определения переменных метода согласно принципу близости (principle of proximity)?
#Quiz #BestPractices
#Quiz #BestPractices
Anonymous Quiz
13%
Общей группой в начале метода
18%
Общей группой в начале их области видимости
4%
Группами по типу переменных
66%
Как можно ближе к месту использования
Как бы вы реализовали класс 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)
14%
Слабая связанность (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