.NET Разработчик
6.69K subscribers
463 photos
4 videos
14 files
2.22K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 2528.
Дорогие подписчики и все разработчики ПО, с новым 2026м годом!

Пусть наступающий год принесёт вам адекватных клиентов, понимающих менеджеров, зелёные тесты, молниеносные сборки и отсутствие ошибок в проде. Ваша преданность созданию надежных, элегантных и масштабируемых решений обеспечивает бесперебойную работу цифрового мира. Надеюсь, 2026 год вознаградит вас захватывающими проектами, поддержкой команд и множеством моментов, когда все компилируется с первой попытки.

Продолжайте исследовать новые фреймворки, расширять границы и формировать будущее программного обеспечения своим творчеством и точностью. Желаю вам вдохновения, роста и радости в каждой написанной вами строке кода.

Ну и чтобы скоротать время после отмечания нового года, вот вам лёгкое видео от Айти Бороды. Вайбкодинг, наверное, слово года в IT-мире. Что это, с чем его едят, почему многие воспринимают его как ругательство и что нас ждёт в мире разработки, который захватывают ИИ-агенты. Приятного просмотра.

https://youtu.be/2EZxvgRiaoY
2👍46
День 2529. #ЗаметкиНаПолях
Технический Долг — Миф, Созданный Плохими Менеджерами. Начало

Тысячи статей, выступлений на конференциях и десятки книг были посвящены техническому долгу, проповедованию принципов чистого кода и надёжной архитектуры. Разработчиков учили, как его избегать, гасить, как вести переговоры с менеджерами.
В чём проблема? Не в практиках — они по-прежнему хороши. А вот технический долг не просто неправильно понимается; это принципиально неверная метафора, которая искажает наше представление о разработке ПО. И что хуже всего, мы продолжаем использовать её, потому что это единственная финансовая метафора, понятная руководителям, а это значит, что мы застряли в объяснении инженерных проблем в терминах, которые маскируют то, что происходит на самом деле.

Проблема с метафорой
Уорд Каннингем в 1992 году ввёл термин «технический долг» для описания конкретной ситуации: преднамеренный выбор быстрой реализации с пониманием того, что позже её нужно будет переписать. Как и финансовый долг, вы берёте время взаймы сейчас с обещанием вернуть его с процентами.

Но вот что на самом деле происходит в большинстве организаций:
Менеджер: «Почему эта функция так долго разрабатывается? Я думал, вы сказали, что она будет готова за две недели?»
Инженер: «Ну, у нас много технического долга, который нужно преодолеть…»
М: «Так почему вы не писали более качественный код с самого начала?»


И вот так инженеры оказываются плохими парнями. Теми, кто «накопил долг». Теми, кто «выбирал короткие пути». Теми, кто теперь тормозит развитие компании. Только это полная чушь.

Долг подразумевает, что у вас был выбор
Реальный долг работает так: вы обращаетесь к кредитору, договариваетесь об условиях, подписываете документы и соглашаетесь выплатить основную сумму плюс проценты. Вы понимаете условия сделки. Вы соглашаетесь на них.

Что происходит с техническим долгом:
М: «Нам нужно выпустить это к пятнице для демонстрации инвесторам».
И: «Этого времени недостаточно, чтобы сделать это как следует. Нам понадобится как минимум три недели, чтобы все сделать правильно».
М: «Сделайте так, чтобы это работало. Мне все равно, как».
[Три месяца спустя]
М: «Этот код — полный бардак».


Видите проблему? Инженер ничего не «заимствовал». Он не выбирал долг. Ему поставили невыполнимые задачи, и он сделал всё, что мог. А теперь его обвиняют в «процентах». Это не технический долг. Это технические последствия решений руководства.

Любой код стареет (это не долг, это энтропия)
Ещё одна странность - называть любой старый код «техническим долгом». Ваш 4-летний код, использующий .NET 6 вместо последней версии, — это не «долг». API, возвращающий XML вместо GraphQL, — это не «долг». Монолит, который все теперь хотели бы видеть в виде микросервисов, — это не «долг». Это просто код, существующий во времени.

Требования меняются. Платформы развиваются. Лучшие практики меняются. Появляются новые фреймворки. Контекст, в котором был написан ваш код, отличается от контекста, в котором он существует сегодня.

Называть это «долгом» подразумевает, что кто-то совершил ошибку. Это подразумевает халатность. Это подразумевает, что, если бы инженеры были умнее, дальновиднее, компетентнее, этой проблемы не было бы. Но так ПО не работает. Так не работает ничего. Вы не можете предсказать будущее. Невозможно создавать решения, отвечающие требованиям, которых ещё не существует. И даже если бы это было возможно, вы бы переусложнили систему и потратили время на создание гибкости, которая вам никогда не понадобится.

Продолжение следует…

Источник:
https://dev.to/adamthedeveloper/technical-debt-is-a-myth-created-by-bad-managers-2l3k
👍44
День 2530. #ЗаметкиНаПолях
Технический Долг — Миф, Созданный Плохими Менеджерами. Продолжение

Начало

«Долг» - обычно правильное решение
Поговорим о том самом MVP, который вы создали 2 года назад. О том, который теперь «устарел», «нуждается в переработке», «тормозит ваше развитие».

Знаете, что ещё сделал этот MVP? Он подтвердил жизнеспособность бизнес-модели. Он привлек первую тысячу пользователей. Он сгенерировал доход, который позволяет нам вести этот разговор. Без этого «плохого кода» у вас ничего бы не было. Вы бы обанкротились в ожидании «идеальной архитектуры».

Но теперь, когда он успешен, когда он масштабируется, когда вы хотите двигаться быстрее… внезапно это становится «техническим долгом». Внезапно инженеров, которые создали то, что сделало вашу компанию жизнеспособной, обвиняют в том, что они сделали это «неправильно». Это сочетание ошибки выжившего и крепости задним умом.

То, что менеджеры называют «долгом», инженеры называют «компромиссами»
Каждое инженерное решение — это компромисс. Не некоторые из них. Не большинство. Все!
- Скорость или гибкость;
- Простота или функциональность;
- Проверенные технологии или передовые решения;
- Разработка собственными силами или покупка;
- Монолитная архитектура или микросервисы;
- SQL или NoSQL;
- Покрытие тестами или скорость выпуска.
На эти вопросы нет «правильного» ответа. Есть только «правильный для нашего текущего контекста, ограничений и приоритетов». Хорошие менеджеры это понимают. Они участвуют в принятии этих решений. Они говорят что-то вроде: «Сейчас нас заботит скорость выпуска, потому что нам нужно проверить рынок. Мы вернемся к архитектуре, когда достигнем соответствия продукта рынку».
Плохие менеджеры говорят: «Просто заставьте это работать. Разберитесь».
А потом: «Почему так много технического долга?»

