День 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
.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. Замените его содержимое следующим:
Этот скрипт сначала пытается использовать стандартную команду
Предупреждение:
Средства запуска 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
Снижаем Нагрузку на 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
Топ Советов по Повышению Продуктивности. Часть 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-запроса:
Это промежуточное ПО измеряет время обработки каждого запроса и добавляет его в заголовки ответа. Это может быть особенно полезно при мониторинге производительности, помогая разработчикам выявлять медленные участки приложения.
Преимущества
- Модульность: компоненты промежуточного ПО могут быть разработаны, протестированы и повторно использованы в различных приложениях.
- Гибкость: позволяет создавать конвейер обработки запросов, соответствующий потребностям приложения.
- Контроль: вы получаете контроль над запросом и можете манипулировать как объектами запроса, так и объектами ответа.
Понимая и используя промежуточное ПО, разработчики могут значительно улучшить функциональность и производительность приложений 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
Марк Прайс предложил свой набор из 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
Под конец праздников предлагаю вам развлекательное видео от канала The PrimeTime. Я уже, кажется, рекомендовал какие-то из его видео. Автор - бывший разработчик из Netflix и частенько, с юмором, комментирует статьи по разработке, новости ИТ-индустрии (вроде очередного краха Cloudflare) и рассказывает прочие истории из мира разработки.
Это его видео про… пузырьковую сортировку.
Да. Это алгоритм сортировки, которому нас учили в школе/институте (обычно даже не упоминая про его неэффективность). Причина в его невероятной простоте.
Челлендж!
Перед просмотром, подумайте, есть ли вообще в природе случаи, когда можно реально и эффективно применить пузырьковую сортировку? Напишите в комментариях.
https://youtu.be/qGH8gKdpZMQ
YouTube
Bubblesort is useless
check out https://trm.sh/g2i for all of your hiring needs! Thank you all for all the support :)
https://twitch.tv/ThePrimeagen - I Stream on Twitch
https://twitter.com/terminaldotshop - Want to order coffee over SSH?
ssh terminal.shop
Become Backend Dev:…
https://twitch.tv/ThePrimeagen - I Stream on Twitch
https://twitter.com/terminaldotshop - Want to order coffee over SSH?
ssh terminal.shop
Become Backend Dev:…
День 2539. #ЗаметкиНаПолях
Создаём BinaryData из MemoryStream без Копирования
При работе с BinaryData и MemoryStream в .NET может потребоваться преобразование данных потока в экземпляр BinaryData. Типичный подход с использованием BinaryData.FromStream() предполагает копирование всего буфера, что может повлиять на производительность и увеличить объем выделяемой памяти. Однако существует более эффективный способ достижения этой цели без копирования памяти.
Проблема с BinaryData.FromStream()
Стандартный способ создания BinaryData из потока прост, но сопряжен с затратами:
При вызове метода BinaryData.FromStream(), метод считывает поток и копирует его содержимое в новый буфер. Для больших потоков или приложений, где производительность критична, это дополнительное копирование может быть неэффективным.
Подход без копирования
Если вы работаете с MemoryStream, вы можете напрямую получить доступ к его базовому буферу и создать экземпляр BinaryData без копирования:
Этот подход использует 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
Создаём 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
Хотите Выступить на Конференции Разработчиков?
Это может быть полезным опытом, который не только поможет вам побороть страх публичных выступлений, но и заставит как следует разобраться в теме, и, возможно, взглянуть на неё по-новому.
Но сначала…
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/
Добавляем ИИ в Существующие 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.
Примечание: на данный момент MCP C# SDK находится в режиме предварительного просмотра, поэтому вам также потребуется флаг
Добавим в Program.cs код для настройки сервера MCP:
Шаг 2: Создание инструментов MCP для конечных точек API
Далее мы определяем инструменты MCP, которые сопоставляются с нашими существующими конечными точками. Это делается путём добавления определённых атрибутов к методам, которые будут предоставлять функциональность системе ИИ.
Например, так конечная точка GetToDos (Список дел) может быть сопоставлена с инструментом MCP:
Шаг 3: Интеграция с моделями ИИ
Теперь, когда MCP-сервер настроен, мы можем интегрировать его с моделями ИИ, такими как Claude или ChatGPT. Когда агент ИИ запрашивает задачу (например, проверку списка дел), он будет использовать протокол MCP для запроса к вашему серверу.
Например, используя ИИ, такой как Claude, вы можете программно получать данные из своего списка дел:
Этот запрос получит данные через сервер MCP, что позволит модели ИИ действовать на их основе, например, отмечать задачи как выполненные.
Полный код примера API тут.
Будущее MCP и интеграции ИИ
По мере того, как все больше систем внедряют MCP, мы ожидаем увеличения взаимодействия между моделями ИИ и бэкэнд-системами. MCP упрощает для организаций внедрение ИИ в приложения без необходимости полной переработки кода. Это помогает создать перспективную архитектуру, которая может масштабироваться с новыми технологическими достижениями.
Итого
Интеграция MCP с вашими REST API предоставляет мощные возможности ИИ для ваших существующих систем. Независимо от того, создаёте ли вы чат-бота, автоматизируете поддержку клиентов или заблаговременно уведомляете пользователей о ключевых показателях эффективности, MCP обеспечивает необходимую связь для бесперебойной работы.
Источник: https://trailheadtechnology.com/reusing-your-existing-net-rest-apis-for-ai-with-mcp/
Добавляем ИИ в Существующие 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 прямо рядом с кодом.
- Храните файл
- Для API используйте спецификации OpenAPI/Swagger в качестве инструмента для создания документации.
Изменение мышления
Вы не разработчик, который пишет документацию. Вы дизайнер, который выражает свои замыслы как через документацию, так и через код. Документация — это не налог, который вы платите после создания чего-либо, — это план, который делает создание продукта возможным.
Попробуйте это, реализуя свою следующую задачу. Сначала README. Затем напишите описания и интерфейсы функций перед реализацией тел функций. Напишите документацию API перед реализацией конечных точек. Это кажется странным примерно 30 минут, а потом проявляется путь до самого конца, где на каждом этапе очевидно, что делать.
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
Топ Советов по Повышению Продуктивности. Часть 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:
В appsettings.json:
Затем в Program.cs настроим привязку класса настроек к конфигурации и их использование:
В этой конфигурации 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
Марк Прайс предложил свой набор из 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
Некоторые Недостатки Частых Советов по Оптимизации Производительности
Давайте будем откровенны: в большинстве случаев сосредоточение внимания на времени задержки не очень полезно. Даже если задержка является серьёзной проблемой, простое изучение времени редко приводит к полезным выводам. Например, если время ответа увеличивается с 5 секунд до 15, эта информация сама по себе не раскрывает первопричину. Нужно понять, что вызывает эти задержки. Ответ обычно заключается в каком-либо потреблении ресурсов — ЦП, память, диск, БД, сеть или что-то ещё. Ключевым моментом является изучение, что вы потребляете и как вы это потребляете. Именно это покажет вам, что нужно изменить и откуда возьмутся самые значительные улучшения.
Важность понимания потребления ресурсов
Классическая ошибка — прекращение анализа потребления ресурсов, как только вы приходите к выводу вроде: «О, у меня проблемы с диском». Хотя диск, безусловно, может быть критически важным ресурсом, это не означает, что нужно игнорировать другие виды потребления. Это лишь означает, что важно досконально изучить потребление дисковых ресурсов: какие файлы читаются, в каком порядке и необходимы ли эти чтения. Т.е. необходимо полное понимание того, как потребляется критически важный ресурс.
Но и другие ресурсы в вашей системе всё ещё могут быть полезны для оптимизации. Предположим, фронтенд системы ограничен вычислительными ресурсами, но основным источником задержки является БД на бэкенде. Вы можете подумать, что можно игнорировать фронтенд, т.к. ожидание ответа от БД больше. Это ошибочный подход. Если есть возможность сократить нагрузку на фронтэнд, следует стремиться к этой экономии, даже если ваши клиенты не заметят разницы.
Анализ ресурсов и предельное сокращение
Это справедливо независимо от того, сократите ли вы количество серверов, потоков или уменьшите загрузку ЦП. Потенциальная экономия средств может быть существенной. У вас редко бывает эксклюзивный доступ ко всем ресурсам ЦП, другие пользователи или процессы могут извлечь выгоду из любого снижения нагрузки. Даже если вы «владеете машиной», у вас, вероятно, есть другие задачи, которые вы хотите выполнить.
Независимо от того, идёт ли речь об экономии заряда батареи, снижении тепловыделения или просто освобождении места для других приложений, существует множество причин, по которым сокращение потребления ресурсов имеет смысл. Но важно оговориться, что практически в каждом сценарии нужно учитывать баланс между необходимыми усилиями и потенциальной экономией.
Время — это следствие, а не причина
Важно помнить, что задержку следует рассматривать как второстепенный показатель. Основные показатели — это потребление ресурсов. Время — это следствие, а не причина, и это делает его одним из самых сложных для понимания и прогнозирования. Всегда лучше соотносить время с каким-либо видом использования ресурсов.
Программные ресурсы
Помните, что всякий раз, когда вы используете вычисление в критической секции, вы фактически создаёте программный ресурс. Он имеет длину очереди, среднее время обслуживания и так далее. Его можно измерить так же, как диск или другой физический ресурс.
Представлять систему как сеть очередей и анализировать работу, выполняемую в каждой из них, чрезвычайно полезно. Сокращение среднего времени обслуживания в каждой из этих областей — надёжная стратегия улучшения. Ваша задача — определить, как выглядит время обслуживания и почему оно может быть высоким — возможно, из-за неэффективных шаблонов доступа к данным или плохого асинхронного упорядочивания. Понимая и решая эти проблемы, вы добьётесь значительного прогресса. Любое снижение потребления — это победа.
Ценность бережливости и широкой оптимизации
Не стоит игнорировать экономию ресурсов только потому, что она не связана с текущим критическим узким местом. Часто снижение потребления приносит дополнительные выгоды. Экономия ресурсов — это почти всегда универсальная и хорошая политика.
Источник: https://ricomariani.medium.com/common-performance-tuning-advice-some-flaws-b2c427fad7ca
👍2
День 2546. #ЧтоНовенького #NET11
Аргументы Выражений Коллекций в C #15
В репозитории .NET появилось неплохое предложение, которое немного улучшит работу с выражениями коллекций — предоставление пользователям возможности передавать аргументы при создании.
Замечание: пока это только предложение, и оно может появиться в C# 15 (или, вероятно, позже), а может и никогда.
Что такое выражения коллекций?
Вкратце: выражения коллекций — это альтернативный синтаксис для создания коллекций в C#:
Естественно, это работает не только с List<T>, но и с любым типом, который реализует определённый шаблон. См. подробнее.
Преимущество в том, что синтаксис более лаконичен, а в некоторых случаях, возможно, и улучшается производительность.
Но и это можно улучшить!
Здесь в случае с all компилятор создаст новый List с нужной ёмкостью:
Но бывают случаи, когда компилятор не знает, сколько элементов будет в коллекции, а вы знаете (например, при обращении к базе данных). Сейчас у нас нет возможности указать ёмкость списка в выражении коллекции. Но предлагаемый вариант позволит это изменить. Как уже говорилось ранее, это всего лишь предложение, и синтаксис, используемый в следующем примере, не окончательный (и, откровенно говоря, выглядит он пока странно):
Это сразу создаст список вместимостью 32 (хотя это и не очень полезно, но суть понятна). В итоге получится
Источник: https://steven-giesel.com/blogPost/352fe495-9cc4-4df8-8ad1-a3e26a64185c/collection-expression-arguments-in-c-15
Аргументы Выражений Коллекций в 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
👍6👎1
This media is not supported in your browser
VIEW IN TELEGRAM
Вышли первые выпуски IT-покера от K2 Cloud
Турнир, где айтишники собирают идеальные билды из карт, интуиции и навыков. Вместо привычной колоды — технологии, сервисы и архитектурные решения.
Идем смотреть
#реклама
Турнир, где айтишники собирают идеальные билды из карт, интуиции и навыков. Вместо привычной колоды — технологии, сервисы и архитектурные решения.
Идем смотреть
#реклама
👎9👍2
День 2547. #ЗаметкиНаПолях
Передавайте Состояние. Начало
Представьте, что вы создали простую функцию фильтрации:
А затем решили, что нужно добавить параметр. Интуиция предлагает простое решение:
Для фрагментов кода, которые выполняются редко, это будет работать. А на горячем пути? Или в параллельном коде с отменой или продолжением? Давайте разберёмся!
Лямбда-функции
C# позволяет нам определить анонимную функцию, которую можно передать как Func или Action. Сначала определяем параметры, а потом тело функции после стрелки:
Есть одна проблема: эти функции захватывают контекст, т.е. переменные или параметры из окружения. В реальности компилятор создаёт класс, поля которого содержат необходимые данные (в примере выше – переменную minSize).
Это может показаться не такой уж большой проблемой, но, если подобные случаи накапливаются на горячем пути, можно столкнуться с проблемами выделения памяти.
В C# 9.0 добавлены статические анонимные функции, которые запрещают захват контекста. Однако, в примере выше это приведёт к ошибке компиляции:
Не всегда возможно избежать захвата контекста. Для использования статических анонимных функций необходимо выполнение одного из двух условий:
1. Функция требует только предоставленных параметров.
2. Существует перегрузка, которая принимает состояние, передаваемое в качестве дополнительного параметра.
Рассмотрим второе условие подробнее:
Очевидно, что, если для предиката требуется какое-либо внешнее состояние, потребуется захватить его. А в следующей перегрузке:
…добавлен дополнительный параметр, называемый контекстом, который можно передать функции. Суть в том, что он также передается предикату. Если у вас есть чётко определённый контекст, вы можете просто передать его в качестве дополнительного параметра:
Теперь мы знаем, что, объединив статические лямбда-функции и параметр контекста, мы можем многого добиться, не захватывая состояние (не выделяя память). Далее рассмотрим примеры.
Продолжение следует…
Источник: https://blog.scooletz.com/2025/10/08/pass-the-state
Передавайте Состояние. Начало
Представьте, что вы создали простую функцию фильтрации:
public IEnumerable<Item>
GetOversized(IEnumerable<Item> items)
=> items.Where(item => item.Size > 45);
А затем решили, что нужно добавить параметр. Интуиция предлагает простое решение:
public IEnumerable<Item>
GetOversized(IEnumerable<Item> items, int minSize)
=> items.Where(item => item.Size > minSize);
Для фрагментов кода, которые выполняются редко, это будет работать. А на горячем пути? Или в параллельном коде с отменой или продолжением? Давайте разберёмся!
Лямбда-функции
C# позволяет нам определить анонимную функцию, которую можно передать как Func или Action. Сначала определяем параметры, а потом тело функции после стрелки:
item => item.Size > minSize;
Есть одна проблема: эти функции захватывают контекст, т.е. переменные или параметры из окружения. В реальности компилятор создаёт класс, поля которого содержат необходимые данные (в примере выше – переменную minSize).
Это может показаться не такой уж большой проблемой, но, если подобные случаи накапливаются на горячем пути, можно столкнуться с проблемами выделения памяти.
В C# 9.0 добавлены статические анонимные функции, которые запрещают захват контекста. Однако, в примере выше это приведёт к ошибке компиляции:
// Нельзя использовать static и minSize вместе
items.Where(static (item) => item.Size > minSize);
Не всегда возможно избежать захвата контекста. Для использования статических анонимных функций необходимо выполнение одного из двух условий:
1. Функция требует только предоставленных параметров.
2. Существует перегрузка, которая принимает состояние, передаваемое в качестве дополнительного параметра.
Рассмотрим второе условие подробнее:
public IEnumerable<T> Query(Func<T, bool> predicate);
Очевидно, что, если для предиката требуется какое-либо внешнее состояние, потребуется захватить его. А в следующей перегрузке:
public IEnumerable<T> Query<TContext>(
Func<T, TContext, bool> predicate,
TContext ctx);
…добавлен дополнительный параметр, называемый контекстом, который можно передать функции. Суть в том, что он также передается предикату. Если у вас есть чётко определённый контекст, вы можете просто передать его в качестве дополнительного параметра:
repo.Query(
// ctxMinSize передаст параметр minSize в лямбду
static (item, ctxMinSize) =>
(item) => item.Size > ctxMinSize,
minSize);
Теперь мы знаем, что, объединив статические лямбда-функции и параметр контекста, мы можем многого добиться, не захватывая состояние (не выделяя память). Далее рассмотрим примеры.
Продолжение следует…
Источник: https://blog.scooletz.com/2025/10/08/pass-the-state
👍15
День 2548. #ЗаметкиНаПолях
Передавайте Состояние. Продолжение
Начало
Начнём с нескольких простых случаев. Первый максимально прост - агрегирующая функция:
Это метод расширения, который перебирает перечислимый объект. Он принимает контекст в виде параметра seed. У него есть функция, которая принимает контекст и элемент перечисляемого объекта. Тот факт, что он возвращает значение типа контекста, является особенностью агрегирующей функции. Это не имеет ничего общего с идеей передачи контекста. Использование:
Как видите, мы передали контекст и использовали статическую лямбда-функцию, чем избежали захвата контекста.
Следующий пример основан на методе, который принимает делегат и некоторое состояние. В данном случае мы рассматриваем одну из перегрузок AddOrUpdate из ConcurrentDictionary:
ConcurrentDictionary — словарь, который может обрабатывать одновременный доступ нескольких потоков. Один из распространённых сценариев — добавление или обновление значения. Вот не самый удачный пример его использования (просто для демонстрации):
Состояния такого счетчика:
1. Счётчик для конкретного ключа не существует и требуется его создать.
Нужен ключ и делегат для создания значения, который принимает ключ и контекст.
2. Счётчик для конкретного ключа существует и требуется его обновить.
Аналогично, но здесь потребуется ещё один параметр – предыдущее значение.
Синхронизация их выполнения остаётся на усмотрение реализации словаря. Вы можете быть уверены, что после завершения работы этого метода возвращаемое значение будет тем, которое было установлено одним из методов. Обратите внимание: благодаря использованию дополнительного параметра контекста можно использовать статические лямбда-функции! Захват контекста не требуется.
Окончание следует…
Источник: https://blog.scooletz.com/2025/10/08/pass-the-state
Передавайте Состояние. Продолжение
Начало
Начнём с нескольких простых случаев. Первый максимально прост - агрегирующая функция:
public static TAccumulate
Aggregate<TSource,TAccumulate>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate,TSource,TAccumulate> func);
Это метод расширения, который перебирает перечислимый объект. Он принимает контекст в виде параметра seed. У него есть функция, которая принимает контекст и элемент перечисляемого объекта. Тот факт, что он возвращает значение типа контекста, является особенностью агрегирующей функции. Это не имеет ничего общего с идеей передачи контекста. Использование:
var sumOfEven = numbers
.Aggregate(
0,
static (a, item) =>
a + (item % 2 == 0 ? 1 : 0));
Как видите, мы передали контекст и использовали статическую лямбда-функцию, чем избежали захвата контекста.
Следующий пример основан на методе, который принимает делегат и некоторое состояние. В данном случае мы рассматриваем одну из перегрузок AddOrUpdate из ConcurrentDictionary:
TValue AddOrUpdate<TArg>(TKey key,
Func<TKey,TArg,TValue> addValueFactory,
Func<TKey,TValue,TArg,TValue> updateValueFactory,
TArg factoryArgument);
ConcurrentDictionary — словарь, который может обрабатывать одновременный доступ нескольких потоков. Один из распространённых сценариев — добавление или обновление значения. Вот не самый удачный пример его использования (просто для демонстрации):
var counters =
new ConcurrentDictionary<string, long>();
counters.AddOrUpdate("tag",
static (_, v) => v, // задаём значение
static (_, prev, update) => prev + update, // обновляем
1); // начальное значение
Состояния такого счетчика:
1. Счётчик для конкретного ключа не существует и требуется его создать.
Нужен ключ и делегат для создания значения, который принимает ключ и контекст.
2. Счётчик для конкретного ключа существует и требуется его обновить.
Аналогично, но здесь потребуется ещё один параметр – предыдущее значение.
Синхронизация их выполнения остаётся на усмотрение реализации словаря. Вы можете быть уверены, что после завершения работы этого метода возвращаемое значение будет тем, которое было установлено одним из методов. Обратите внимание: благодаря использованию дополнительного параметра контекста можно использовать статические лямбда-функции! Захват контекста не требуется.
Окончание следует…
Источник: https://blog.scooletz.com/2025/10/08/pass-the-state
День 2549. #ЗаметкиНаПолях
Передавайте Состояние. Окончание
Начало
Продолжение
CancellationToken.Register
Вы можете зарегистрировать функцию обратного вызова, которая будет вызвана при отмене токена:
Та же проблема. Попытка добавить модификатор static приведёт к ошибке:
Однако, если создатель функции подумал о производительности, он предоставит перегрузку, принимающую состояние.
Да, здесь требуется привести состояние к нужному типу и правильно его передать. В обычном бизнес-приложении это может быть необязательно. Но, например, в RavenDB, распределённой БД, созданной на .NET и использующей CancellationToken из BCL, PR #21205 предлагает такие улучшения, используя перегрузку с передачей состояния.
Принцип улучшений прост:
- Вы замечаете использование Register с нестатическии методом.
- Делаете лямбду статической и ждёте ошибок компилятора.
- При возможности используйте перегрузку с передачей состояния.
Task.ContinueWith
Аналогичный подход, как и с CancellationToken, можно использовать с продолжениями, которые можно прикреплять к задачам вручную. Иногда необходимо прикрепить продолжение к задаче без использования сложного механизма async-await. В таком случае можно использовать метод ContinueWith:
Мы можем следовать тому же подходу, сначала сделав метод статическим. Затем, обратив внимание на ошибку компиляции, исправим её с помощью перегрузки метода, передающей состояние, и приведения типов:
Итого
Захват переменных в лямбдах может стать серьёзной проблемой на горячих путях приложений .NET. К счастью, существуют контрмеры в виде статических лямбда-выражений и перегрузок, передающих состояние, которые позволяют устранить эти проблемы.
Источник: https://blog.scooletz.com/2025/10/08/pass-the-state
Передавайте Состояние. Окончание
Начало
Продолжение
CancellationToken.Register
Вы можете зарегистрировать функцию обратного вызова, которая будет вызвана при отмене токена:
CancellationToken ct;
TaskCompletionSource tcs = new ();
ct.Register(() => tcs.TrySetCanceled());
Та же проблема. Попытка добавить модификатор static приведёт к ошибке:
ct.Register(static () => tcs.TrySetCanceled());
Однако, если создатель функции подумал о производительности, он предоставит перегрузку, принимающую состояние.
…
ct.Register(
static (state) =>
((TaskCompletionSource)state).TrySetCanceled(),
tcs); // Состояние передаётся в последнем параметре
Да, здесь требуется привести состояние к нужному типу и правильно его передать. В обычном бизнес-приложении это может быть необязательно. Но, например, в RavenDB, распределённой БД, созданной на .NET и использующей CancellationToken из BCL, PR #21205 предлагает такие улучшения, используя перегрузку с передачей состояния.
Принцип улучшений прост:
- Вы замечаете использование Register с нестатическии методом.
- Делаете лямбду статической и ждёте ошибок компилятора.
- При возможности используйте перегрузку с передачей состояния.
Task.ContinueWith
Аналогичный подход, как и с CancellationToken, можно использовать с продолжениями, которые можно прикреплять к задачам вручную. Иногда необходимо прикрепить продолжение к задаче без использования сложного механизма async-await. В таком случае можно использовать метод ContinueWith:
Task connection;
TaskCompletionSource tcs;
connection.ContinueWith ( (t) => {
if (t.IsFaulted)
tcs.TrySetException(t.Exception);
else if (t.IsCanceled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(null);
});
Мы можем следовать тому же подходу, сначала сделав метод статическим. Затем, обратив внимание на ошибку компиляции, исправим её с помощью перегрузки метода, передающей состояние, и приведения типов:
Task connection;
TaskCompletionSource tcs;
// лямбда теперь статическая
connection.ContinueWith ( static (t, state) => {
// приводим к типу продолжения
var c = (TaskCompletionSource) state;
if (t.IsFaulted)
c.TrySetException(t.Exception);
else if (t.IsCanceled)
c.TrySetCanceled();
else
c.TrySetResult(null);
}, tcs); // передаём состояние
Итого
Захват переменных в лямбдах может стать серьёзной проблемой на горячих путях приложений .NET. К счастью, существуют контрмеры в виде статических лямбда-выражений и перегрузок, передающих состояние, которые позволяют устранить эти проблемы.
Источник: https://blog.scooletz.com/2025/10/08/pass-the-state
👍4
День 2550. #Карьера
Топ Советов по Повышению Продуктивности. Часть 5
Части 1, 2, 3, 4
5. Правило 2 минут для проверок кода
Проверки кода — место, где умирают благие намерения. Как обычно бывает: кто-то открывает пул-реквест с 47 измененными файлами и 2300 строками. Вы видите уведомление и думаете: «Я проверю это позже, когда будет время». «Позже» никогда не наступает. PR лежит три дня. Автор пишет вам. Вы наконец выделяете час, открываете PR, сразу чувствуете себя перегруженным, бегло просматриваете его, одобряете с комментарием «Выглядит неплохо», и возвращаетесь к своим делами. Так вы сами способствуете той же проблеме, которая вас раздражает, когда вы ждёте проверки ваших PR.
Правило 2 минут
Если проверка кода займет меньше 2 минут, сделайте её немедленно.
Не «когда закончите текущую задачу». Не «после этой встречи». Не «в назначенное для проверок время». Немедленно.
Небольшие проверки выполняются быстро. PR на 30 строк с чётким контекстом можно проверить за 90 секунд. Прочитать код, убедиться, что он понятен, оставить комментарий или одобрение — готово.
Когда люди знают, что небольшие PR проверяются мгновенно, а большие остаются в очереди бесконечно, поведение меняется органично. Команда естественным образом начинает разбивать работу на более мелкие, более удобные для проверки части.
Это снижает и вашу когнитивную нагрузку. Вместо того чтобы 12 ожидающих проверок преследовали вас, как технический долг, вы сразу же выполняете небольшие. Чувство вины за то, что вы являетесь узким местом, исчезает.
Это улучшает качество кода. Быстрая обратная связь означает, что разработчики работают над проектом, пока контекст свеж. Они все ещё думают о проблеме. Они не переключились на три другие задачи. Раннее выявление проблем делает их исправление дешевле.
Но вот в чем загвоздка: небольшие PR должны быть легко идентифицируемыми.
Работайте с командой над установлением правил:
- PR менее 200 строк получают метку «small».
- Используйте префиксы заголовков PR: [SMALL] или [QUICK].
- Настройте уведомления в Slack или по email, которые будут отправляться по-разному для небольших и больших PR.
- Составьте командное соглашение: небольшие PR проходят проверку в тот же день, большие — когда будет время.
Для PR, занимающих более 2 минут, выделите время в календаре для работы по проверке кода. Относитесь к этому как к любой другой важной задаче. Но не позволяйте большим проверкам мешать вам немедленно выполнять быстрые.
Когда команда коллективно внедряет это, скорость проверки резко возрастает. Эта тесная обратная связь ускоряет всё. Функции выпускаются быстрее. Знания распространяются более равномерно. Ошибки обнаруживаются раньше. Сотрудничество ощущается не как бюрократия, а как настоящая командная работа.
Самое сложное — остановить текущую работу, чтобы что-то проверить. Мозг сопротивляется переключению контекста. Но двухминутная проверка — это кратковременное переключение внимания, которое обеспечивает движение вперёд.
Советы
- Сделайте уведомления о PR видимыми (Slack, email, расширение для браузера);
- Используйте мобильное приложение GitHub или GitLab для просмотра небольших PR во время перерывов на кофе;
- Создайте сочетание клавиш для быстрого перехода к очереди проверок;
- Отслеживайте время ответа на проверки PR в течение недели — осведомлённость приводит к улучшению;
- Создайте шаблоны PR, которые поощряют просмотр небольших PR. Включите пункт в контрольный список: «Этот PR содержит менее 200 строк или разбит на несколько». Сделайте осознание размера частью культуры команды.
Накопительный эффект быстрой обратной связи — одно из самых эффективных улучшений производительности, которых может добиться команда. Правило двух минут — это не просто проверка кода, это целая философия. Уменьшите препятствия для быстрых действий, и вы будете совершать их чаще. Сделайте отзывчивость простой, и вы сами станете отзывчивыми.
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
Топ Советов по Повышению Продуктивности. Часть 5
Части 1, 2, 3, 4
5. Правило 2 минут для проверок кода
Проверки кода — место, где умирают благие намерения. Как обычно бывает: кто-то открывает пул-реквест с 47 измененными файлами и 2300 строками. Вы видите уведомление и думаете: «Я проверю это позже, когда будет время». «Позже» никогда не наступает. PR лежит три дня. Автор пишет вам. Вы наконец выделяете час, открываете PR, сразу чувствуете себя перегруженным, бегло просматриваете его, одобряете с комментарием «Выглядит неплохо», и возвращаетесь к своим делами. Так вы сами способствуете той же проблеме, которая вас раздражает, когда вы ждёте проверки ваших PR.
Правило 2 минут
Если проверка кода займет меньше 2 минут, сделайте её немедленно.
Не «когда закончите текущую задачу». Не «после этой встречи». Не «в назначенное для проверок время». Немедленно.
Небольшие проверки выполняются быстро. PR на 30 строк с чётким контекстом можно проверить за 90 секунд. Прочитать код, убедиться, что он понятен, оставить комментарий или одобрение — готово.
Когда люди знают, что небольшие PR проверяются мгновенно, а большие остаются в очереди бесконечно, поведение меняется органично. Команда естественным образом начинает разбивать работу на более мелкие, более удобные для проверки части.
Это снижает и вашу когнитивную нагрузку. Вместо того чтобы 12 ожидающих проверок преследовали вас, как технический долг, вы сразу же выполняете небольшие. Чувство вины за то, что вы являетесь узким местом, исчезает.
Это улучшает качество кода. Быстрая обратная связь означает, что разработчики работают над проектом, пока контекст свеж. Они все ещё думают о проблеме. Они не переключились на три другие задачи. Раннее выявление проблем делает их исправление дешевле.
Но вот в чем загвоздка: небольшие PR должны быть легко идентифицируемыми.
Работайте с командой над установлением правил:
- PR менее 200 строк получают метку «small».
- Используйте префиксы заголовков PR: [SMALL] или [QUICK].
- Настройте уведомления в Slack или по email, которые будут отправляться по-разному для небольших и больших PR.
- Составьте командное соглашение: небольшие PR проходят проверку в тот же день, большие — когда будет время.
Для PR, занимающих более 2 минут, выделите время в календаре для работы по проверке кода. Относитесь к этому как к любой другой важной задаче. Но не позволяйте большим проверкам мешать вам немедленно выполнять быстрые.
Когда команда коллективно внедряет это, скорость проверки резко возрастает. Эта тесная обратная связь ускоряет всё. Функции выпускаются быстрее. Знания распространяются более равномерно. Ошибки обнаруживаются раньше. Сотрудничество ощущается не как бюрократия, а как настоящая командная работа.
Самое сложное — остановить текущую работу, чтобы что-то проверить. Мозг сопротивляется переключению контекста. Но двухминутная проверка — это кратковременное переключение внимания, которое обеспечивает движение вперёд.
Советы
- Сделайте уведомления о PR видимыми (Slack, email, расширение для браузера);
- Используйте мобильное приложение GitHub или GitLab для просмотра небольших PR во время перерывов на кофе;
- Создайте сочетание клавиш для быстрого перехода к очереди проверок;
- Отслеживайте время ответа на проверки PR в течение недели — осведомлённость приводит к улучшению;
- Создайте шаблоны PR, которые поощряют просмотр небольших PR. Включите пункт в контрольный список: «Этот PR содержит менее 200 строк или разбит на несколько». Сделайте осознание размера частью культуры команды.
Накопительный эффект быстрой обратной связи — одно из самых эффективных улучшений производительности, которых может добиться команда. Правило двух минут — это не просто проверка кода, это целая философия. Уменьшите препятствия для быстрых действий, и вы будете совершать их чаще. Сделайте отзывчивость простой, и вы сами станете отзывчивыми.
Источник: https://dev.to/thebitforge/top-10-productivity-hacks-every-developer-should-know-151h
👍6👎2
Что выведет код с картинки в первом комментарии? Выберите наиболее подходящий на ваш взгляд ответ.
#Quiz #CSharp
#Quiz #CSharp
Anonymous Quiz
21%
ничего
8%
0;
8%
526;1=>460,2=>269,3=>230,4=>192
8%
517;1=>496,2=>499,3=>500,4=>492
10%
1351;1=>500,2=>499,3=>496,4=>492
16%
1429;1=>500,2=>500,3=>500,4=>500
8%
2032;1=>500,2=>499,3=>496,4=>492
16%
2054;1=>500,2=>500,3=>500,4=>500
6%
2071;1=>0,2=>500,3=>0,4=>0
👎17