День 1899. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 4. В требованиях главное особенности использования, а затем — функциональность
В индустрии ПО существует убеждение, что от 50 до 80% возможностей ПО используются редко или не используются никогда.
Если разработчики стремятся удовлетворить требования к возможностям продукта, растёт риск появления невостребованных функций. Ориентированность на богатство функциональных возможностей может привести к выпуску продукта, который вроде имеет нужные функции, но не позволяет пользователям решать их задачи.
Нужно смещать акцент с функциональности на особенности использования, с решения на потребность. Это поможет быстрее понять контекст и цели пользователя и точнее определить, какими возможностями должно обладать решение, для кого оно, как и когда будет использоваться. Учитывая и технические возможности, и особенности использования, можно определить и функциональные требования. Но фокус на особенностях использования позволит гарантировать, что в продукт будут добавлены те функции, которые действительно необходимы пользователям для выполнения их задач.
Меняется суть вопросов во время сбора информации. Вместо «Что вы хотите?» или «Что должна делать система?» можно спросить: «Как предполагается использовать систему?» Редкие пользователи запускают приложение ради определённой функции; подавляющее большинство стремится достичь конкретной цели. Я открываю приложение, имея определённое намерение, и выполняю последовательность шагов, вызывая функции, необходимые для решения задачи. Если всё хорошо, то я успешно решаю свою задачу и закрываю приложение.
Преимущества вариантов использования
1. Помогают пользователям задуматься о своих потребностях. Им сложно правильно сформулировать перечень функций продукта, но они легко расскажут о сценариях использования из своей жизни. По этим описаниям можно определить, какие функции должно предоставить приложение, чтобы пользователи могли решать поставленные задачи. Также учитывайте, какие ошибки могут возникнуть и как система должна их обрабатывать.
2. Помогают расставить приоритеты. Одни варианты использования будут более важными, поэтому должны быть реализованы в первую очередь. Наивысший приоритет имеет нормальный сценарий вместе с возможными нештатными ситуациями. Альтернативные сценарии имеют более низкий приоритет, их реализацию часто откладывают или отменяют вообще.
3. Более продуктивное взаимодействие с пользователем и более полное представление об ограничениях реализации, которое труднее получить, при разговоре о функциональности продукта.
Проблема пользовательских историй
Пользовательская история (user story) описывает функциональность, которая будет полезна как пользователю, так и покупателю системы. Они обычно записываются с использованием простого шаблона:
или
Одна из проблем пользовательских историй в том, что они не имеют внутренней организационной схемы. Множество историй, даже записанных по шаблону, мало чем отличается от вопроса: «Чего вы хотите?» Вы получаете много кусочков важной информации, перемешанных с посторонними сведениями. Требуется, чтобы кто-то отсортировал их и выявил темы, связанные с пользовательскими задачами.
Альтернативой является шаблон истории работы (job story), который ёмко и структурированно описывает потребность:
Правильно оформленные с точки зрения задач, целей и вариантов использования истории работы и пользовательские истории побуждают участников разработки требований сосредоточиться на особенностях использования продукта людьми, а не только на его функционале.
Даже ограничившись подмножеством вариантов использования, вы всё равно придёте к решениям, удовлетворяющим потребности клиентов, если будете ориентироваться на особенности использования.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 4. В требованиях главное особенности использования, а затем — функциональность
В индустрии ПО существует убеждение, что от 50 до 80% возможностей ПО используются редко или не используются никогда.
Если разработчики стремятся удовлетворить требования к возможностям продукта, растёт риск появления невостребованных функций. Ориентированность на богатство функциональных возможностей может привести к выпуску продукта, который вроде имеет нужные функции, но не позволяет пользователям решать их задачи.
Нужно смещать акцент с функциональности на особенности использования, с решения на потребность. Это поможет быстрее понять контекст и цели пользователя и точнее определить, какими возможностями должно обладать решение, для кого оно, как и когда будет использоваться. Учитывая и технические возможности, и особенности использования, можно определить и функциональные требования. Но фокус на особенностях использования позволит гарантировать, что в продукт будут добавлены те функции, которые действительно необходимы пользователям для выполнения их задач.
Меняется суть вопросов во время сбора информации. Вместо «Что вы хотите?» или «Что должна делать система?» можно спросить: «Как предполагается использовать систему?» Редкие пользователи запускают приложение ради определённой функции; подавляющее большинство стремится достичь конкретной цели. Я открываю приложение, имея определённое намерение, и выполняю последовательность шагов, вызывая функции, необходимые для решения задачи. Если всё хорошо, то я успешно решаю свою задачу и закрываю приложение.
Преимущества вариантов использования
1. Помогают пользователям задуматься о своих потребностях. Им сложно правильно сформулировать перечень функций продукта, но они легко расскажут о сценариях использования из своей жизни. По этим описаниям можно определить, какие функции должно предоставить приложение, чтобы пользователи могли решать поставленные задачи. Также учитывайте, какие ошибки могут возникнуть и как система должна их обрабатывать.
2. Помогают расставить приоритеты. Одни варианты использования будут более важными, поэтому должны быть реализованы в первую очередь. Наивысший приоритет имеет нормальный сценарий вместе с возможными нештатными ситуациями. Альтернативные сценарии имеют более низкий приоритет, их реализацию часто откладывают или отменяют вообще.
3. Более продуктивное взаимодействие с пользователем и более полное представление об ограничениях реализации, которое труднее получить, при разговоре о функциональности продукта.
Проблема пользовательских историй
Пользовательская история (user story) описывает функциональность, которая будет полезна как пользователю, так и покупателю системы. Они обычно записываются с использованием простого шаблона:
Как <тип пользователя>, я хочу <описание решаемой задачи>, чтобы я мог <достижение некой цели>.
или
Как <тип пользователя>, я хочу достичь <некая цель>, чтобы <некий результат>.
Одна из проблем пользовательских историй в том, что они не имеют внутренней организационной схемы. Множество историй, даже записанных по шаблону, мало чем отличается от вопроса: «Чего вы хотите?» Вы получаете много кусочков важной информации, перемешанных с посторонними сведениями. Требуется, чтобы кто-то отсортировал их и выявил темы, связанные с пользовательскими задачами.
Альтернативой является шаблон истории работы (job story), который ёмко и структурированно описывает потребность:
Когда <ситуация>, я хочу выполнить <задачу>, чтобы я достичь <желаемый результат>.
Правильно оформленные с точки зрения задач, целей и вариантов использования истории работы и пользовательские истории побуждают участников разработки требований сосредоточиться на особенностях использования продукта людьми, а не только на его функционале.
Даже ограничившись подмножеством вариантов использования, вы всё равно придёте к решениям, удовлетворяющим потребности клиентов, если будете ориентироваться на особенности использования.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
👍11
День 1900. #ЗаметкиНаПолях
Добавляем Деконструктор в Сторонние Типы
Деконструктор — это функция языка C#, позволяющая определить метод, который будет вызываться при разделении объекта на компоненты. Это легко реализовать для ваших собственных типов, но можно добавить и для сторонних типов.
Например:
Красиво и просто, но ваш класс должен определить метод Deconstruct. Что делать, если вы хотите деконструировать сторонний тип, который вы не можете изменить? Компилятор будет искать метод с сигнатурой Deconstruct в типе, который вы пытаетесь деконструировать, но он также будет искать и метод расширения с той же сигнатурой. Т.е. можно определить деконструктор для стороннего типа, определив метод расширения с той же сигнатурой:
Это довольно нишевая функция, и она скорее про удобство, чем про необходимость. Однако если у вас есть фиксированный набор необходимых свойств типа, это может быть очень кратким способом их получения.
Источник: https://steven-giesel.com/blogPost/0775d3d3-8f90-4546-95d8-71a6b1e7b0e8/equip-3rd-party-types-with-a-deconstructor
Добавляем Деконструктор в Сторонние Типы
Деконструктор — это функция языка C#, позволяющая определить метод, который будет вызываться при разделении объекта на компоненты. Это легко реализовать для ваших собственных типов, но можно добавить и для сторонних типов.
Например:
public class Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y)
{
X = x;
Y = y;
}
public void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
}
}
// Использование
var point = new Point(3, 4);
var (x, y) = point;
Красиво и просто, но ваш класс должен определить метод Deconstruct. Что делать, если вы хотите деконструировать сторонний тип, который вы не можете изменить? Компилятор будет искать метод с сигнатурой Deconstruct в типе, который вы пытаетесь деконструировать, но он также будет искать и метод расширения с той же сигнатурой. Т.е. можно определить деконструктор для стороннего типа, определив метод расширения с той же сигнатурой:
public static class Extensions
{
public static void Deconstruct(
this Uri uri,
out string scheme,
out string host,
out string path,
out string query,
out string fragment)
{
scheme = uri.Scheme;
host = uri.Host;
path = uri.AbsolutePath;
query = uri.Query;
fragment = uri.Fragment;
}
}
// Использование
var url =
"https://www.google.com/search?q=dotnet#ip=1";
var (scheme, host, path, query, fragment)
= new Uri(url);
Console.WriteLine($"Scheme: {scheme}"); // https
Console.WriteLine($"Host: {host}"); // google.com
Console.WriteLine($"Path: {path}"); // /search
Console.WriteLine($"Query: {query}"); // ?q=dotnet
Console.WriteLine($"Fragment: {fragment}"); // #ip=1
Это довольно нишевая функция, и она скорее про удобство, чем про необходимость. Однако если у вас есть фиксированный набор необходимых свойств типа, это может быть очень кратким способом их получения.
Источник: https://steven-giesel.com/blogPost/0775d3d3-8f90-4546-95d8-71a6b1e7b0e8/equip-3rd-party-types-with-a-deconstructor
👍25
Вы разрабатываете веб-API ASP.NET Core, который должен поддерживать форматирование ответов в как в JSON, так и в XML. По умолчанию поддерживается только форматирование в JSON. Как добавить форматирование в XML?
#Quiz #ASPNET
#Quiz #ASPNET
Anonymous Quiz
15%
Добавить опцию AcceptXml = true в промежуточное ПО AddControllers в Startup.ConfigureServices
13%
Добавить NuGet пакет Microsoft.Extensions.XmlFormatters
28%
Добавить UseXmlSerializer в Startup.Configure
44%
Добавить AddXmlSerializerFormatters в Startup.ConfigureServices
👍18👎18
День 1901. #ЧтоНовенького #Csharp13
Простая Обработка Асинхронных Задач по Мере их Завершения в .NET 9
Допустим, вам нужно обрабатывать результаты нескольких асинхронных задач по мере их завершения. Мы можем предположить, что это обращения к API, БД, файловой системе, долгие вычисления и т.п.
Например, симулируем некоторую задачу Calculate, которая выдаёт результат через случайное (от 0,5 до 5 секунд) время:
И пусть у нас есть несколько таких задач:
Если мы будем ожидать окончания всех задач, и выводить их результаты, то получим результаты в порядке очереди (от 1 до 10) вне зависимости от того, когда завершилась каждая задача, потому что мы сначала ждём завершения всех:
Более эффективно было бы ожидать завершения каждой задачи и обрабатывать её результат сразу. До сих пор существовал некоторый обходной путь, позволяющий это сделать. Примерно так:
Это работает, но логика не совсем очевидная. Кроме того, должна быть доступна операция удаления выполненной задачи (т.е. должен быть список задач).
В .NET 9 появился новый метод, позволяющий упростить эту логику, Tasks.WhenEach, который выдаёт IAsyncEnumerable. Тогда код выше сокращается до:
Теперь вы избавлены от необходимости иметь список задач в List’е (метод принимает Task<T>[], ReadOnlySpan<Task<T>>, IEnumerable<Task<T>>. Кроме того, он использует новые возможности ключевого слова params.
Аналогичная функциональность уже существует в библиотеке AsyncEx Стивена Клири. Там это метод OrderByCompletion. Поэтому можно эмулировать метод WhenEach так:
Источники:
- https://youtu.be/WqXgl8EZzcs
- https://github.com/dotnet/runtime/issues/61959
- https://devblogs.microsoft.com/pfxteam/processing-tasks-as-they-complete/
Простая Обработка Асинхронных Задач по Мере их Завершения в .NET 9
Допустим, вам нужно обрабатывать результаты нескольких асинхронных задач по мере их завершения. Мы можем предположить, что это обращения к API, БД, файловой системе, долгие вычисления и т.п.
Например, симулируем некоторую задачу Calculate, которая выдаёт результат через случайное (от 0,5 до 5 секунд) время:
async Task<int> Calculate(int order)
{
var wait = Random.Shared.Next(500, 5000);
await Task.Delay(wait);
return order;
}
И пусть у нас есть несколько таких задач:
var tasks = Enumerable.Range(1,10)
.Select(Calculate).ToList();
Если мы будем ожидать окончания всех задач, и выводить их результаты, то получим результаты в порядке очереди (от 1 до 10) вне зависимости от того, когда завершилась каждая задача, потому что мы сначала ждём завершения всех:
var results = await Task.WhenAll(tasks);
foreach (var r in results)
Console.WriteLine(r);
Более эффективно было бы ожидать завершения каждой задачи и обрабатывать её результат сразу. До сих пор существовал некоторый обходной путь, позволяющий это сделать. Примерно так:
while (tasks.Any())
{
var finished = await Task.WhenAny(tasks);
tasks.Remove(finished);
Console.WriteLine(await finished);
}
Это работает, но логика не совсем очевидная. Кроме того, должна быть доступна операция удаления выполненной задачи (т.е. должен быть список задач).
В .NET 9 появился новый метод, позволяющий упростить эту логику, Tasks.WhenEach, который выдаёт IAsyncEnumerable. Тогда код выше сокращается до:
await foreach (var finished
in Task.WhenEach(tasks))
{
Console.WriteLine(await finished);
}
Теперь вы избавлены от необходимости иметь список задач в List’е (метод принимает Task<T>[], ReadOnlySpan<Task<T>>, IEnumerable<Task<T>>. Кроме того, он использует новые возможности ключевого слова params.
Аналогичная функциональность уже существует в библиотеке AsyncEx Стивена Клири. Там это метод OrderByCompletion. Поэтому можно эмулировать метод WhenEach так:
async IAsyncEnumerable<T> WhenEach(Task<T>[] tasks) {
foreach (Task<T> task in tasks.OrderByCompletion())
yield return await task;
}
}
await foreach (var task in WhenEach(tasks))
{
Console.WriteLine(await finished);
}
Источники:
- https://youtu.be/WqXgl8EZzcs
- https://github.com/dotnet/runtime/issues/61959
- https://devblogs.microsoft.com/pfxteam/processing-tasks-as-they-complete/
👍40
День 1902. #ЗаметкиНаПолях
8 Способов Задать URL в Приложении ASP.NET Core. Начало
По умолчанию приложения ASP.NET Core в .NET 8 прослушивают URL-адрес https://localhost:5000. Рассмотрим 8 различных способов изменить его.
Существует три класса URL, которые вы можете привязать:
- Адрес обратной связи (loopback) для IPv4 и IPv6 (например,
- Конкретный IP, доступный на вашем компьютере (например,
- «Любой» IP для заданного порта (например,
- В .NET 8, помимо TCP, вы также можете прослушивать запросы по именованным каналам и сокетам Unix, но это тема для отдельного поста.
Порт является необязательным. Если его не указывать, будет использован порт по умолчанию (80 или 8080 для http и 443 для https).
Выбор варианта будет зависеть от механизма развёртывания. Если у вас несколько приложений на машине, может потребоваться указать явный IP. Если одно в контейнере, то вы можете использовать «любой» адрес, но обычно используют localhost.
Замечание: В формате «любой» IP не обязательно использовать
После выбора подходящего варианта, необходимо установить URL, к которым привязывается ASP.NET Core при запуске. Есть следующие способы:
1. UseUrls() в Program.cs.
2. WebApplication.Urls и WebApplication.Run() в Program.cs.
3. Аргументы командной строки: параметр --urls.
4. Переменные окружения для URL: DOTNET_URLS или ASPNETCORE_URLS.
5. Переменные окружения для портов: DOTNET_HTTP_PORTS или ASPNETCORE_HTTP_PORTS (и аналогично для HTTPS).
6. В appSettings.json: свойство urls.
7. В launchSettings.json: свойство applicationUrl.
8. В KestrelServerOptions.Listen() либо в IConfiguration, используя свойство Kestrel.
Далее рассмотрим их подробно.
Продолжение следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
8 Способов Задать URL в Приложении ASP.NET Core. Начало
По умолчанию приложения ASP.NET Core в .NET 8 прослушивают URL-адрес https://localhost:5000. Рассмотрим 8 различных способов изменить его.
Существует три класса URL, которые вы можете привязать:
- Адрес обратной связи (loopback) для IPv4 и IPv6 (например,
https://localhost:5000
, https://127.0.0.1:5000
или https://[::1]:5000
) в формате: {scheme}://{loopbackAddress}:{port}
- Конкретный IP, доступный на вашем компьютере (например,
https://192.168.8.31:5005
), в формате {scheme}://{IPAddress}:{port}
.- «Любой» IP для заданного порта (например,
https://*:6264
) в формате {scheme}://*:{port}
- В .NET 8, помимо TCP, вы также можете прослушивать запросы по именованным каналам и сокетам Unix, но это тема для отдельного поста.
Порт является необязательным. Если его не указывать, будет использован порт по умолчанию (80 или 8080 для http и 443 для https).
Выбор варианта будет зависеть от механизма развёртывания. Если у вас несколько приложений на машине, может потребоваться указать явный IP. Если одно в контейнере, то вы можете использовать «любой» адрес, но обычно используют localhost.
Замечание: В формате «любой» IP не обязательно использовать
*
. Подойдёт всё, что не является IP или localhost: https://*
, https://+
, https://mydomain
или https://example.org
. Все варианты прослушивают любой IP-адрес. Если вы хотите обрабатывать запросы только от определённого имени хоста, необходимо дополнительно настроить фильтрацию хостов.После выбора подходящего варианта, необходимо установить URL, к которым привязывается ASP.NET Core при запуске. Есть следующие способы:
1. UseUrls() в Program.cs.
2. WebApplication.Urls и WebApplication.Run() в Program.cs.
3. Аргументы командной строки: параметр --urls.
4. Переменные окружения для URL: DOTNET_URLS или ASPNETCORE_URLS.
5. Переменные окружения для портов: DOTNET_HTTP_PORTS или ASPNETCORE_HTTP_PORTS (и аналогично для HTTPS).
6. В appSettings.json: свойство urls.
7. В launchSettings.json: свойство applicationUrl.
8. В KestrelServerOptions.Listen() либо в IConfiguration, используя свойство Kestrel.
Далее рассмотрим их подробно.
Продолжение следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
👍14
День 1903. #ЗаметкиНаПолях
8 Способов Задать URL в Приложении ASP.NET Core. Продолжение
Начало
1. UseUrls()
Первый и самый простой вариант установки URL — жёстко запрограммировать их при настройке WebApplicationBuilder с помощью UseUrls():
2. WebApplication.Urls и WebApplication.Run()
WebApplication предоставляет свойство Urls:
Аналогичного эффекта можно достичь, передав URL в app.Run():
Однако в app.Run() вы можете предоставить только один URL.
Жёсткое кодирование URL не особенно чистое или расширяемое решение, поэтому оно используется редко. Чаще URL задают через конфигурацию приложения.
ASP.NET Core имеет расширяемую систему конфигурации, которая может загружать значения из нескольких источников конфигурации. По умолчанию ConfigurationManager, используемый в .NET 8, загружает значения из следующих мест:
- файл appsettings.json,
- необязательный файл для конкретной среды: appsettings.ENVIRONMENT.json,
- пользовательские секреты,
- переменные среды,
- аргументы командной строки
Вы можете добавить дополнительных поставщиков для загрузки из других мест. Вы можете использовать эту систему для загрузки настроек приложения, но ASP.NET Core также использует её для настройки своих внутренних компонентов.
3. Аргументы командной строки
Аргументы командной строки по умолчанию переопределяют значения всех других параметров конфигурации. Передайте переменную в качестве аргумента при запуске приложения, добавив префикс
Можно передать несколько значений, разделённых точкой с запятой:
Это также работает и в среде выполнения dotnet, где вы передаёте путь к скомпилированной dll в dotnet вместо использования dotnet run:
Аналогично можно задать порты --http_ports и --https_ports:
Заметьте, что лишние -- в команде dotnet run не являются опечаткой; они необходимы для того, чтобы аргументы определённо интерпретировались как аргументы для конфигурации, а не как аргументы самой команды run.
Продолжение следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
8 Способов Задать URL в Приложении ASP.NET Core. Продолжение
Начало
1. UseUrls()
Первый и самый простой вариант установки URL — жёстко запрограммировать их при настройке WebApplicationBuilder с помощью UseUrls():
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls(
"https://localhost:5003",
"https://localhost:5004");
var app = builder.Build();
…
app.Run();
2. WebApplication.Urls и WebApplication.Run()
WebApplication предоставляет свойство Urls:
…
var app = builder.Build();
…
app.Urls.Add("https://*:5003");
app.Run();
Аналогичного эффекта можно достичь, передав URL в app.Run():
app.Run("https://*:5003");
Однако в app.Run() вы можете предоставить только один URL.
Жёсткое кодирование URL не особенно чистое или расширяемое решение, поэтому оно используется редко. Чаще URL задают через конфигурацию приложения.
ASP.NET Core имеет расширяемую систему конфигурации, которая может загружать значения из нескольких источников конфигурации. По умолчанию ConfigurationManager, используемый в .NET 8, загружает значения из следующих мест:
- файл appsettings.json,
- необязательный файл для конкретной среды: appsettings.ENVIRONMENT.json,
- пользовательские секреты,
- переменные среды,
- аргументы командной строки
Вы можете добавить дополнительных поставщиков для загрузки из других мест. Вы можете использовать эту систему для загрузки настроек приложения, но ASP.NET Core также использует её для настройки своих внутренних компонентов.
3. Аргументы командной строки
Аргументы командной строки по умолчанию переопределяют значения всех других параметров конфигурации. Передайте переменную в качестве аргумента при запуске приложения, добавив префикс
--
:dotnet run -- --urls "https://localhost:5100"
Можно передать несколько значений, разделённых точкой с запятой:
dotnet run -- --urls "https://*:5100;https://localhost:5101"
Это также работает и в среде выполнения dotnet, где вы передаёте путь к скомпилированной dll в dotnet вместо использования dotnet run:
dotnet ./WebApplication1.dll --urls "https://*:5100;https://localhost:5101"
Аналогично можно задать порты --http_ports и --https_ports:
dotnet run -- --http_ports "5100;5101" --https_ports "5003;5004"
Заметьте, что лишние -- в команде dotnet run не являются опечаткой; они необходимы для того, чтобы аргументы определённо интерпретировались как аргументы для конфигурации, а не как аргументы самой команды run.
Продолжение следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
👍19
День 1904. #ЗаметкиНаПолях
8 Способов Задать URL в Приложении ASP.NET Core. Продолжение
Начало
Способы 1-3
4. Переменные окружения
ASP.NET Core добавляет в систему конфигурации всё нижеследующее:
- Все переменные окружения.
- Переменные с префиксом DOTNET_ (без префикса).
- В приложениях ASP.NET Core (кроме сервисов, созданных через HostApplicationBuilder) переменные с префиксом ASPNETCORE_ (без префикса).
Таким образом, можно задать любой вариант переменной окружения для URL: URLS, ASPNETCORE_URLS или DOTNET_URLS.
Вы можете установить переменные окружения обычным способом в зависимости от вашей среды:
PowerShell:
Bash:
Можно передавать несколько адресов (для HTTP и HTTPS), разделяя их точкой с запятой.
5. Переменные окружения для портов
В .NET 8 добавлены новые ключи конфигурации. Вместо указания URL вы указываете HTTP_PORTS и HTTPS_PORTS, и они используются для привязки любого IP-адреса. Можно указать несколько портов, используя точку с запятой. Например, следующие переменные окружения:
Соответствуют привязке следующих URL:
Точно так же можно использовать префиксы ASPNETCORE_ и DOTNET_.
Замечание: если вы добавите значения и для PORTS, и для URLS, URLS будет иметь приоритет, и будет записано предупреждение:
warn: Microsoft.AspNetCore.Hosting.Diagnostics[15]
Overriding HTTP_PORTS '5002' and HTTPS_PORTS ''. Binding to values defined by URLS instead 'https://*:5003'.
В образах докера с .NET 8 переменная ASPNETCORE_HTTP_PORTS по умолчанию установлена в 8080 (в предыдущих версиях была ASPNETCORE_URLS).
6. appsettings.json
appsettings.json и файлы appsettings.<Environment>.json, специфичные для среды, включены практически в каждый шаблон приложения .NET и предоставляют простой способ добавления значений в систему конфигурации ASP.NET Core.
Используем те же самые ключи urls:
или http_ports и https_ports:
Если вы хотите использовать разные порты при разработке и в производстве, можно использовать appsettings.json в производстве и appsettings.Development.json для разработки.
Продолжение следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
8 Способов Задать URL в Приложении ASP.NET Core. Продолжение
Начало
Способы 1-3
4. Переменные окружения
ASP.NET Core добавляет в систему конфигурации всё нижеследующее:
- Все переменные окружения.
- Переменные с префиксом DOTNET_ (без префикса).
- В приложениях ASP.NET Core (кроме сервисов, созданных через HostApplicationBuilder) переменные с префиксом ASPNETCORE_ (без префикса).
Таким образом, можно задать любой вариант переменной окружения для URL: URLS, ASPNETCORE_URLS или DOTNET_URLS.
Вы можете установить переменные окружения обычным способом в зависимости от вашей среды:
setx ASPNETCORE_URLS "https://localhost:5001"
PowerShell:
$Env:ASPNETCORE_URLS="https://localhost:5001"
Bash:
export ASPNETCORE_URLS="https://localhost:5001;https://localhost:5002"
Можно передавать несколько адресов (для HTTP и HTTPS), разделяя их точкой с запятой.
5. Переменные окружения для портов
В .NET 8 добавлены новые ключи конфигурации. Вместо указания URL вы указываете HTTP_PORTS и HTTPS_PORTS, и они используются для привязки любого IP-адреса. Можно указать несколько портов, используя точку с запятой. Например, следующие переменные окружения:
HTTP_PORTS=5001;5002
HTTPS_PORTS=5003
Соответствуют привязке следующих URL:
https://*:5001
https://*:5002
https://*:5003
Точно так же можно использовать префиксы ASPNETCORE_ и DOTNET_.
Замечание: если вы добавите значения и для PORTS, и для URLS, URLS будет иметь приоритет, и будет записано предупреждение:
warn: Microsoft.AspNetCore.Hosting.Diagnostics[15]
Overriding HTTP_PORTS '5002' and HTTPS_PORTS ''. Binding to values defined by URLS instead 'https://*:5003'.
В образах докера с .NET 8 переменная ASPNETCORE_HTTP_PORTS по умолчанию установлена в 8080 (в предыдущих версиях была ASPNETCORE_URLS).
6. appsettings.json
appsettings.json и файлы appsettings.<Environment>.json, специфичные для среды, включены практически в каждый шаблон приложения .NET и предоставляют простой способ добавления значений в систему конфигурации ASP.NET Core.
Используем те же самые ключи urls:
{
"urls": "https://*:5003",
…
}
или http_ports и https_ports:
{
"http_ports": "5001;5002",
"https_ports": "5003",
…
}
Если вы хотите использовать разные порты при разработке и в производстве, можно использовать appsettings.json в производстве и appsettings.Development.json для разработки.
Продолжение следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
👍7
День 1905. #ЗаметкиНаПолях
8 Способов Задать URL в Приложении ASP.NET Core. Продолжение
Начало
Способы 1-3
Способы 4-6
7. launchSettings.json
Помимо файла appsettings.json, большинство шаблонов проектов .NET также включают файл launchSettings.json в папке Properties. Этот файл не добавляет значений в конфигурацию, а содержит различные профили для запуска разрабатываемого приложения в dotnet run. Он управляет выпадающим списком отладки в Visual Studio.
Типичный файл содержит определения для запуска профиля из командной строки и из IIS Express:
Как видите, launchSettings.json также предоставляет простой способ установки дополнительных переменных окружения в environmentVariables.
Когда вы запускаете приложение из командной строки с помощью dotnet run, оно будет использовать свойства applicationUrl из команды Project:
Этот файл — самый простой способ настроить среду при локальной разработке. Чтобы запустить приложение без использования launchSettings.json, нужно добавить параметр:
Окончание следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
8 Способов Задать URL в Приложении ASP.NET Core. Продолжение
Начало
Способы 1-3
Способы 4-6
7. launchSettings.json
Помимо файла appsettings.json, большинство шаблонов проектов .NET также включают файл launchSettings.json в папке Properties. Этот файл не добавляет значений в конфигурацию, а содержит различные профили для запуска разрабатываемого приложения в dotnet run. Он управляет выпадающим списком отладки в Visual Studio.
Типичный файл содержит определения для запуска профиля из командной строки и из IIS Express:
{
…
"iisSettings": {
…
"iisExpress": {
// URL для профиля IIS Express
"applicationUrl": "https://localhost:49412",
"sslPort": 44381
}
},
"profiles": {
// профиль только HTTP
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:5005",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
// профиль HTTP и HTTPS
"https": {
// аналогично "http"
…
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Как видите, launchSettings.json также предоставляет простой способ установки дополнительных переменных окружения в environmentVariables.
Когда вы запускаете приложение из командной строки с помощью dotnet run, оно будет использовать свойства applicationUrl из команды Project:
https://localhost:5005
в профиле http выше. В IISExpress - будет использовать applicationUrl из узла iisSettings.iisExpress: https://localhost:49412
.Этот файл — самый простой способ настроить среду при локальной разработке. Чтобы запустить приложение без использования launchSettings.json, нужно добавить параметр:
dotnet run --no-launch-profile
Окончание следует…
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
👍11
День 1906. #ЗаметкиНаПолях
8 Способов Задать URL в Приложении ASP.NET Core. Окончание
Начало
Способы 1-3
Способы 4-6
Способ 7
8. KestrelServerOptions.Listen()
Kestrel настроен по умолчанию в большинстве приложений ASP.NET Core. При желании вы можете настроить конечные точки для Kestrel, если вам требуется тонкая настройка, например, сертификатов HTTPS, протоколов SSL/TLS и комбинаций шифров, а также конфигураций SNI. Доступно множество вариантов конфигурации (см. документацию).
Например, вы можете использовать функции Listen(), предоставляемые KestrelServerOptions, следующим образом:
Эта конфигурация устанавливает прослушивание по нескольким адресам. Когда вы так устанавливаете URL для Kestrel таким образом, они переопределяют значения из конфигурации и вы получите предупреждение об этом в логах.
Но и конфигурацию Kestrel можно привязать с помощью IConfiguration, аналогично urls или http_ports. Например, приведенную выше конфигурацию Kestrel можно настроить в appsettings.json:
Это позволяет полностью настроить привязку вашего приложения и конфигурацию сертификата HTTPS из IConfiguration. Т.е. вы можете воспользоваться безопасным секретным хранилищем, например Key Vault, для хранения сертификатов и паролей сертификатов.
Если вы используете конфигурацию appsettings.json, указанную выше, не нужно вызывать ConfigureKestrel().
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
8 Способов Задать URL в Приложении ASP.NET Core. Окончание
Начало
Способы 1-3
Способы 4-6
Способ 7
8. KestrelServerOptions.Listen()
Kestrel настроен по умолчанию в большинстве приложений ASP.NET Core. При желании вы можете настроить конечные точки для Kestrel, если вам требуется тонкая настройка, например, сертификатов HTTPS, протоколов SSL/TLS и комбинаций шифров, а также конфигураций SNI. Доступно множество вариантов конфигурации (см. документацию).
Например, вы можете использовать функции Listen(), предоставляемые KestrelServerOptions, следующим образом:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(opts =>
{
opts.Listen(IPAddress.Loopback, port: 5002);
opts.ListenAnyIP(5003);
opts.ListenLocalhost(5004,
listenOptions => listenOptions.UseHttps());
opts.ListenAnyIP(5005,
listenOptions =>
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
var app = builder.Build();
…
Эта конфигурация устанавливает прослушивание по нескольким адресам. Когда вы так устанавливаете URL для Kestrel таким образом, они переопределяют значения из конфигурации и вы получите предупреждение об этом в логах.
Но и конфигурацию Kestrel можно привязать с помощью IConfiguration, аналогично urls или http_ports. Например, приведенную выше конфигурацию Kestrel можно настроить в appsettings.json:
{
"Kestrel": {
"Endpoints": {
"HttpLoopback": {
"Url": "https://localhost:5002"
},
"HttpAny": {
"Url": "https://*:5003"
},
"HttpsDefaultCert": {
"Url": "https://localhost:5004"
},
"HttpsInlineCertFile": {
"Url": "https://*:5005",
"Certificate": {
"Path": "testCert.pfx",
"Password": "testPassword"
}
}
}
}
}
Это позволяет полностью настроить привязку вашего приложения и конфигурацию сертификата HTTPS из IConfiguration. Т.е. вы можете воспользоваться безопасным секретным хранилищем, например Key Vault, для хранения сертификатов и паролей сертификатов.
Если вы используете конфигурацию appsettings.json, указанную выше, не нужно вызывать ConfigureKestrel().
Источник: https://andrewlock.net/8-ways-to-set-the-urls-for-an-aspnetcore-app/
👍7
День 1907. #Карьера
Просить о Помощи — Основной Навык Разработчика
В одном из форумов Reddit был пост, где автор рассказал, что испытывает трудности в работе. Он застрял с проблемой уже на 3 недели и беспокоился, что скажет начальник, когда узнает. Он переживал, что взялся за что-то слишком сложное и не довёл до конца.
Как мы учим детей становиться взрослыми? Мы пытаемся помочь им стать теми, кем, по нашему мнению, они могут быть. Не нужно специально подталкивать их становиться инженерами, учёными или врачами. Задача родителя - научить их быть вдумчивыми, организованными и, конечно же, уметь просить о помощи.
Индивидуалисты часто теряют понимание, что мы не можем существовать сами по себе. Мне потребовалось много времени, чтобы усвоить это. Я хотел всего добиваться сам. Мне не приходило в голову, что я добьюсь большего, если другие люди помогут мне.
Разработчики увлечены своей работой, потому что, по сути, разработка — это решение головоломок. Эти головоломки становятся нашей собственностью, и может быть трудно позволить другим играть с ними.
Каждый раз, когда вы застреваете, вы на самом деле карабкаетесь вверх по кривой обучения. Для тех, кто учится, есть утешение в осознании того, что при достаточной настойчивости, если они просто продолжат идти вперёд, в итоге они это преодолеют. Так учился я. Иногда это занимает много времени, но меня это устраивает.
Но сегодня я, вероятно, стал бы лучшим разработчиком, если бы в начале карьеры тратил больше времени на просьбы о помощи. Я работал с превосходными разработчиками и сожалею, что не спрашивал у них совета чаще. Большая часть ценности заключалась бы не в решении конкретной проблемы, а в том, чтобы лучше понять, как опытные профессионалы решали подобные проблемы, разбивали вещи на части и выстраивали решения. Недели, которые я тратил на решение проблем самостоятельно, я мог бы учиться у умных, успешных людей с большим опытом.
Иногда вы получаете задачу, которая не соответствует вашим ограничениям: времени, ресурсам, часто знаниям и опыту. Когда вы берётесь за проблему, вы не знаете, каким будет решение. Вы тыкаетесь туда и сюда, находите её края и заполняете пробелы, пока не получите чёткое представление, на какую головоломку вы смотрите. Чем меньше у вас опыта в конкретной области, тем дольше это займёт. Такова природа обучения по ходу дела, и так мы развиваемся.
В личном контексте это нормально. Всё занимает столько времени, сколько нужно, и цель в том, чтобы накопить знания и превратить идеи в продукты. В профессиональном контексте это может быть проблемой. В компании необходимо найти баланс между свободой для творчества разработчиков и задачами бизнеса.
Вам придётся установить ограничения на то, сколько времени вы потратите, пытаясь добиться успеха самостоятельно, прежде чем обратиться к коллегам с просьбой о помощи. Это один из основных принципов Agile-разработки: блокирующие факторы следует выявлять как можно раньше, чтобы команда могла вместе с ними справиться. В компании мы действуем как пул знаний о бизнесе и коде. Если ответа нет в вашей голове, он, скорее всего, есть в чьей-то другой. Индивидуалист часто проводит слишком много времени в тупике, и это отрицательно влияет как на продукт, над которым он работает, так и на бизнес, который платит ему зарплату. Подходящее время для обращения за помощью – раньше, а не позже.
В жизни нас часто приучают к индивидуальному успеху. В школе оценивают не успехи класса, а ваши индивидуальные. Мы учим детей добиваться успеха как личности. Но это плохо отражает то, как на самом деле устроен мир. Я никто без поддержки жены, друзей и группы, в которой работаю. Успешное ПО — это не о вас и не о головоломках, которые вы можете решить. Просить о помощи – ключевой навык. Он может помочь гарантировать, что продукт, который вы создаёте, увидит свет, и, что вы продолжите прогрессировать как разработчик.
Источник: https://www.ramijames.com/thoughts/asking-for-help-is-a-core-skill
Просить о Помощи — Основной Навык Разработчика
В одном из форумов Reddit был пост, где автор рассказал, что испытывает трудности в работе. Он застрял с проблемой уже на 3 недели и беспокоился, что скажет начальник, когда узнает. Он переживал, что взялся за что-то слишком сложное и не довёл до конца.
Как мы учим детей становиться взрослыми? Мы пытаемся помочь им стать теми, кем, по нашему мнению, они могут быть. Не нужно специально подталкивать их становиться инженерами, учёными или врачами. Задача родителя - научить их быть вдумчивыми, организованными и, конечно же, уметь просить о помощи.
Индивидуалисты часто теряют понимание, что мы не можем существовать сами по себе. Мне потребовалось много времени, чтобы усвоить это. Я хотел всего добиваться сам. Мне не приходило в голову, что я добьюсь большего, если другие люди помогут мне.
Разработчики увлечены своей работой, потому что, по сути, разработка — это решение головоломок. Эти головоломки становятся нашей собственностью, и может быть трудно позволить другим играть с ними.
Каждый раз, когда вы застреваете, вы на самом деле карабкаетесь вверх по кривой обучения. Для тех, кто учится, есть утешение в осознании того, что при достаточной настойчивости, если они просто продолжат идти вперёд, в итоге они это преодолеют. Так учился я. Иногда это занимает много времени, но меня это устраивает.
Но сегодня я, вероятно, стал бы лучшим разработчиком, если бы в начале карьеры тратил больше времени на просьбы о помощи. Я работал с превосходными разработчиками и сожалею, что не спрашивал у них совета чаще. Большая часть ценности заключалась бы не в решении конкретной проблемы, а в том, чтобы лучше понять, как опытные профессионалы решали подобные проблемы, разбивали вещи на части и выстраивали решения. Недели, которые я тратил на решение проблем самостоятельно, я мог бы учиться у умных, успешных людей с большим опытом.
Иногда вы получаете задачу, которая не соответствует вашим ограничениям: времени, ресурсам, часто знаниям и опыту. Когда вы берётесь за проблему, вы не знаете, каким будет решение. Вы тыкаетесь туда и сюда, находите её края и заполняете пробелы, пока не получите чёткое представление, на какую головоломку вы смотрите. Чем меньше у вас опыта в конкретной области, тем дольше это займёт. Такова природа обучения по ходу дела, и так мы развиваемся.
В личном контексте это нормально. Всё занимает столько времени, сколько нужно, и цель в том, чтобы накопить знания и превратить идеи в продукты. В профессиональном контексте это может быть проблемой. В компании необходимо найти баланс между свободой для творчества разработчиков и задачами бизнеса.
Вам придётся установить ограничения на то, сколько времени вы потратите, пытаясь добиться успеха самостоятельно, прежде чем обратиться к коллегам с просьбой о помощи. Это один из основных принципов Agile-разработки: блокирующие факторы следует выявлять как можно раньше, чтобы команда могла вместе с ними справиться. В компании мы действуем как пул знаний о бизнесе и коде. Если ответа нет в вашей голове, он, скорее всего, есть в чьей-то другой. Индивидуалист часто проводит слишком много времени в тупике, и это отрицательно влияет как на продукт, над которым он работает, так и на бизнес, который платит ему зарплату. Подходящее время для обращения за помощью – раньше, а не позже.
В жизни нас часто приучают к индивидуальному успеху. В школе оценивают не успехи класса, а ваши индивидуальные. Мы учим детей добиваться успеха как личности. Но это плохо отражает то, как на самом деле устроен мир. Я никто без поддержки жены, друзей и группы, в которой работаю. Успешное ПО — это не о вас и не о головоломках, которые вы можете решить. Просить о помощи – ключевой навык. Он может помочь гарантировать, что продукт, который вы создаёте, увидит свет, и, что вы продолжите прогрессировать как разработчик.
Источник: https://www.ramijames.com/thoughts/asking-for-help-is-a-core-skill
👍33
День 1908. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 5. Разработка требований — итеративный процесс
Тщательное изучение требований важно перед тем, как начнётся написание кода. Но в процессе разработки ПО для других людей часто могут возникать вопросы и обнаруживаться пробелы в знаниях. Приходится возвращаться к клиентам, чтобы прояснить задачи, освежить информацию в памяти и закрыть пробелы. Клиенты не всегда рады видеть вас снова, но разработка требований — итеративный и поэтапный процесс.
Важно понять общее направление движения, прежде чем приступать к написанию кода, но сложно заранее узнать все требования или продумать все детали даже для небольшого приложения. В этом нет ничего страшного. Нужно достаточно информации, чтобы начать.
Эффективная разработка требований подразумевает постепенное уточнение требований и их деталей. Получите достаточно точную информацию о требованиях, прежде чем создавать какую-либо часть продукта, иначе придётся создавать её заново. Вот примерный процесс:
1. Разработайте предварительный список пользовательских требований. Узнайте достаточное количество подробностей о каждом из них, чтобы понять их объём и относительную важность.
2. Распределите требования по циклам разработки в зависимости от их приоритета.
3. Продолжите выявлять и уточнять детали тех требований, реализация которых запланирована в ближайшем цикле разработки.
4. Перераспределите приоритеты, добавляя любые новые требования, и двигайтесь вниз по списку приоритетов по мере разработки.
5. Вернитесь к шагу 2 и повторите.
Постоянная расстановка приоритетов играет важную роль, поскольку нет смысла углубляться в детали требований, реализация которых не горит. По мере развития проекта некоторые потребности могут отойти на второй план или стать неактуальными.
Возникающие функциональные требования
Когда люди начинают использовать ПО, у них появляются новые идеи. Если они достаточно важны, то потребуется изменить систему, чтобы добавить их. Независимо от жизненного цикла разработки планы проектов должны учитывать это естественное и полезное расширение требований.
Мы можем использовать разные методы для выявления некоторых возникающих требований, например, создать несколько представлений требований.
1) Вместо записи сценариев использования и историй нарисуйте несколько картинок. Визуальные модели описывают требования на более высоком уровне абстракции, позволяют отвлечься от деталей и увидеть более широкую картину рабочего процесса и взаимосвязей.
2) Тесты на ранней стадии помогут обнаружить неясности и ошибки в требованиях, либо отсутствующие требования, например необработанные исключения. Можно заметить, что некоторые требования не нужны, если нельзя придумать тесты, требующие их реализации. Это легло в основу разработки через тестирование.
3) Благодаря прототипам пользователи получают нечто осязаемое. Инкрементное прототипирование ускоряет обсуждение требований и помогает пользователям находить ошибки и упущения в требованиях до того, как на создание продукта будет затрачено слишком много усилий.
Возникающие нефункциональные требования
Детали некоторых нефункциональных требований тоже трудно выяснить на ранней стадии. Не ждите осмысленного ответа, когда впервые спросите: «Каковы ваши требования к удобству использования?» Начните с осознания важности удобства. Со временем вы расширите это осознание до понимания различных аспектов и в итоге определите целевые характеристики каждого из таких требований.
Итого
Формирование полезного набора требований любого рода требует терпения для переосмысления, повторных попыток и накопления знаний, необходимых для создания правильного продукта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 5. Разработка требований — итеративный процесс
Тщательное изучение требований важно перед тем, как начнётся написание кода. Но в процессе разработки ПО для других людей часто могут возникать вопросы и обнаруживаться пробелы в знаниях. Приходится возвращаться к клиентам, чтобы прояснить задачи, освежить информацию в памяти и закрыть пробелы. Клиенты не всегда рады видеть вас снова, но разработка требований — итеративный и поэтапный процесс.
Важно понять общее направление движения, прежде чем приступать к написанию кода, но сложно заранее узнать все требования или продумать все детали даже для небольшого приложения. В этом нет ничего страшного. Нужно достаточно информации, чтобы начать.
Эффективная разработка требований подразумевает постепенное уточнение требований и их деталей. Получите достаточно точную информацию о требованиях, прежде чем создавать какую-либо часть продукта, иначе придётся создавать её заново. Вот примерный процесс:
1. Разработайте предварительный список пользовательских требований. Узнайте достаточное количество подробностей о каждом из них, чтобы понять их объём и относительную важность.
2. Распределите требования по циклам разработки в зависимости от их приоритета.
3. Продолжите выявлять и уточнять детали тех требований, реализация которых запланирована в ближайшем цикле разработки.
4. Перераспределите приоритеты, добавляя любые новые требования, и двигайтесь вниз по списку приоритетов по мере разработки.
5. Вернитесь к шагу 2 и повторите.
Постоянная расстановка приоритетов играет важную роль, поскольку нет смысла углубляться в детали требований, реализация которых не горит. По мере развития проекта некоторые потребности могут отойти на второй план или стать неактуальными.
Возникающие функциональные требования
Когда люди начинают использовать ПО, у них появляются новые идеи. Если они достаточно важны, то потребуется изменить систему, чтобы добавить их. Независимо от жизненного цикла разработки планы проектов должны учитывать это естественное и полезное расширение требований.
Мы можем использовать разные методы для выявления некоторых возникающих требований, например, создать несколько представлений требований.
1) Вместо записи сценариев использования и историй нарисуйте несколько картинок. Визуальные модели описывают требования на более высоком уровне абстракции, позволяют отвлечься от деталей и увидеть более широкую картину рабочего процесса и взаимосвязей.
2) Тесты на ранней стадии помогут обнаружить неясности и ошибки в требованиях, либо отсутствующие требования, например необработанные исключения. Можно заметить, что некоторые требования не нужны, если нельзя придумать тесты, требующие их реализации. Это легло в основу разработки через тестирование.
3) Благодаря прототипам пользователи получают нечто осязаемое. Инкрементное прототипирование ускоряет обсуждение требований и помогает пользователям находить ошибки и упущения в требованиях до того, как на создание продукта будет затрачено слишком много усилий.
Возникающие нефункциональные требования
Детали некоторых нефункциональных требований тоже трудно выяснить на ранней стадии. Не ждите осмысленного ответа, когда впервые спросите: «Каковы ваши требования к удобству использования?» Начните с осознания важности удобства. Со временем вы расширите это осознание до понимания различных аспектов и в итоге определите целевые характеристики каждого из таких требований.
Итого
Формирование полезного набора требований любого рода требует терпения для переосмысления, повторных попыток и накопления знаний, необходимых для создания правильного продукта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
👍10
День 1909. #ЧтоНовенького
OpenTelemetry SDK от Elastic с Открытым Кодом для .NET
Elastic объявили об выпуске альфа-версии пакета OpenTelemetry SDK для .NET. Он настраивает сбор трассировки, метрик и логов, а также гарантирует, что экспортёр OTLP включен по умолчанию. Проект имеет открытый исходный код.
Чтобы начать работу с Elastic OpenTelemetry, необходимо добавить в проект ссылку на пакет NuGet Elastic OpenTelemetry:
Пакет добавляет транзитивную зависимость от OpenTelemetry SDK. Поэтому нет необходимости добавлять в проект OpenTelemetry SDK.
Чтобы воспользоваться преимуществами инструментария OpenTelemetry SDK для ASP.NET Core, разработчикам также следует добавить пакет NuGet OpenTelemetry.Instrumentation.AspNetCore. Он включает поддержку сбора инструментов (трассировок и метрик) для запросов, обрабатываемых конечными точками ASP.NET Core. Пакет SDK OpenTelemetry содержит методы расширения IServiceCollection для включения и настройки поставщиков трассировки, метрик и логов. Elastic переопределяет регистрацию SDK по умолчанию.
Как минимум необходимо настроить две переменные окружения: OTEL_EXPORTER_OTLP_ENDPOINT и OTEL_EXPORTER_OTLP_HEADERS. Elastic автоматически позволит экспортировать сигналы телеметрии с помощью экспортёра OTLP. Для экспортёра OTLP требуется настроить хотя бы одну конечную точку.
Текущая альфа-версия дистрибутива ограничена в возможностях. Elastic сообщает, что их цель — оценить пригодность дизайна API и простоту использования. Однако они подчёркивают, что он подходит не для всех сценариев применения, поэтому не рекомендуют его использовать в производстве.
Код полностью открыт и доступен на GitHub.
Источник: https://www.infoq.com/news/2024/04/elastics-open-telemetry-net/
OpenTelemetry SDK от Elastic с Открытым Кодом для .NET
Elastic объявили об выпуске альфа-версии пакета OpenTelemetry SDK для .NET. Он настраивает сбор трассировки, метрик и логов, а также гарантирует, что экспортёр OTLP включен по умолчанию. Проект имеет открытый исходный код.
Чтобы начать работу с Elastic OpenTelemetry, необходимо добавить в проект ссылку на пакет NuGet Elastic OpenTelemetry:
<PackageReference Include="Elastic.OpenTelemetry" Version="1.0.0-alpha.1" />
Пакет добавляет транзитивную зависимость от OpenTelemetry SDK. Поэтому нет необходимости добавлять в проект OpenTelemetry SDK.
Чтобы воспользоваться преимуществами инструментария OpenTelemetry SDK для ASP.NET Core, разработчикам также следует добавить пакет NuGet OpenTelemetry.Instrumentation.AspNetCore. Он включает поддержку сбора инструментов (трассировок и метрик) для запросов, обрабатываемых конечными точками ASP.NET Core. Пакет SDK OpenTelemetry содержит методы расширения IServiceCollection для включения и настройки поставщиков трассировки, метрик и логов. Elastic переопределяет регистрацию SDK по умолчанию.
Как минимум необходимо настроить две переменные окружения: OTEL_EXPORTER_OTLP_ENDPOINT и OTEL_EXPORTER_OTLP_HEADERS. Elastic автоматически позволит экспортировать сигналы телеметрии с помощью экспортёра OTLP. Для экспортёра OTLP требуется настроить хотя бы одну конечную точку.
Текущая альфа-версия дистрибутива ограничена в возможностях. Elastic сообщает, что их цель — оценить пригодность дизайна API и простоту использования. Однако они подчёркивают, что он подходит не для всех сценариев применения, поэтому не рекомендуют его использовать в производстве.
Код полностью открыт и доступен на GitHub.
Источник: https://www.infoq.com/news/2024/04/elastics-open-telemetry-net/
👍13
День 1910. #ВопросыНаСобеседовании #ASP.NET #Architecture
Самые часто задаваемые вопросы на собеседовании по C#
31. Как бы вы подошли к обработке ошибок и отладке в распределённом приложении .NET Core с несколькими микросервисами?
Обработка ошибок и отладка в таком приложении может оказаться сложной задачей. Можно использовать несколько стратегий:
1. Централизованные логи.
Все микросервисы должны отправлять свои логи (естественно, структурированные) в централизованное место, где они сопоставляются и индексируются. Это позволит искать и визуализировать логи всех сервисов в одном месте.
2. Использование идентификаторов корреляции.
Идентификаторы корреляции (CorrelationId) — это уникальные идентификаторы, присваиваемые запросу. Затем этот идентификатор передаётся всем сервисам, участвующим в обработке этого запроса. Это позволяет отслеживать всю цепочку запросов и ответов.
3. Проверки работоспособности.
Проверки работоспособности можно реализовать для мониторинга состояния микросервисов. Они могут сообщать такие показатели, как время безотказной работы, загрузка ЦП, использование памяти и т. д.
4. Промежуточное ПО для обработки исключений.
В архитектуре микросервисов ошибки должны обрабатываться на уровне сервиса. Каждый сервис должен обрабатывать свои собственные исключения и возвращать подходящее сообщение об ошибке или код ответа.
Можно создать промежуточное ПО, которое обрабатывает каждый запрос микросервиса. Если во время выполнения запроса возникает исключение, это промежуточное ПО перехватит исключение и ответит подходящим сообщением об ошибке.
См. также «Улучшенная Обработка Исключений в ASP.NET Core 8.»
5. Использовать распределённую систему трассировки.
Она собирает данные и показатели от каждого микросервиса, а затем сопоставляет эти данные в комплексный визуальный обзор производительности системы. См. документацию.
Источник: https://dev.to/bytehide/net-core-interview-question-answers-4bc1
Самые часто задаваемые вопросы на собеседовании по C#
31. Как бы вы подошли к обработке ошибок и отладке в распределённом приложении .NET Core с несколькими микросервисами?
Обработка ошибок и отладка в таком приложении может оказаться сложной задачей. Можно использовать несколько стратегий:
1. Централизованные логи.
Все микросервисы должны отправлять свои логи (естественно, структурированные) в централизованное место, где они сопоставляются и индексируются. Это позволит искать и визуализировать логи всех сервисов в одном месте.
2. Использование идентификаторов корреляции.
Идентификаторы корреляции (CorrelationId) — это уникальные идентификаторы, присваиваемые запросу. Затем этот идентификатор передаётся всем сервисам, участвующим в обработке этого запроса. Это позволяет отслеживать всю цепочку запросов и ответов.
3. Проверки работоспособности.
Проверки работоспособности можно реализовать для мониторинга состояния микросервисов. Они могут сообщать такие показатели, как время безотказной работы, загрузка ЦП, использование памяти и т. д.
4. Промежуточное ПО для обработки исключений.
В архитектуре микросервисов ошибки должны обрабатываться на уровне сервиса. Каждый сервис должен обрабатывать свои собственные исключения и возвращать подходящее сообщение об ошибке или код ответа.
Можно создать промежуточное ПО, которое обрабатывает каждый запрос микросервиса. Если во время выполнения запроса возникает исключение, это промежуточное ПО перехватит исключение и ответит подходящим сообщением об ошибке.
См. также «Улучшенная Обработка Исключений в ASP.NET Core 8.»
5. Использовать распределённую систему трассировки.
Она собирает данные и показатели от каждого микросервиса, а затем сопоставляет эти данные в комплексный визуальный обзор производительности системы. См. документацию.
Источник: https://dev.to/bytehide/net-core-interview-question-answers-4bc1
👍21
День 1911. #ЗаметкиНаПолях
Реализуем Пессимистическую Блокировку в EF Core. Начало
Иногда, особенно в сценариях с высоким трафиком, вам абсолютно необходимо убедиться, что только один процесс может одновременно изменять какую-то часть данных.
Стандартный пример - система продажи билетов на популярное событие. При большом трафике билеты на одно место могут быть куплены одновременно несколькими людьми. В EF Core нет прямого механизма пессимистичной блокировки. Оптимистическая блокировка (с использованием версий) может работать, но в сценариях с высоким уровнем конфликтов это может привести к множеству повторных попыток.
Вот упрощённый фрагмент кода, иллюстрирующий проблему с билетами:
Пример выше надуманный, но суть понятна. Во время оформления заказа мы проверяем доступное количество для каждого типа билетов. Что, если мы получим одновременные запросы на покупку одного и того же билета? В худшем случае мы продадим билеты несколько раз. Одновременные запросы могут увидеть доступность билета и оба завершить оформление заказа.
Поскольку EF Core не предлагает пессимистическую блокировку напрямую, немного углубимся в старый добрый SQL. Заменим вызов GetAsync для получения билета на GetWithLockAsync:
Вызов GetWithLockAsync нужно обернуть в try-catch, чтобы корректно обрабатывать сбои блокировки, либо повторяя попытку, либо уведомляя пользователя.
Поскольку в EF Core нет встроенного способа добавления подсказок к запросам, приходится писать чистый SQL-запрос. Мы можем использовать оператор
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
Реализуем Пессимистическую Блокировку в EF Core. Начало
Иногда, особенно в сценариях с высоким трафиком, вам абсолютно необходимо убедиться, что только один процесс может одновременно изменять какую-то часть данных.
Стандартный пример - система продажи билетов на популярное событие. При большом трафике билеты на одно место могут быть куплены одновременно несколькими людьми. В EF Core нет прямого механизма пессимистичной блокировки. Оптимистическая блокировка (с использованием версий) может работать, но в сценариях с высоким уровнем конфликтов это может привести к множеству повторных попыток.
Вот упрощённый фрагмент кода, иллюстрирующий проблему с билетами:
public async Task Checkout(ShopCart cart)
{
await using var trans = await
context.BeginTransactionAsync();
…
var order = new Order();
foreach (CartItem item in cart.Items)
{
// Проверяем доступность билета
// Что, если два запроса проверят его в одно время?
var ticket = await ticketRepo.GetAsync(
item.TicketId);
ticket.UpdateQuantity(item.Quantity);
order.Add(ticket, item.Quantity, item.Price);
}
orderRepo.Insert(order);
await context.SaveChangesAsync();
await trans.CommitAsync();
…
}
Пример выше надуманный, но суть понятна. Во время оформления заказа мы проверяем доступное количество для каждого типа билетов. Что, если мы получим одновременные запросы на покупку одного и того же билета? В худшем случае мы продадим билеты несколько раз. Одновременные запросы могут увидеть доступность билета и оба завершить оформление заказа.
Поскольку EF Core не предлагает пессимистическую блокировку напрямую, немного углубимся в старый добрый SQL. Заменим вызов GetAsync для получения билета на GetWithLockAsync:
public async Task<Ticket> GetWithLockAsync(Guid id)
{
return await context
.Tickets
.FromSql(
$@"SELECT id, event_id, price, quantity
FROM tickets WHERE id = {id}
FOR UPDATE NOWAIT")
.SingleAsync();
}
FOR UPDATE NOWAIT
- суть пессимистической блокировки в PostgreSQL (и Oracle). Он сообщает базе данных: «Захвати эту строку, заблокируй её для меня, и, если она уже заблокирована, прямо сейчас выдай ошибку».Вызов GetWithLockAsync нужно обернуть в try-catch, чтобы корректно обрабатывать сбои блокировки, либо повторяя попытку, либо уведомляя пользователя.
Поскольку в EF Core нет встроенного способа добавления подсказок к запросам, приходится писать чистый SQL-запрос. Мы можем использовать оператор
SELECT FOR UPDATE
, чтобы получить блокировку на уровне выбранных строк. Любые конкурирующие транзакции будут заблокированы до тех пор, пока текущая транзакция не снимет блокировку. Это очень простой способ реализовать пессимистическую блокировку.Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
👍40
День 1912. #ЗаметкиНаПолях
Реализуем Пессимистическую Блокировку в EF Core. Окончание
Начало
Варианты блокировки и когда их использовать
Чтобы операция не ждала, пока другие транзакции освободят заблокированные строки, вы можете объединить
-
-
В SQL Server для аналогичного эффекта можно использовать подсказку запроса
А затем запросить блокировку только тех нужных строк:
Пессимистическая блокировка или сериализуемые транзакции
Сериализуемые транзакции - наивысший уровень согласованности данных. Они гарантируют, что транзакции выполняются так, как если бы они происходили строго последовательно, даже если происходят одновременно.
Когда транзакция начинается на уровне изоляции Serializable, БД блокирует все данные, к которым может получить доступ транзакция. Эти блокировки удерживаются до тех пор, пока вся транзакция не будет зафиксирована или отменена. Любая другая транзакция, пытающаяся получить доступ к заблокированным данным, будет заблокирована до тех пор, пока первая транзакция не снимет блокировки.
Хотя сериализуемые транзакции обеспечивают максимальную изоляцию, они сопряжены со значительными затратами:
- Блокировка большого объёма данных может серьезно повлиять на производительность, особенно в сценариях с высоким уровнем параллелизма.
- При большом количестве блокировок существует более высокий риск возникновения взаимоблокировок, когда две или более транзакции ожидают блокировок, удерживаемых друг другом.
Пессимистическая блокировка с помощью
Когда что использовать, зависит от ваших конкретных потребностей:
- Сериализуемые транзакции: идеально подходят для сценариев, связанных с конфиденциальными данными, где даже малейшее несоответствие недопустимо: финансовые операции или обновления медицинской документации.
- Пессимистическая блокировка: отличный выбор для большинства случаев использования, особенно в приложениях с высоким трафиком. Она обеспечивает высокую согласованность, сохраняя при этом хорошую производительность и снижая риски взаимоблокировок.
Итого
И сериализуемые транзакции, и пессимистическая блокировка с помощью
Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
Реализуем Пессимистическую Блокировку в EF Core. Окончание
Начало
Варианты блокировки и когда их использовать
Чтобы операция не ждала, пока другие транзакции освободят заблокированные строки, вы можете объединить
FOR UPDATE
с:-
NO WAIT
— вместо ожидания снятия блокировки, сообщает об ошибке, если строку невозможно заблокировать.-
SKIP LOCKED
— пропускает любые выбранные строки, которые нельзя заблокировать. Заметьте, что в этом случае вы будете получать противоречивые результаты из БД. Однако это может быть полезно, чтобы избежать конфликта блокировок, когда несколько потребителей обращаются к таблице, похожей на очередь. Реализация паттерна Outbox является отличным примером.В SQL Server для аналогичного эффекта можно использовать подсказку запроса
WITH (UPDLOCK, READPAST)
. Однако SQL Server блокирует все строки, которые ему необходимо прочитать, чтобы получить нужную. Таким образом, если не определить индекс для прямого доступа к строке, все предшествующие строки будут заблокированы. Допустим, есть таблица TBL с полем id. Вы хотите заблокировать строку с id=10. Необходимо определить индекс для id (или других полей, по которым выбираете):CREATE INDEX TBLINDEX ON TBL ( id );
А затем запросить блокировку только тех нужных строк:
SELECT * FROM TBL WITH (UPDLOCK, INDEX(TBLINDEX)) WHERE id=10;
Пессимистическая блокировка или сериализуемые транзакции
Сериализуемые транзакции - наивысший уровень согласованности данных. Они гарантируют, что транзакции выполняются так, как если бы они происходили строго последовательно, даже если происходят одновременно.
Когда транзакция начинается на уровне изоляции Serializable, БД блокирует все данные, к которым может получить доступ транзакция. Эти блокировки удерживаются до тех пор, пока вся транзакция не будет зафиксирована или отменена. Любая другая транзакция, пытающаяся получить доступ к заблокированным данным, будет заблокирована до тех пор, пока первая транзакция не снимет блокировки.
Хотя сериализуемые транзакции обеспечивают максимальную изоляцию, они сопряжены со значительными затратами:
- Блокировка большого объёма данных может серьезно повлиять на производительность, особенно в сценариях с высоким уровнем параллелизма.
- При большом количестве блокировок существует более высокий риск возникновения взаимоблокировок, когда две или более транзакции ожидают блокировок, удерживаемых друг другом.
Пессимистическая блокировка с помощью
SELECT FOR UPDATE
явно блокирует определённые строки, которые необходимо изменить. Другие транзакции, пытающиеся получить доступ к заблокированным строкам, блокируются до тех пор, пока блокировка не будет снята. Т.к. вы блокируете меньше ресурсов, вероятность взаимоблокировок снижается.Когда что использовать, зависит от ваших конкретных потребностей:
- Сериализуемые транзакции: идеально подходят для сценариев, связанных с конфиденциальными данными, где даже малейшее несоответствие недопустимо: финансовые операции или обновления медицинской документации.
- Пессимистическая блокировка: отличный выбор для большинства случаев использования, особенно в приложениях с высоким трафиком. Она обеспечивает высокую согласованность, сохраняя при этом хорошую производительность и снижая риски взаимоблокировок.
Итого
И сериализуемые транзакции, и пессимистическая блокировка с помощью
SELECT FOR UPDATE
— отличные варианты обеспечения согласованности данных. При выборе учитывайте требуемый уровень изоляции, потенциальное влияние на производительность и вероятность взаимоблокировок.Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
👍18
День 1913. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Начало
Многие компании, занимающиеся разработкой ПО, используют методы Agile. Бизнес-аналитики и владельцы продуктов иногда применяют термин «Agile-требования». Но они не отличаются от требований в проектах с другим подходом.
Agile подразумевает, что мы адаптируемся к неизбежным изменениям, а не воображаем, что все требования можно досконально понять на раннем этапе и они будут оставаться неизменными на протяжении всего проекта. Но проекты требуют выполнения одних и тех же шагов по работе требованиями. Кто-то должен составить список заинтересованных сторон, собрать требования из различных источников и подтвердить, что решение, основанное на этих требованиях, достигнет бизнес-целей проекта. Основные различия в обработке требований в Agile- и традиционных проектах можно разделить на несколько категорий.
1. Роли и обязанности
В состав большинства традиционных проектных групп входит один или несколько бизнес-аналитиков, которые отвечают за работу по выявлению требований к проекту, анализу, спецификации, проверке и управлению или возглавляют её. Во многих Agile-проектах отсутствует официальная должность бизнес-аналитика. Разработка требований — совместный процесс, в котором участвуют владелец продукта, представители пользователей и другие заинтересованные стороны. Но за полноту информации в историях ответственность несут разработчики, а не бизнес-аналитики.
2. Терминология
Традиционные подходы обычно основаны на вариантах использования и функциональных требованиях. В Agile используют пользовательские истории, обобщенные описания функций или задач, разбитые на более мелкие пользовательские истории, приёмочные тесты и пожелания клиентов. Но это те же самые знания о требованиях, просто они по-другому называются.
3. Детальность документации
Agile-методы полагаются на доступность документации в нужный момент. Благодаря тесному сотрудничеству клиентов с разработчиками в Agile-проектах требования могут содержать меньше деталей, чем в традиционных проектах. Заинтересованные стороны могут сообщить все необходимые детали, когда это действительно потребуется, на встречах и в соответствующей документации. Некоторые пользовательские истории могут содержать мало подробностей, а сложные или важные функции могут прорабатываться более детально. Но не стоит чрезмерно полагаться только на устное общение. Каждой проектной группе необходимо создать достаточный объём документации, позволяющей решать задачи поддержки и совершенствования системы, но при этом не тратить время на запись информации, которую никто не будет использовать.
4. Время выполнения действий
Традиционные подходы предполагают создание довольно полного списка требований на ранней стадии проекта. Agile-команды предпочитают детализировать требования непосредственно перед реализацией определённой части функциональности. Это снижает риск того, что информация устареет или требования станут неактуальны, но затрудняет выявление зависимостей между требованиями и потенциальными архитектурными последствиями, которые желательно устранять как можно раньше, чтобы обеспечить стабильное развитие продукта. Agile-команды должны на ранних итерациях рассмотреть широкий спектр вопросов и подумать, какие важные архитектурные решения могут потребоваться. Также как можно раньше нужно начать изучение нефункциональных требований, чтобы проект достиг высокой производительности, доступности и других важных целей.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Начало
Многие компании, занимающиеся разработкой ПО, используют методы Agile. Бизнес-аналитики и владельцы продуктов иногда применяют термин «Agile-требования». Но они не отличаются от требований в проектах с другим подходом.
Agile подразумевает, что мы адаптируемся к неизбежным изменениям, а не воображаем, что все требования можно досконально понять на раннем этапе и они будут оставаться неизменными на протяжении всего проекта. Но проекты требуют выполнения одних и тех же шагов по работе требованиями. Кто-то должен составить список заинтересованных сторон, собрать требования из различных источников и подтвердить, что решение, основанное на этих требованиях, достигнет бизнес-целей проекта. Основные различия в обработке требований в Agile- и традиционных проектах можно разделить на несколько категорий.
1. Роли и обязанности
В состав большинства традиционных проектных групп входит один или несколько бизнес-аналитиков, которые отвечают за работу по выявлению требований к проекту, анализу, спецификации, проверке и управлению или возглавляют её. Во многих Agile-проектах отсутствует официальная должность бизнес-аналитика. Разработка требований — совместный процесс, в котором участвуют владелец продукта, представители пользователей и другие заинтересованные стороны. Но за полноту информации в историях ответственность несут разработчики, а не бизнес-аналитики.
2. Терминология
Традиционные подходы обычно основаны на вариантах использования и функциональных требованиях. В Agile используют пользовательские истории, обобщенные описания функций или задач, разбитые на более мелкие пользовательские истории, приёмочные тесты и пожелания клиентов. Но это те же самые знания о требованиях, просто они по-другому называются.
3. Детальность документации
Agile-методы полагаются на доступность документации в нужный момент. Благодаря тесному сотрудничеству клиентов с разработчиками в Agile-проектах требования могут содержать меньше деталей, чем в традиционных проектах. Заинтересованные стороны могут сообщить все необходимые детали, когда это действительно потребуется, на встречах и в соответствующей документации. Некоторые пользовательские истории могут содержать мало подробностей, а сложные или важные функции могут прорабатываться более детально. Но не стоит чрезмерно полагаться только на устное общение. Каждой проектной группе необходимо создать достаточный объём документации, позволяющей решать задачи поддержки и совершенствования системы, но при этом не тратить время на запись информации, которую никто не будет использовать.
4. Время выполнения действий
Традиционные подходы предполагают создание довольно полного списка требований на ранней стадии проекта. Agile-команды предпочитают детализировать требования непосредственно перед реализацией определённой части функциональности. Это снижает риск того, что информация устареет или требования станут неактуальны, но затрудняет выявление зависимостей между требованиями и потенциальными архитектурными последствиями, которые желательно устранять как можно раньше, чтобы обеспечить стабильное развитие продукта. Agile-команды должны на ранних итерациях рассмотреть широкий спектр вопросов и подумать, какие важные архитектурные решения могут потребоваться. Также как можно раньше нужно начать изучение нефункциональных требований, чтобы проект достиг высокой производительности, доступности и других важных целей.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
👍3
Разожжём вечный спор вечером в пятницу с подачи Ника)))
Не учитывая кодстайл компании, какой вариант лично вам больше по душе (см. картинку в первом комментарии)?
Не учитывая кодстайл компании, какой вариант лично вам больше по душе (см. картинку в первом комментарии)?
Anonymous Poll
32%
1
11%
2
9%
3
49%
4
👍2
День 1914. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Окончание
Начало
5. Итоговое оформление требований
В общем случае пользовательские истории похожи на сценарии использования. Разница лишь в том, насколько тщательно вы их детализируете и записываете ли информацию. В традиционном проекте бизнес-аналитик может разработать набор функциональных требований на основе сценариев использования. Agile-команды конкретизируют каждую пользовательскую историю, определяя критерии приёмки и тесты, которые покажут, правильно ли разработчики реализовали её.
Функциональные требования и соответствующие им тесты — альтернативные варианты представления одной и той же информации. Требования определяют, что создавать; тесты описывают, как выяснить, демонстрирует ли система ожидаемое поведение. Наилучшие результаты получаются, когда разные люди пишут требования и тесты на основе одного и того же источника информации, например сценария использования.
Можно прибегнуть к альтернативной стратегии — записывать детали пользовательской истории в форме приёмочных тестов, которые затем проверяет тестировщик. Когда создаётся несколько представлений требований, нестыковки между ними помогают выявить проблемы. Если вы создаёте только одно представление, то независимо от выбранного метода будете вынуждены доверять его точности.
6. Расстановка приоритетов
Расстановка приоритетов учитывает относительную ценность каждого требования для клиента по сравнению с усилиями, риском и стоимостью его реализации. Традиционные проекты могут определить приоритеты требований на раннем этапе и в дальнейшем почти не пересматривать их. В Agile-проекте задачи приоритизируются непрерывно. Вы должны постоянно выбирать, что добавить в ближайшие итерации, а что может быть вообще исключено. На самом деле все команды, а не только те, кто практикует Agile, должны управлять оставшимися задачами, чтобы как можно быстрее передать клиенту максимально ценный для него продукт.
Есть ли разница?
Большинству клиентов неинтересно, как создаются приложения. Они хотят, чтобы продукты отвечали их потребностям, были эффективными, удобными и легко расширяемыми, а также удовлетворяли другие ожидания в отношении качества. Большинство методов разработки требований и управления ими в традиционных проектах в равной степени применимы и к Agile-проектам. Любая команда должна адаптировать методы разработки, чтобы они соответствовали их целям, культуре, среде и ограничениям.
В Agile всякое изменение добавляет независимую часть функциональности. Продукт — это система, которую вы итеративно совершенствуете, извлекая уроки из неудачных изменений и отыскивая лучшие способы реализации каждой его части. Выделение небольших требований, каждое из которых определяет ограниченное и функционирующее изменение, — совсем другой вид анализа, отличающийся от дробления большого интегрированного решения на фрагменты, вписывающиеся в итерации разработки.
Процесс бизнес-анализа в Agile-проектах тоже несколько иной. Несмотря на то, что устаревшие методы бизнес-анализа все ещё находят применение (анализ заинтересованных сторон и бизнес-правил, моделирование процессов и многое другое), их интеграция в поэтапный гибкий процесс оказывается большой проблемой для многих бизнес-аналитиков.
Успешный переход требует развития нового мышления. Роль бизнес-аналитика в Agile-проекте заключается не столько в том, чтобы заранее определить, что будет сделано, сколько в постоянном пересмотре условий в процессе разработки. Происходит постоянная оценка того, что должна или не должна делать команда, — компромиссов, необходимых для максимизации доставляемой ценности.
Однако в целом сведения о требованиях, используемые в Agile-проекте, качественно не отличаются от сведений в традиционном проекте. Разработка требований по-прежнему сводится к выявлению и передаче точной информации, чтобы участники проекта могли благополучно создать определённую часть продукта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Окончание
Начало
5. Итоговое оформление требований
В общем случае пользовательские истории похожи на сценарии использования. Разница лишь в том, насколько тщательно вы их детализируете и записываете ли информацию. В традиционном проекте бизнес-аналитик может разработать набор функциональных требований на основе сценариев использования. Agile-команды конкретизируют каждую пользовательскую историю, определяя критерии приёмки и тесты, которые покажут, правильно ли разработчики реализовали её.
Функциональные требования и соответствующие им тесты — альтернативные варианты представления одной и той же информации. Требования определяют, что создавать; тесты описывают, как выяснить, демонстрирует ли система ожидаемое поведение. Наилучшие результаты получаются, когда разные люди пишут требования и тесты на основе одного и того же источника информации, например сценария использования.
Можно прибегнуть к альтернативной стратегии — записывать детали пользовательской истории в форме приёмочных тестов, которые затем проверяет тестировщик. Когда создаётся несколько представлений требований, нестыковки между ними помогают выявить проблемы. Если вы создаёте только одно представление, то независимо от выбранного метода будете вынуждены доверять его точности.
6. Расстановка приоритетов
Расстановка приоритетов учитывает относительную ценность каждого требования для клиента по сравнению с усилиями, риском и стоимостью его реализации. Традиционные проекты могут определить приоритеты требований на раннем этапе и в дальнейшем почти не пересматривать их. В Agile-проекте задачи приоритизируются непрерывно. Вы должны постоянно выбирать, что добавить в ближайшие итерации, а что может быть вообще исключено. На самом деле все команды, а не только те, кто практикует Agile, должны управлять оставшимися задачами, чтобы как можно быстрее передать клиенту максимально ценный для него продукт.
Есть ли разница?
Большинству клиентов неинтересно, как создаются приложения. Они хотят, чтобы продукты отвечали их потребностям, были эффективными, удобными и легко расширяемыми, а также удовлетворяли другие ожидания в отношении качества. Большинство методов разработки требований и управления ими в традиционных проектах в равной степени применимы и к Agile-проектам. Любая команда должна адаптировать методы разработки, чтобы они соответствовали их целям, культуре, среде и ограничениям.
В Agile всякое изменение добавляет независимую часть функциональности. Продукт — это система, которую вы итеративно совершенствуете, извлекая уроки из неудачных изменений и отыскивая лучшие способы реализации каждой его части. Выделение небольших требований, каждое из которых определяет ограниченное и функционирующее изменение, — совсем другой вид анализа, отличающийся от дробления большого интегрированного решения на фрагменты, вписывающиеся в итерации разработки.
Процесс бизнес-анализа в Agile-проектах тоже несколько иной. Несмотря на то, что устаревшие методы бизнес-анализа все ещё находят применение (анализ заинтересованных сторон и бизнес-правил, моделирование процессов и многое другое), их интеграция в поэтапный гибкий процесс оказывается большой проблемой для многих бизнес-аналитиков.
Успешный переход требует развития нового мышления. Роль бизнес-аналитика в Agile-проекте заключается не столько в том, чтобы заранее определить, что будет сделано, сколько в постоянном пересмотре условий в процессе разработки. Происходит постоянная оценка того, что должна или не должна делать команда, — компромиссов, необходимых для максимизации доставляемой ценности.
Однако в целом сведения о требованиях, используемые в Agile-проекте, качественно не отличаются от сведений в традиционном проекте. Разработка требований по-прежнему сводится к выявлению и передаче точной информации, чтобы участники проекта могли благополучно создать определённую часть продукта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.