Реальная проблема: Накопление невежества
Вот что на самом деле происходит, когда менеджеры не понимают накопительного характера затрат на поддержку ПО:
Год 1: «Выпускайте быстро! Не беспокойтесь о идеальном коде!»
Год 2: «Почему новые функции требуют больше времени? Раньше мы выпускали их так быстро!»
Год 3: «Нам нужно остановить всю работу над функциями и переписать код».
Это не технический долг. Это непонимание руководством того, что поддержка ПО не бесплатна. Что каждая функция увеличивает площадь покрытия. Что каждая зависимость нуждается в обновлении. Что каждый API нуждается в версионировании.
Инженеры знали это. Они говорили вам. Вы не слушали, потому что были сосредоточены на показателях следующего квартала.

А что насчёт реального срезания углов?
Да, иногда инженеры действительно халтурят. Мы пропускаем написание тестов, жёстко кодируем значения, неправильно обрабатываем ошибки, копируем и вставляем вместо того, чтобы переиспользовать код. Но это почти всегда происходит из-за внешнего давления:
- «Нам это нужно для демонстрации завтра».
- «Клиент угрожает уйти, если мы не выпустим продукт на этой неделе».
- «Мы теряем деньги и нам нужна прибыль прямо сейчас».

Даже действительно плохие инженерные решения обычно принимаются под давлением, в условиях ограниченного времени, неполной информации и огромного давления со стороны… руководства.

Продолжение следует…

Источник:
https://dev.to/adamthedeveloper/technical-debt-is-a-myth-created-by-bad-managers-2l3k
👍17
День 2531. #ЗаметкиНаПолях
Технический Долг — Миф, Созданный Плохими Менеджерами. Продолжение

Начало
Продолжение

Неприятная правда: иногда дело действительно в плохой работе
Будем честны: иногда код действительно просто плохой, и это не вина руководства. Иногда вы нанимаете разработчика, который:
- Не понимает язык или фреймворк, который использует;
- Копирует ответы ИИ, не понимая их;
- Пишет кучу вложенных if;
- Создает «божественные» классы, потому что «проще хранить всё в одном месте»;
- Отказывается учиться или развиваться, потому что «я всегда так делал»…
А иногда ваш процесс проверки кода настолько несовершенен, что всё это попадает в прод.

Формальные ревью кода
Вы знаете, как это бывает. Кто-то открывает пул-реквест в 16:45 в пятницу. Там 847 строк изменений в 23 файлах. Рецензент бегло просматривает код, не видит очевидных ошибок и нажимает «Одобрить» и уходит на выходные.
Или ещё хуже, есть сеньор, который агрессивно воспринимает критику, и все боятся давать реальную обратную связь, т.к. когда-то кто-то предложил ему рефакторинг, и получил эссе на 2000 слов о том, почему он не прав, а затем три недели пассивно-агрессивной переписки.

У команды нет стандартов
Некоторые команды действительно не имеют стандартов кодирования, руководства по стилю, архитектурных принципов или согласованных шаблонов. Каждый просто делает то, что ему кажется правильным в данный момент.
Один пишет функциональный код с неизменяемыми структурами данных. Другой - ООП с сильным наследованием. Третий просто хочет выпустить продукт и ему на всё пофиг. Результат? Кодовая база Франкенштейна, где каждый модуль кажется написанным другой компанией.

Джун без присмотра
Встречается чаще, чем нам хотелось бы признать: вы нанимаете джуна, даёте ему задачу, и… никто не проверяет, как он справляется. Он две недели мучается, в конце концов, методом проб и ошибок добивается работоспособности и выпускает продукт. Продукт (в принципе) работает, поэтому запускается в прод.
Шесть месяцев спустя кому-то приходится модифицировать этот код, и – внезапно - всё держится на честном слове и молитвах. Никаких тестов или обработки ошибок, переменные temp1, temp2, бизнес-логика смешана с UI-кодом и запросами к БД.
Это технический долг или вина руководства? Руководство не обеспечило наставничество и контроль. Но и инженер мог попросить о помощи, посмотреть на существующий код на предмет шаблонов и т.п.

Тут и начинаются сложности. Потому что даже когда код действительно плох из-за инженерных ошибок, формулировка «технический долг» всё равно неверна, т.к. отнесение этого к «долгу» всё равно:
- Представляет это как преднамеренный компромисс (чего не было);
- Подразумевает, что долг нужно «вернуть» (это нужно исправить);
- Маскирует первопричину (проблемы с наймом, обучением, проверкой кода или стандартами).
Если вы наняли кого-то недостаточно хорошего, это проблема с наймом. Если код-ревью не выявляют проблемы - проблема с процессом. Если у команды нет стандартов - проблема с руководством. Если джуны выпускают неподдерживаемый код - проблема с наставничеством.

Ничто из этого не является «долгом». Это организационные сбои, которые проявляются как проблемы с качеством кода. И даже эти неудачи часто сводятся к решениям руководства. Кто-то решил:
- Нанять дешёвых разработчиков вместо лучших;
- Пропустить техническую часть собеседования, потому что кандидат «казался умным»;
- Не выделить время старших инженеров на проверку кода и наставничество;
- Не инвестировать в установление командных стандартов или архитектурных принципов;
- Приоритет отдавать баллам истории, а не качеству кода.
Мы постоянно возвращаемся к проблемам с руководством.

Окончание следует…

Источник:
https://dev.to/adamthedeveloper/technical-debt-is-a-myth-created-by-bad-managers-2l3k
👍18
День 2532. #ЗаметкиНаПолях
Технический Долг — Миф, Созданный Плохими Менеджерами. Окончание

Начало
Продолжение 1
Продолжение 2

Когда инженерам нужно брать на себя ответственность
Как инженеры, мы должны брать на себя ответственность за своё дело. Нам необходимо:
- Действительно проверять код, а не просто одобрять пул-реквест, не глядя;
- Давать и получать обратную связь как профессионалы;
- Инвестировать в обучение и развитие;
- Просить о помощи, когда мы застряли;
- Отказывать ужасному коду в пул-реквестах, даже если неудобно перед коллегами;
- Устанавливать и поддерживать стандарты в команде.
Если вы одобрили пул-реквест, не прочитав его, вы несёте ответственность за этот код. Если вы написали небрежный код, потому что вам было лень, это ваша вина. Если вы совершаете одни и те же ошибки в течение пяти лет и отказываетесь учиться, проблема в вас.

В чём разница? Когда мы признаём эти ошибки, мы можем их исправить. Мы можем улучшить культуру проверки кода. Мы можем повысить свой уровень квалификации. Мы можем внедрить лучшие практики. Но когда мы прячемся за «техническим долгом» как за расплывчатым общим термином, мы ничего не можем исправить, потому что даже не выявляем реальную проблему.

