День 2299. #Оффтоп
Доброй субботы, дорогие подписчики. Давно не рекомендовал вам познавательных видосиков. Я обожаю истории про историю (извините за тавтологию) развития компьютеров и программирования. И сегодня порекомендую вам одну из таких ламповых – в прямом смысле – историй.
Как появились первые диоды и триоды? Почему алгебру логики называют булевой? Как «считают» компьютеры на самом нижнем уровне? Сколько энергии потреблял первый ЭНИАК?
Об этом и не только в видео с канала Veritasium. Приятного просмотра.
https://youtu.be/FU_YFpfDqqA
(видео с переводом на русский здесь)
А для тех, кому захочется ещё больше углубиться в историю и узнать про аналоговые компьютеры, вот видео в двух частях: часть 1, часть 2 (видео с переводом на русский: часть 1, часть 2).
Доброй субботы, дорогие подписчики. Давно не рекомендовал вам познавательных видосиков. Я обожаю истории про историю (извините за тавтологию) развития компьютеров и программирования. И сегодня порекомендую вам одну из таких ламповых – в прямом смысле – историй.
Как появились первые диоды и триоды? Почему алгебру логики называют булевой? Как «считают» компьютеры на самом нижнем уровне? Сколько энергии потреблял первый ЭНИАК?
Об этом и не только в видео с канала Veritasium. Приятного просмотра.
https://youtu.be/FU_YFpfDqqA
(видео с переводом на русский здесь)
А для тех, кому захочется ещё больше углубиться в историю и узнать про аналоговые компьютеры, вот видео в двух частях: часть 1, часть 2 (видео с переводом на русский: часть 1, часть 2).
YouTube
Why The First Computers Were Made Out Of Light Bulbs
How were the first computers made? Head to https://brilliant.org/veritasium to start your free 30-day trial, and the first 200 people get 20% off an annual premium subscription.
A huge thanks to David Lovett for showing me his awesome relay and vacuum tube…
A huge thanks to David Lovett for showing me his awesome relay and vacuum tube…
👍13
День 2300. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 51. Остерегайтесь «менеджмента по Businessweek». Начало
Разочарование неутешительными результатами — мощная мотивация попробовать другой подход. Однако при этом важно иметь уверенность, что любая новая стратегия, которую вы примете, имеет хорошие шансы на успех в решении вашей проблемы. Организации иногда выбирают модные решения и горячие новинки в области разработки ПО, считая их волшебным эликсиром, способным решить их задачи.
Руководитель может прочитать о многообещающей, но, возможно, чересчур разрекламированной методологии и настаивать на немедленном принятии её в организации. Этот феномен называют «менеджмент по Businessweek». Либо разработчик, посетив конференцию, узнаёт о новом способе решения своих задач и торопится попробовать его. Стремление к совершенствованию похвально, но вы должны направить эту энергию в правильное русло и оценить, насколько хорошо потенциальное решение соответствует вашей культуре, прежде чем принять его.
За прошедшие годы люди изобрели бесчисленное множество парадигм, методологий и систем управления разработкой ПО:
- анализ и проектирование структурированных систем;
- объектно-ориентированное программирование;
- информационная инженерия;
- быстрая разработка приложений;
- спиральная модель;
- разработка через тестирование;
- рациональный унифицированный процесс;
- DevOps.
Методология Agile-разработки во многих её вариациях (экстремальное программирование, адаптивная разработка, разработка на основе функциональности, Scrum, Lean, Kanban, Scaled Agile Framework и др.) ещё один пример стремления к идеальным решениям.
Увы, как учит дядюшка Брукс, «серебряной пули не существует». Все вышеперечисленные подходы имеют свои достоинства и недостатки и должны применяться к соответствующим задачам правильно подготовленными командами и руководителями. В качестве примера далее рассмотрим некий новый подход к разработке ПО под названием «Метод Х».
Сначала проблема, потом решение
В статьях и книгах, написанных изобретателями и первыми последователями «Метода Х», восхвалялись его преимущества. Некоторые компании выбрали «Метод Х», желая создавать продукты, которые лучше удовлетворяют потребности клиентов. Хотите быстрее доставлять полезное ПО? (А кто не хочет?) «Метод Х» поможет в этом. Хотите уменьшить количество дефектов, раздражающих клиентов и отнимающих у команды время на доработку? (Опять же, кто не хочет?) «Метод Х» придёт на помощь! В этом суть совершенствования процессов: постановка целей, выявление препятствий и выбор методов, которые, по вашему мнению, могут помочь их устранить.
Однако прежде, чем выбрать какой-либо новый подход к разработке, спросите себя: «Что мешает нам добиться таких же результатов, которые он обещает, уже сегодня?» Если вы хотите быстрее доставлять продукты, что вам мешает? Если цель — уменьшить количество дефектов, то почему сегодня их много? И т.п. Т.е., если «Метод Х» является решением проблем, в чём их причина?
Не все организации тщательно анализируют первопричины, прежде чем хвататься за решения, выглядящие многообещающими. Постановка целей совершенствования — отличное начало, но, помимо этого, важно понимать, какие препятствия стоят на пути к этим целям. Лечить нужно причины, а не симптомы. Если вы не понимаете причины проблем, то выбор любого нового подхода — выстрел в пустоту.
Предположим, вы хотите поставлять программные продукты, хорошо удовлетворяющие потребности клиентов. Вы прочитали, что в командах, применяющих «Метод Х», есть роль под названием «гуру», который отвечает за то, чтобы продукт достиг желаемого результата. «Отлично! — думаете вы. — Гуру позаботится о том, чтобы мы создали правильный продукт. Клиенты будут счастливы». Проблема решена? Может быть, но, прежде чем изменять процессы, ваша команда должна понять, почему ваши продукты не вызывают восторга у клиентов уже сейчас.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
Уроки 50 Лет Разработки ПО
Урок 51. Остерегайтесь «менеджмента по Businessweek». Начало
Разочарование неутешительными результатами — мощная мотивация попробовать другой подход. Однако при этом важно иметь уверенность, что любая новая стратегия, которую вы примете, имеет хорошие шансы на успех в решении вашей проблемы. Организации иногда выбирают модные решения и горячие новинки в области разработки ПО, считая их волшебным эликсиром, способным решить их задачи.
Руководитель может прочитать о многообещающей, но, возможно, чересчур разрекламированной методологии и настаивать на немедленном принятии её в организации. Этот феномен называют «менеджмент по Businessweek». Либо разработчик, посетив конференцию, узнаёт о новом способе решения своих задач и торопится попробовать его. Стремление к совершенствованию похвально, но вы должны направить эту энергию в правильное русло и оценить, насколько хорошо потенциальное решение соответствует вашей культуре, прежде чем принять его.
За прошедшие годы люди изобрели бесчисленное множество парадигм, методологий и систем управления разработкой ПО:
- анализ и проектирование структурированных систем;
- объектно-ориентированное программирование;
- информационная инженерия;
- быстрая разработка приложений;
- спиральная модель;
- разработка через тестирование;
- рациональный унифицированный процесс;
- DevOps.
Методология Agile-разработки во многих её вариациях (экстремальное программирование, адаптивная разработка, разработка на основе функциональности, Scrum, Lean, Kanban, Scaled Agile Framework и др.) ещё один пример стремления к идеальным решениям.
Увы, как учит дядюшка Брукс, «серебряной пули не существует». Все вышеперечисленные подходы имеют свои достоинства и недостатки и должны применяться к соответствующим задачам правильно подготовленными командами и руководителями. В качестве примера далее рассмотрим некий новый подход к разработке ПО под названием «Метод Х».
Сначала проблема, потом решение
В статьях и книгах, написанных изобретателями и первыми последователями «Метода Х», восхвалялись его преимущества. Некоторые компании выбрали «Метод Х», желая создавать продукты, которые лучше удовлетворяют потребности клиентов. Хотите быстрее доставлять полезное ПО? (А кто не хочет?) «Метод Х» поможет в этом. Хотите уменьшить количество дефектов, раздражающих клиентов и отнимающих у команды время на доработку? (Опять же, кто не хочет?) «Метод Х» придёт на помощь! В этом суть совершенствования процессов: постановка целей, выявление препятствий и выбор методов, которые, по вашему мнению, могут помочь их устранить.
Однако прежде, чем выбрать какой-либо новый подход к разработке, спросите себя: «Что мешает нам добиться таких же результатов, которые он обещает, уже сегодня?» Если вы хотите быстрее доставлять продукты, что вам мешает? Если цель — уменьшить количество дефектов, то почему сегодня их много? И т.п. Т.е., если «Метод Х» является решением проблем, в чём их причина?
Не все организации тщательно анализируют первопричины, прежде чем хвататься за решения, выглядящие многообещающими. Постановка целей совершенствования — отличное начало, но, помимо этого, важно понимать, какие препятствия стоят на пути к этим целям. Лечить нужно причины, а не симптомы. Если вы не понимаете причины проблем, то выбор любого нового подхода — выстрел в пустоту.
Предположим, вы хотите поставлять программные продукты, хорошо удовлетворяющие потребности клиентов. Вы прочитали, что в командах, применяющих «Метод Х», есть роль под названием «гуру», который отвечает за то, чтобы продукт достиг желаемого результата. «Отлично! — думаете вы. — Гуру позаботится о том, чтобы мы создали правильный продукт. Клиенты будут счастливы». Проблема решена? Может быть, но, прежде чем изменять процессы, ваша команда должна понять, почему ваши продукты не вызывают восторга у клиентов уже сейчас.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍9
День 2301. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 51. Остерегайтесь «менеджмента по Businessweek». Окончание
Начало
Анализ первопричин — это процесс размышлений, когда несколько раз задаётся вопрос «почему?», пока вы не доберётесь до проблем, на которые можно воздействовать с помощью тщательно подобранных действий по улучшению. Первая найденная причина может не оказывать прямого влияния и не быть первопричиной. Следовательно, её устранение не решит проблему. Вам нужно спросить «почему?» еще раз или два, чтобы убедиться, что вы добрались до основания дерева анализа.
На рисунке выше показан фрагмент диаграммы «Рыбий скелет» (диаграмма Исикавы) — удобного способа анализа первопричин. Ваша цель — выпускать продукты, лучше удовлетворяющие потребности клиентов. Напишите эту цель вдоль длинной горизонтальной линии. Это представляет вашу основную проблему. Затем спросите команду: «Почему мы не удовлетворяем потребности наших клиентов?» Один из возможных ответов: команда не получает адекватной информации о требованиях от конечных пользователей — обычная ситуация. Запишите эту причину вдоль диагональной линии, отходящей от формулировки цели. Хорошо, но решение проблемы требует более глубокого понимания. Поэтому далее вы спрашиваете: «Почему мы не получаем такой информации?» Один из членов группы говорит: «Мы пытались поговорить с реальными пользователями, но их руководители говорят, что они слишком заняты, чтобы работать с командой разработчиков». Кто-то ещё жалуется, что представители клиента, работающие с командой, не имеют полного представления о реальных потребностях конечных пользователей. Напишите эти причины второго уровня вдоль горизонтальных линий, отходящих от диагональной линии родительской проблемы.
Кто-то отмечает, что разработчики задают представителям клиента неправильные вопросы: «Почему задаются неправильные вопросы?» Причин может быть несколько, в том числе отсутствие образования или интереса у разработчиков к работе с требованиями. Возможно, бизнес-анализ не является основным навыком команды или в команде нет подготовленного бизнес-аналитика. Каждая причина записывается вдоль новой диагональной линии, соединяющейся с родительской.
Так вы приближаетесь к фактическим препятствиям, стоящим на пути к желаемой цели. Продолжайте анализ до тех пор, пока участники не придут к полному пониманию, почему не достигаются желаемые результаты. Такая диаграмма может стать неразборчивой, поэтому попробуйте записать причины на стикерах, чтобы их можно было перетасовывать по мере исследования.
Постановка диагноза ведёт к излечению
Дальше стоит перейти к поиску практических решений для устранения этих первопричин. Возможно, вы решите, что добавление бизнес-аналитика в команду более ценно, чем принятие «Метода Х» с его «гуру». Или вам нужна комбинация этих двух методов. Вы не узнаете этого, пока не продумаете всё до конца.
Вот несколько хороших вопросов, которые следует задать себе:
- Потребуется ли команде обучение, инструменты или консультации, чтобы начать работу и двигаться вперед?
- Принесёт ли решение выгоду по сравнению с вложениями?
- Какое культурное влияние окажет переход к новым методам на вашу команду, клиентов и их организации?
- Насколько крутой может быть кривая обучения?
Результаты анализа первопричин могут помочь выявить более эффективные методы решения каждой обнаруженной проблемы. Это разумное вложение средств в концентрацию усилий по совершенствованию процессов. Прежде, чем назначать лечение, нужно поставить диагноз.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
Уроки 50 Лет Разработки ПО
Урок 51. Остерегайтесь «менеджмента по Businessweek». Окончание
Начало
Анализ первопричин — это процесс размышлений, когда несколько раз задаётся вопрос «почему?», пока вы не доберётесь до проблем, на которые можно воздействовать с помощью тщательно подобранных действий по улучшению. Первая найденная причина может не оказывать прямого влияния и не быть первопричиной. Следовательно, её устранение не решит проблему. Вам нужно спросить «почему?» еще раз или два, чтобы убедиться, что вы добрались до основания дерева анализа.
На рисунке выше показан фрагмент диаграммы «Рыбий скелет» (диаграмма Исикавы) — удобного способа анализа первопричин. Ваша цель — выпускать продукты, лучше удовлетворяющие потребности клиентов. Напишите эту цель вдоль длинной горизонтальной линии. Это представляет вашу основную проблему. Затем спросите команду: «Почему мы не удовлетворяем потребности наших клиентов?» Один из возможных ответов: команда не получает адекватной информации о требованиях от конечных пользователей — обычная ситуация. Запишите эту причину вдоль диагональной линии, отходящей от формулировки цели. Хорошо, но решение проблемы требует более глубокого понимания. Поэтому далее вы спрашиваете: «Почему мы не получаем такой информации?» Один из членов группы говорит: «Мы пытались поговорить с реальными пользователями, но их руководители говорят, что они слишком заняты, чтобы работать с командой разработчиков». Кто-то ещё жалуется, что представители клиента, работающие с командой, не имеют полного представления о реальных потребностях конечных пользователей. Напишите эти причины второго уровня вдоль горизонтальных линий, отходящих от диагональной линии родительской проблемы.
Кто-то отмечает, что разработчики задают представителям клиента неправильные вопросы: «Почему задаются неправильные вопросы?» Причин может быть несколько, в том числе отсутствие образования или интереса у разработчиков к работе с требованиями. Возможно, бизнес-анализ не является основным навыком команды или в команде нет подготовленного бизнес-аналитика. Каждая причина записывается вдоль новой диагональной линии, соединяющейся с родительской.
Так вы приближаетесь к фактическим препятствиям, стоящим на пути к желаемой цели. Продолжайте анализ до тех пор, пока участники не придут к полному пониманию, почему не достигаются желаемые результаты. Такая диаграмма может стать неразборчивой, поэтому попробуйте записать причины на стикерах, чтобы их можно было перетасовывать по мере исследования.
Постановка диагноза ведёт к излечению
Дальше стоит перейти к поиску практических решений для устранения этих первопричин. Возможно, вы решите, что добавление бизнес-аналитика в команду более ценно, чем принятие «Метода Х» с его «гуру». Или вам нужна комбинация этих двух методов. Вы не узнаете этого, пока не продумаете всё до конца.
Вот несколько хороших вопросов, которые следует задать себе:
- Потребуется ли команде обучение, инструменты или консультации, чтобы начать работу и двигаться вперед?
- Принесёт ли решение выгоду по сравнению с вложениями?
- Какое культурное влияние окажет переход к новым методам на вашу команду, клиентов и их организации?
- Насколько крутой может быть кривая обучения?
Результаты анализа первопричин могут помочь выявить более эффективные методы решения каждой обнаруженной проблемы. Это разумное вложение средств в концентрацию усилий по совершенствованию процессов. Прежде, чем назначать лечение, нужно поставить диагноз.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍10
День 2302. #ЧтоНовенького #TipsAndTricks
Используем Расширения C# 14 для Парсинга Enum
Расширения ещё только в планах для C# 14, а умельцы уже предлагают интересные варианты их использования.
В .NET многие типы предоставляют статический метод Parse для преобразования строк в соответствующие им типы. Например:
В перечислениях используется обобщённый метод Enum.Parse:
А вот это не сработает:
Было бы более интуитивно понятно, если бы перечисления поддерживали метод Parse напрямую. С помощью C# 14 и его новой функции членов-расширений мы можем этого добиться.
Следующий код демонстрирует, как добавить методы Parse и TryParse к перечислениям с использованием расширений C# 14:
Теперь мы можем использовать методы Parse/TryParse для самого типа enum, так же как мы это делаем для других типов:
Источник: https://www.meziantou.net/use-csharp-14-extensions-to-simplify-enum-parsing.htm
Используем Расширения C# 14 для Парсинга Enum
Расширения ещё только в планах для C# 14, а умельцы уже предлагают интересные варианты их использования.
В .NET многие типы предоставляют статический метод Parse для преобразования строк в соответствующие им типы. Например:
int.Parse("123");
double.Parse("123.45");
DateTime.Parse("2023-01-01");
IPAddress.Parse("192.168.0.1");
В перечислениях используется обобщённый метод Enum.Parse:
Enum.Parse<MyEnum>("Value1");
А вот это не сработает:
MyEnum.Parse("Value1");
Было бы более интуитивно понятно, если бы перечисления поддерживали метод Parse напрямую. С помощью C# 14 и его новой функции членов-расширений мы можем этого добиться.
Следующий код демонстрирует, как добавить методы Parse и TryParse к перечислениям с использованием расширений C# 14:
static class EnumExtensions
{
extension<T>(T _) where T : struct, Enum
{
public static T Parse(string value)
=> Enum.Parse<T>(value);
public static T Parse(string value, bool ignoreCase)
=> Enum.Parse<T>(value, ignoreCase);
public static T Parse(ReadOnlySpan<char> value)
=> Enum.Parse<T>(value);
public static T Parse(
ReadOnlySpan<char> value,
bool ignoreCase)
=> Enum.Parse<T>(value, ignoreCase);
public static bool TryParse(
[NotNullWhen(true)] string? value,
out T result)
=> Enum.TryParse(value, out result);
public static bool TryParse(
[NotNullWhen(true)] string? value,
bool ignoreCase,
out T result)
=> Enum.TryParse(value, ignoreCase, out result);
public static bool TryParse(
ReadOnlySpan<char> value,
out T result)
=> Enum.TryParse(value, out result);
public static bool TryParse(
ReadOnlySpan<char> value,
bool ignoreCase,
out T result)
=> Enum.TryParse(value, ignoreCase, out result);
}
}
Теперь мы можем использовать методы Parse/TryParse для самого типа enum, так же как мы это делаем для других типов:
MyEnum.Parse("Value1");
if (MyEnum.TryParse("Value1", out var result))
{
//…
}
Источник: https://www.meziantou.net/use-csharp-14-extensions-to-simplify-enum-parsing.htm
👍35
День 2303. #ЗаметкиНаПолях
AsyncEnumerable в C#: Важность Атрибута EnumeratorCancellation
Сегодня рассмотрим IAsyncEnumerable<T> и почему атрибут EnumeratorCancellation для параметра CancellationToken имеет решающее значение для написания надёжного отменяемого асинхронного кода.
IAsyncEnumerable<T> — это асинхронный аналог IEnumerable<T> (см. подробнее про создание и потребление асинхронных потоков).
IAsyncEnumerable<T> позволяет:
- Выполнять асинхронные операции во время итерации последовательности;
- Выдавать результаты по мере их появления;
- Обрабатывать отмену.
Необходимость отмены
Поддержка отмены в асинхронных операциях нужна в следующих сценариях:
- Пользователь уходит с веб-страницы, которая извлекает данные;
- Операция поиска занимает слишком много времени, и пользователь отменяет её;
- Сервис завершает работу во время выполнения операций.
Без надлежащей поддержки отмены ресурсы могут быть потрачены впустую, а приложения могут перестать отвечать или произойдёт утечка ресурсов.
Атрибут EnumeratorCancellation
При применении к параметру CancellationToken в методе асинхронного итератора этот атрибут сообщает компилятору о необходимости передать этот токен методу GetAsyncEnumerator, когда итератор используется через await foreach. Вот простой пример:
Использование метода через вызов WithCancellation:
Без атрибута EnumeratorCancellation существует разрыв между токеном отмены, переданным в метод асинхронного итератора, и токеном, переданным в GetAsyncEnumerator при потреблении перечисляемого объекта. Атрибут EnumeratorCancellation гарантирует, что этот токен попадёт в метод асинхронного итератора, позволяя вам реагировать на запросы отмены от потребителя.
Чтобы помочь вам избежать этой ошибки, компилятор выдает предупреждение CS8425 в качестве напоминания о правильной реализации отмены в ваших методах асинхронного итератора:
CS8425: Async-iterator method 'MyMethod' has parameters that are declared with 'CancellationToken' but are not decorated with the 'EnumeratorCancellation' attribute, and will not be passed the cancellation token from 'WithCancellation' method calls
CS8425: Метод асинхронного итератора 'MyMethod' имеет параметры, объявленные с 'CancellationToken', но не декорированные атрибутом 'EnumeratorCancellation', и ему не будет передан токен отмены из вызовов метода 'WithCancellation'.
Предупреждение возникает, когда вы определяете метод асинхронного итератора, который возвращает IAsyncEnumerable<T> и включает параметр CancellationToken, но вы не декорировали этот параметр атрибутом [EnumeratorCancellation].
Игнорирование этого предупреждения может привести к неявным ошибкам, когда отмена, кажется, реализована, но на самом деле не работает. Код будет компилироваться и запускаться, но запросы на отмену от потребителей будут игнорироваться.
Итого
При работе с асинхронными потоками:
- Используйте атрибут EnumeratorCancellation для параметров токена отмены;
- Регулярно проверяйте отмену;
- Распространяйте токен на внутренние операции;
- Обратите внимание на предупреждение компилятора CS8425, поскольку оно указывает на потенциальную проблему отмены.
Источник: https://bartwullems.blogspot.com/2025/04/asyncenumerable-in-c-importance-of.html
AsyncEnumerable в C#: Важность Атрибута EnumeratorCancellation
Сегодня рассмотрим IAsyncEnumerable<T> и почему атрибут EnumeratorCancellation для параметра CancellationToken имеет решающее значение для написания надёжного отменяемого асинхронного кода.
IAsyncEnumerable<T> — это асинхронный аналог IEnumerable<T> (см. подробнее про создание и потребление асинхронных потоков).
IAsyncEnumerable<T> позволяет:
- Выполнять асинхронные операции во время итерации последовательности;
- Выдавать результаты по мере их появления;
- Обрабатывать отмену.
Необходимость отмены
Поддержка отмены в асинхронных операциях нужна в следующих сценариях:
- Пользователь уходит с веб-страницы, которая извлекает данные;
- Операция поиска занимает слишком много времени, и пользователь отменяет её;
- Сервис завершает работу во время выполнения операций.
Без надлежащей поддержки отмены ресурсы могут быть потрачены впустую, а приложения могут перестать отвечать или произойдёт утечка ресурсов.
Атрибут EnumeratorCancellation
При применении к параметру CancellationToken в методе асинхронного итератора этот атрибут сообщает компилятору о необходимости передать этот токен методу GetAsyncEnumerator, когда итератор используется через await foreach. Вот простой пример:
public async IAsyncEnumerable<int>
GenerateNumbersAsync(
int count,
[EnumeratorCancellation]
CancellationToken ct = default)
{
for (int i = 0; i < count; i++)
{
// Проверяем отмену
ct.ThrowIfCancellationRequested();
// Симулируем асинхронную работу
await Task.Delay(100, ct);
yield return i;
}
}
Использование метода через вызов WithCancellation:
CancellationTokenSource cts = new();
await foreach (var item in
GenerateNumbersAsync(10)
.WithCancellation(cts.Token))
{
Console.WriteLine(item);
}
Без атрибута EnumeratorCancellation существует разрыв между токеном отмены, переданным в метод асинхронного итератора, и токеном, переданным в GetAsyncEnumerator при потреблении перечисляемого объекта. Атрибут EnumeratorCancellation гарантирует, что этот токен попадёт в метод асинхронного итератора, позволяя вам реагировать на запросы отмены от потребителя.
Чтобы помочь вам избежать этой ошибки, компилятор выдает предупреждение CS8425 в качестве напоминания о правильной реализации отмены в ваших методах асинхронного итератора:
CS8425: Async-iterator method 'MyMethod' has parameters that are declared with 'CancellationToken' but are not decorated with the 'EnumeratorCancellation' attribute, and will not be passed the cancellation token from 'WithCancellation' method calls
CS8425: Метод асинхронного итератора 'MyMethod' имеет параметры, объявленные с 'CancellationToken', но не декорированные атрибутом 'EnumeratorCancellation', и ему не будет передан токен отмены из вызовов метода 'WithCancellation'.
Предупреждение возникает, когда вы определяете метод асинхронного итератора, который возвращает IAsyncEnumerable<T> и включает параметр CancellationToken, но вы не декорировали этот параметр атрибутом [EnumeratorCancellation].
Игнорирование этого предупреждения может привести к неявным ошибкам, когда отмена, кажется, реализована, но на самом деле не работает. Код будет компилироваться и запускаться, но запросы на отмену от потребителей будут игнорироваться.
Итого
При работе с асинхронными потоками:
- Используйте атрибут EnumeratorCancellation для параметров токена отмены;
- Регулярно проверяйте отмену;
- Распространяйте токен на внутренние операции;
- Обратите внимание на предупреждение компилятора CS8425, поскольку оно указывает на потенциальную проблему отмены.
Источник: https://bartwullems.blogspot.com/2025/04/asyncenumerable-in-c-importance-of.html
👍18
День 2304. #ЧтоНовенького
Режим ИИ-Агента в Превью для Visual Studio
Режим ИИ-агента теперь доступен превью VS 17.14. Он позволяет определять задачи с использованием естественного языка, при этом Copilot автономно планирует, редактирует вашу кодовую базу, вызывает инструменты и выполняет итерации для решения проблем. В отличие от Чата Copilot или отдельных правок, режим агента не останавливается на одном предложении или редактировании файла, а работает итеративно до тех пор, пока задача не будет выполнена.
Что может делать режим агента?
Режим агента не просто помогает вам писать код — он помогает вам сделать работу. Всё делается итеративно, то есть Copilot продолжит изучать и выполнять вашу задачу на своём собственном выводе и результатах этого вывода, пока не выполнит ваш запрос. Т.е. режим агента может:
- Автономно определять соответствующий контекст и файлы для редактирования;
- Предлагать вам команды терминала для одобрения и выполнения;
- Выполняться итеративно до тех пор, пока задача не будет выполнена: проверять наличие ошибок и запускать сборки/тесты для проверки результатов;
- Вызывать доверенные инструменты через серверы MCP — включая линтеры, среды исполнения тестовые и статические анализаторы в вашей среде разработки.
Как включить
Режим агента по умолчанию отключен на данном этапе превью. Чтобы включить его в Visual Studio 17.14+ перейдите в раздел поиска функций (
Использование
Режим агента позволяет создавать приложения с нуля, рефакторить код в нескольких файлах, писать и запускать тесты, генерировать документацию, интегрировать новые библиотеки и отвечать на вопросы о сложных кодовых базах. При определении того, является ли режим агента подходящим инструментом для работы, учтите следующее.
1. Область редактирования: режим агента просматривает вашу кодовую базу и определяет соответствующий контекст и файлы для редактирования.
2. Сложность задачи: агент обрабатывает вызовы инструментов и команды терминала, что делает его идеальным для сложных проектов.
3. Длительность: режим агента включает несколько этапов обработки запроса. Получение ответа может занять больше времени, так как он определяет контекст, планирует действие и многое другое.
4. Самостоятельная итерация: агент оценивает результат сгенерированных правок и выполняет итерации несколько раз для решения промежуточных проблем.
5. Множественные запросы: в зависимости от сложности задачи режим агента может привести к нескольким запросам к бэкенду из одного запроса.
Вот несколько примеров запросов для агента:
- Добавить обработку ошибок в этот API;
- Преобразовать этот проект для использования переменных среды;
- Написать тесты для этого класса и исправить всё, что даёт сбой;
- Добавить структурированное ведение журнала с помощью Serilog;
- Заменить HttpClient на IHttpClientFactory.
Важно предоставить агенту достаточный контекст о ваших предпочтительных стандартах кодирования, предпочтениях команды, библиотеках и многом другом. Это можно сделать с помощью пользовательских инструкций (см. документацию).
Серверы MCP
Model Context Protocol (MCP) серверы предоставляют агенту Copilot дополнительный контекст и дают ему доступ к инструментам, данным и ресурсам. MCP позволяют подключать приложения ИИ к другим данным и инструментам без необходимости создания настраиваемого соединения с каждым источником данных. Например, напрямую подключаться к БД и анализировать схемы, извлекать информацию для репозиториев GitHub, такую как проблемы и пул-реквесты, автоматизировать сквозное тестирование с помощью Playwright и т.п.
У Тима Кори появилось видео с примером использования режима агента.
Источник: https://devblogs.microsoft.com/visualstudio/agent-mode-has-arrived-in-preview-for-visual-studio/
Режим ИИ-Агента в Превью для Visual Studio
Режим ИИ-агента теперь доступен превью VS 17.14. Он позволяет определять задачи с использованием естественного языка, при этом Copilot автономно планирует, редактирует вашу кодовую базу, вызывает инструменты и выполняет итерации для решения проблем. В отличие от Чата Copilot или отдельных правок, режим агента не останавливается на одном предложении или редактировании файла, а работает итеративно до тех пор, пока задача не будет выполнена.
Что может делать режим агента?
Режим агента не просто помогает вам писать код — он помогает вам сделать работу. Всё делается итеративно, то есть Copilot продолжит изучать и выполнять вашу задачу на своём собственном выводе и результатах этого вывода, пока не выполнит ваш запрос. Т.е. режим агента может:
- Автономно определять соответствующий контекст и файлы для редактирования;
- Предлагать вам команды терминала для одобрения и выполнения;
- Выполняться итеративно до тех пор, пока задача не будет выполнена: проверять наличие ошибок и запускать сборки/тесты для проверки результатов;
- Вызывать доверенные инструменты через серверы MCP — включая линтеры, среды исполнения тестовые и статические анализаторы в вашей среде разработки.
Как включить
Режим агента по умолчанию отключен на данном этапе превью. Чтобы включить его в Visual Studio 17.14+ перейдите в раздел поиска функций (
Ctrl+Q
), выполните поиск «copilot agent», либо перейдите в Tools > Options > GitHub > Copilot (Инструменты > Параметры > GitHub > Copilot) и отметьте флажок Enable Agent mode in chat pane (Включить режим агента в панели чата). Внизу окна чата Copilot переключитесь с Ask на Agent.Использование
Режим агента позволяет создавать приложения с нуля, рефакторить код в нескольких файлах, писать и запускать тесты, генерировать документацию, интегрировать новые библиотеки и отвечать на вопросы о сложных кодовых базах. При определении того, является ли режим агента подходящим инструментом для работы, учтите следующее.
1. Область редактирования: режим агента просматривает вашу кодовую базу и определяет соответствующий контекст и файлы для редактирования.
2. Сложность задачи: агент обрабатывает вызовы инструментов и команды терминала, что делает его идеальным для сложных проектов.
3. Длительность: режим агента включает несколько этапов обработки запроса. Получение ответа может занять больше времени, так как он определяет контекст, планирует действие и многое другое.
4. Самостоятельная итерация: агент оценивает результат сгенерированных правок и выполняет итерации несколько раз для решения промежуточных проблем.
5. Множественные запросы: в зависимости от сложности задачи режим агента может привести к нескольким запросам к бэкенду из одного запроса.
Вот несколько примеров запросов для агента:
- Добавить обработку ошибок в этот API;
- Преобразовать этот проект для использования переменных среды;
- Написать тесты для этого класса и исправить всё, что даёт сбой;
- Добавить структурированное ведение журнала с помощью Serilog;
- Заменить HttpClient на IHttpClientFactory.
Важно предоставить агенту достаточный контекст о ваших предпочтительных стандартах кодирования, предпочтениях команды, библиотеках и многом другом. Это можно сделать с помощью пользовательских инструкций (см. документацию).
Серверы MCP
Model Context Protocol (MCP) серверы предоставляют агенту Copilot дополнительный контекст и дают ему доступ к инструментам, данным и ресурсам. MCP позволяют подключать приложения ИИ к другим данным и инструментам без необходимости создания настраиваемого соединения с каждым источником данных. Например, напрямую подключаться к БД и анализировать схемы, извлекать информацию для репозиториев GitHub, такую как проблемы и пул-реквесты, автоматизировать сквозное тестирование с помощью Playwright и т.п.
У Тима Кори появилось видео с примером использования режима агента.
Источник: https://devblogs.microsoft.com/visualstudio/agent-mode-has-arrived-in-preview-for-visual-studio/
👍7👎2
День 2305. #ЧтоНовенького #TipsAndTricks
Используем Расширения C# 14 для Написания Защитных Конструкций
Продолжаем рассматривать примеры применения ещё не вышедших расширений в C# 14 (первая часть тут).
В C# есть много хороших защитных конструкций, расположенных поверх статических классов исключений, таких как ArgumentNullException, ArgumentOutOfRangeException и т.д. Например, ArgumentException.ThrowIfNullOrEmpty, ArgumentException.ThrowIfNullOrWhiteSpace. Теперь мы можем легко их расширить!
Расширения в C#14 позволяют добавлять новые защитные конструкции к существующим классам. Например, если мы хотим иметь такую «жутко полезную» семантику, как: «Выбрасывать исключение, если строка содержит ровно один символ», мы можем сделать что-то вроде этого:
Теперь мы можем использовать этот метод-расширение так:
Он прекрасно вливается в семейство существующих защитных конструкций:
Конечно, это слишком упрощённый пример. Но вы поняли идею. Мы получаем что-то похожее на существующие защитные конструкции.
Заметьте, что до C#14 этого сделать нельзя, т.к. здесь мы использовали статический метод-расширение, который можно вызвать так:
Существующие на данный момент методы-расширения позволяют делать только экземплярные методы, которые пришлось бы вызывать так:
Источник: https://steven-giesel.com/blogPost/e2552b7a-293a-4f46-892f-95a0cd677e4d/writing-new-guards-with-extensions-in-c-14
Используем Расширения C# 14 для Написания Защитных Конструкций
Продолжаем рассматривать примеры применения ещё не вышедших расширений в C# 14 (первая часть тут).
В C# есть много хороших защитных конструкций, расположенных поверх статических классов исключений, таких как ArgumentNullException, ArgumentOutOfRangeException и т.д. Например, ArgumentException.ThrowIfNullOrEmpty, ArgumentException.ThrowIfNullOrWhiteSpace. Теперь мы можем легко их расширить!
Расширения в C#14 позволяют добавлять новые защитные конструкции к существующим классам. Например, если мы хотим иметь такую «жутко полезную» семантику, как: «Выбрасывать исключение, если строка содержит ровно один символ», мы можем сделать что-то вроде этого:
static class EnumExtensions
{
extension(ArgumentException)
{
public static void
ThrowIfHasOneCharacter(
string arg,
[CallerArgumentExpression("arg")]
string? paramName = null)
{
if (arg.Length == 1)
throw new ArgumentException($"Аргумент '{paramName}' не может иметь только один символ.", paramName);
}
}
}
Теперь мы можем использовать этот метод-расширение так:
public void MyMethod(string arg)
{
ArgumentException.ThrowIfHasOneCharacter(arg);
…
}
Он прекрасно вливается в семейство существующих защитных конструкций:
public void MyMethod(string arg)
{
ArgumentException.ThrowIfNullOrEmpty(arg);
ArgumentException.ThrowIfHasOneCharacter(arg);
…
}
Конечно, это слишком упрощённый пример. Но вы поняли идею. Мы получаем что-то похожее на существующие защитные конструкции.
Заметьте, что до C#14 этого сделать нельзя, т.к. здесь мы использовали статический метод-расширение, который можно вызвать так:
ArgumentException.ThrowIfHasOneCharacter(…);
Существующие на данный момент методы-расширения позволяют делать только экземплярные методы, которые пришлось бы вызывать так:
var ex = new ArgumentException();
ex.ThrowIfHasOneCharacter(…);
Источник: https://steven-giesel.com/blogPost/e2552b7a-293a-4f46-892f-95a0cd677e4d/writing-new-guards-with-extensions-in-c-14
👍17
День 2306. #ЗаметкиНаПолях
Проверка на null, Которая не Проверяет на null
Рассмотрим следующий код:
Мы сопоставляем массив строк с шаблоном (массив из одного элемента) и, если этот элемент не пустая строка, выводим его. Код красивый и краткий. Но мы внезапно получаем ошибку NullReferenceException во время выполнения.
Посмотрим на пример в SharpLab, что поможет быстро понять, что происходит «под капотом» для подобного синтаксиса.
Вы можете видеть 3 версии проверки по приведённой выше ссылке:
Оказывается, есть различие между шаблоном var (допускает null) и шаблоном не-var. Третий вариант — это шаблон не-null, который делает то же самое (но не требует явного указания типа). Обычно var используется вместо явного типа лишь для удобства чтения, но здесь у нас есть реальная разница в поведении.
Источник: https://ayende.com/blog/202403-B/the-null-check-that-didnt-check-for-nulls
Проверка на null, Которая не Проверяет на null
Рассмотрим следующий код:
string Test1(List<string> strs)
{
if(strs is [var s])
{
if (s.Length > 0)
return s;
}
return string.Join(",", strs);
}
Мы сопоставляем массив строк с шаблоном (массив из одного элемента) и, если этот элемент не пустая строка, выводим его. Код красивый и краткий. Но мы внезапно получаем ошибку NullReferenceException во время выполнения.
Посмотрим на пример в SharpLab, что поможет быстро понять, что происходит «под капотом» для подобного синтаксиса.
Вы можете видеть 3 версии проверки по приведённой выше ссылке:
// if (text.Length > 0)
// нет проверки на null!!!
if(strs is [var s])
// if (text != null && text.Length > 0)
if(strs is [string s])
// if (text != null && text.Length > 0)
if(strs is [{} s])
Оказывается, есть различие между шаблоном var (допускает null) и шаблоном не-var. Третий вариант — это шаблон не-null, который делает то же самое (но не требует явного указания типа). Обычно var используется вместо явного типа лишь для удобства чтения, но здесь у нас есть реальная разница в поведении.
Источник: https://ayende.com/blog/202403-B/the-null-check-that-didnt-check-for-nulls
👍26
День 2307. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 52. Не спрашивайте: «Что это даст мне?» Спрашивайте: «Что это даст нам?»
Когда людям предлагают использовать новый подход к разработке, следовать другой процедуре или взяться за неожиданное задание, они инстинктивно задаются вопросом: «Что это даст мне?» Это естественная реакция, но не совсем правильный вопрос. Правильный вопрос: «Что это даст нам?»
«Нам» тут может относиться к остальным членам команды, IT-отделу, компании или даже индустрии, только не к отдельному человеку. Инициативы по внедрению изменений должны учитывать коллективные результаты работы, а не только влияние на продуктивность, эффективность или уровень комфорта каждого человека.
Может показаться, что просьба к занятому коллеге, например проверить вашу работу, не принесёт ему выгоды. Однако все вместе такие усилия позволят команде сэкономить больше времени, и тем самым внести чистый положительный вклад в проект. Ревью кода может занять два-три часа времени каждого участника. Эти часы рецензенты не смогут потратить на выполнение своих обязанностей. Но проверка выявит дефекты, а чем раньше они обнаруживаются, тем дешевле их исправление.
Выгода для команды
Предположим, Ари (бизнес-аналитик) написала несколько страниц требований и попросила троих коллег просмотреть их. Каждый из четверых потратил по часу на изучение материала перед встречей команды, которая тоже длилась час:
затраты на подготовку = 1 час/рецензент × 4 рецензента = 4 часа;
затраты на встречу = 1 час/рецензент × 4 рецензента = 4 часа;
общие затраты на рецензирование = 4 часа + 4 часа = 8 часов
Предположим, в процессе рецензирования обнаружены 24 дефекта разной степени серьёзности и на исправление каждого у Ари ушло в среднем 5 минут:
фактические затраты на доработку = 24 дефекта × 0,0833 часа/дефект = 2 часа
Теперь представьте, что Ари не запросила рецензирование. Дефекты останутся в наборе требований и будут обнаружены позже, при разработке. Ари всё так же придётся исправить их, а другим членам команды — переделывать проектное решение, код, тесты и документацию после исправления дефектов. На все эти работы легко может понадобиться в десять раз больше времени. Стоимость переделки может возрасти ещё, если дефекты попадут в конечный продукт:
потенциальные затраты на доработку = 24 дефекта × 0,833 часа/дефект = 20 часов
То есть это гипотетическое рецензирование требований предотвратило потенциальные затраты 18 часов на доработку на последних этапах реализации проекта. Поэтому минимальная окупаемость затрат на рецензирование составляет 225% (18 часов сэкономленного времени ÷ 8 часов на рецензирование). Многие крупные компании оценивают рентабельность вложений в раннее рецензирование как десятикратную. У вас могут получиться другие цифры, но лишь немногие методы разработки ПО могут десятикратно окупить вложения.
Вносите свой вклад в общее дело
В следующий раз, когда коллега или руководитель попросит вас сделать в проекте что-то, что не принесёт вам личной выгоды, думайте не только о своих интересах. Сотрудники несут ответственность за соблюдение установленных правил и приёмов разработки. Справедливо спросить: «Что нам это даст, если я это сделаю?» На просителе лежит бремя объяснения того, какую пользу всей команде принесет ваш вклад. А вы старайтесь внести свой вклад в общий успех команды.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
Уроки 50 Лет Разработки ПО
Урок 52. Не спрашивайте: «Что это даст мне?» Спрашивайте: «Что это даст нам?»
Когда людям предлагают использовать новый подход к разработке, следовать другой процедуре или взяться за неожиданное задание, они инстинктивно задаются вопросом: «Что это даст мне?» Это естественная реакция, но не совсем правильный вопрос. Правильный вопрос: «Что это даст нам?»
«Нам» тут может относиться к остальным членам команды, IT-отделу, компании или даже индустрии, только не к отдельному человеку. Инициативы по внедрению изменений должны учитывать коллективные результаты работы, а не только влияние на продуктивность, эффективность или уровень комфорта каждого человека.
Может показаться, что просьба к занятому коллеге, например проверить вашу работу, не принесёт ему выгоды. Однако все вместе такие усилия позволят команде сэкономить больше времени, и тем самым внести чистый положительный вклад в проект. Ревью кода может занять два-три часа времени каждого участника. Эти часы рецензенты не смогут потратить на выполнение своих обязанностей. Но проверка выявит дефекты, а чем раньше они обнаруживаются, тем дешевле их исправление.
Выгода для команды
Предположим, Ари (бизнес-аналитик) написала несколько страниц требований и попросила троих коллег просмотреть их. Каждый из четверых потратил по часу на изучение материала перед встречей команды, которая тоже длилась час:
затраты на подготовку = 1 час/рецензент × 4 рецензента = 4 часа;
затраты на встречу = 1 час/рецензент × 4 рецензента = 4 часа;
общие затраты на рецензирование = 4 часа + 4 часа = 8 часов
Предположим, в процессе рецензирования обнаружены 24 дефекта разной степени серьёзности и на исправление каждого у Ари ушло в среднем 5 минут:
фактические затраты на доработку = 24 дефекта × 0,0833 часа/дефект = 2 часа
Теперь представьте, что Ари не запросила рецензирование. Дефекты останутся в наборе требований и будут обнаружены позже, при разработке. Ари всё так же придётся исправить их, а другим членам команды — переделывать проектное решение, код, тесты и документацию после исправления дефектов. На все эти работы легко может понадобиться в десять раз больше времени. Стоимость переделки может возрасти ещё, если дефекты попадут в конечный продукт:
потенциальные затраты на доработку = 24 дефекта × 0,833 часа/дефект = 20 часов
То есть это гипотетическое рецензирование требований предотвратило потенциальные затраты 18 часов на доработку на последних этапах реализации проекта. Поэтому минимальная окупаемость затрат на рецензирование составляет 225% (18 часов сэкономленного времени ÷ 8 часов на рецензирование). Многие крупные компании оценивают рентабельность вложений в раннее рецензирование как десятикратную. У вас могут получиться другие цифры, но лишь немногие методы разработки ПО могут десятикратно окупить вложения.
Вносите свой вклад в общее дело
В следующий раз, когда коллега или руководитель попросит вас сделать в проекте что-то, что не принесёт вам личной выгоды, думайте не только о своих интересах. Сотрудники несут ответственность за соблюдение установленных правил и приёмов разработки. Справедливо спросить: «Что нам это даст, если я это сделаю?» На просителе лежит бремя объяснения того, какую пользу всей команде принесет ваш вклад. А вы старайтесь внести свой вклад в общий успех команды.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍5
День 2308. #ЧтоНовенького
Вышла Новая Версия Dev Proxy
Вышел Dev Proxy версии 0.27. В этой версии улучшили опыт разработчиков с помощью нескольких новых функций, упростили генерацию спецификаций API, улучшили предложения по редактированию и заложили основу для будущих интеграций с AI.
Dev Proxy, ранее называвшийся Microsoft 365 Developer Proxy, - это инструмент командной строки, используемый для имитации поведения API во время тестирования приложений. С помощью Dev Proxy разработчики могут создавать устойчивые приложения, умеющие управлять ошибками и ограничениями. См. подробнее про Dev Proxy.
Одной из ключевых функций в этой версии - возможность генерировать определения TypeSpec из перехваченных запросов. TypeSpec — это новый метод моделирования API и генерации кода в различных экосистемах. Это обновление позволяет Dev Proxy быстро создавать определения TypeSpec из реального трафика, что упрощает и ускоряет моделирование API. Подобно созданию спецификаций OpenAPI, разработчики теперь могут использовать эту функцию для ускорения своей работы.
Ещё одним заметным дополнением является экспериментальный сервер Dev Proxy MCP. Он позволяет пользователям настраивать Dev Proxy с помощью естественного языка, предоставляя контекстную помощь и помогая пользователям находить и понимать функции Dev Proxy. Интеграция сервера Model Context Protocol (MCP) с агентами ИИ направлена на упрощение процесса настройки, позволяя пользователям работать с платформой более интуитивно. Однако эта функция в настоящее время доступна в экспериментальной версии для инсайдеров Visual Studio Code с более широкой доступностью через npm.
Обновление также включает значительные улучшения локального соединения с языковой моделью Dev Proxy. Команда разработчиков заявляет следующее:
«Мы реорганизовали локальное соединение с языковой моделью, сделав его универсальным. Ранее логика соединения была тесно связана с Ollama. В этом обновлении мы вводим поддержку подключения Dev Proxy к любому клиенту языковой модели, который предоставляет API, совместимые с OpenAI, что упрощает подключение к поставщикам ИИ, которые вы предпочитаете.»
Кроме того, схемы JSON Dev Proxy были улучшены описаниями и поддержкой markdown. Это изменение упрощает разработчикам понимание и настройку свойств в конфигурации Dev Proxy, особенно при работе в Visual Studio Code.
Прочие обновления улучшают перехват URL-адресов и перезагрузку моков при внесении изменений. Предыдущая проблема с производительностью, когда файлы моков перезагружались несколько раз, была устранена. Обновление также уточняет определение URL-адресов для включения и исключения, улучшая общую обработку моков.
Расширение Dev Proxy Toolkit для Visual Studio Code также было обновлено, в него добавлены новые команды для создания файлов конфигурации и перезапуска Dev Proxy, а также обновлённые фрагменты кода, которые теперь включают последнюю схему и конфигурации TypeSpecGeneratorPlugin.
Полный список изменений в этой версии доступен тут.
Источник: https://www.infoq.com/news/2025/05/microsoft-dev-proxy-0-27/
Вышла Новая Версия Dev Proxy
Вышел Dev Proxy версии 0.27. В этой версии улучшили опыт разработчиков с помощью нескольких новых функций, упростили генерацию спецификаций API, улучшили предложения по редактированию и заложили основу для будущих интеграций с AI.
Dev Proxy, ранее называвшийся Microsoft 365 Developer Proxy, - это инструмент командной строки, используемый для имитации поведения API во время тестирования приложений. С помощью Dev Proxy разработчики могут создавать устойчивые приложения, умеющие управлять ошибками и ограничениями. См. подробнее про Dev Proxy.
Одной из ключевых функций в этой версии - возможность генерировать определения TypeSpec из перехваченных запросов. TypeSpec — это новый метод моделирования API и генерации кода в различных экосистемах. Это обновление позволяет Dev Proxy быстро создавать определения TypeSpec из реального трафика, что упрощает и ускоряет моделирование API. Подобно созданию спецификаций OpenAPI, разработчики теперь могут использовать эту функцию для ускорения своей работы.
Ещё одним заметным дополнением является экспериментальный сервер Dev Proxy MCP. Он позволяет пользователям настраивать Dev Proxy с помощью естественного языка, предоставляя контекстную помощь и помогая пользователям находить и понимать функции Dev Proxy. Интеграция сервера Model Context Protocol (MCP) с агентами ИИ направлена на упрощение процесса настройки, позволяя пользователям работать с платформой более интуитивно. Однако эта функция в настоящее время доступна в экспериментальной версии для инсайдеров Visual Studio Code с более широкой доступностью через npm.
Обновление также включает значительные улучшения локального соединения с языковой моделью Dev Proxy. Команда разработчиков заявляет следующее:
«Мы реорганизовали локальное соединение с языковой моделью, сделав его универсальным. Ранее логика соединения была тесно связана с Ollama. В этом обновлении мы вводим поддержку подключения Dev Proxy к любому клиенту языковой модели, который предоставляет API, совместимые с OpenAI, что упрощает подключение к поставщикам ИИ, которые вы предпочитаете.»
Кроме того, схемы JSON Dev Proxy были улучшены описаниями и поддержкой markdown. Это изменение упрощает разработчикам понимание и настройку свойств в конфигурации Dev Proxy, особенно при работе в Visual Studio Code.
Прочие обновления улучшают перехват URL-адресов и перезагрузку моков при внесении изменений. Предыдущая проблема с производительностью, когда файлы моков перезагружались несколько раз, была устранена. Обновление также уточняет определение URL-адресов для включения и исключения, улучшая общую обработку моков.
Расширение Dev Proxy Toolkit для Visual Studio Code также было обновлено, в него добавлены новые команды для создания файлов конфигурации и перезапуска Dev Proxy, а также обновлённые фрагменты кода, которые теперь включают последнюю схему и конфигурации TypeSpecGeneratorPlugin.
Полный список изменений в этой версии доступен тут.
Источник: https://www.infoq.com/news/2025/05/microsoft-dev-proxy-0-27/
День 2309. #ЗаметкиНаПолях
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Начало
Если вы когда-либо работали с устаревшей кодовой базой C#, вы знаете боль анемичной модели домена. Вы открывали какой-нибудь OrderService и думали: «Этот класс делает всё: логика ценообразования, правила скидок, проверка остатков, запись в БД и т.п.» Это работает… какое-то время. Но новые функции превращаются в регрессионную рулетку, а тестовое покрытие резко падает, потому что доменная логика погребена под инфраструктурной.
Это классический симптом анемичной модели домена, где сущности — это всего лишь держатели данных, а вся логика находится в другом месте. Это затрудняет понимание системы, и каждое изменение превращается в угадайку.
В этой серии мы:
- Изучим типичную анемичную реализацию.
- Определим скрытые бизнес-правила, которые делают её хрупкой.
- Выполним рефакторинг в сторону агрегата с богатым поведением.
- Выделим конкретные выгоды, чтобы вы могли обосновать изменение для членов команды.
Начало: Божественный Класс Сервиса
Ниже приведён (к сожалению, распространённый пример) OrderService. Помимо расчёта итоговых сумм он также:
- применяет скидку VIP 5%,
- выбрасывает исключение, если какой-то товар отсутствует на складе,
- отклоняет заказы, которые превышают кредитный лимит клиента.
Что здесь не так?
1. Разрозненные правила: применение скидок, проверка остатков и проверки кредитного лимита зарыты внутри сервиса.
2. Тесная связь: OrderService должен знать о ценах, запасах и EF Core только для того, чтобы разместить заказ.
3. Болезненное тестирование: каждому модульному тесту нужны моки для доступа к БД, ценообразования, запасов и потоки для VIP и не VIP клиентов.
Наша цель - внедрить эти правила в домен, чтобы прикладной уровень занимался только оркестрацией.
Руководящие принципы
1. Размещаем защитные инварианты близко к данным.
Проверки остатков, скидок и кредита относятся к месту, где находятся данные — внутри агрегата Order.
2. Раскрываем намерение, скрываем механику.
Прикладной уровень должен читаться как история: «разместить заказ», а не «рассчитать итоги, проверить кредит, записать в БД».
3. Выполняем рефакторинг в срезах.
Каждый ход безопасен и компилируется; никаких больших переписываний.
4. Балансируем чистоту с прагматизмом.
Изменяйте правила только тогда, когда выгода (ясность, безопасность, тестируемость) перевешивает дополнительные строки кода.
Продолжение следует…
Источник: https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Начало
Если вы когда-либо работали с устаревшей кодовой базой C#, вы знаете боль анемичной модели домена. Вы открывали какой-нибудь OrderService и думали: «Этот класс делает всё: логика ценообразования, правила скидок, проверка остатков, запись в БД и т.п.» Это работает… какое-то время. Но новые функции превращаются в регрессионную рулетку, а тестовое покрытие резко падает, потому что доменная логика погребена под инфраструктурной.
Это классический симптом анемичной модели домена, где сущности — это всего лишь держатели данных, а вся логика находится в другом месте. Это затрудняет понимание системы, и каждое изменение превращается в угадайку.
В этой серии мы:
- Изучим типичную анемичную реализацию.
- Определим скрытые бизнес-правила, которые делают её хрупкой.
- Выполним рефакторинг в сторону агрегата с богатым поведением.
- Выделим конкретные выгоды, чтобы вы могли обосновать изменение для членов команды.
Начало: Божественный Класс Сервиса
Ниже приведён (к сожалению, распространённый пример) OrderService. Помимо расчёта итоговых сумм он также:
- применяет скидку VIP 5%,
- выбрасывает исключение, если какой-то товар отсутствует на складе,
- отклоняет заказы, которые превышают кредитный лимит клиента.
// OrderService.cs
public void PlaceOrder(
Guid customerId,
IEnumerable<OrderItemDto> items)
{
var customer = _db.Customers.Find(customerId);
if (customer is null)
throw new ArgumentException("Клиент не найден");
var order = new Order { CustomerId = customerId };
foreach (var dto in items)
{
var inventory = _invService
.GetStock(dto.ProductId);
if (inventory < dto.Quantity)
throw new InvalidOperationException("Товара недостаточно");
var price = _pricingService
.GetPrice(dto.ProductId);
var lineTotal = price * dto.Quantity;
// скидка 5% для VIP
if (customer.IsVip)
lineTotal *= 0.95m;
order.Items.Add(new OrderItem
{
ProductId = dto.ProductId,
Quantity = dto.Quantity,
UnitPrice = price,
LineTotal = lineTotal
});
}
order.Total = order.Items
.Sum(i => i.LineTotal);
if (customer.CreditUsed + order.Total > customer.CreditLimit)
throw new InvalidOperationException("Кредитный лимит превышен ");
_db.Orders.Add(order);
_db.SaveChanges();
}
Что здесь не так?
1. Разрозненные правила: применение скидок, проверка остатков и проверки кредитного лимита зарыты внутри сервиса.
2. Тесная связь: OrderService должен знать о ценах, запасах и EF Core только для того, чтобы разместить заказ.
3. Болезненное тестирование: каждому модульному тесту нужны моки для доступа к БД, ценообразования, запасов и потоки для VIP и не VIP клиентов.
Наша цель - внедрить эти правила в домен, чтобы прикладной уровень занимался только оркестрацией.
Руководящие принципы
1. Размещаем защитные инварианты близко к данным.
Проверки остатков, скидок и кредита относятся к месту, где находятся данные — внутри агрегата Order.
2. Раскрываем намерение, скрываем механику.
Прикладной уровень должен читаться как история: «разместить заказ», а не «рассчитать итоги, проверить кредит, записать в БД».
3. Выполняем рефакторинг в срезах.
Каждый ход безопасен и компилируется; никаких больших переписываний.
4. Балансируем чистоту с прагматизмом.
Изменяйте правила только тогда, когда выгода (ясность, безопасность, тестируемость) перевешивает дополнительные строки кода.
Продолжение следует…
Источник: https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
👍27👎2
День 2310. #ЗаметкиНаПолях
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Продолжение
Начало
Пошаговый рефакторинг
Цель здесь не в погоне за чистотой или академическим DDD. Она в постепенном улучшении связности и создании пространства для самовыражения домена. На каждом шаге мы спрашиваем: должно ли это поведение принадлежать домену? Если да, мы добавляем его внутрь домена.
Внедрение логики создания и проверки
Первый шаг — сделать агрегат ответственным за самосборку. Статический метод Create даёт нам единую точку входа, где все инварианты могут работать по принципу «fail fast».
Хотя добавление проверки остатков в Order улучшает тестируемость, оно связывает поток заказов с доступностью товаров на складе. В некоторых доменах лучше смоделировать это как событие домена и проверять асинхронно.
Зачем мы это сделали?
Создание заказа теперь быстро завершается неудачей, если какой-либо инвариант нарушен. Сервис больше не занимается микроуправлением запасами или скидками.
Обратите внимание, как мы теперь следуем принципу «Скажи, не спрашивай». Вместо того, чтобы сервис проверял условия и затем манипулировал заказом, мы говорим заказу создать себя с необходимыми встроенными проверками. Это фундаментальный сдвиг в сторону инкапсуляции.
Замечание: О внедрении сервисов в методы домена
Передача сервисов, таких как IPricingService или IInventoryService, в метод домена, такой как Order.Create, на первый взгляд может показаться нетрадиционной и спорной. Но это осознанный выбор дизайна: он сохраняет оркестрацию внутри модели домена, где естественным образом находится бизнес-логика вместо того, чтобы раздувать сервис приложения процедурными рабочими процессами.
Такой подход сохраняет автономность сущности, при этом по-прежнему согласуясь с принципами внедрения зависимостей: зависимости передаются явно, а не разрешаются изнутри. Это мощный метод, но его следует использовать избирательно — только тогда, когда операция явно вписывается в сферу ответственности домена и выигрывает от прямого доступа к внешним сервисам.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Продолжение
Начало
Пошаговый рефакторинг
Цель здесь не в погоне за чистотой или академическим DDD. Она в постепенном улучшении связности и создании пространства для самовыражения домена. На каждом шаге мы спрашиваем: должно ли это поведение принадлежать домену? Если да, мы добавляем его внутрь домена.
Внедрение логики создания и проверки
Первый шаг — сделать агрегат ответственным за самосборку. Статический метод Create даёт нам единую точку входа, где все инварианты могут работать по принципу «fail fast».
Хотя добавление проверки остатков в Order улучшает тестируемость, оно связывает поток заказов с доступностью товаров на складе. В некоторых доменах лучше смоделировать это как событие домена и проверять асинхронно.
// Order.cs (Фабричный метод)
public static Order Create(
Customer customer,
IEnumerable<(Guid productId, int quantity)> lines,
IPricingService pricingService,
IInventoryService invService)
{
var order = new Order(customer.Id);
foreach (var (id, quantity) in lines)
{
if (invService.GetStock(id) < quantity)
throw new InvalidOperationException("Товара недостаточно");
var price = pricingService.GetPrice(id);
order.AddItem(id, quantity,
price, customer.IsVip);
}
order.EnsureCreditWithinLimit(customer);
return order;
}
Зачем мы это сделали?
Создание заказа теперь быстро завершается неудачей, если какой-либо инвариант нарушен. Сервис больше не занимается микроуправлением запасами или скидками.
Обратите внимание, как мы теперь следуем принципу «Скажи, не спрашивай». Вместо того, чтобы сервис проверял условия и затем манипулировал заказом, мы говорим заказу создать себя с необходимыми встроенными проверками. Это фундаментальный сдвиг в сторону инкапсуляции.
Замечание: О внедрении сервисов в методы домена
Передача сервисов, таких как IPricingService или IInventoryService, в метод домена, такой как Order.Create, на первый взгляд может показаться нетрадиционной и спорной. Но это осознанный выбор дизайна: он сохраняет оркестрацию внутри модели домена, где естественным образом находится бизнес-логика вместо того, чтобы раздувать сервис приложения процедурными рабочими процессами.
Такой подход сохраняет автономность сущности, при этом по-прежнему согласуясь с принципами внедрения зависимостей: зависимости передаются явно, а не разрешаются изнутри. Это мощный метод, но его следует использовать избирательно — только тогда, когда операция явно вписывается в сферу ответственности домена и выигрывает от прямого доступа к внешним сервисам.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
👍8
День 2311. #ЗаметкиНаПолях
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Окончание
Начало
Продолжение
Защищаем Внутреннее Состояние Агрегата
Зачем?
1. Инкапсуляция
Потребители не могут напрямую изменять _items, гарантируя сохранение инвариантов.
2. Самозащита
Модель домена защищает свою собственную согласованность, а не полагается на проверки на уровне сервисов.
3. Истинный ООП
Объекты теперь объединяют данные и поведение, как и задумано объектно-ориентированным программированием.
4. Более простые сервисы
Сервисы приложений могут сосредоточиться на координации, а не на бизнес-правилах.
Сокращаем слой приложения до чистой оркестрации
Метод PlaceOrder сокращается в 3 раза, при этом бизнес-логика отсутствует.
Что мы получили
- Агрегат владеет всеми бизнес-правилами; сервис только оркеструет.
- Чистые тесты предметной области — контейнер базы данных не требуется.
- Большинство изменений изолированы в агрегате Order.
Итого
Настоящая ценность рефакторинга анемичных моделей не техническая, а стратегическая. Переместив бизнес-логику ближе к данным, мы:
- Уменьшили площадь распространения изменений;
- Сделали бизнес-правила явными и проверяемыми.
Именно так устаревшие системы превращаются в удобные в обслуживании архитектуры.
Источник: https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Окончание
Начало
Продолжение
Защищаем Внутреннее Состояние Агрегата
// Order.cs (вырезка)
private readonly List<OrderItem> _items = new();
public IReadOnlyCollection<OrderItem> Items
=> _items.AsReadOnly(); // C# 12 -> [.._items]
private void AddItem(Guid id, int quantity,
decimal price, bool isVip)
{
if (quantity <= 0)
throw new ArgumentException("Количество должно быть положительным");
var finalPrice = isVip
? price * 0.95m
: price;
_items.Add(
new OrderItem(id, quantity, finalPrice)
);
RecalculateTotal();
}
private void EnsureCreditWithinLimit(Customer customer)
{
if (customer.CreditUsed + Total > customer.CreditLimit)
throw new InvalidOperationException("Кредитный лимит превышен");
}
Зачем?
1. Инкапсуляция
Потребители не могут напрямую изменять _items, гарантируя сохранение инвариантов.
2. Самозащита
Модель домена защищает свою собственную согласованность, а не полагается на проверки на уровне сервисов.
3. Истинный ООП
Объекты теперь объединяют данные и поведение, как и задумано объектно-ориентированным программированием.
4. Более простые сервисы
Сервисы приложений могут сосредоточиться на координации, а не на бизнес-правилах.
Сокращаем слой приложения до чистой оркестрации
public void PlaceOrder(
Guid customerId,
IEnumerable<OrderLineDto> lines)
{
var customer = _db.Customers.Find(customerId);
if (customer is null)
throw new ArgumentException("Клиент не найден");
var input = lines.Select(l => (l.ProductId, l.Quantity));
var order = Order.Create(
customer, input,
_pricingService, _inventoryService);
_db.Orders.Add(order);
_db.SaveChanges();
}
Метод PlaceOrder сокращается в 3 раза, при этом бизнес-логика отсутствует.
Что мы получили
- Агрегат владеет всеми бизнес-правилами; сервис только оркеструет.
- Чистые тесты предметной области — контейнер базы данных не требуется.
- Большинство изменений изолированы в агрегате Order.
Итого
Настоящая ценность рефакторинга анемичных моделей не техническая, а стратегическая. Переместив бизнес-логику ближе к данным, мы:
- Уменьшили площадь распространения изменений;
- Сделали бизнес-правила явными и проверяемыми.
Именно так устаревшие системы превращаются в удобные в обслуживании архитектуры.
Источник: https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
👍4👎1
День 2312. #Карьера
Советы по Эффективной Письменной Рабочей Коммуникации. Начало
Важность эффективной, чёткой коммуникации сейчас так же важна, как и когда-либо.
Разве ИИ не может сделать это за меня?
ИИ может создавать контент для вас — и вы даже можете включить некоторые из советов ниже в промпт. Но контент, который вы создаёте, исходит от ВАС, поэтому он по-прежнему отражает вашу способность создавать чёткое сообщение.
Типы коммуникаций
Список ниже, безусловно, не является исчерпывающим, но охватывает многие из форматов общений, которые создают разработчики:
- Email
- Сообщения в блогах
- Сообщения в соц. сетях
- Teams/Slack
- Официальные деловые заметки
- Резюме для руководства
- Презентации Power Point
- Страницы Wiki / Документация
- Файлы Readme
Вот несколько советов и предложений, которые позволят вашему сообщению дойти до адресата максимально эффективно и результативно.
1. Знайте свою аудиторию
Определите цель общения и подумайте, что у вас общего и различного с аудиторией. Вот несколько вопросов, которые могут помочь:
- Выполняют ли они ту же работу, что и я?
- Это в той же области бизнеса?
- У них тот же уровень опыта?
- Должен ли контент быть актуальным через год? Больше?
Ваше общение должно быть направлено не на то, чтобы показать, как много вы знаете, а на то, что вы хотите, чтобы ваша аудитория получила от него, или на действия, которые вы хотите, чтобы они предприняли. Зачастую они не знают вашу работу или ваш бизнес.
2. Используйте списки и форматирование
Чтение длинного повествования или абзаца — сложная задача. Краткое изложение ключевых моментов помогает читателям быстрее усваивать контент.
- Сделайте это лёгким
- Пусть маркеры будут простыми
- Используйте форматирование, чтобы привлечь внимание к ключевым моментам
3. Меньше значит больше
После того, как вы создали контент, перечитайте его и удалите ненужные слова и абзацы.
Вот пример потенциальных гиперссылок:
- Нажмите здесь, чтобы сделать что-то интересное
- Нажмите здесь, чтобы сделать что-то ещё
Его можно легко упростить:
- Сделайте что-то интересное
- Сделайте что-то ещё
Обратите внимание, что ссылка сама «говорит», что нужно сделать. В зависимости от реальной ситуации слова могут быть потенциально упрощены ещё больше.
4. Избегайте внутренних шуток
Чем шире ваша аудитория, тем меньше вероятность того, что все поймут юмор, который вы включаете в сообщение. Прежде чем включать сленг, юмор, шутки или подобный контент, подумайте, будет ли этот контент одинаково понятен всем, кто может его прочитать. Наличие контента, который некоторые не понимают, часто будет означать, что остальная часть вашего сообщения также будет менее понятна.
Сохранение игривого тона 😄 возможно, просто будьте осторожны с «внутрячками», которые поймут лишь немногие.
5. Минимизируйте предположения
Предположения часто могут иметь форму TLA (трехбуквенных аббревиатур), и, если вас немного сбила с толку «TLA» — это и является примером такого рода предположений, которые могут отвлечь читателей от сути сообщения.
Чёткое понимание аудитории и того, что они могут знать, а что нет, может помочь. Использование аббревиатур может быть приемлемым в случаях, когда вы уверены, что все их знают.
Окончание следует…
Источник: https://knowyourtoolset.com/2025/05/tips-for-communication/
Советы по Эффективной Письменной Рабочей Коммуникации. Начало
Важность эффективной, чёткой коммуникации сейчас так же важна, как и когда-либо.
Разве ИИ не может сделать это за меня?
ИИ может создавать контент для вас — и вы даже можете включить некоторые из советов ниже в промпт. Но контент, который вы создаёте, исходит от ВАС, поэтому он по-прежнему отражает вашу способность создавать чёткое сообщение.
Типы коммуникаций
Список ниже, безусловно, не является исчерпывающим, но охватывает многие из форматов общений, которые создают разработчики:
- Сообщения в блогах
- Сообщения в соц. сетях
- Teams/Slack
- Официальные деловые заметки
- Резюме для руководства
- Презентации Power Point
- Страницы Wiki / Документация
- Файлы Readme
Вот несколько советов и предложений, которые позволят вашему сообщению дойти до адресата максимально эффективно и результативно.
1. Знайте свою аудиторию
Определите цель общения и подумайте, что у вас общего и различного с аудиторией. Вот несколько вопросов, которые могут помочь:
- Выполняют ли они ту же работу, что и я?
- Это в той же области бизнеса?
- У них тот же уровень опыта?
- Должен ли контент быть актуальным через год? Больше?
Ваше общение должно быть направлено не на то, чтобы показать, как много вы знаете, а на то, что вы хотите, чтобы ваша аудитория получила от него, или на действия, которые вы хотите, чтобы они предприняли. Зачастую они не знают вашу работу или ваш бизнес.
2. Используйте списки и форматирование
Чтение длинного повествования или абзаца — сложная задача. Краткое изложение ключевых моментов помогает читателям быстрее усваивать контент.
- Сделайте это лёгким
- Пусть маркеры будут простыми
- Используйте форматирование, чтобы привлечь внимание к ключевым моментам
3. Меньше значит больше
После того, как вы создали контент, перечитайте его и удалите ненужные слова и абзацы.
Вот пример потенциальных гиперссылок:
- Нажмите здесь, чтобы сделать что-то интересное
- Нажмите здесь, чтобы сделать что-то ещё
Его можно легко упростить:
- Сделайте что-то интересное
- Сделайте что-то ещё
Обратите внимание, что ссылка сама «говорит», что нужно сделать. В зависимости от реальной ситуации слова могут быть потенциально упрощены ещё больше.
4. Избегайте внутренних шуток
Чем шире ваша аудитория, тем меньше вероятность того, что все поймут юмор, который вы включаете в сообщение. Прежде чем включать сленг, юмор, шутки или подобный контент, подумайте, будет ли этот контент одинаково понятен всем, кто может его прочитать. Наличие контента, который некоторые не понимают, часто будет означать, что остальная часть вашего сообщения также будет менее понятна.
Сохранение игривого тона 😄 возможно, просто будьте осторожны с «внутрячками», которые поймут лишь немногие.
5. Минимизируйте предположения
Предположения часто могут иметь форму TLA (трехбуквенных аббревиатур), и, если вас немного сбила с толку «TLA» — это и является примером такого рода предположений, которые могут отвлечь читателей от сути сообщения.
Чёткое понимание аудитории и того, что они могут знать, а что нет, может помочь. Использование аббревиатур может быть приемлемым в случаях, когда вы уверены, что все их знают.
Окончание следует…
Источник: https://knowyourtoolset.com/2025/05/tips-for-communication/
👍5
День 2313. #Карьера
Советы по Эффективной Письменной Рабочей Коммуникации. Окончание
Начало
6. Эффективно используйте визуальные элементы
Изображение стоит тысячи слов. Потоки, отношения или архитектуры можно кратко представить с помощью диаграммы. Код — ещё один пример хорошего визуального элемента, но имейте в виду, что если вы используете какой-то «реальный» код, удалите лишние строки, не существенные для примера (даже несущественные комментарии, как в примере ниже):
7. Резюмируйте заранее
Обычное сокращение в мире технологий — tl;dr — что означает «слишком долго;не читал» (для олдов: «ниасилил ибо войнаимир»). В верхней части сообщения добавьте краткое резюме того, о чём оно будет.
Краткое резюме может помочь читателю понять, СТОИТ ли ему продолжать читать, поскольку оно обобщает всё содержимое в короткой аннотации. Если аннотация интересна, он может продолжить чтение и углубиться в детали.
Резюмирование особенно важно, если вы просите о действии или даёте рекомендацию. В таких случаях сразу переходите к сути (и используйте форматирование), как в следующих примерах, которые могут быть в начале сообщения:
- Пожалуйста, создайте функцию до следующего вторника
- Рекомендую использовать фреймворк A
Далее вы можете подробно изложить как требования, так и рекомендации, но изложение своей точки зрения сразу устраняет путаницу.
8. Избегайте метафор
Метафоры могут отвлекать от реального сообщения, которое вы пытаетесь донести. Часто они сами по себе не очень понятны, и то, что вы пытаетесь представить, теперь зависит от метафоры.
9. Избегайте «Привет»-ственных сообщений
Не начинайте новое общение с одного сообщения, типа: «Привет, Имярек».
Это раздражающее сообщение встречается слишком часто и не помогает общению. Никакого ответа не требуется, а собеседник понятия не имеет, что вы хотите, и вынужден ждать продолжения. Это особенно раздражает, если он сосредоточен на чём-то, а теперь нужно подумать о том, кто отправитель и чего он может хотеть.
Гораздо лучше написать: «Привет, Имярек, нужна твоя помощь с багом, который мы получили…»
На этом этапе собеседник даже может оценить приоритет на основе дополнительного контекста сообщения и решить, заняться ли им немедленно или ответить позже, когда не будет занят.
10. Создавайте важные сообщения в два этапа
При написании важного сообщения создайте черновик, а затем выполните одно из двух действий или оба:
- Вернитесь к нему позже (лучше всего на следующий день, после сна).
- Попросите людей, которым вы доверяете, дать отзыв
Часто свежий взгляд и вторая пара глаз могут помочь улучшить сообщение или избежать проблемной фразы.
Источник: https://knowyourtoolset.com/2025/05/tips-for-communication/
Советы по Эффективной Письменной Рабочей Коммуникации. Окончание
Начало
6. Эффективно используйте визуальные элементы
Изображение стоит тысячи слов. Потоки, отношения или архитектуры можно кратко представить с помощью диаграммы. Код — ещё один пример хорошего визуального элемента, но имейте в виду, что если вы используете какой-то «реальный» код, удалите лишние строки, не существенные для примера (даже несущественные комментарии, как в примере ниже):
public void SomeMethod()
{
// логика метода тут
}
7. Резюмируйте заранее
Обычное сокращение в мире технологий — tl;dr — что означает «слишком долго;не читал» (для олдов: «ниасилил ибо войнаимир»). В верхней части сообщения добавьте краткое резюме того, о чём оно будет.
Краткое резюме может помочь читателю понять, СТОИТ ли ему продолжать читать, поскольку оно обобщает всё содержимое в короткой аннотации. Если аннотация интересна, он может продолжить чтение и углубиться в детали.
Резюмирование особенно важно, если вы просите о действии или даёте рекомендацию. В таких случаях сразу переходите к сути (и используйте форматирование), как в следующих примерах, которые могут быть в начале сообщения:
- Пожалуйста, создайте функцию до следующего вторника
- Рекомендую использовать фреймворк A
Далее вы можете подробно изложить как требования, так и рекомендации, но изложение своей точки зрения сразу устраняет путаницу.
8. Избегайте метафор
Метафоры могут отвлекать от реального сообщения, которое вы пытаетесь донести. Часто они сами по себе не очень понятны, и то, что вы пытаетесь представить, теперь зависит от метафоры.
9. Избегайте «Привет»-ственных сообщений
Не начинайте новое общение с одного сообщения, типа: «Привет, Имярек».
Это раздражающее сообщение встречается слишком часто и не помогает общению. Никакого ответа не требуется, а собеседник понятия не имеет, что вы хотите, и вынужден ждать продолжения. Это особенно раздражает, если он сосредоточен на чём-то, а теперь нужно подумать о том, кто отправитель и чего он может хотеть.
Гораздо лучше написать: «Привет, Имярек, нужна твоя помощь с багом, который мы получили…»
На этом этапе собеседник даже может оценить приоритет на основе дополнительного контекста сообщения и решить, заняться ли им немедленно или ответить позже, когда не будет занят.
10. Создавайте важные сообщения в два этапа
При написании важного сообщения создайте черновик, а затем выполните одно из двух действий или оба:
- Вернитесь к нему позже (лучше всего на следующий день, после сна).
- Попросите людей, которым вы доверяете, дать отзыв
Часто свежий взгляд и вторая пара глаз могут помочь улучшить сообщение или избежать проблемной фразы.
Источник: https://knowyourtoolset.com/2025/05/tips-for-communication/
👍2
День 2314. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 53. Боль — лучшая мотивация для изменения методов работы
Для команд и организаций, как и для отдельных людей, боль является мощным мотиватором, подталкивающим к изменениям. Мы говорим не о боли, искусственно вызванной извне, когда руководители или клиенты требуют невозможного, а о боли, которую команда испытывает от используемых методов работы.
Мероприятия по совершенствованию процессов не особенно приятны. Они отвлекают от «настоящей работы», которая более интересна членам команды и приносит пользу бизнесу. Усилия по изменению могут казаться сизифовым трудом, поскольку много факторов препятствуют проведению устойчивых организационных изменений. Чтобы мотивировать людей участвовать в изменении, обещанное уменьшение боли должно перевешивать дискомфорт, вызываемый самой процедурой совершенствования. И в какой-то момент участники должны почувствовать, что боль уменьшилась, иначе откажутся участвовать в подобной работе в следующий раз.
Боль причиняет неудобства!
Как бы вы определили «боль» в вашей организации? Какие хронические проблемы возникают в ваших проектах? Определив их, вы сможете сконцентрировать усилия по совершенствованию там, где они принесут наибольшую пользу. Вот несколько типичных примеров «болей» в проектах:
- несоблюдение запланированных сроков поставки;
- выпуск продуктов с чрезмерным количеством дефектов или функциональными недостатками;
- неспособность поспевать за запросами на изменение;
- создание систем, которые трудно расширять без значительных доработок;
- поставка продуктов, не отвечающих в должной мере потребностям клиентов;
- частые сбои системы, вынуждающие дежурного специалиста по поддержке работать по ночам;
- взаимодействие с руководителями, недостаточно хорошо разбирающимися в текущих технологических проблемах и подходах к разработке ПО;
- сложности из-за рисков, которые не были выявлены или уменьшены.
Цель любой деятельности по оценке процесса (группового обсуждения, ретроспективного обзора проекта или оценки сторонним консультантом) — выявить эти проблемные области. После этого появляется возможность определить основные причины проблем и предпринять шаги по их устранению.
Незаметная боль
Проблемы, затрагивающие одних участников проекта, могут быть незаметны другим. Вы можете работать с командой над созданием какой-то функциональности, фонтанировать идеями о постоянном её улучшении. Но с точки зрения команды это будет кошмаром, потому что вы никак не можете определиться с требованиями или выбрать один метод работы. Это подчёркивает необходимость чёткого информирования всех заинтересованных сторон об ожиданиях и проблемах.
Кроме того, трудно продать мышеловку тому, кто не знает, что у него есть мыши. Если вы не замечаете негативных последствий использования текущего подхода, то, скорее всего, не будете восприимчивы к предложениям об изменениях. Любое предлагаемое изменение должно выглядеть как решение проблемы. Поэтому важным аспектом совершенствования процессов выступает выявление причин и затрат, обусловленных проблемами, которые порождает процесс, и последующее информирование тех, кого это касается. Такая осведомлённость может побудить всех участников начать поступать иным образом.
Иногда вы можете стимулировать это осознание. Часто даже групповое обсуждение проблем, с которыми сталкиваются разные члены команды: бизнес-аналитики, руководители проекта, разработчики, заказчики, тестировщики, маркетологи и т.д., - помогает людям понять трудности других и служит хорошей отправной точкой для совершенствования подходов к работе, приносящего пользу всем.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
Уроки 50 Лет Разработки ПО
Урок 53. Боль — лучшая мотивация для изменения методов работы
Для команд и организаций, как и для отдельных людей, боль является мощным мотиватором, подталкивающим к изменениям. Мы говорим не о боли, искусственно вызванной извне, когда руководители или клиенты требуют невозможного, а о боли, которую команда испытывает от используемых методов работы.
Мероприятия по совершенствованию процессов не особенно приятны. Они отвлекают от «настоящей работы», которая более интересна членам команды и приносит пользу бизнесу. Усилия по изменению могут казаться сизифовым трудом, поскольку много факторов препятствуют проведению устойчивых организационных изменений. Чтобы мотивировать людей участвовать в изменении, обещанное уменьшение боли должно перевешивать дискомфорт, вызываемый самой процедурой совершенствования. И в какой-то момент участники должны почувствовать, что боль уменьшилась, иначе откажутся участвовать в подобной работе в следующий раз.
Боль причиняет неудобства!
Как бы вы определили «боль» в вашей организации? Какие хронические проблемы возникают в ваших проектах? Определив их, вы сможете сконцентрировать усилия по совершенствованию там, где они принесут наибольшую пользу. Вот несколько типичных примеров «болей» в проектах:
- несоблюдение запланированных сроков поставки;
- выпуск продуктов с чрезмерным количеством дефектов или функциональными недостатками;
- неспособность поспевать за запросами на изменение;
- создание систем, которые трудно расширять без значительных доработок;
- поставка продуктов, не отвечающих в должной мере потребностям клиентов;
- частые сбои системы, вынуждающие дежурного специалиста по поддержке работать по ночам;
- взаимодействие с руководителями, недостаточно хорошо разбирающимися в текущих технологических проблемах и подходах к разработке ПО;
- сложности из-за рисков, которые не были выявлены или уменьшены.
Цель любой деятельности по оценке процесса (группового обсуждения, ретроспективного обзора проекта или оценки сторонним консультантом) — выявить эти проблемные области. После этого появляется возможность определить основные причины проблем и предпринять шаги по их устранению.
Незаметная боль
Проблемы, затрагивающие одних участников проекта, могут быть незаметны другим. Вы можете работать с командой над созданием какой-то функциональности, фонтанировать идеями о постоянном её улучшении. Но с точки зрения команды это будет кошмаром, потому что вы никак не можете определиться с требованиями или выбрать один метод работы. Это подчёркивает необходимость чёткого информирования всех заинтересованных сторон об ожиданиях и проблемах.
Кроме того, трудно продать мышеловку тому, кто не знает, что у него есть мыши. Если вы не замечаете негативных последствий использования текущего подхода, то, скорее всего, не будете восприимчивы к предложениям об изменениях. Любое предлагаемое изменение должно выглядеть как решение проблемы. Поэтому важным аспектом совершенствования процессов выступает выявление причин и затрат, обусловленных проблемами, которые порождает процесс, и последующее информирование тех, кого это касается. Такая осведомлённость может побудить всех участников начать поступать иным образом.
Иногда вы можете стимулировать это осознание. Часто даже групповое обсуждение проблем, с которыми сталкиваются разные члены команды: бизнес-аналитики, руководители проекта, разработчики, заказчики, тестировщики, маркетологи и т.д., - помогает людям понять трудности других и служит хорошей отправной точкой для совершенствования подходов к работе, приносящего пользу всем.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍4
День 2315. #ЧтоНовенького
Представляем dotnet run app.cs. Начало
В .NET 10 превью 4 упрощено начало работы с C#. Теперь вы можете запустить файл C# напрямую с помощью
До сих пор для выполнения кода C# с помощью dotnet CLI требовалась структура проекта, включающая файл .csproj. Теперь с помощью «файловых приложений» (file-based apps), вы можете запустить автономный файл .cs напрямую, как и в случае с такими языками сценариев, как Python или JavaScript.
Это снижает порог входа для изучения C# и делает язык гораздо более привлекательным выбором для сценариев обучения, прототипирования или автоматизации:
- Быстрый старт, не требуется файл проекта — отлично подходит для обучения, экспериментов и небольших скриптов.
- Первоклассная интеграция CLI — никаких дополнительных инструментов, никаких зависимостей, только dotnet и файл .cs.
- Масштабируется до реальных приложений — это не отдельный диалект или среда выполнения. Когда скрипт вырастет, он может превратиться в полноценный проект, использующий тот же язык, синтаксис и инструменты.
Новые директивы уровня файла для файловых приложений C#
Файловые приложения также поддерживают набор мощных директив уровня файла, которые позволяют объявлять небольшое количество важных вещей, хранящихся в файлах проекта для стандартных приложений. Эти директивы делают файловые приложения более гибкими и выразительными, сохраняя совместимость с концепциями MSBuild.
Ссылаемся на NuGet-пакеты
Вы можете добавить ссылку на NuGet-пакет напрямую в файле .cs, используя директиву #:package:
Указываем SDK
По умолчанию файловые приложения используют Microsoft.NET.Sdk SDK. Если вы создаете что-то вроде веб-API, вы можете изменить SDK с помощью директивы #:sdk:
Это сообщает инструментам, что файл следует обрабатывать так, как если бы он был частью веб-проекта, что позволяет использовать такие функции ASP.NET Core, как Minimal API и MVC.
Настраиваем MSBuild
Вы можете настроить дополнительные свойства сборки с помощью #:property:
Это позволяет файловому приложению использовать расширенные языковые функции и таргетинг на платформу без необходимости в полном файле проекта.
Использование строк шебанг для шелл-скриптов
Файловые приложения также поддерживают строки шебанг (#!), что позволяет писать кроссплатформенные шелл-скрипты на C#, которые можно выполнять непосредственно в Unix-подобных системах:
Вы можете сделать файл выполняемым и выполнить его напрямую:
Это позволяет сделать C# удобной опцией для утилит CLI, скриптов автоматизации и тулинга, никакой настройки проекта не требуется.
Окончание следует…
Источник: https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/
Представляем dotnet run app.cs. Начало
В .NET 10 превью 4 упрощено начало работы с C#. Теперь вы можете запустить файл C# напрямую с помощью
dotnet run app.cs
. Т.е. больше не нужно создавать файл проекта или создавать каркас целого приложения для запуска быстрого скрипта, тестирования фрагмента кода или простого эксперимента.До сих пор для выполнения кода C# с помощью dotnet CLI требовалась структура проекта, включающая файл .csproj. Теперь с помощью «файловых приложений» (file-based apps), вы можете запустить автономный файл .cs напрямую, как и в случае с такими языками сценариев, как Python или JavaScript.
Это снижает порог входа для изучения C# и делает язык гораздо более привлекательным выбором для сценариев обучения, прототипирования или автоматизации:
- Быстрый старт, не требуется файл проекта — отлично подходит для обучения, экспериментов и небольших скриптов.
- Первоклассная интеграция CLI — никаких дополнительных инструментов, никаких зависимостей, только dotnet и файл .cs.
- Масштабируется до реальных приложений — это не отдельный диалект или среда выполнения. Когда скрипт вырастет, он может превратиться в полноценный проект, использующий тот же язык, синтаксис и инструменты.
Новые директивы уровня файла для файловых приложений C#
Файловые приложения также поддерживают набор мощных директив уровня файла, которые позволяют объявлять небольшое количество важных вещей, хранящихся в файлах проекта для стандартных приложений. Эти директивы делают файловые приложения более гибкими и выразительными, сохраняя совместимость с концепциями MSBuild.
Ссылаемся на NuGet-пакеты
Вы можете добавить ссылку на NuGet-пакет напрямую в файле .cs, используя директиву #:package:
#:package [email protected]
using System.Globalization;
using Humanizer;
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-ru");
var net9Release = DateTimeOffset.Parse("2024-12-03");
var since = DateTimeOffset.Now - net9Release;
Console.WriteLine($"Прошло {since.Humanize()} с релиза .NET 9.");
// Прошло 25 недель с релиза .NET 9.
Указываем SDK
По умолчанию файловые приложения используют Microsoft.NET.Sdk SDK. Если вы создаете что-то вроде веб-API, вы можете изменить SDK с помощью директивы #:sdk:
#:sdk Microsoft.NET.Sdk.Web
Это сообщает инструментам, что файл следует обрабатывать так, как если бы он был частью веб-проекта, что позволяет использовать такие функции ASP.NET Core, как Minimal API и MVC.
Настраиваем MSBuild
Вы можете настроить дополнительные свойства сборки с помощью #:property:
#:property LangVersion preview
Это позволяет файловому приложению использовать расширенные языковые функции и таргетинг на платформу без необходимости в полном файле проекта.
Использование строк шебанг для шелл-скриптов
Файловые приложения также поддерживают строки шебанг (#!), что позволяет писать кроссплатформенные шелл-скрипты на C#, которые можно выполнять непосредственно в Unix-подобных системах:
#!/usr/bin/dotnet run
Console.WriteLine("Привет из скрипта C#!");
Вы можете сделать файл выполняемым и выполнить его напрямую:
chmod +x app.cs
./app.cs
Это позволяет сделать C# удобной опцией для утилит CLI, скриптов автоматизации и тулинга, никакой настройки проекта не требуется.
Окончание следует…
Источник: https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/
👍28
День 2316. #ЧтоНовенького
Представляем dotnet run app.cs. Окончание
Начало
Преобразование в приложение на основе проекта
Когда ваше файловое приложение становится сложнее или вам просто нужны дополнительные возможности, предоставляемые полноценными приложениями на основе проектов, вы можете преобразовать его в стандартный проект с помощью:
Эта команда создаст новый каталог с именем файла, файл .csproj и преобразует все директивы #: в свойства и ссылки MSBuild. Например, из этого файла:
Будет создан такой файл .csproj:
Это делает переход плавным, от одного файла к полностью функциональному, собираемому и расширяемому проекту.
Существующие способы запуска C# без проектов
Это далеко не первый случай, когда разработчики хотят запустить C# без проекта. Такие проекты сообщества, как CS-Script, dotnet-script, Cake и другие, уже давно выполняют эту роль, обеспечивая рабочие процессы сценариев, возможности REPL и другие возможности C#.
Эти инструменты остаются ценными и заслуживают внимания, особенно для более сложных сценариев. Однако новая встроенная поддержка позволяет начать работу немедленно: не требуется дополнительных шагов по установке и настройке.
Что дальше?
Эта новая функция делает C# более доступным, сохраняя при этом всю мощь и глубину экосистемы .NET. Независимо от того, изучаете вы язык, обучаете ему других, создаёте прототипы или производственные системы, эта функция поможет вам быстрее перейти от идеи к реализации.
В предстоящих предварительных версиях .NET 10 обещают улучшить опыт работы с файловыми приложениями в VS Code с улучшенным IntelliSense для новых файловых директив, улучшенной производительностью и поддержкой отладки. Для командной строки идёт работа над обеспечением поддержки файловых приложений с несколькими файлами и способами ускорения запуска.
Создатели призывают вас попробовать новую функцию и ждут ваших отзывов на GitHub.
Источник: https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/
Представляем dotnet run app.cs. Окончание
Начало
Преобразование в приложение на основе проекта
Когда ваше файловое приложение становится сложнее или вам просто нужны дополнительные возможности, предоставляемые полноценными приложениями на основе проектов, вы можете преобразовать его в стандартный проект с помощью:
dotnet project convert app.cs
Эта команда создаст новый каталог с именем файла, файл .csproj и преобразует все директивы #: в свойства и ссылки MSBuild. Например, из этого файла:
#:sdk Microsoft.NET.Sdk.Web
#:package Microsoft.AspNetCore.OpenApi@10.*-*
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapGet("/", () => "Hello, world!");
app.Run();
Будет создан такой файл .csproj:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.*-*" />
</ItemGroup>
</Project>
Это делает переход плавным, от одного файла к полностью функциональному, собираемому и расширяемому проекту.
Существующие способы запуска C# без проектов
Это далеко не первый случай, когда разработчики хотят запустить C# без проекта. Такие проекты сообщества, как CS-Script, dotnet-script, Cake и другие, уже давно выполняют эту роль, обеспечивая рабочие процессы сценариев, возможности REPL и другие возможности C#.
Эти инструменты остаются ценными и заслуживают внимания, особенно для более сложных сценариев. Однако новая встроенная поддержка позволяет начать работу немедленно: не требуется дополнительных шагов по установке и настройке.
Что дальше?
Эта новая функция делает C# более доступным, сохраняя при этом всю мощь и глубину экосистемы .NET. Независимо от того, изучаете вы язык, обучаете ему других, создаёте прототипы или производственные системы, эта функция поможет вам быстрее перейти от идеи к реализации.
В предстоящих предварительных версиях .NET 10 обещают улучшить опыт работы с файловыми приложениями в VS Code с улучшенным IntelliSense для новых файловых директив, улучшенной производительностью и поддержкой отладки. Для командной строки идёт работа над обеспечением поддержки файловых приложений с несколькими файлами и способами ускорения запуска.
Создатели призывают вас попробовать новую функцию и ждут ваших отзывов на GitHub.
Источник: https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/
👍7
День 2317. #ЗаметкиНаПолях
Почему Перебор List Быстрее, чем IList?
Если у нас есть List<T> и IList<T>, перебор List<T> быстрее, чем IList<T>. Почему?
Запустим бенчмарк
Результаты будут примерно такие:
40 байт
Откуда взялись эти 40 байт? Когда вы вызываете List<T>.GetEnumerator() (что будет в каждом цикле foreach), вы получаете структуру с именем Enumerator. Когда вы вызываете IList<T>.GetEnumerator(), вы получаете переменную типа IEnumerator, которая содержит упакованную версию указанного перечислителя. Это объясняет 40 байт выделения в куче и некоторую разницу в производительности.
Вызовы виртуальных методов
Но есть и второе измерение. Когда вы вызываете IList<T>.GetEnumerator(), он должен вызвать виртуальный метод, что медленнее, чем вызов невиртуального метода. По сути, кто-то должен проверить, какой конкретный тип действительно используется, а затем вызвать правильный метод. Это не относится к List<T>, который уже является конкретным типом.
Источник: https://steven-giesel.com/blogPost/c624c170-c16c-4414-8506-2ae25ba54df7/why-is-enumerating-over-list-faster-than-ilist
Почему Перебор List Быстрее, чем IList?
Если у нас есть List<T> и IList<T>, перебор List<T> быстрее, чем IList<T>. Почему?
Запустим бенчмарк
[MemoryDiagnoser]
public class Benchmark
{
private List<int> list
= [.. Enumerable.Range(0, 10_000)];
private IList<int> ilist
= [.. Enumerable.Range(0, 10_000)];
[Benchmark(Baseline = true)]
public int GetSumOfList()
{
var sum = 0;
foreach (var n in list) { sum += n; }
return sum;
}
[Benchmark]
public int GetSumOfIList()
{
var sum = 0;
foreach (var n in ilist) { sum += n; }
return sum;
}
}
Результаты будут примерно такие:
|Method |Mean |…|Allocated|
|-------------|--------:|…|--------:|
|GetSumOfList | 4.214 us|…| -|
|GetSumOfIList|19.508 us|…| 40 B|
40 байт
Откуда взялись эти 40 байт? Когда вы вызываете List<T>.GetEnumerator() (что будет в каждом цикле foreach), вы получаете структуру с именем Enumerator. Когда вы вызываете IList<T>.GetEnumerator(), вы получаете переменную типа IEnumerator, которая содержит упакованную версию указанного перечислителя. Это объясняет 40 байт выделения в куче и некоторую разницу в производительности.
Вызовы виртуальных методов
Но есть и второе измерение. Когда вы вызываете IList<T>.GetEnumerator(), он должен вызвать виртуальный метод, что медленнее, чем вызов невиртуального метода. По сути, кто-то должен проверить, какой конкретный тип действительно используется, а затем вызвать правильный метод. Это не относится к List<T>, который уже является конкретным типом.
Источник: https://steven-giesel.com/blogPost/c624c170-c16c-4414-8506-2ae25ba54df7/why-is-enumerating-over-list-faster-than-ilist
👍33
День 2318. #ЗаметкиНаПолях
DTO и Маппинг: Хорошее, Плохое, Лишнее. Начало
DTO — это объекты, используемые для передачи данных между различными слоями или уровнями приложения. Они часто используются для сопоставления (маппинга) данных из одного представления в другое, особенно при пересечении границ, например, между БД и слоем UI или API.
Часто возникает путаница вокруг термина «сущность». Некоторые думают о сущностях в контексте ORM, такого как Entity Framework в .NET. В этом случае сущность — это просто сопоставление модели данных с таблицей БД. Другие думают о сущностях в смысле DDD, где это модель с поведением и идентичностью в пределах предметной области.
Зачем добавляют DTO?
Самая распространённая причина - нежелание раскрывать свою базовую модель данных или модель домена. Например, если сущность ORM напрямую отображается в схему БД, вы можете не захотеть отправлять именно эту сущность через API или на другой уровень приложения. Вместо этого вы создаёте DTO (отображение этой сущности), который отправляете дальше. Это справедливо в некоторых контекстах. Но почему просто не возвращать базовую сущность?
Сервисы сущностей и HTTP API: корень некоторых догм DTO
Часто люди создают DTO, почти идентичные своим сущностям. Конечные точки API сопоставляют операции CRUD напрямую с таблицами БД:
- GET – получение заказа,
- POST – создание,
- PUT – обновление,
- PATCH - частичное обновление,
- DELETE – удаление.
При этом API напрямую отображает методы HTTP на CRUD-операции БД. В этом поначалу нет ничего плохого, но это заставляет вас следовать определённым путем. В итоге вы начинаете думать об API просто как о тонком слое поверх схемы БД. Но API не должен быть таким. Ресурсы, предоставляемые API, не должны быть идентичны записям БД. В приложении, где UI создаётся на стороне сервера, вы бы собирали данные из нескольких источников, чтобы создать полноценное HTML-представление, а не брали бы голые данные из одной таблицы.
Например, если вы возвращаете DTO созданного заказа вы бы включили только его ID, дату создания и статус. Но если вы создаёте UI на стороне сервера, вы бы добавили информацию о клиенте (например, имя), которой может не быть непосредственно в объекте заказа. Также вы бы отобразили возможные действия, которые может выполнить пользователь, вроде «Выполнить», «Отменить» или «Отметить оплату».
Когда вы думаете исключительно в терминах сервисов сущностей и записей БД, вы упускаете эту более богатую композицию. В итоге вы получаете DTO, которые являются просто тонкими оболочками вокруг таблиц БД, не сильно отличающимися от самих сущностей.
Реальная ценность DTO
Есть два основных преимущества использования DTO:
1. Управление связанностью.
DTO помогают контролировать, насколько тесно внешние слои или потребители связаны с внутренними моделями данных.
2. Композиция
DTO позволяют составлять данные из нескольких источников или моделей в единую удобную форму, оптимизированную для конкретного варианта использования или потребителя.
Если вы не делаете никакой композиции и ваши DTO почти идентичны записям БД, то вы, скорее всего, делаете лишнюю работу. Каждый раз при смене базовой модели данных, вы вынуждены обновлять несколько DTO на разных уровнях, что добавляет сложности и накладных расходов на обслуживание, не обеспечивая при этом реальной ценности.
Но, если вы хорошо управляете связанностью и контролируете, как отображаются ваши внутренние модели, DTO становятся очень полезными. Они действуют как защитный слой, который позволяет развивать внутренние модели данных, не нарушая внешних потребителей. Если у вас пока нет этой проблемы (у вас немного потребителей, и вы хорошо управляете связями), то создание нескольких DTO «на всякий случай» может оказаться преждевременной оптимизацией.
Окончание следует…
Источник: https://codeopinion.com/dtos-mapping-the-good-the-bad-and-the-excessive/
DTO и Маппинг: Хорошее, Плохое, Лишнее. Начало
DTO — это объекты, используемые для передачи данных между различными слоями или уровнями приложения. Они часто используются для сопоставления (маппинга) данных из одного представления в другое, особенно при пересечении границ, например, между БД и слоем UI или API.
Часто возникает путаница вокруг термина «сущность». Некоторые думают о сущностях в контексте ORM, такого как Entity Framework в .NET. В этом случае сущность — это просто сопоставление модели данных с таблицей БД. Другие думают о сущностях в смысле DDD, где это модель с поведением и идентичностью в пределах предметной области.
Зачем добавляют DTO?
Самая распространённая причина - нежелание раскрывать свою базовую модель данных или модель домена. Например, если сущность ORM напрямую отображается в схему БД, вы можете не захотеть отправлять именно эту сущность через API или на другой уровень приложения. Вместо этого вы создаёте DTO (отображение этой сущности), который отправляете дальше. Это справедливо в некоторых контекстах. Но почему просто не возвращать базовую сущность?
Сервисы сущностей и HTTP API: корень некоторых догм DTO
Часто люди создают DTO, почти идентичные своим сущностям. Конечные точки API сопоставляют операции CRUD напрямую с таблицами БД:
- GET – получение заказа,
- POST – создание,
- PUT – обновление,
- PATCH - частичное обновление,
- DELETE – удаление.
При этом API напрямую отображает методы HTTP на CRUD-операции БД. В этом поначалу нет ничего плохого, но это заставляет вас следовать определённым путем. В итоге вы начинаете думать об API просто как о тонком слое поверх схемы БД. Но API не должен быть таким. Ресурсы, предоставляемые API, не должны быть идентичны записям БД. В приложении, где UI создаётся на стороне сервера, вы бы собирали данные из нескольких источников, чтобы создать полноценное HTML-представление, а не брали бы голые данные из одной таблицы.
Например, если вы возвращаете DTO созданного заказа вы бы включили только его ID, дату создания и статус. Но если вы создаёте UI на стороне сервера, вы бы добавили информацию о клиенте (например, имя), которой может не быть непосредственно в объекте заказа. Также вы бы отобразили возможные действия, которые может выполнить пользователь, вроде «Выполнить», «Отменить» или «Отметить оплату».
Когда вы думаете исключительно в терминах сервисов сущностей и записей БД, вы упускаете эту более богатую композицию. В итоге вы получаете DTO, которые являются просто тонкими оболочками вокруг таблиц БД, не сильно отличающимися от самих сущностей.
Реальная ценность DTO
Есть два основных преимущества использования DTO:
1. Управление связанностью.
DTO помогают контролировать, насколько тесно внешние слои или потребители связаны с внутренними моделями данных.
2. Композиция
DTO позволяют составлять данные из нескольких источников или моделей в единую удобную форму, оптимизированную для конкретного варианта использования или потребителя.
Если вы не делаете никакой композиции и ваши DTO почти идентичны записям БД, то вы, скорее всего, делаете лишнюю работу. Каждый раз при смене базовой модели данных, вы вынуждены обновлять несколько DTO на разных уровнях, что добавляет сложности и накладных расходов на обслуживание, не обеспечивая при этом реальной ценности.
Но, если вы хорошо управляете связанностью и контролируете, как отображаются ваши внутренние модели, DTO становятся очень полезными. Они действуют как защитный слой, который позволяет развивать внутренние модели данных, не нарушая внешних потребителей. Если у вас пока нет этой проблемы (у вас немного потребителей, и вы хорошо управляете связями), то создание нескольких DTO «на всякий случай» может оказаться преждевременной оптимизацией.
Окончание следует…
Источник: https://codeopinion.com/dtos-mapping-the-good-the-bad-and-the-excessive/
👍23
День 2319. #ЗаметкиНаПолях
DTO и Маппинг: Хорошее, Плохое, Лишнее. Окончание
Начало
CQRS для иллюстрации DTO в действии
В CQRS вы разделяете систему на две части:
1. Запросы отвечают за извлечение и составление данных, возвращая данные, адаптированные для конкретных вариантов использования.
2. Команды отвечают за намерение и действия, такие как обновление или удаление данных.
При этом ваши ответы на запросы по сути являются DTO, которые содержат все объединённые данные, необходимые для конкретного варианта использования. Например, если вы создаёте UI для отображения сведений о заказе, DTO запроса может включать не только данные заказа, но и сведения о клиенте и доступные действия, такие как «Выполнить» или «Отменить».
Команды, с другой стороны, представляют собой конкретные действия, которые вы хотите выполнить. Вместо того чтобы думать в терминах общих операций CRUD, вы думаете в терминах команд, специфичных для домена, таких как «ОтменитьЗаказ» или «ОтметитьЗаказОплаченным». Эти команды инкапсулируют намерение и поведение, а не просто обновления данных.
CQRS не требует разных БД для команд и запросов. Он больше про то, как вы моделируете свою систему и её взаимодействия. Команды и запросы могут работать с одной БД, но представлять разные модели и DTO, адаптированные для их конкретных целей.
Размышления о DTO
1. Внешние и внутренние данные
- Внутри - данные приватные для системы, детали реализации: схема БД и модели домена.
- Снаружи - данные, предоставляемые публично: контракты API или сообщения в очереди.
Цель в сохранении конфиденциальности внутренних данных, чтобы вы могли развивать и изменять их, не влияя на внешних потребителей. Внешние данные следует рассматривать как контракт, который необходимо тщательно версионировать, поскольку вы не контролируете всех потребителей.
Если вы владеете обеими сторонами взаимодействия и можете эффективно управлять связанностью, возможно, DTO не нужны везде. Но если вы предоставляете данные внешним сторонам или хотите разделить слои, чтобы обеспечить независимую эволюцию, DTO бесценны.
2. Количество потребителей
Сколько потребителей зависят от вашей внутренней модели данных? Если всего пара, и вы хорошо управляете связью, вы можете спокойно возвращать сущность напрямую без DTO. Если 50+, это, вероятно, признак того, что нужно ввести уровень абстракции с DTO, чтобы избежать критических изменений и защитить внутренние модели.
Не перебарщивайте с DTO
Часто люди увлекаются и создают множество слоёв отображений DTO-на-DTO-на-другие-DTO. Это только добавляет сложности без реальной выгоды. Если ваши DTO и сущности почти идентичны, и вы просто копируете данные туда-сюда, это уже лишняя работа.
DTO должны служить чёткой цели, например:
- Разделение внутренних моделей данных от внешних контрактов;
- Составление данных из нескольких источников для конкретных вариантов использования;
- Добавление версионирования для публичного API.
Итого
- DTO в первую очередь предназначены для управления связями и композицией данных. Они помогают избежать раскрытия деталей внутренней реализации и позволяют формировать данные, адаптированные для конкретных потребителей.
- Не создавайте DTO просто так. Если внутренние модели и внешние потребители жёстко контролируются и ограничены, может быть удобно возвращать сущности напрямую.
- Остерегайтесь чрезмерных слоёв сопоставления. Они только добавляют ненужной сложности.
- Используйте шаблоны, вроде CQRS, чтобы по-другому думать о запросах и командах. Это помогает моделировать данные и действия таким образом, чтобы они естественным образом соответствовали DTO и композиции.
- Думайте о данных как о внутренних (частных) и внешних (публичный контракт). Такой образ мышления поможет решить, где необходимы DTO и как версионировать ваш API.
Источник: https://codeopinion.com/dtos-mapping-the-good-the-bad-and-the-excessive/
DTO и Маппинг: Хорошее, Плохое, Лишнее. Окончание
Начало
CQRS для иллюстрации DTO в действии
В CQRS вы разделяете систему на две части:
1. Запросы отвечают за извлечение и составление данных, возвращая данные, адаптированные для конкретных вариантов использования.
2. Команды отвечают за намерение и действия, такие как обновление или удаление данных.
При этом ваши ответы на запросы по сути являются DTO, которые содержат все объединённые данные, необходимые для конкретного варианта использования. Например, если вы создаёте UI для отображения сведений о заказе, DTO запроса может включать не только данные заказа, но и сведения о клиенте и доступные действия, такие как «Выполнить» или «Отменить».
Команды, с другой стороны, представляют собой конкретные действия, которые вы хотите выполнить. Вместо того чтобы думать в терминах общих операций CRUD, вы думаете в терминах команд, специфичных для домена, таких как «ОтменитьЗаказ» или «ОтметитьЗаказОплаченным». Эти команды инкапсулируют намерение и поведение, а не просто обновления данных.
CQRS не требует разных БД для команд и запросов. Он больше про то, как вы моделируете свою систему и её взаимодействия. Команды и запросы могут работать с одной БД, но представлять разные модели и DTO, адаптированные для их конкретных целей.
Размышления о DTO
1. Внешние и внутренние данные
- Внутри - данные приватные для системы, детали реализации: схема БД и модели домена.
- Снаружи - данные, предоставляемые публично: контракты API или сообщения в очереди.
Цель в сохранении конфиденциальности внутренних данных, чтобы вы могли развивать и изменять их, не влияя на внешних потребителей. Внешние данные следует рассматривать как контракт, который необходимо тщательно версионировать, поскольку вы не контролируете всех потребителей.
Если вы владеете обеими сторонами взаимодействия и можете эффективно управлять связанностью, возможно, DTO не нужны везде. Но если вы предоставляете данные внешним сторонам или хотите разделить слои, чтобы обеспечить независимую эволюцию, DTO бесценны.
2. Количество потребителей
Сколько потребителей зависят от вашей внутренней модели данных? Если всего пара, и вы хорошо управляете связью, вы можете спокойно возвращать сущность напрямую без DTO. Если 50+, это, вероятно, признак того, что нужно ввести уровень абстракции с DTO, чтобы избежать критических изменений и защитить внутренние модели.
Не перебарщивайте с DTO
Часто люди увлекаются и создают множество слоёв отображений DTO-на-DTO-на-другие-DTO. Это только добавляет сложности без реальной выгоды. Если ваши DTO и сущности почти идентичны, и вы просто копируете данные туда-сюда, это уже лишняя работа.
DTO должны служить чёткой цели, например:
- Разделение внутренних моделей данных от внешних контрактов;
- Составление данных из нескольких источников для конкретных вариантов использования;
- Добавление версионирования для публичного API.
Итого
- DTO в первую очередь предназначены для управления связями и композицией данных. Они помогают избежать раскрытия деталей внутренней реализации и позволяют формировать данные, адаптированные для конкретных потребителей.
- Не создавайте DTO просто так. Если внутренние модели и внешние потребители жёстко контролируются и ограничены, может быть удобно возвращать сущности напрямую.
- Остерегайтесь чрезмерных слоёв сопоставления. Они только добавляют ненужной сложности.
- Используйте шаблоны, вроде CQRS, чтобы по-другому думать о запросах и командах. Это помогает моделировать данные и действия таким образом, чтобы они естественным образом соответствовали DTO и композиции.
- Думайте о данных как о внутренних (частных) и внешних (публичный контракт). Такой образ мышления поможет решить, где необходимы DTO и как версионировать ваш API.
Источник: https://codeopinion.com/dtos-mapping-the-good-the-bad-and-the-excessive/
👍11