Так как же это называть?
Вместо «технического долга» попробуйте следующие варианты:
- «Технические последствия прошлых бизнес-решений» — многословно, но точно. Это позволяет сохранить ответственность там, где ей место.
- «Затраты на обслуживание» — в каждом коде есть свои затраты. Они растут со временем. Заложите их в «бюджет».
- «Сдвиг контекста» — то, что имело смысл два года назад, сейчас не имеет смысла. Это нормально.
- «Необходимый рефакторинг» — ПО развивается. Рефакторинг — это нормально. Перестаньте относиться к нему как к наказанию.
- «Стоимость обучения» — вы не знали, что то, что вы создавали, будет успешным. Теперь знаете. Пора оптимизировать.

Итого
Технический долг — миф не потому, что коротких путей не существует. Это миф, потому что метафора искажена до неузнаваемости. Он стал способом для менеджеров:
- Обвинять инженеров в бизнес-решениях;
- Избегать ответственности за распределение ресурсов;
- Рассматривать нормальную эволюцию ПО как халатность;
- Уклоняться от ответственности за невыполнимые сроки.

Хорошие менеджеры берут на себя ответственность за компромиссы. Они говорят: «Мы выбрали скорость вместо гибкости, и теперь нужно заново оптимизировать. Это потребует времени и ресурсов. Я распределяю и то, и другое».
Плохие менеджеры используют ретроспективный анализ в качестве оружия. Они говорят: «Вы должны были сделать это правильно с первого раза. Почему так много технического долга?»

Если вы менеджер, читающий это, и вы когда-либо жаловались на технический долг, спросите себя: дали ли вы своей команде время и ресурсы, чтобы сделать это «правильно»? Знали ли вы вообще, что значит «правильно»? Или вы просто хотели, чтобы это было выпущено?

Если вы инженер и читаете это, перестаньте брать на себя вину за решения, которые были приняты не вами. В следующий раз, когда кто-то упомянет технический долг на ретроспективе, попробуйте возразить:
«Давайте поговорим об ограничениях, в которых мы работали, принимая эти решения. Потому что я почти уверен, что мы приняли наилучшее возможное решение, исходя из имеющейся информации и времени».

А если вам будут возражать и будут настаивать, что это «долг», который вы «заимствовали»…
Начните проходить собеседования. Потому что вы работаете на человека, который не понимает разработку ПО и всегда будет винить вас, когда возникнут трудности.

Источник: https://dev.to/adamthedeveloper/technical-debt-is-a-myth-created-by-bad-managers-2l3k
👍23👎1
День 2533. #Оффтоп
Праздники продолжаются, поэтому снова представляю вам полуразвлекательное видео.

Мы все заняты софтом, алгоритмами, оптимизациями. Но редко задумываемся, на чем весь этот софт выполняется. Максимум - выбираем SKU виртуальной машины или контейнера.

А как создаётся железо, на котором всё это крутится? До просмотра этого видео я в общих чертах это представлял, но даже близко не подозревал, насколько это сложный процесс.

В общем, любителям железячек и физики должно зайти. Приятного просмотра.

https://youtu.be/MiUHjLxm3V0
👍11
День 2534. #МоиИнструменты
.NET Toolbox

Подарок на новый год от Steven Giesel. Он создал новый инструмент под названием «Toolbox», который предложит вам полезные UI-инструменты для повседневной работы с .NET. Абсолютно бесплатный, с открытым исходным кодом и полностью в браузере!

Что это?
Toolbox находится здесь: https://toolbox.bitspire.ch/

Он предлагает набор вспомогательных инструментов, которые немного упростят вашу повседневную жизнь. Некоторые функции разработаны специально для новичков в языке (с акцентом на веб-разработку). На данный момент предлагаются следующие функции:
- Преобразование JSON в C#;
- C# в TypeScript (и обратно);
- JWT-декодер;
- Дизайнер Промежуточного ПО (создаёт код Промежуточного ПО ASP.NET);
- Централизатор пакетов (создаёт Directory.Packages.props из ваших файлов .csproj);
- Шпаргалка по C# (все функции языка по версиям);
- Визуализатор List<T> (для новичков – визуализирует, как внутренне создаётся и заполняется список).

Подробно рассмотрим пару функций.
1. Конструктор промежуточного ПО (Middleware Designer)
Предназначен для начинающих, чтобы они могли легко понять, какие промежуточные ПО используются в .NET и как их настраивать. Инструмент также старается предоставлять полезную информацию в случае возникновения проблем. На картинке 1 ниже вы видите, что авторизация используется перед аутентификацией, что неверно, и о чём появляется предупреждение.
Также есть возможность имитировать запросы, чтобы увидеть такие вещи, как ограничения запросов в действии. В идеале это даст вам лучшее представление о наиболее распространённых конвейерах обработки запросов в ASP.NET, а также о том, как их настраивать и использовать.

2. Централизатор пакетов (Package Centralizer)
Суть в том, что вы добавляете несколько своих файлов .csproj и получаете централизованную версию (с возможностью разрешения конфликтов), включая обновлённые файлы .csproj. См. картинку 2 ниже.

Исходный код проекта здесь: https://github.com/BitSpireGmbH/toolbox

Источник: https://steven-giesel.com/blogPost/043491b9-9d2c-433f-bb9b-1cec5b957083/net-toolbox
👍33
День 2535. #ЗаметкиНаПолях
Снижаем Нагрузку на CPU при Использовании GitHub Actions

Если вы используете GitHub Actions на собственных серверах, вы могли заметить, что они могут быть удивительно ресурсоемкими для ЦП, даже в режиме ожидания. При более внимательном рассмотрении становится ясно, что один раннер может загружать CPU на 100%. Это не ошибка в вашем рабочем процессе; это преднамеренное проектное решение в механизме сна раннера.

Проблема: «Занятое ожидание»
Вместо использования стандартных, эффективных функций сна, предоставляемых операционной системой, раннер GitHub Actions использует цикл «занятого ожидания» (Busy-waiting). Это означает, что он постоянно проверяет системные часы в плотном цикле, ожидая истечения заданного промежутка времени. Хотя такой подход обеспечивает совместимость в широком диапазоне сред, включая некоторые без традиционных функций сна, он крайне неэффективен для подавляющего большинства систем, таких как стандартные виртуальные машины Linux или Windows. Эта постоянная проверка поддерживает полную активность CPU, что приводит к нерациональному использованию ресурсов, повышению температуры и потенциальному снижению производительности других задач на той же машине.

Решение: интеллектуальный скрипт установки режима сна
К счастью, мы можем решить эту проблему, заменив стандартный скрипт установки режима сна на более интеллектуальную версию. Цель — использовать наиболее эффективный метод установки режима сна, доступный в системе. Вот скрипт, который отдаёт приоритет стандартным командам установки режима сна и предоставляет резервные варианты, обеспечивая как эффективность, так и совместимость.

Перейдите в папку, где установлен ваш раннер, и отредактируйте файл safe_sleep.sh. Замените его содержимое следующим:
#!/bin/bash

# Используем нативную команду 'sleep', если доступна (наиболее эффективно)
if [ -x "$(command -v sleep)" ]; then
sleep $1
exit 0
fi

# Пробуем 'read' с таймаутом (встроено в bash)
if [[ -n "$BASH_VERSINFO" && "${BASH_VERSINFO[0]}" -ge 4 ]]; then
read -rt "$1" <> <(:) || :
exit 0
fi

# Креативный вариант с 'ping'
if [ -x "$(command -v ping)" ]; then
ping -c $1 127.0.0.1 > /dev/null
exit 0
fi

# Оригинальное «занятое ожидание» (в крайнем случае)
SECONDS=0
while [[ $SECONDS != $1 ]]; do
:
done

Этот скрипт сначала пытается использовать стандартную команду sleep. Если она недоступна, он пытается использовать read с таймаутом, что является встроенной функцией оболочки и всё ещё эффективнее, чем ожидание в активном режиме. В качестве запасного варианта используется ping. Только если ни один из этих вариантов недоступен, скрипт возвращается к исходному циклу «занятого ожидания».

Предупреждение:
Средства запуска GitHub Actions могут обновляться автоматически. При обновлении ваши изменения в файле safe_sleep.sh могут быть перезаписаны. Чтобы гарантировать сохранение исправления, вы можете настроить задание cron или запланированную задачу для периодического повторного применения этого изменения.

Дополнительные ресурсы
Для получения более подробной технической информации и обсуждения этой темы в сообществе вы можете обратиться к этим проблемам и пул-реквестам на GitHub:
- https://github.com/actions/runner/issues/2380
- https://github.com/actions/runner/issues/3792
- https://github.com/actions/runner/pull/3870

Источник: https://www.meziantou.net/reduce-github-actions-runner-cpu-usage.htm
👍4
День 2536. #Карьера
Топ Советов по Повышению Продуктивности. Часть 3

Часть 1
Часть 2

3. Правило 15 минут: секретное оружие против прокрастинации и бесконечных отвлекающих задач
У каждого разработчика есть два заклятых врага: задача, которую не хочется начинать, и задача, от которой невозможно оторваться.

Сценарий 1: нужно переписать устаревший модуль, которого все боятся касаться. С 800 строками в одном файле, без тестов и с комментариями на трёх разных языках. Одна мысль об этом уже изматывает. Поэтому вы… проверяете email и чаты, проводите генеральную уборку клавиатуры и т.п. Всё что угодно, лишь бы не погружаться в эту бездну.

Сценарий 2: Вы выясняете, почему медленно загружается страница. Нужно проверить всего несколько метрик, это займёт десять минут. Три часа спустя вы перестроили всю свою инфраструктуру мониторинга, прочитали 12 статей о производительности запросов в EF и сделали бенчмарк для сравнения трёх разных решений — но всё ещё не решили первоначальную проблему.

Правило 15 минут
1. Для задач, которых вы избегаете: пообещайте себе, что поработаете над задачей всего 15 минут. Через 15 минут вы сможете остановиться без чувства вины.
2. Для задач, в которые вы вкладываете слишком много сил: установите 15-минутный таймер, прежде чем углубляться в какую-либо тему. Когда он зазвонит, спросите себя: «Действительно ли это решает мою проблему, или я просто наслаждаюсь процессом исследования?»

Почему это работает?
Самое сложное — начать. Наш мозг запрограммирован на избегание дискомфорта, и большие, неопределённые задачи провоцируют эту реакцию избегания. Но 15 минут? Это не страшно. Любой сможет делать что угодно в течение 15 минут. Вы не обязуетесь закончить — вы обязуетесь начать.
Прелесть в том, что в большинстве случаев вы не остановитесь через 15 минут. Как только вы начнёте, инерция возьмёт верх. Вы обнаружите, что задача не так уж и сложна, как вы себе представляли. Или же вы войдете в состояние потока и совсем забудете о таймере. Правило 15 минут — это психологический лом для вашей мотивации.

Что касается отвлечений, проблема обратная. Разработчики от природы любопытны и стремятся решать проблемы. Мы видим интересное ответвление, и наш мозг активизируется: «О, я мог бы это оптимизировать! Дайте-ка я быстренько…» Проходит 4 часа, а вы ничего не сделали для достижения реальной цели.
15-минутный таймер заставляет быть предельно честным:
- Важен ли для текущей задачи рефакторинг этой функции?
- Нужно ли изучить все внутренности EF, чтобы этот запрос к БД работал оптимальнее?
Иногда ответ — да! Иногда действительно нужно копнуть глубже. Но часто ответ — нет, и правило 15 минут даёт вам право сделать прагматичный выбор, а не перфекционистский.

Практика
1. Ведите список «задач на 15 минут». Того, чего вы избегали: написание документации для модуля, исправление проблем с тестами, обновление зависимостей и т.п. Когда у вас появится время в течение дня (отмена встречи, ожидание тестов/сборки), выполните одну 15-минутную задачу.
За месяц вы выполните 20-30 таких небольших задач, которые иначе откладывались бы навсегда. Код станет лучше, «технический долг» уменьшится, появится чувство удовлетворения.

2. Когда вы ловите себя на том, что исследуете что-то отвлечённое, установите таймер и спросите себя: «Какой минимум нужно знать, чтобы двигаться дальше?» Найдите ответ на этот конкретный вопрос, задокументируйте полученные знания в комментарии или на странице вики для дальнейшего использования, а затем вернитесь к работе. Вы усвоили знания, не утонув в них.

Правило 15 минут — не про жёсткий лимит, а про целенаправленность. Оно превращает «Мне нужно поработать над этим» в «Я работаю над этим», а «Я просто изучаю» в «Я делаю осознанный выбор в отношении того, куда тратить своё время».

Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
👍23
День 2537. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.

15. Промежуточное ПО в ASP.NET Core
«Объясните роль промежуточного ПО в приложениях ASP.NET Core. Приведите пример того, как можно реализовать пользовательское промежуточное ПО в приложении .NET, и опишите сценарий, в котором это промежуточное ПО может быть особенно полезно».

Хороший ответ
Промежуточное ПО в ASP.NET Core — это блоки кода (классы), которые собираются в конвейер приложения для обработки запросов и ответов. Каждый компонент в конвейере промежуточного ПО отвечает за вызов следующего компонента в цепочке или за прерывание цепочки, если это необходимо. Компоненты промежуточного ПО выполняются в порядке их добавления в конвейер приложения.

Промежуточное ПО может обрабатывать такие задачи, как аутентификация, обработка ошибок, обслуживание статических файлов и сложная обработка запросов. Оно также может изменять входящий запрос или исходящий ответ. Некоторые популярные компоненты промежуточного ПО уже реализованы в платформе .NET: аутентификация, авторизация, обслуживание статических файлов и т.п. Для реализации пользовательского промежуточного ПО в приложении .NET нужно определить класс промежуточного ПО с методом Invoke или InvokeAsync, который обрабатывает контекст HTTP.

Вот пример пользовательского промежуточного ПО в .NET-приложении, которое регистрирует время выполнения каждого HTTP-запроса:
using System.Diagnostics;

public class RequestTimingMiddleware
{
private readonly RequestDelegate _next;

public RequestTimingMiddleware(
RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(
HttpContext context)
{
var sw = Stopwatch.StartNew();
await _next(context);
sw.Stop();
var time = sw.ElapsedMilliseconds;
context.Response.Headers.Add(
"X-Response-Time-ms", time.ToString());
}
}

// в Program.cs
var builder =
WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseMiddleware<RequestTimingMiddleware>();

app.Run(async (context) =>
{
await context.Response
.WriteAsync("Hello Middleware!");
});

app.Run();

Это промежуточное ПО измеряет время обработки каждого запроса и добавляет его в заголовки ответа. Это может быть особенно полезно при мониторинге производительности, помогая разработчикам выявлять медленные участки приложения.

Преимущества
- Модульность: компоненты промежуточного ПО могут быть разработаны, протестированы и повторно использованы в различных приложениях.
- Гибкость: позволяет создавать конвейер обработки запросов, соответствующий потребностям приложения.
- Контроль: вы получаете контроль над запросом и можете манипулировать как объектами запроса, так и объектами ответа.
Понимая и используя промежуточное ПО, разработчики могут значительно улучшить функциональность и производительность приложений ASP.NET Core.

Часто встречающийся неверный ответ
«Чтобы добавить промежуточное ПО в .NET, можно использовать app.Use() в Program.cs и добавить лямбда-функцию с любым кодом для обработки запроса и ответа непосредственно внутрь этого метода».

Почему это неверно
- Чрезмерное упрощение использования промежуточного ПО: встроенный код в Program.cs с использованием app.Use() удобен для простых сценариев, но не подходит для сложного или многократно используемого промежуточного ПО.

- Игнорирование лучших практик: написание сложной логики непосредственно в Program.cs может привести к коду, который трудно поддерживать и тестировать. Это нивелирует преимущества создания отдельных классов, инкапсулирующих функциональность и помогающих тестировать логику.

Обычно эта ошибка возникает, когда разработчики знакомы с настройкой промежуточного ПО на базовом уровне, но не обладают глубокими знаниями лучших практик создания масштабируемых и поддерживаемых компонентов промежуточного ПО в ASP.NET Core.

Источник:
https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍3
День 2538. #Оффтоп
Под конец праздников предлагаю вам развлекательное видео от канала The PrimeTime. Я уже, кажется, рекомендовал какие-то из его видео. Автор - бывший разработчик из Netflix и частенько, с юмором, комментирует статьи по разработке, новости ИТ-индустрии (вроде очередного краха Cloudflare) и рассказывает прочие истории из мира разработки.

Это его видео про… пузырьковую сортировку.

Да. Это алгоритм сортировки, которому нас учили в школе/институте (обычно даже не упоминая про его неэффективность). Причина в его невероятной простоте.

Челлендж!
Перед просмотром, подумайте, есть ли вообще в природе случаи, когда можно реально и эффективно применить пузырьковую сортировку? Напишите в комментариях.

https://youtu.be/qGH8gKdpZMQ
День 2539. #ЗаметкиНаПолях
Создаём BinaryData из MemoryStream без Копирования
При работе с BinaryData и MemoryStream в .NET может потребоваться преобразование данных потока в экземпляр BinaryData. Типичный подход с использованием BinaryData.FromStream() предполагает копирование всего буфера, что может повлиять на производительность и увеличить объем выделяемой памяти. Однако существует более эффективный способ достижения этой цели без копирования памяти.

Проблема с BinaryData.FromStream()
Стандартный способ создания BinaryData из потока прост, но сопряжен с затратами:
var stream = new MemoryStream();
stream.Write([1, 2, 3]);
stream.Seek(0, SeekOrigin.Begin);

// Это требует копирования памяти
var data = BinaryData.FromStream(stream);

При вызове метода BinaryData.FromStream(), метод считывает поток и копирует его содержимое в новый буфер. Для больших потоков или приложений, где производительность критична, это дополнительное копирование может быть неэффективным.

Подход без копирования
Если вы работаете с MemoryStream, вы можете напрямую получить доступ к его базовому буферу и создать экземпляр BinaryData без копирования:
var stream = new MemoryStream();
stream.Write([1, 2, 3]);

// Это не требует копирования памяти
var data = new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position));


Этот подход использует GetBuffer() для доступа к базовому массиву байт MemoryStream, а затем оборачивает его в срез Memory<byte>, представляющий только записанную часть. Конструктор BinaryData принимает ReadOnlyMemory<byte>, поэтому преобразование происходит неявно.

Предупреждение: Изменчивость буфера: поскольку вы используете общий буфер, любые изменения исходного буфера MemoryStream могут повлиять данные в BinaryData. Убедитесь, что вы закончили запись в поток, прежде чем создавать BinaryData.

Интересно, что сама реализация BinaryData.FromStream создаёт новый экземпляр BinaryData таким же образом.

Источник: https://www.meziantou.net/zero-copy-binarydata-creation-from-memorystream-in-dotnet.htm
👍20
День 2540. #Карьера
Хотите Выступить на Конференции Разработчиков?
Это может быть полезным опытом, который не только поможет вам побороть страх публичных выступлений, но и заставит как следует разобраться в теме, и, возможно, взглянуть на неё по-новому.

Но сначала…
1. Спросите себя, зачем? Хотите продвигать свою компанию, курсы или программные продукты? Завести полезные контакты и продвигаться по карьере? Просто путешествовать и знакомиться с людьми? Определите, что для вас означает «успех».
2. Будьте реалистичны в отношении объёма работы. Если вы думаете, что можете набросать какой-нибудь код, написать доклад, и вы уже на пути к крупному мероприятию, то… нет. Так это не работает.

Этап 1: Напишите доклад
Желательно об уникальной теме. Выясните, чему аудитория хочет научиться и почему вы лучший человек, чтобы им это рассказать. Выступите с докладом перед группой коллег. Всё может пройти отлично… а может провально. В этом и смысл практики. Исправьте примеры и слайды. Дополните короткий доклад или сократите длинный. Выступите с докладом в другой группе.

Этап 2: Заявите о себе
Открытые митапы проводят как крупные компании, так и сообщество DotNetRu в разных городах несколько раз в год. Обычно это небольшие однодневные мероприятия, как правило, бесплатные (или очень дешёвые) для посещения. Это отличный способ познакомиться с другими докладчиками и людьми, участвующими в технических мероприятиях, и вы почти наверняка встретите нескольких человек из программных комитетов более крупных конференций.
Такие мероприятия — шанс привлечь к себе внимание. Используйте митап по полной: выступите со своим докладом, посмотрите другие сессии. Общайтесь с организаторами. Найдите способ поддерживать связь с людьми, с которыми вы познакомились. Присоединяйтесь к чатам, обменяйтесь контактами.

Этап 3: Подайте заявку
У вас есть пара докладов. Вы выступали с ними достаточно часто, чтобы знать, что они хороши. Можно подать заявку на более крупную конференцию. Например, DotNext принимает заявки круглый год. Многие мероприятия покрывают ваши расходы на проезд и проживание в отеле. Если нет, возможно, вы сможете убедить работодателя покрыть ваши расходы.
Поддерживайте актуальность контента либо напишите новый доклад специально для этой конференции. Хотя, новый доклад желательно также предварительно протестировать на одном из митапов.
Не отправляйте множество заявок на одну конференцию в надежде, что хотя бы одна будет принята. К авторам со множеством заявок организаторы могут отнестись с подозрением, посчитав, что на самом деле у него в реальности не готов ни один доклад.

Этап 4: Знайте, когда остановиться
Выступления — это не только весело, но и утомительно. Одни выступают везде, заводят множество друзей и создают счастливые воспоминания, а потом однажды решают, что хватит. Другие выступают, вычёркивают пункт из списка желаний и решают, что им достаточно. Третьи привыкают к размеренному распорядку из 3-4 мероприятий в год.
Поэтому заранее определите, что значит «успех». Если вы делаете это ради удовольствия, помните, что, когда это перестаёт нравиться, нужно остановиться. Если в целях продвижения или маркетинга? Отслеживайте потенциальных клиентов. Убедитесь, что это действительно привлекает внимание и приносит ожидаемый доход.

Наконец: уважайте свою аудиторию
Обращаетесь вы к 5 коллегам или к тысячам на большой конференции, эти люди потратили своё время — и часто значительные средства — чтобы услышать то, что вы хотите сказать. Они заслуживают вашего лучшего выступления каждый раз. Если вы заскучали, устали, проводите выступления на автопилоте… пора попробовать что-то другое.

PS: По моему опыту выступления на DotNext, это действительно увлекательно, и не так страшно, как кажется. Организаторы, в случае принятия вашей заявки, помогут вам со всеми вопросами, и даже могут предложить пару митапов, на которых вы сможете отработать доклад.

Источник: https://dylanbeattie.net/2025/12/08/so-you-want-to-speak-at-software-conferences.html
👍8
День 2541. #AI
Добавляем ИИ в Существующие REST API с Помощью MCP. Начало
Сегодня многие организации стремятся интегрировать ИИ в существующую инфраструктуру, не переписывая всё заново. Рассмотрим процесс добавления возможностей MCP в существующие REST API на .NET, что позволит обеспечить бесперебойное взаимодействие между системами ИИ и вашими бэкэнд-данными и приложениями.

Что это?
MCP (Model Context Protocol - Протокол Контекста Модели) —стандартизированный протокол с открытым кодом, представленный компанией Anthropic. Он был разработан для обеспечения взаимодействия моделей ИИ (таких как чат-боты или большие языковые модели — LLM) с внешними системами. Одна из его основных особенностей — двусторонняя связь, позволяющая ИИ не только получать данные, но и выполнять действия, такие как внесение обновлений в эти системы.

Главное преимущество MCP в том, что он связывает системы ИИ (такие как ChatGPT или Claude) и бэкэнд-системы, такие как базы данных или сторонние сервисы, создавая гибкий двусторонний поток данных. Если вы хотите добавить функциональность ИИ в приложение без полной переработки, MCP предлагает простое и эффективное решение.

Интеграция моделей ИИ в API позволит им взаимодействовать с данными, хранящимися в существующих базах данных или других системах. Это позволит агентам ИИ извлекать, обновлять, агрегировать данные и т.п. Эти интеграции могут автоматизировать рутинные задачи, оптимизировать принятие решений и предоставлять аналитические данные в режиме реального времени на основе ваших данных.

Как MCP работает с API .NET?
В то время как REST — это широко используемая архитектура для межсервисного взаимодействия, MCP оптимизирован для взаимодействия ИИ с системами.

Сравнение
1. Целевая аудитория:
REST: В основном используется разработчиками для интеграции сервисов.
MCP: Разработан для взаимодействия моделей и агентов ИИ с бэкэнд-системами. Создан для упрощения интеграции с нетехническими пользователями и системами.

2. Передача информации:
REST: Связь обычно осуществляется по протоколу HTTP с использованием методов GET, POST, PUT, DELETE.
MCP: Может использовать стандартный ввод-вывод для локальной связи или потоковый HTTP для удалённой связи, что поддерживает обмен данными в реальном времени.

3. Доступность:
REST: Требует таких инструментов, как OpenAPI (Swagger), для документирования.
MCP: Автоматически обнаруживает доступные инструменты, ресурсы и подсказки во время выполнения, что делает его более динамичным.

4. Варианты использования:
REST: Отлично подходит для связи между серверами или между сервером и клиентом.
MCP: Лучше всего подходит для интеграции агентов ИИ с бэкэнд-системами, такими как CRM, базы данных или даже сторонние сервисы.

Окончание следует…

Источник:
https://trailheadtechnology.com/reusing-your-existing-net-rest-apis-for-ai-with-mcp/
👎14👍6
День 2542. #AI
Добавляем ИИ в Существующие REST API с Помощью MCP. Окончание

Начало

Добавление MCP в.NET API
Рассмотрим необходимые шаги. Мы будем использовать .NET 10 и MCP C# SDK настройки базового MCP-сервера.

Шаг 1: Установка MCP SDK и настройка сервера
Начните с установки MCP SDK в .NET-проект. SDK предоставляет все необходимые инструменты для создания сервера, который может взаимодействовать с моделями ИИ через MCP.
dotnet add package ModelContextProtocol

Примечание: на данный момент MCP C# SDK находится в режиме предварительного просмотра, поэтому вам также потребуется флаг --version 0.5.0-preview.1.

Добавим в Program.cs код для настройки сервера MCP:
builder.Services
.AddMcpServer()
// Для удалённой коммуникации
.WithHttpTransport()
// Автоматическое обнаружение утилит в проекте
.WithToolsFromAssembly();


Шаг 2: Создание инструментов MCP для конечных точек API
Далее мы определяем инструменты MCP, которые сопоставляются с нашими существующими конечными точками. Это делается путём добавления определённых атрибутов к методам, которые будут предоставлять функциональность системе ИИ.

Например, так конечная точка GetToDos (Список дел) может быть сопоставлена с инструментом MCP:
[McpServerTool]
[Description("Get todos from the todo list.")]
public async Task<IEnumerable<ToDo>> GetToDos()
{
// Логика получения списка дел
}


Шаг 3: Интеграция с моделями ИИ
Теперь, когда MCP-сервер настроен, мы можем интегрировать его с моделями ИИ, такими как Claude или ChatGPT. Когда агент ИИ запрашивает задачу (например, проверку списка дел), он будет использовать протокол MCP для запроса к вашему серверу.

Например, используя ИИ, такой как Claude, вы можете программно получать данные из своего списка дел:
var request = new AIModelRequest("Get To-Dos");
var response = await aiModel.ExecuteRequest(request);

Этот запрос получит данные через сервер MCP, что позволит модели ИИ действовать на их основе, например, отмечать задачи как выполненные.

Полный код примера API тут.

Будущее MCP и интеграции ИИ
По мере того, как все больше систем внедряют MCP, мы ожидаем увеличения взаимодействия между моделями ИИ и бэкэнд-системами. MCP упрощает для организаций внедрение ИИ в приложения без необходимости полной переработки кода. Это помогает создать перспективную архитектуру, которая может масштабироваться с новыми технологическими достижениями.

Итого
Интеграция MCP с вашими REST API предоставляет мощные возможности ИИ для ваших существующих систем. Независимо от того, создаёте ли вы чат-бота, автоматизируете поддержку клиентов или заблаговременно уведомляете пользователей о ключевых показателях эффективности, MCP обеспечивает необходимую связь для бесперебойной работы.

Источник:
https://trailheadtechnology.com/reusing-your-existing-net-rest-apis-for-ai-with-mcp/
👎7👍4
День 2543. #Карьера
Топ Советов по Повышению Продуктивности. Часть 4

Части 1, 2, 3

4. Разработка, основанная на документации: пишите документацию до написания кода
Звучит нелогично, пока вы не попробуете.

Традиционный рабочий процесс разработчика: написать код, заставить его работать, отполировать его, а затем (возможно, если кто-то напомнит вам или есть контрольный список для PR) написать документацию, объясняющую, что вы только что создали. Документация — это результат разработки, овощи, которые вы едите, потому что они полезны, а не потому что хотите.

Сделайте наоборот. Прежде чем писать код реализации, напишите документацию о том, как будет работать функция или API. Опишите, что она делает, какие параметры принимает, что возвращает, какие граничные случаи обрабатывает и как её использовать.

Преимущества
1. Мгновенная ясность
Написание документации заставляет продумывать детали так, как это никогда не происходит при написании кода. Вы обнаружите проблемы проектирования до того, как их будет дорого исправлять. «А что произойдет, если клиент передаст null?» — вопрос, на который вы ответите на этапе проектирования, а не ошибка, обнаруженная кем-то в продакшене.

2. Улучшение API
Когда вы сначала пишете документацию с точки зрения пользователя, вы естественным образом проектируете более интуитивно понятные интерфейсы. Вы заметите непонятные имена, отсутствующие параметры или неудобные шаблоны использования, потому что придётся их пояснять в документации.

3. Упрощение реализации
Вы уже продумали логику. Документация — это ваше техзадание. Теперь просто переведите это в код. Больше не нужно смотреть на пустой файл, не зная, с чего начать.

4. Документация никогда не устаревает
Поскольку она была написана первой, она соответствует тому, что вы создали. Не нужно пытаться восстановить документацию из готового кода, где вы уже забыли половину процесса принятия решений.

Новый уровень
Для сложных функций пишите три типа документации перед написанием кода:
1. Документация для пользователя - как кто-то будет использовать эту функцию.
2. Документация API - сигнатуры функций, параметры, возвращаемые значения.
3. Журнал решений - почему вы приняли те или иные проектные решения (это бесценно для вас в будущем). См. также ADR.

Инструменты, поддерживающие этот рабочий процесс:
- Пишите документацию в формате Markdown прямо рядом с кодом.
- Храните файл decisions.md (журнал решений) в корневой директории проекта.
- Для API используйте спецификации OpenAPI/Swagger в качестве инструмента для создания документации.

Изменение мышления
Вы не разработчик, который пишет документацию. Вы дизайнер, который выражает свои замыслы как через документацию, так и через код. Документация — это не налог, который вы платите после создания чего-либо, — это план, который делает создание продукта возможным.

Попробуйте это, реализуя свою следующую задачу. Сначала README. Затем напишите описания и интерфейсы функций перед реализацией тел функций. Напишите документацию API перед реализацией конечных точек. Это кажется странным примерно 30 минут, а потом проявляется путь до самого конца, где на каждом этапе очевидно, что делать.

Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
👍9
День 2544. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.

16. Настройки и паттерн Options
«Опишите, как реализовать паттерн Options в .NET для управления настройками приложения? Приведите пример настройки и доступа к параметрам из файла конфигурации».

Хороший ответ
В .NET паттерн Options используется для доступа к группам связанных параметров из файлов конфигурации (таких как appsettings.json), переменных среды или других источников конфигурации. Этот паттерн обеспечивает строгую типизацию данных конфигурации с поддержкой проверки данных, что улучшает удобство сопровождения и уменьшает количество ошибок.

Для реализации паттерна Options обычно необходимо:
- Создать класс, представляющий параметры конфигурации.
- Зарегистрировать класс в контейнере внедрения зависимостей (DI).
- Получить доступ к параметрам конфигурации через внедрение зависимостей классах-потребителях.

Определим класс, соответствующий структуре параметров в appsettings.json:
public class MySettings
{
public string ConnectionString { get; set; }
public int RetryCount { get; set; }
}

В appsettings.json:
{
"MySettings": {
"ConnectionString": "…",
"RetryCount": 3
}
}

Затем в Program.cs настроим привязку класса настроек к конфигурации и их использование:
var builder =
WebApplication.CreateBuilder(args);

// привязка
builder.Services.Configure<MySettings>(
builder.Configuration.GetSection("MySettings"));

var app = builder.Build();

// использование
app.MapGet("/", (IOptions<MySettings> options) =>
{
MySettings settings = options.Value;
// …
});

app.Run();

В этой конфигурации MySettings настраивается в контейнере внедрения зависимостей и может быть внедрён в любое место приложения. Для доступа к настройкам используется интерфейс IOptions<T>.

Преимущества
- Строгая типизация: Настройки конфигурации сопоставляются с классами C#, что помогает выявлять ошибки на этапе компиляции.
- Централизованное управление: Все настройки управляются в одном месте, что упрощает обслуживание.
- Гибкость и повторное использование: Настройки могут быть повторно использованы в приложении без жёсткого кодирования.
Этот подход не только упрощает управление конфигурацией, но и повышает масштабируемость и удобство сопровождения приложения.

Часто встречающийся плохой ответ
«Настройки конфигурации определяются в файле appsettings.json. А для доступа к ним используется объект Configuration. Например, Configuration["MySettings:ConnectionString"].»

Почему это неверно
- Отсутствие строгой типизации: Прямой доступ к настройкам с помощью строковых ключей (Configuration["key"]) подвержен ошибкам во время выполнения и не имеет проверки на этапе компиляции. Этот метод увеличивает риск опечаток и не использует преимущества строгой типизации.

- Нарушение принципа единственной ответственности: Распределение доступа к конфигурации по всему приложению приводит к дублированию кода и нарушает принцип единственной ответственности. Это затрудняет поддержку и тестирование кода.

- Упущение преимуществ внедрения зависимостей: Этот подход не использует внедрение зависимостей, которое имеет решающее значение для создания масштабируемых и тестируемых приложений. Он игнорирует преимущества использования IOptions или аналогичных интерфейсов, предоставляемых .NET для управления конфигурациями.

См. также:
- Подробнее про паттерн Options
- Проверка Конфигурации .NET
- Не внедряйте IOptions

Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍15
День 2545. #ЗаметкиНаПолях
Некоторые Недостатки Частых Советов по Оптимизации Производительности
Давайте будем откровенны: в большинстве случаев сосредоточение внимания на времени задержки не очень полезно. Даже если задержка является серьёзной проблемой, простое изучение времени редко приводит к полезным выводам. Например, если время ответа увеличивается с 5 секунд до 15, эта информация сама по себе не раскрывает первопричину. Нужно понять, что вызывает эти задержки. Ответ обычно заключается в каком-либо потреблении ресурсов — ЦП, память, диск, БД, сеть или что-то ещё. Ключевым моментом является изучение, что вы потребляете и как вы это потребляете. Именно это покажет вам, что нужно изменить и откуда возьмутся самые значительные улучшения.

Важность понимания потребления ресурсов
Классическая ошибка — прекращение анализа потребления ресурсов, как только вы приходите к выводу вроде: «О, у меня проблемы с диском». Хотя диск, безусловно, может быть критически важным ресурсом, это не означает, что нужно игнорировать другие виды потребления. Это лишь означает, что важно досконально изучить потребление дисковых ресурсов: какие файлы читаются, в каком порядке и необходимы ли эти чтения. Т.е. необходимо полное понимание того, как потребляется критически важный ресурс.

Но и другие ресурсы в вашей системе всё ещё могут быть полезны для оптимизации. Предположим, фронтенд системы ограничен вычислительными ресурсами, но основным источником задержки является БД на бэкенде. Вы можете подумать, что можно игнорировать фронтенд, т.к. ожидание ответа от БД больше. Это ошибочный подход. Если есть возможность сократить нагрузку на фронтэнд, следует стремиться к этой экономии, даже если ваши клиенты не заметят разницы.

Анализ ресурсов и предельное сокращение
Это справедливо независимо от того, сократите ли вы количество серверов, потоков или уменьшите загрузку ЦП. Потенциальная экономия средств может быть существенной. У вас редко бывает эксклюзивный доступ ко всем ресурсам ЦП, другие пользователи или процессы могут извлечь выгоду из любого снижения нагрузки. Даже если вы «владеете машиной», у вас, вероятно, есть другие задачи, которые вы хотите выполнить.

Независимо от того, идёт ли речь об экономии заряда батареи, снижении тепловыделения или просто освобождении места для других приложений, существует множество причин, по которым сокращение потребления ресурсов имеет смысл. Но важно оговориться, что практически в каждом сценарии нужно учитывать баланс между необходимыми усилиями и потенциальной экономией.

Время — это следствие, а не причина
Важно помнить, что задержку следует рассматривать как второстепенный показатель. Основные показатели — это потребление ресурсов. Время — это следствие, а не причина, и это делает его одним из самых сложных для понимания и прогнозирования. Всегда лучше соотносить время с каким-либо видом использования ресурсов.

Программные ресурсы
Помните, что всякий раз, когда вы используете вычисление в критической секции, вы фактически создаёте программный ресурс. Он имеет длину очереди, среднее время обслуживания и так далее. Его можно измерить так же, как диск или другой физический ресурс.

Представлять систему как сеть очередей и анализировать работу, выполняемую в каждой из них, чрезвычайно полезно. Сокращение среднего времени обслуживания в каждой из этих областей — надёжная стратегия улучшения. Ваша задача — определить, как выглядит время обслуживания и почему оно может быть высоким — возможно, из-за неэффективных шаблонов доступа к данным или плохого асинхронного упорядочивания. Понимая и решая эти проблемы, вы добьётесь значительного прогресса. Любое снижение потребления — это победа.

Ценность бережливости и широкой оптимизации
Не стоит игнорировать экономию ресурсов только потому, что она не связана с текущим критическим узким местом. Часто снижение потребления приносит дополнительные выгоды. Экономия ресурсов — это почти всегда универсальная и хорошая политика.

Источник: https://ricomariani.medium.com/common-performance-tuning-advice-some-flaws-b2c427fad7ca
👍2
День 2546. #ЧтоНовенького #NET11
Аргументы Выражений Коллекций в C #15

В репозитории .NET появилось неплохое предложение, которое немного улучшит работу с выражениями коллекций — предоставление пользователям возможности передавать аргументы при создании.

Замечание: пока это только предложение, и оно может появиться в C# 15 (или, вероятно, позже), а может и никогда.

Что такое выражения коллекций?
Вкратце: выражения коллекций — это альтернативный синтаксис для создания коллекций в C#:
List<int> evens = [2, 4, 6, 8, 10];
List<int> odds = [1, 3, 5, 7, 9];

// Сливаем обе коллекции и добавляем 0 в начало
List<int> all = [0, ..evens, ..odds];

Естественно, это работает не только с List<T>, но и с любым типом, который реализует определённый шаблон. См. подробнее.

Преимущество в том, что синтаксис более лаконичен, а в некоторых случаях, возможно, и улучшается производительность.

Но и это можно улучшить!
Здесь в случае с all компилятор создаст новый List с нужной ёмкостью:
num2 = 1 + (list4.Count + list5.Count);
List<int> list6 = new List<int>(num2);


Но бывают случаи, когда компилятор не знает, сколько элементов будет в коллекции, а вы знаете (например, при обращении к базе данных). Сейчас у нас нет возможности указать ёмкость списка в выражении коллекции. Но предлагаемый вариант позволит это изменить. Как уже говорилось ранее, это всего лишь предложение, и синтаксис, используемый в следующем примере, не окончательный (и, откровенно говоря, выглядит он пока странно):
List<int> all = 
[args(capacity: 32), 0, ..evens, ..odds];

Это сразу создаст список вместимостью 32 (хотя это и не очень полезно, но суть понятна). В итоге получится new List<int>(32);. Это может пригодиться и в других случаях. Например, HashSet<T> позволяет передавать IEqualityComparer<T> для сравнения строк:
HashSet<string> names = 
[args(comparer: StringComparer.OrdinalIgnoreCase), "Alice", "Bob", "alice"];


Источник: https://steven-giesel.com/blogPost/352fe495-9cc4-4df8-8ad1-a3e26a64185c/collection-expression-arguments-in-c-15
👍7👎1