День 2599. #Оффтоп
Размер Веб-Страницы Должен Укладываться в 14кБ
Меньше размер – быстрее загрузка, это понятно. Удивительно, что страница в 14кБ может загружаться гораздо быстрее, чем в 15кБ, а разница между 15 и 16кБ незначительна. Дело в алгоритме медленного старта TCP.
TCP
Протокол управления передачей (TCP) — это способ использования интернет-протокола (IP) для надёжной отправки пакетов данных. Сервер отправляет несколько пакетов, затем ждёт ответа от браузера о получении (ACK), затем отправляет ещё — или, если не получил ACK, может отправить пакеты снова.
Алгоритм медленного старта TCP используется серверами для определения количества пакетов, которые они могут отправить за один раз. Сервер не знает, какой объём данных может обработать соединение, поэтому начинает с отправки небольшого и безопасного количества данных — обычно 10 TCP-пакетов. Если на это получен ACK, сервер отправляет больше данных, удваивая количество пакетов. Так до тех пор, пока пакеты не будут потеряны и сервер не получит ACK. (Тогда он продолжает отправлять пакеты, но с меньшей скоростью). В реальности реализация алгоритма может отличаться, но суть та же.
Откуда 14кБ?
Максимальный размер TCP-пакета составляет 1500 байт: 40 байт заголовка (16 – IP, 24 – TCP). Т.е., 10 пакетов по 1460 = 14600 байт или примерно 14кБ!
Таким образом, если страницы (хотя бы важные) вашего сайта умещаются в 14кБ, вы можете сэкономить посетителям много времени. Люди очень нетерпеливы, и даже один обмен данными может быть удивительно долгим, особенно в нестабильных сетях.
Что делать?
Очевидно – делать сайт как можно меньше. Хорошая цель – уместить каждую страницу в 14кБ. Эти 14кБ включают сжатие — так что на самом деле это может быть около 50кБ несжатых данных, что довольно много.
Так что, если избавиться от лишнего CSS и JS, автовоспроизводимых видео, использовать минимизацию кода и т.п., вы, вероятно, легко достигнете цели. Но, даже если этого не получится, из правила 14кБ всё ещё можно извлечь пользу. Первые 14кБ данных, отправляемых посетителям, могут быть использованы для отображения чего-то полезного — например, важных первых нескольких абзацев текста, объясняющих, как использовать ваше приложение.
Примечание: 14кБ включают в себя HTTP-заголовки — которые не сжимаются (даже в HTTP/2 при первом ответе), а также изображения, поэтому выдавайте только то, что находится в видимой области экрана, делайте их очень маленькими, или используйте заполнители, чтобы посетители знали, что на этом месте будет что-то полезное.
Некоторые оговорки:
- Правило 14кБ больше эмпирическое правило, чем фундаментальный закон вычислительной техники. Некоторые серверы увеличили начальное окно медленного старта TCP до 30 пакетов вместо 10.
- Иногда сервер знает, что может начать с большего количества пакетов, потому что он использовал TLS-рукопожатие для установления большего лимита.
- Серверы могут кэшировать количество пакетов, которые может обработать маршрут, и отправлять больше при следующем подключении.
HTTP/2, HTTP/3 и QUIC
Существует мнение, что правило 14кБ больше не действует при использовании HTTP/2+. Однако строгих доказательств этому нет. Если вы знаете, отпишитесь в комментариях.
Источник: https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/
Размер Веб-Страницы Должен Укладываться в 14кБ
Меньше размер – быстрее загрузка, это понятно. Удивительно, что страница в 14кБ может загружаться гораздо быстрее, чем в 15кБ, а разница между 15 и 16кБ незначительна. Дело в алгоритме медленного старта TCP.
TCP
Протокол управления передачей (TCP) — это способ использования интернет-протокола (IP) для надёжной отправки пакетов данных. Сервер отправляет несколько пакетов, затем ждёт ответа от браузера о получении (ACK), затем отправляет ещё — или, если не получил ACK, может отправить пакеты снова.
Алгоритм медленного старта TCP используется серверами для определения количества пакетов, которые они могут отправить за один раз. Сервер не знает, какой объём данных может обработать соединение, поэтому начинает с отправки небольшого и безопасного количества данных — обычно 10 TCP-пакетов. Если на это получен ACK, сервер отправляет больше данных, удваивая количество пакетов. Так до тех пор, пока пакеты не будут потеряны и сервер не получит ACK. (Тогда он продолжает отправлять пакеты, но с меньшей скоростью). В реальности реализация алгоритма может отличаться, но суть та же.
Откуда 14кБ?
Максимальный размер TCP-пакета составляет 1500 байт: 40 байт заголовка (16 – IP, 24 – TCP). Т.е., 10 пакетов по 1460 = 14600 байт или примерно 14кБ!
Таким образом, если страницы (хотя бы важные) вашего сайта умещаются в 14кБ, вы можете сэкономить посетителям много времени. Люди очень нетерпеливы, и даже один обмен данными может быть удивительно долгим, особенно в нестабильных сетях.
Что делать?
Очевидно – делать сайт как можно меньше. Хорошая цель – уместить каждую страницу в 14кБ. Эти 14кБ включают сжатие — так что на самом деле это может быть около 50кБ несжатых данных, что довольно много.
Так что, если избавиться от лишнего CSS и JS, автовоспроизводимых видео, использовать минимизацию кода и т.п., вы, вероятно, легко достигнете цели. Но, даже если этого не получится, из правила 14кБ всё ещё можно извлечь пользу. Первые 14кБ данных, отправляемых посетителям, могут быть использованы для отображения чего-то полезного — например, важных первых нескольких абзацев текста, объясняющих, как использовать ваше приложение.
Примечание: 14кБ включают в себя HTTP-заголовки — которые не сжимаются (даже в HTTP/2 при первом ответе), а также изображения, поэтому выдавайте только то, что находится в видимой области экрана, делайте их очень маленькими, или используйте заполнители, чтобы посетители знали, что на этом месте будет что-то полезное.
Некоторые оговорки:
- Правило 14кБ больше эмпирическое правило, чем фундаментальный закон вычислительной техники. Некоторые серверы увеличили начальное окно медленного старта TCP до 30 пакетов вместо 10.
- Иногда сервер знает, что может начать с большего количества пакетов, потому что он использовал TLS-рукопожатие для установления большего лимита.
- Серверы могут кэшировать количество пакетов, которые может обработать маршрут, и отправлять больше при следующем подключении.
HTTP/2, HTTP/3 и QUIC
Существует мнение, что правило 14кБ больше не действует при использовании HTTP/2+. Однако строгих доказательств этому нет. Если вы знаете, отпишитесь в комментариях.
Источник: https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/
👍16
День 2600. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
26. Навыки решения проблем
«Опишите какую-нибудь сложную техническую проблему, с которой вы столкнулись в вашей практике и как вы подошли к её решению? Какие инструменты и стратегии вы использовали, и каков был результат?»
Хороший ответ
В недавнем проекте на .NET я столкнулся с проблемой производительности, когда время ответа веб-API резко возросло при высокой нагрузке. API отвечал за получение сложных данных из БД и преобразование их в определённый формат для использования на стороне клиента.
Я применил следующий подход.
1. Выявление проблемы
Используя логи, я отследил, что узкое место возникает во время получения и обработки данных.
2. Выдвижение гипотез о решениях
Я предположил, что проблема может быть связана с неэффективными запросами к базе и неоптимальной обработкой данных в API.
3. Реализация и тестирование решений
Сначала я оптимизировал SQL-запросы с помощью анализа планов выполнения и обнаружил несколько отсутствующих индексов и некоторые запросы, которые можно переписать для повышения эффективности.
Затем я провёл рефакторинг кода .NET, чтобы использовать асинхронные шаблоны программирования. Я изменил уровень доступа к данным, чтобы использовать async и await, гарантируя, что операции с БД не блокируют потоки без необходимости.
4. Проверка и итерация
После внедрения изменений я повторно провёл нагрузочное тестирование и заметил значительное улучшение времени отклика. Изменения также были рассмотрены на код-ревью, чтобы убедиться в их соответствии передовым практикам.
5. Развёртывание и мониторинг
После развёртывания я продолжил мониторинг производительности приложения и подтвердил, что проблема решена.
6. Результат
Производительность API значительно улучшилась, приложение справляется с более высокими нагрузками с лучшим временем отклика, а решение также улучшило общую масштабируемость приложения.
Этот опыт подчеркнул важность систематической отладки, тщательного тестирования и использования надёжных инструментов для мониторинга и оптимизации ПО.
Часто встречающийся плохой ответ
«Какой-то конкретный случай выделить сложно. Когда я нахожу проблему, я просто пробую разные варианты, обычно что-то срабатывает. Часто я спрашиваю ИИ, обычно он предлагает хорошие решения».
Почему это неправильно:
- Отсутствие систематического подхода: полагаться исключительно на метод проб и ошибок может быть неэффективно, долго и не обязательно приведёт к пониманию первопричины проблемы.
- Неэффективность и риск: случайные попытки решения различных задач без стратегического плана или понимания могут привести к появлению новых ошибок, потенциально вызвать новые проблемы и потратить ценное время на разработку.
- Упущенная возможность обучения: такой подход не позволяет в полной мере использовать возможности обучения, предоставляемые сложными задачами. Понимание того, почему то или иное решение работает, так же важно, как и решение самой проблемы, чтобы предотвратить будущие проблемы и улучшить свои навыки.
Эта ошибка часто возникает из-за недостатка опыта или непонимания эффективных методов решения проблем в разработке ПО.
PS: неспособность привести конкретный пример из вашей практики также не добавит вам плюсов на собеседовании, поэтому заранее продумайте, как бы вы ответили на такой вопрос.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
26. Навыки решения проблем
«Опишите какую-нибудь сложную техническую проблему, с которой вы столкнулись в вашей практике и как вы подошли к её решению? Какие инструменты и стратегии вы использовали, и каков был результат?»
Хороший ответ
В недавнем проекте на .NET я столкнулся с проблемой производительности, когда время ответа веб-API резко возросло при высокой нагрузке. API отвечал за получение сложных данных из БД и преобразование их в определённый формат для использования на стороне клиента.
Я применил следующий подход.
1. Выявление проблемы
Используя логи, я отследил, что узкое место возникает во время получения и обработки данных.
2. Выдвижение гипотез о решениях
Я предположил, что проблема может быть связана с неэффективными запросами к базе и неоптимальной обработкой данных в API.
3. Реализация и тестирование решений
Сначала я оптимизировал SQL-запросы с помощью анализа планов выполнения и обнаружил несколько отсутствующих индексов и некоторые запросы, которые можно переписать для повышения эффективности.
Затем я провёл рефакторинг кода .NET, чтобы использовать асинхронные шаблоны программирования. Я изменил уровень доступа к данным, чтобы использовать async и await, гарантируя, что операции с БД не блокируют потоки без необходимости.
4. Проверка и итерация
После внедрения изменений я повторно провёл нагрузочное тестирование и заметил значительное улучшение времени отклика. Изменения также были рассмотрены на код-ревью, чтобы убедиться в их соответствии передовым практикам.
5. Развёртывание и мониторинг
После развёртывания я продолжил мониторинг производительности приложения и подтвердил, что проблема решена.
6. Результат
Производительность API значительно улучшилась, приложение справляется с более высокими нагрузками с лучшим временем отклика, а решение также улучшило общую масштабируемость приложения.
Этот опыт подчеркнул важность систематической отладки, тщательного тестирования и использования надёжных инструментов для мониторинга и оптимизации ПО.
Часто встречающийся плохой ответ
«Какой-то конкретный случай выделить сложно. Когда я нахожу проблему, я просто пробую разные варианты, обычно что-то срабатывает. Часто я спрашиваю ИИ, обычно он предлагает хорошие решения».
Почему это неправильно:
- Отсутствие систематического подхода: полагаться исключительно на метод проб и ошибок может быть неэффективно, долго и не обязательно приведёт к пониманию первопричины проблемы.
- Неэффективность и риск: случайные попытки решения различных задач без стратегического плана или понимания могут привести к появлению новых ошибок, потенциально вызвать новые проблемы и потратить ценное время на разработку.
- Упущенная возможность обучения: такой подход не позволяет в полной мере использовать возможности обучения, предоставляемые сложными задачами. Понимание того, почему то или иное решение работает, так же важно, как и решение самой проблемы, чтобы предотвратить будущие проблемы и улучшить свои навыки.
Эта ошибка часто возникает из-за недостатка опыта или непонимания эффективных методов решения проблем в разработке ПО.
PS: неспособность привести конкретный пример из вашей практики также не добавит вам плюсов на собеседовании, поэтому заранее продумайте, как бы вы ответили на такой вопрос.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👎4👍2
День 2601. #SystemDesign101 #Шпаргалка
CPU, GPU и TPU
Почему один и тот же код быстро работает на GPU, медленно на CPU, а на TPU значительно быстрее их обоих? Ответ кроется в архитектуре. CPU, GPU и TPU разработаны для разных рабочих нагрузок.
CPU (Центральный процессор)
CPU обрабатывает вычисления общего назначения. Он создан для работы с низкой задержкой и сложным потоком управления, ветвящейся логикой, системными вызовами, прерываниями и кодом, требующим принятия решений.
Операционные системы, базы данных и большинство приложений работают на CPU, поскольку им необходима такая гибкость.
GPU (Графический процессор)
Вместо нескольких ядер они распределяют работу между тысячами ядер, которые выполняют одну и ту же инструкцию для огромных наборов данных в стиле SIMT (Single Instruction, Multiple Threads — «одна инструкция, множество потоков») / SIMD (Single Instruction, Multiple Data – «одна инструкция, много данных»).
Если ваша рабочая нагрузка повторяющаяся, например, матричные вычисления, затенение пикселей, тензорные операции, GPU справятся с ней быстро.
TPU (Тензорный процессор)
Это специализированное оборудование. Архитектура построена на основе матричного умножения с использованием систолических массивов, с управляемым компилятором потоком данных и встроенными буферами для весов и активаций. По сравнению с графическими процессорами, рассчитан на более высокий объём вычислений с пониженной точностью (например, всего 8-разрядную точность) при более высокой производительности.
Они быстры в обучении нейронных сетей, если рабочая нагрузка хорошо соответствует аппаратному обеспечению.
Источник: https://blog.bytebytego.com/p/ep205-cpu-vs-gpu-vs-tpu
CPU, GPU и TPU
Почему один и тот же код быстро работает на GPU, медленно на CPU, а на TPU значительно быстрее их обоих? Ответ кроется в архитектуре. CPU, GPU и TPU разработаны для разных рабочих нагрузок.
CPU (Центральный процессор)
CPU обрабатывает вычисления общего назначения. Он создан для работы с низкой задержкой и сложным потоком управления, ветвящейся логикой, системными вызовами, прерываниями и кодом, требующим принятия решений.
Операционные системы, базы данных и большинство приложений работают на CPU, поскольку им необходима такая гибкость.
GPU (Графический процессор)
Вместо нескольких ядер они распределяют работу между тысячами ядер, которые выполняют одну и ту же инструкцию для огромных наборов данных в стиле SIMT (Single Instruction, Multiple Threads — «одна инструкция, множество потоков») / SIMD (Single Instruction, Multiple Data – «одна инструкция, много данных»).
Если ваша рабочая нагрузка повторяющаяся, например, матричные вычисления, затенение пикселей, тензорные операции, GPU справятся с ней быстро.
TPU (Тензорный процессор)
Это специализированное оборудование. Архитектура построена на основе матричного умножения с использованием систолических массивов, с управляемым компилятором потоком данных и встроенными буферами для весов и активаций. По сравнению с графическими процессорами, рассчитан на более высокий объём вычислений с пониженной точностью (например, всего 8-разрядную точность) при более высокой производительности.
Они быстры в обучении нейронных сетей, если рабочая нагрузка хорошо соответствует аппаратному обеспечению.
Источник: https://blog.bytebytego.com/p/ep205-cpu-vs-gpu-vs-tpu
👍12
День 2602. #ЧтоНовенького #NET11
Объединения Наконец Появятся в .NET? Начало
После многих лет раздумий, обсуждений дизайна и костылей на уровне библиотек, объединения наконец-то становятся полноценной частью C#. Предложение в репозитории языка C# больше не является отдалённой идеей. Теперь, похоже, что эта функция появилась в превью 2 .NET 11 в качестве одной из ранних возможностей C# 15.
Это важно, потому что объединения решают проблему моделирования, которая существовала в C# очень давно: значение часто имеет ровно одну из нескольких допустимых форм, но система типов не имела встроенного способа выразить это замкнутое множество. В результате обычно использовалось что-то из следующего: обнуляемое значение, управление потоком через исключение, логический флаг или написанная вручную обёртка для результата.
Что именно есть в предложении?
Предложение шире, чем просто единая синтаксическая форма. Оно определяет модель объединений для языка и лаконичный синтаксис объявления поверх этой модели. На высоком уровне предложение вводит 4 возможности, которые важны в повседневном коде (поведения объединения):
1. Неявные преобразования из типов-вариантов в тип объединения;
2. Сопоставление по образцу, которое автоматически распаковывает содержимое объединения;
3. Проверка полноты в выражениях switch, что охвачены все типы-варианты;
4. Улучшения обнуляемости для содержимого объединения.
Основной синтаксис прост:
Это объявление означает, что Pet может содержать ровно один из этих типов-вариантов. Компилятор разрешает прямое построение через значения вариантов и рассматривает сопоставление с образцом в Pet как работу с замкнутым множеством.
Вариант
Типы-объединения и объявления объединения — не одно и то же
C# не просто добавляет форму объявления объединения… Он также определяет, что такое тип-объединение.
Согласно предложению, любой класс или структура, помеченные атрибутом
1. Объединения разработаны как языковая возможность, которая может выходить за рамки объявлений, генерируемых компилятором. Существующие или написанные вручную типы также могут использовать эту модель.
2. Это оставляет место для специализированных реализаций. Сокращённое объявление, показанное выше, намеренно оставлено нечётким, но языковая модель шире, чем это сокращённое объявление.
Окончание следует…
Источник: https://medium.com/@benjaminabt/c-15-unions-unions-are-finally-in-net-ben-abt-f4493c1e9ffc
Объединения Наконец Появятся в .NET? Начало
После многих лет раздумий, обсуждений дизайна и костылей на уровне библиотек, объединения наконец-то становятся полноценной частью C#. Предложение в репозитории языка C# больше не является отдалённой идеей. Теперь, похоже, что эта функция появилась в превью 2 .NET 11 в качестве одной из ранних возможностей C# 15.
Это важно, потому что объединения решают проблему моделирования, которая существовала в C# очень давно: значение часто имеет ровно одну из нескольких допустимых форм, но система типов не имела встроенного способа выразить это замкнутое множество. В результате обычно использовалось что-то из следующего: обнуляемое значение, управление потоком через исключение, логический флаг или написанная вручную обёртка для результата.
Что именно есть в предложении?
Предложение шире, чем просто единая синтаксическая форма. Оно определяет модель объединений для языка и лаконичный синтаксис объявления поверх этой модели. На высоком уровне предложение вводит 4 возможности, которые важны в повседневном коде (поведения объединения):
1. Неявные преобразования из типов-вариантов в тип объединения;
2. Сопоставление по образцу, которое автоматически распаковывает содержимое объединения;
3. Проверка полноты в выражениях switch, что охвачены все типы-варианты;
4. Улучшения обнуляемости для содержимого объединения.
Основной синтаксис прост:
public union Pet(Cat, Dog, Bird);
Это объявление означает, что Pet может содержать ровно один из этих типов-вариантов. Компилятор разрешает прямое построение через значения вариантов и рассматривает сопоставление с образцом в Pet как работу с замкнутым множеством.
public sealed record Cat(string Name);
public sealed record Dog(string Name);
public sealed record Bird(string Name);
public union Pet(Cat, Dog, Bird);
public static string Describe(Pet pet) =>
pet switch
{
Cat cat => $"Cat: {cat.Name}",
Dog dog => $"Dog: {dog.Name}",
Bird bird => $"Bird: {bird.Name}"
};
Вариант
default не требуется, т.к. объединение считается исчерпывающим после обработки всех типов-вариантов.Типы-объединения и объявления объединения — не одно и то же
C# не просто добавляет форму объявления объединения… Он также определяет, что такое тип-объединение.
Согласно предложению, любой класс или структура, помеченные атрибутом
[Union], могут участвовать в поведении объединения (см. 4 варианта выше), если они предоставляют необходимые открытые члены. Т.е. в язык добавляется новый паттерн обработки, а не просто ключевое слово union. Это важно по двум причинам:1. Объединения разработаны как языковая возможность, которая может выходить за рамки объявлений, генерируемых компилятором. Существующие или написанные вручную типы также могут использовать эту модель.
2. Это оставляет место для специализированных реализаций. Сокращённое объявление, показанное выше, намеренно оставлено нечётким, но языковая модель шире, чем это сокращённое объявление.
Окончание следует…
Источник: https://medium.com/@benjaminabt/c-15-unions-unions-are-finally-in-net-ben-abt-f4493c1e9ffc
👍20
День 2603. #ЧтоНовенького #NET11
Объединения Наконец Появятся в .NET? Окончание
Начало
Объявление объединения намеренно размыто
Предложение чётко определяет представление по умолчанию, выбранное для объявлений объединений. Объявление преобразуется в простую структуру со свойством Value типа object и сгенерированным конструктором для каждого типа-варианта. Это означает, что:
- Оно компактно.
- Типы-вариантов в виде типов-значений упаковываются при хранении через форму объявления по умолчанию.
Это не случайность. Предложение позиционирует объявления объединений как простой и широко применимый вариант по умолчанию. Для многих случаев на уровне приложений это правильный компромисс. В результатах, получаемых из сервисов, команд, парсинга и т.п. часто важны ясность и корректность, а не эффективность использования памяти.
Тем не менее, в предложении также признаётся, что этот вариант по умолчанию не будет идеальным для каждого сценария. Он явно оставляет место для пользовательских объединений и для паттернов доступа без упаковки, где структура и производительность имеют большее значение, чем компактное представление в одном поле.
Этот нюанс важен. Нативные объединения станут значительным улучшением для основного кода, но они не делают специализированные библиотеки объединений устаревшими. В основном они заменяют необходимость ручной разработки для распространённых случаев.
Зачем?
Важность объединении в коде C# заключается в возможности указать в системе типов, что операция имеет замкнутый набор допустимых результатов.
Рассмотрим сервис, который получает заказ. Во многих кодовых базах можно найти несколько вариантов реализации:
- тип возврата Order? (обнуляемый),
- исключение при отсутствии данных,
- пользовательская обёртка, которую не проверить, не открыв реализацию.
Объединение делает контракт видимым в прямо в сигнатуре:
Эта сигнатура документирует три типа-результата. Компилятор отвечает за корректность работы. Так объединения переносят проверки корректности на более ранние этапы, уменьшают скрытое управление потоком выполнения и значительно усложняют неправильное использование результатов.
Это также причина, по которой объединения органично вписываются в другие перспективные разработки C#, такие как закрытые иерархии типов и объявления вариантов. Язык движется к более чёткому пониманию замкнутых множеств и исчерпываемости, и объединения являются одним из наиболее ярких выражений этого направления.
Итого
Долгое время объединения в C# обсуждались как нечто, что есть в других языках, а в C# нет. Наконец, это будет не так. Интерес теперь заключается не в том, должны ли в C# быть объединения, а в том, как кодовые базы могут начать использовать преимущества этой модели уже сейчас.
Предложение C#15 наконец-то дает языку первоклассное решение для замкнутых форм результатов и исчерпывающей обработки. Это сочетание необычайно сильно.
Источник: https://medium.com/@benjaminabt/c-15-unions-unions-are-finally-in-net-ben-abt-f4493c1e9ffc
Объединения Наконец Появятся в .NET? Окончание
Начало
Объявление объединения намеренно размыто
Предложение чётко определяет представление по умолчанию, выбранное для объявлений объединений. Объявление преобразуется в простую структуру со свойством Value типа object и сгенерированным конструктором для каждого типа-варианта. Это означает, что:
- Оно компактно.
- Типы-вариантов в виде типов-значений упаковываются при хранении через форму объявления по умолчанию.
Это не случайность. Предложение позиционирует объявления объединений как простой и широко применимый вариант по умолчанию. Для многих случаев на уровне приложений это правильный компромисс. В результатах, получаемых из сервисов, команд, парсинга и т.п. часто важны ясность и корректность, а не эффективность использования памяти.
Тем не менее, в предложении также признаётся, что этот вариант по умолчанию не будет идеальным для каждого сценария. Он явно оставляет место для пользовательских объединений и для паттернов доступа без упаковки, где структура и производительность имеют большее значение, чем компактное представление в одном поле.
Этот нюанс важен. Нативные объединения станут значительным улучшением для основного кода, но они не делают специализированные библиотеки объединений устаревшими. В основном они заменяют необходимость ручной разработки для распространённых случаев.
Зачем?
Важность объединении в коде C# заключается в возможности указать в системе типов, что операция имеет замкнутый набор допустимых результатов.
Рассмотрим сервис, который получает заказ. Во многих кодовых базах можно найти несколько вариантов реализации:
- тип возврата Order? (обнуляемый),
- исключение при отсутствии данных,
- пользовательская обёртка, которую не проверить, не открыв реализацию.
Объединение делает контракт видимым в прямо в сигнатуре:
public sealed record NotFound;
public sealed record Unauthorized;
public sealed record Order(int Id);
public union GetOrderResult(Order, NotFound, Unauthorized);
Эта сигнатура документирует три типа-результата. Компилятор отвечает за корректность работы. Так объединения переносят проверки корректности на более ранние этапы, уменьшают скрытое управление потоком выполнения и значительно усложняют неправильное использование результатов.
Это также причина, по которой объединения органично вписываются в другие перспективные разработки C#, такие как закрытые иерархии типов и объявления вариантов. Язык движется к более чёткому пониманию замкнутых множеств и исчерпываемости, и объединения являются одним из наиболее ярких выражений этого направления.
Итого
Долгое время объединения в C# обсуждались как нечто, что есть в других языках, а в C# нет. Наконец, это будет не так. Интерес теперь заключается не в том, должны ли в C# быть объединения, а в том, как кодовые базы могут начать использовать преимущества этой модели уже сейчас.
Предложение C#15 наконец-то дает языку первоклассное решение для замкнутых форм результатов и исчерпывающей обработки. Это сочетание необычайно сильно.
Источник: https://medium.com/@benjaminabt/c-15-unions-unions-are-finally-in-net-ben-abt-f4493c1e9ffc
👍9
День 2604. #МоиИнструменты #PG
Инструменты Оптимизации Запросов в PostgreSQL. Часть 4
4. pg_stat_statements (встроенное расширение PostgreSQL)
Что даёт: отслеживание производительности запросов без использования внешних инструментов.
Тип: Бесплатное (встроено в PostgreSQL).
Зачем: Перед установкой внешних инструментов включите это расширение. Оно уже есть в PostgreSQL, просто не активировано по умолчанию. Отслеживает время выполнения каждого запроса, количество вызовов и использование ресурсов — важные данные для оптимизации.
Настройка
1. Включаем (однократно)
2. Добавляем в postgresql.conf
3. Перезагружаем Postgres.
Использование
Самые медленные по времени запросы:
Вернёт:
Запросы с большой вариативностью (непостоянная производительность):
Высокий CV (коэффициент вариативности) означает периодические проблемы с производительностью (блокировки, промахи кэша и т.д.).
Когда использовать
- Любая БД Postgres (нет причин не включать);
- Нужен лёгкий мониторинг;
- Нужны метрики на уровне запросов;
- Ограничен бюджет.
Когда отказаться
Особых причин не использовать нет.
Скрытая функция
Выявление запросов, вызывающих нагрузку на ввод-вывод (промахи кэша):
Высокий cache_miss_ratio означает, что запрос сканирует данные не в памяти. Оптимизация: улучшить индексы или увеличить размер shared_buffers.
С осторожностью
У pg_stat_statements буфер фиксированного размера. Проверяем, не достигаем ли мы лимита:
При высоком queries_evicted, увеличьте в postgresql.conf pg_stat_statements.max = 50000 (с 10000), перезапустите Postgres.
Замечание: увеличится расход памяти (~400 байт на запрос).
Источник: https://medium.com/@reliabledataengineering/15-sql-optimization-tools-that-make-queries-10x-faster-8629ac451d97
Инструменты Оптимизации Запросов в PostgreSQL. Часть 4
4. pg_stat_statements (встроенное расширение PostgreSQL)
Что даёт: отслеживание производительности запросов без использования внешних инструментов.
Тип: Бесплатное (встроено в PostgreSQL).
Зачем: Перед установкой внешних инструментов включите это расширение. Оно уже есть в PostgreSQL, просто не активировано по умолчанию. Отслеживает время выполнения каждого запроса, количество вызовов и использование ресурсов — важные данные для оптимизации.
Настройка
1. Включаем (однократно)
CREATE EXTENSION pg_stat_statements;
2. Добавляем в postgresql.conf
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.track = all
pg_stat_statements.max = 10000
3. Перезагружаем Postgres.
Использование
Самые медленные по времени запросы:
SELECT
query,
calls,
total_exec_time,
mean_exec_time,
max_exec_time,
stddev_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
Вернёт:
query | calls | total_exec_time | mean_exec_time
SELECT … FROM orders JOIN … | 50,423 | 8,234,567 ms | 163.4 ms
UPDATE inventory SET … | 12,345 | 4,567,890 ms | 370.0 ms
Запросы с большой вариативностью (непостоянная производительность):
SELECT
query,
calls,
mean_exec_time,
stddev_exec_time,
(stddev_exec_time / mean_exec_time) AS cv
FROM pg_stat_statements
WHERE calls > 100
ORDER BY cv DESC
LIMIT 10;
Высокий CV (коэффициент вариативности) означает периодические проблемы с производительностью (блокировки, промахи кэша и т.д.).
Когда использовать
- Любая БД Postgres (нет причин не включать);
- Нужен лёгкий мониторинг;
- Нужны метрики на уровне запросов;
- Ограничен бюджет.
Когда отказаться
Особых причин не использовать нет.
Скрытая функция
Выявление запросов, вызывающих нагрузку на ввод-вывод (промахи кэша):
SELECT
query,
calls,
shared_blks_hit,
shared_blks_read,
(shared_blks_read::float / NULLIF(shared_blks_hit + shared_blks_read, 0)) AS cache_miss_ratio
FROM pg_stat_statements
WHERE shared_blks_read > 0
ORDER BY shared_blks_read DESC
LIMIT 10;
Высокий cache_miss_ratio означает, что запрос сканирует данные не в памяти. Оптимизация: улучшить индексы или увеличить размер shared_buffers.
С осторожностью
У pg_stat_statements буфер фиксированного размера. Проверяем, не достигаем ли мы лимита:
sql
SELECT
pg_stat_statements_info.dealloc AS queries_evicted,
pg_stat_statements_info.stats_reset AS last_reset
FROM pg_stat_statements_info;
При высоком queries_evicted, увеличьте в postgresql.conf pg_stat_statements.max = 50000 (с 10000), перезапустите Postgres.
Замечание: увеличится расход памяти (~400 байт на запрос).
Источник: https://medium.com/@reliabledataengineering/15-sql-optimization-tools-that-make-queries-10x-faster-8629ac451d97
👍16
День 2605. #ЗаметкиНаПолях
5 Малоизвестных Функций C#, Которые Упростят Вашу Жизнь
Фреймворк уже имеет надёжные инструменты для решения различных проблем, но многие из них мало известны. Сегодня рассмотрим некоторые.
1. OperatingSystem.IsX вместо RuntimeInformation
В течение многих лет проверка текущей ОС в .NET означала написание чего-то вроде:
Теперь появились более чистые варианты:
- OperatingSystem.IsWindows,
- OperatingSystem.IsLinux,
- OperatingSystem.IsMacOS
и т.п.
2. Правильная изоляция плагинов с помощью AssemblyLoadContext
Если вы когда-либо пытались создать систему плагинов в .NET, вы знаете, насколько болезненны конфликты сборок. Загрузите две версии одной и той же зависимости, и внезапно всё перестаёт работать. AssemblyLoadContext позволяет загружать сборки изолированно, так что два плагина могут зависеть от разных версий одной и той же DLL, не мешая друг другу. Вот минимальный код для начала:
Теперь каждый плагин существует в своей среде. Вы также можете их выгружать, что очень важно для длительно работающих процессов, таких как серверы.
3. Разбор зависимостей с помощью AssemblyDependencyResolver
AssemblyDependencyResolver, получив путь к плагину или сборке, определяет, откуда должны браться зависимости:
Вы получаете правильные правила разрешения зависимостей, соответствующие тому, как это обычно делает .NET, но с областью действия в контексте плагина. Так вы избегаете неприятных сюрпризов, когда плагин ссылается на Newtonsoft.Json 13.0.1, а хост-приложение использует 12.0.3.
4. Получение версий сборок без ошибок
Часто в коде можно встретить что-то такое:
Дело в том, что это значение не всегда совпадает с версией, которую вы указали в проекте. Это версия сборки, а не обязательно версия файла или информационная версия. Какая из них вам нужна?
-
-
-
Лучший подход – выражаться более явно:
Так вы получите именно ту строку, которую хотели передать, а не то, что MSBuild по умолчанию присвоил вашей DLL.
5. Получение зависимостей из контейнера с помощью ActivatorUtilities
Иногда нужно создать объект, который не зарегистрирован в контейнере, но имеет зависимости, которые зарегистрированы. Используйте ActivatorUtilities:
Это говорит контейнеру: «Я знаю, что MyService не зарегистрирован, но, пожалуйста, внедри все необходимые ему сервисы». Это удобный обходной путь, который избавляет вас от необходимости создавать неудобные фабрики или засорять код логикой разрешения сервисов.
Источник: https://blog.stackademic.com/if-youre-not-using-these-5-net-features-you-re-working-too-hard-0aefbf5a6fdc?gi=bb3ac273e638
5 Малоизвестных Функций C#, Которые Упростят Вашу Жизнь
Фреймворк уже имеет надёжные инструменты для решения различных проблем, но многие из них мало известны. Сегодня рассмотрим некоторые.
1. OperatingSystem.IsX вместо RuntimeInformation
В течение многих лет проверка текущей ОС в .NET означала написание чего-то вроде:
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
//…
}
Теперь появились более чистые варианты:
- OperatingSystem.IsWindows,
- OperatingSystem.IsLinux,
- OperatingSystem.IsMacOS
и т.п.
if (OperatingSystem.IsWindows())
{
//…
}
2. Правильная изоляция плагинов с помощью AssemblyLoadContext
Если вы когда-либо пытались создать систему плагинов в .NET, вы знаете, насколько болезненны конфликты сборок. Загрузите две версии одной и той же зависимости, и внезапно всё перестаёт работать. AssemblyLoadContext позволяет загружать сборки изолированно, так что два плагина могут зависеть от разных версий одной и той же DLL, не мешая друг другу. Вот минимальный код для начала:
class PluginLoadContext : AssemblyLoadContext
{
private AssemblyDependencyResolver _resolver;
public PluginLoadContext(string path) =>
_resolver = new(path);
protected override Assembly? Load(AssemblyName name)
{
var path = _resolver
.ResolveAssemblyToPath(name);
return path != null
? LoadFromAssemblyPath(path)
: null;
}
}
Теперь каждый плагин существует в своей среде. Вы также можете их выгружать, что очень важно для длительно работающих процессов, таких как серверы.
3. Разбор зависимостей с помощью AssemblyDependencyResolver
AssemblyDependencyResolver, получив путь к плагину или сборке, определяет, откуда должны браться зависимости:
var resolver =
new AssemblyDependencyResolver(pluginPath);
var path = resolver
.ResolveAssemblyToPath(assemblyName);
Вы получаете правильные правила разрешения зависимостей, соответствующие тому, как это обычно делает .NET, но с областью действия в контексте плагина. Так вы избегаете неприятных сюрпризов, когда плагин ссылается на Newtonsoft.Json 13.0.1, а хост-приложение использует 12.0.3.
4. Получение версий сборок без ошибок
Часто в коде можно встретить что-то такое:
var version = Assembly
.GetExecutingAssembly()
.GetName()
.Version;
Дело в том, что это значение не всегда совпадает с версией, которую вы указали в проекте. Это версия сборки, а не обязательно версия файла или информационная версия. Какая из них вам нужна?
-
AssemblyName.Version - версия сборки, полученная во время компиляции,-
FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion - версия файла,-
AssemblyInformationalVersionAttribute - семантическая версия, вроде 1.0.0-beta+sha.abc123.Лучший подход – выражаться более явно:
var version = Assembly
.GetExecutingAssembly()
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
.InformationalVersion;
Так вы получите именно ту строку, которую хотели передать, а не то, что MSBuild по умолчанию присвоил вашей DLL.
5. Получение зависимостей из контейнера с помощью ActivatorUtilities
Иногда нужно создать объект, который не зарегистрирован в контейнере, но имеет зависимости, которые зарегистрированы. Используйте ActivatorUtilities:
var myService = ActivatorUtilities
.CreateInstance<MyService>(serviceProvider);
Это говорит контейнеру: «Я знаю, что MyService не зарегистрирован, но, пожалуйста, внедри все необходимые ему сервисы». Это удобный обходной путь, который избавляет вас от необходимости создавать неудобные фабрики или засорять код логикой разрешения сервисов.
Источник: https://blog.stackademic.com/if-youre-not-using-these-5-net-features-you-re-working-too-hard-0aefbf5a6fdc?gi=bb3ac273e638
👍14
День 2606. #Здоровье
Утренние Привычки, Которые Разрушают Ваш Мозг. Начало
Автор оригинала: нейробиолог Патрисия Шмидт
Утро предоставляет уникальную возможность максимально эффективно использовать возможности мозга в течение всего дня. То, что вы делаете (или не делаете) в первые 60–90 минут после пробуждения, повлияет на ваше настроение и когнитивные способности в последующие часы. Горькая правда в том, что большинство людей неосознанно саботируют работу своего мозга утром и удивляются, почему они не могут сосредоточиться или постоянно испытывают стресс. Рассмотрим распространённые утренние привычки с точки зрения нейробиологии и найдём лучшие альтернативы для каждой.
1. Проверка телефона первым делом утром
84% населения США проверяют свои телефоны в течение первых 10 минут после пробуждения.
Почему это проблема:
В первые 30–45 минут после пробуждения происходит реакция пробуждения кортизола (резкое повышение уровня). Здоровая реакция пробуждения кортизола подготавливает вас к предстоящему дню, к ожидаемым ежедневным нагрузкам, и когда вы вводите непосредственные стрессовые факторы (контент на телефоне) в этот чувствительный период, вы нарушаете свою естественную систему подготовки.
Что делать вместо этого:
Подождите хотя бы 45 минут, прежде чем проверять свой телефон. Позвольте реакции пробуждения кортизола развиться естественным образом.
2. Пропуск утреннего воздействия света
Большая часть современной жизни проходит в домах, квартирах и офисах. Воздействие естественного дневного света становится всё более редким явлением.
Почему это проблема:
Наибольшее влияние на ваши внутренние биологические часы оказывает воздействие света. Свет, попадающий в глаза, стимулирует область в мозге, называемую супрахиазматическим ядром (СХЯ). Эта область задаёт темп для мозга и тела, используя солнечный свет для установки суточных ритмов.
Когда свет попадает утром в глаза, начинается каскад нейрохимических событий:
- Естественным образом усиливается здоровая реакция пробуждения кортизола.
- Мелатонин («гормон сна») подавляется, что оптимизирует вечернюю выработку мелатонина, улучшая сон следующей ночью.
- Улучшается оборот серотонина в мозге. Воздействие яркого дневного света может способствовать регулированию настроения, делая вас счастливее и спокойнее.
Воздействие света, особенно рано утром, имеет решающее значение для настройки ваших биологических часов. Недостаточное воздействие утреннего света может привести к вялости в течение дня и ухудшить качество сна следующей ночью.
Что делать:
Как можно скорее после пробуждения, в идеале в течение первых 30 минут, подвергайте глаза воздействию естественного солнечного света. Стремитесь к как минимум 10 минутам пребывания на солнце или 15–20 минутам в пасмурные дни.
Если вы не можете выйти на улицу рано или встаёте в темноте, яркое комнатное освещение может помочь. Стандартные комнатные лампы недостаточно яркие, поэтому подумайте о приобретении лампы солнечного света (яркостью не менее 10 000 люкс). Но не используйте её вечером, так как это может нарушить сон!
Окончание следует…
Источник: https://medium.com/write-a-catalyst/as-a-neuroscientist-i-quit-these-5-morning-habits-that-destroy-your-brain-3efe1f410226
Утренние Привычки, Которые Разрушают Ваш Мозг. Начало
Автор оригинала: нейробиолог Патрисия Шмидт
Утро предоставляет уникальную возможность максимально эффективно использовать возможности мозга в течение всего дня. То, что вы делаете (или не делаете) в первые 60–90 минут после пробуждения, повлияет на ваше настроение и когнитивные способности в последующие часы. Горькая правда в том, что большинство людей неосознанно саботируют работу своего мозга утром и удивляются, почему они не могут сосредоточиться или постоянно испытывают стресс. Рассмотрим распространённые утренние привычки с точки зрения нейробиологии и найдём лучшие альтернативы для каждой.
1. Проверка телефона первым делом утром
84% населения США проверяют свои телефоны в течение первых 10 минут после пробуждения.
Почему это проблема:
В первые 30–45 минут после пробуждения происходит реакция пробуждения кортизола (резкое повышение уровня). Здоровая реакция пробуждения кортизола подготавливает вас к предстоящему дню, к ожидаемым ежедневным нагрузкам, и когда вы вводите непосредственные стрессовые факторы (контент на телефоне) в этот чувствительный период, вы нарушаете свою естественную систему подготовки.
Что делать вместо этого:
Подождите хотя бы 45 минут, прежде чем проверять свой телефон. Позвольте реакции пробуждения кортизола развиться естественным образом.
2. Пропуск утреннего воздействия света
Большая часть современной жизни проходит в домах, квартирах и офисах. Воздействие естественного дневного света становится всё более редким явлением.
Почему это проблема:
Наибольшее влияние на ваши внутренние биологические часы оказывает воздействие света. Свет, попадающий в глаза, стимулирует область в мозге, называемую супрахиазматическим ядром (СХЯ). Эта область задаёт темп для мозга и тела, используя солнечный свет для установки суточных ритмов.
Когда свет попадает утром в глаза, начинается каскад нейрохимических событий:
- Естественным образом усиливается здоровая реакция пробуждения кортизола.
- Мелатонин («гормон сна») подавляется, что оптимизирует вечернюю выработку мелатонина, улучшая сон следующей ночью.
- Улучшается оборот серотонина в мозге. Воздействие яркого дневного света может способствовать регулированию настроения, делая вас счастливее и спокойнее.
Воздействие света, особенно рано утром, имеет решающее значение для настройки ваших биологических часов. Недостаточное воздействие утреннего света может привести к вялости в течение дня и ухудшить качество сна следующей ночью.
Что делать:
Как можно скорее после пробуждения, в идеале в течение первых 30 минут, подвергайте глаза воздействию естественного солнечного света. Стремитесь к как минимум 10 минутам пребывания на солнце или 15–20 минутам в пасмурные дни.
Если вы не можете выйти на улицу рано или встаёте в темноте, яркое комнатное освещение может помочь. Стандартные комнатные лампы недостаточно яркие, поэтому подумайте о приобретении лампы солнечного света (яркостью не менее 10 000 люкс). Но не используйте её вечером, так как это может нарушить сон!
Окончание следует…
Источник: https://medium.com/write-a-catalyst/as-a-neuroscientist-i-quit-these-5-morning-habits-that-destroy-your-brain-3efe1f410226
👍22
День 2607. #Здоровье
Утренние Привычки, Которые Разрушают Ваш Мозг. Окончание
Начало
3. Немедленное погружение в сложную работу, требующую глубокой концентрации
Некоторые люди просыпаются и сразу же начинают работу, требующую глубокой концентрации, чтобы использовать утреннее спокойствие для продуктивности.
Почему это проблема:
Вы просыпаетесь в состоянии, называемом инерцией сна, когда мышление и принятие решений нарушены. Рано утром вы находитесь в расслабленном состоянии ума, которое может быть полезно для творческой работы, но не для глубокой концентрации. Мозг просыпается постепенно, и необходимо, чтобы активизировалась реакция пробуждения кортизола (см. п.1), прежде чем вы сможете выполнять сложную работу.
Что делать вместо этого:
Позвольте мозгу и телу проснуться и поддержите здоровую реакцию пробуждения кортизола с помощью воздействия света, избегания новостей и некоторой физической активности.
4. Сладкий завтрак
Сладкий завтрак очень распространённое явление.
Почему это проблема:
Это приводит к резкому скачку уровня глюкозы в крови, за которым следует его значительное падение через несколько часов. Такая нестабильность влияет на мозг, поскольку он использует глюкозу в качестве топлива.
Что делать вместо этого:
Сосредоточьтесь на белке. Богатый белком завтрак (25–35 граммов белка) поддерживает когнитивные функции, чувство сытости и обеспечивает энергией на протяжении всего дня. То есть не только улучшает работу мозга, но и регулирует аппетит.
5. Недостаток жидкости
Многие люди не знают, что после пробуждения они испытывают лёгкое обезвоживание. Организм постоянно теряет жидкость, и после многих часов без питья утром возникает ее дефицит.
Почему это проблема:
Мозг и тело в основном состоят из воды, и для нормального функционирования им необходима достаточная гидратация. Необходимо восполнять запасы жидкости утром, поскольку даже лёгкое обезвоживание влияет на когнитивные функции и настроение.
Что делать:
Пейте воду сразу после пробуждения. Достаточно 250–350 мл. Держите бутылку или стакан с водой на прикроватной тумбочке, чтобы они были под рукой, когда вы проснётесь.
Итого
Эти 5 привычек могут показаться незначительными, но их влияние накапливается. Ваша утренняя рутина создаёт условия либо для успеха, либо для провального дня. То, что вы делаете в первые 60–90 минут после пробуждения, влияет на вашу когнитивную работоспособность, настроение, энергию и концентрацию внимания в течение всего дня, и даже на качество сна следующей ночью.
Источник: https://medium.com/write-a-catalyst/as-a-neuroscientist-i-quit-these-5-morning-habits-that-destroy-your-brain-3efe1f410226
Утренние Привычки, Которые Разрушают Ваш Мозг. Окончание
Начало
3. Немедленное погружение в сложную работу, требующую глубокой концентрации
Некоторые люди просыпаются и сразу же начинают работу, требующую глубокой концентрации, чтобы использовать утреннее спокойствие для продуктивности.
Почему это проблема:
Вы просыпаетесь в состоянии, называемом инерцией сна, когда мышление и принятие решений нарушены. Рано утром вы находитесь в расслабленном состоянии ума, которое может быть полезно для творческой работы, но не для глубокой концентрации. Мозг просыпается постепенно, и необходимо, чтобы активизировалась реакция пробуждения кортизола (см. п.1), прежде чем вы сможете выполнять сложную работу.
Что делать вместо этого:
Позвольте мозгу и телу проснуться и поддержите здоровую реакцию пробуждения кортизола с помощью воздействия света, избегания новостей и некоторой физической активности.
4. Сладкий завтрак
Сладкий завтрак очень распространённое явление.
Почему это проблема:
Это приводит к резкому скачку уровня глюкозы в крови, за которым следует его значительное падение через несколько часов. Такая нестабильность влияет на мозг, поскольку он использует глюкозу в качестве топлива.
Что делать вместо этого:
Сосредоточьтесь на белке. Богатый белком завтрак (25–35 граммов белка) поддерживает когнитивные функции, чувство сытости и обеспечивает энергией на протяжении всего дня. То есть не только улучшает работу мозга, но и регулирует аппетит.
5. Недостаток жидкости
Многие люди не знают, что после пробуждения они испытывают лёгкое обезвоживание. Организм постоянно теряет жидкость, и после многих часов без питья утром возникает ее дефицит.
Почему это проблема:
Мозг и тело в основном состоят из воды, и для нормального функционирования им необходима достаточная гидратация. Необходимо восполнять запасы жидкости утром, поскольку даже лёгкое обезвоживание влияет на когнитивные функции и настроение.
Что делать:
Пейте воду сразу после пробуждения. Достаточно 250–350 мл. Держите бутылку или стакан с водой на прикроватной тумбочке, чтобы они были под рукой, когда вы проснётесь.
Итого
Эти 5 привычек могут показаться незначительными, но их влияние накапливается. Ваша утренняя рутина создаёт условия либо для успеха, либо для провального дня. То, что вы делаете в первые 60–90 минут после пробуждения, влияет на вашу когнитивную работоспособность, настроение, энергию и концентрацию внимания в течение всего дня, и даже на качество сна следующей ночью.
Источник: https://medium.com/write-a-catalyst/as-a-neuroscientist-i-quit-these-5-morning-habits-that-destroy-your-brain-3efe1f410226
👍14
👍11👎2
День 2608. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
27. Инструменты управления проектами
«Опишите ваш опыт использования инструментов управления проектами. Как вы использовали эти инструменты для повышения эффективности проекта и улучшения взаимодействия в команде?»
Хороший ответ
В своих предыдущих проектах на .NET я активно использовал такие инструменты управления проектами, как JIRA для управления задачами и Confluence для документирования. Они сыграли решающую роль в поддержании организованности проекта и повышении эффективности и взаимодействия команды.
Мы использовали JIRA для управления жизненным циклом разработки ПО, от управления бэклогом до планирования и отслеживания спринтов. Создавая пользовательские истории и задачи в JIRA, мы могли назначать работу членам команды, отслеживать прогресс и эффективно управлять спринтами. Интеграция JIRA с другими инструментами позволила нам связывать коммиты и пул-реквесты с задачами, обеспечивая полную отслеживаемость изменений.
Для документирования мы использовали Confluence для ведения централизованного хранилища информации, связанной с проектом, включая архитектурные проекты, протоколы совещаний и руководства по проекту. Это позволило всей команде получать доступ к актуальной информации о проекте, способствуя лучшему пониманию и согласованию целей проекта и технических подходов.
Такие инструменты помогают оптимизировать рабочий процесс, минимизировать ошибки, связанные с ручным вводом данных, улучшают прозрачность проекта и повышают производительность команды, обеспечивая согласованность действий и информированность всех участников.
Часто встречающийся неверный ответ
«Я, как правило, не использую инструменты управления проектами; предпочитаю управлять ими посредством регулярных встреч и прямой коммуникации. Инструменты часто могут усложнять простые проекты и замедлять разработку».
Почему это неверно:
- Недооценка преимуществ инструментов: ответ недооценивает ценность инструментов управления проектами в организации и автоматизации аспектов разработки ПО, особенно в крупных проектах или командах.
- Риск неэффективного управления: полагаясь исключительно на встречи и прямую коммуникацию, можно допустить потерю или некорректную передачу информации. Такие инструменты, как JIRA, предоставляют структурированный и документированный процесс, который помогает предотвратить эти проблемы.
- Проблемы масштабируемости: по мере масштабирования проектов возрастает их сложность, и потребность в формальных инструментах управления проектами становится критической. Без этих инструментов эффективное управление более крупными или сложными проектами становится все более сложным.
Этот часто встречающийся неверный ответ может быть следствием недостаточного знакомства с преимуществами интегрированных сред управления проектами или работы в небольших командах, где неформальные методы могли бы быть достаточными, но не масштабируемы или неэффективны для более крупных структур.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
27. Инструменты управления проектами
«Опишите ваш опыт использования инструментов управления проектами. Как вы использовали эти инструменты для повышения эффективности проекта и улучшения взаимодействия в команде?»
Хороший ответ
В своих предыдущих проектах на .NET я активно использовал такие инструменты управления проектами, как JIRA для управления задачами и Confluence для документирования. Они сыграли решающую роль в поддержании организованности проекта и повышении эффективности и взаимодействия команды.
Мы использовали JIRA для управления жизненным циклом разработки ПО, от управления бэклогом до планирования и отслеживания спринтов. Создавая пользовательские истории и задачи в JIRA, мы могли назначать работу членам команды, отслеживать прогресс и эффективно управлять спринтами. Интеграция JIRA с другими инструментами позволила нам связывать коммиты и пул-реквесты с задачами, обеспечивая полную отслеживаемость изменений.
Для документирования мы использовали Confluence для ведения централизованного хранилища информации, связанной с проектом, включая архитектурные проекты, протоколы совещаний и руководства по проекту. Это позволило всей команде получать доступ к актуальной информации о проекте, способствуя лучшему пониманию и согласованию целей проекта и технических подходов.
Такие инструменты помогают оптимизировать рабочий процесс, минимизировать ошибки, связанные с ручным вводом данных, улучшают прозрачность проекта и повышают производительность команды, обеспечивая согласованность действий и информированность всех участников.
Часто встречающийся неверный ответ
«Я, как правило, не использую инструменты управления проектами; предпочитаю управлять ими посредством регулярных встреч и прямой коммуникации. Инструменты часто могут усложнять простые проекты и замедлять разработку».
Почему это неверно:
- Недооценка преимуществ инструментов: ответ недооценивает ценность инструментов управления проектами в организации и автоматизации аспектов разработки ПО, особенно в крупных проектах или командах.
- Риск неэффективного управления: полагаясь исключительно на встречи и прямую коммуникацию, можно допустить потерю или некорректную передачу информации. Такие инструменты, как JIRA, предоставляют структурированный и документированный процесс, который помогает предотвратить эти проблемы.
- Проблемы масштабируемости: по мере масштабирования проектов возрастает их сложность, и потребность в формальных инструментах управления проектами становится критической. Без этих инструментов эффективное управление более крупными или сложными проектами становится все более сложным.
Этот часто встречающийся неверный ответ может быть следствием недостаточного знакомства с преимуществами интегрированных сред управления проектами или работы в небольших командах, где неформальные методы могли бы быть достаточными, но не масштабируемы или неэффективны для более крупных структур.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍2👎1
День 2609. #ЧтоНовенького #NET11
Обновления ASP.NET Core в Превью 2 .NET 11
1. ASP.NET Core теперь нативно добавляет атрибуты семантического соглашения OpenTelemetry к активности HTTP-сервера, что соответствует спецификации трассировки HTTP-сервера OpenTelemetry. Все необходимые атрибуты теперь включены по умолчанию, что соответствует метаданным, ранее доступным только через библиотеку OpenTelemetry.Instrumentation.AspNetCore.
Для сбора встроенных данных трассировки подпишитесь на источник активности Microsoft.AspNetCore в конфигурации OpenTelemetry:
Дополнительных библиотек инструментирования (например, OpenTelemetry.Instrumentation.AspNetCore) не требуется. Теперь фреймворк напрямую заполняет атрибуты семантических соглашений, такие как http.request.method, url.path, http.response.status_code и server.address, в активности запроса.
Если вы не хотите, чтобы атрибуты OpenTelemetry добавлялись к активности, вы можете отключить это, установив параметр AppContext Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData в true.
2. В Blazor Server-Side Rendering (SSR) теперь поддерживается TempData — механизм хранения данных, сохраняющийся между HTTP-запросами. TempData идеально подходит для таких сценариев, как всплывающие сообщения после отправки формы, передача данных при перенаправлениях (шаблон POST-Redirect-GET) и одноразовые уведомления.
3. Представлен новый шаблон проекта dotnet new webworker, позволяющий приложениям Blazor WebAssembly переносить ресурсоемкие вычисления на Web Worker без блокировки UI-потока, обеспечивая отзывчивость приложений во время ресурсоемких операций:
Шаблон генерирует класс
4. Поддержка OpenAPI 3.2.0 (Ломающее изменение)
Microsoft.AspNetCore.OpenApi теперь поддерживает OpenAPI 3.2.0 через обновлённую зависимость в Microsoft.OpenApi 3.3.1. Это обновление включает ломающие изменения в зависимых библиотеках. Детали в гайде по обновлению Microsoft.OpenApi. Чтобы сгененировать документ OpenAPI 3.2.0, укажите версию при вызове AddOpenApi():
В последующих обновлениях будут использованы новые возможности спецификации 3.2.0, такие как поддержка схем элементов для потоковых событий.
5. Парсер HTTP/1.1 запросов Kestrel был переработан, чтобы избежать генерации исключений при некорректных запросах. В сценариях с высокой интенсивностью некорректного трафика, таких как сканирование портов или неправильно настроенные клиенты, отмечено повышение пропускной способности на 20–40 процентов.
Источники:
- https://www.infoq.com/news/2026/03/dotnet-11-preview-2/
- https://github.com/dotnet/core/blob/main/release-notes/11.0/preview/preview2/aspnetcore.md
Обновления ASP.NET Core в Превью 2 .NET 11
1. ASP.NET Core теперь нативно добавляет атрибуты семантического соглашения OpenTelemetry к активности HTTP-сервера, что соответствует спецификации трассировки HTTP-сервера OpenTelemetry. Все необходимые атрибуты теперь включены по умолчанию, что соответствует метаданным, ранее доступным только через библиотеку OpenTelemetry.Instrumentation.AspNetCore.
Для сбора встроенных данных трассировки подпишитесь на источник активности Microsoft.AspNetCore в конфигурации OpenTelemetry:
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddSource("Microsoft.AspNetCore")
.AddConsoleExporter());
Дополнительных библиотек инструментирования (например, OpenTelemetry.Instrumentation.AspNetCore) не требуется. Теперь фреймворк напрямую заполняет атрибуты семантических соглашений, такие как http.request.method, url.path, http.response.status_code и server.address, в активности запроса.
Если вы не хотите, чтобы атрибуты OpenTelemetry добавлялись к активности, вы можете отключить это, установив параметр AppContext Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData в true.
2. В Blazor Server-Side Rendering (SSR) теперь поддерживается TempData — механизм хранения данных, сохраняющийся между HTTP-запросами. TempData идеально подходит для таких сценариев, как всплывающие сообщения после отправки формы, передача данных при перенаправлениях (шаблон POST-Redirect-GET) и одноразовые уведомления.
3. Представлен новый шаблон проекта dotnet new webworker, позволяющий приложениям Blazor WebAssembly переносить ресурсоемкие вычисления на Web Worker без блокировки UI-потока, обеспечивая отзывчивость приложений во время ресурсоемких операций:
dotnet new webworker -n MyWebWorker
Шаблон генерирует класс
WebWorkerClient с фабрикой для создания экземпляров исполнителей. Методы исполнителя используют [JSExport] и могут быть вызваны из компонентов:await using var worker =
await WebWorkerClient.CreateAsync(JSRuntime);
var result = await worker
.InvokeAsync<string>("MyApp.MyWorker.Greet", ["World"]);
4. Поддержка OpenAPI 3.2.0 (Ломающее изменение)
Microsoft.AspNetCore.OpenApi теперь поддерживает OpenAPI 3.2.0 через обновлённую зависимость в Microsoft.OpenApi 3.3.1. Это обновление включает ломающие изменения в зависимых библиотеках. Детали в гайде по обновлению Microsoft.OpenApi. Чтобы сгененировать документ OpenAPI 3.2.0, укажите версию при вызове AddOpenApi():
builder.Services.AddOpenApi(options =>
{
options.OpenApiVersion =
Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_2;
});
В последующих обновлениях будут использованы новые возможности спецификации 3.2.0, такие как поддержка схем элементов для потоковых событий.
5. Парсер HTTP/1.1 запросов Kestrel был переработан, чтобы избежать генерации исключений при некорректных запросах. В сценариях с высокой интенсивностью некорректного трафика, таких как сканирование портов или неправильно настроенные клиенты, отмечено повышение пропускной способности на 20–40 процентов.
Источники:
- https://www.infoq.com/news/2026/03/dotnet-11-preview-2/
- https://github.com/dotnet/core/blob/main/release-notes/11.0/preview/preview2/aspnetcore.md
👍1
День 2610. #Testing
TUnit – Новый Фреймворк Тестирования в .NET. Начало
xUnit, NUnit и MSTest многие годы хорошо служили командам для модульного, интеграционного и даже приёмочного тестирования. Однако по мере развития .NET с появлением новых версий среды выполнения, AOT-компиляции, требований кроссплатформенности, всё более крупных наборов тестов и более быстрых конвейеров CI/CD ограничения устаревших фреймворков стали более очевидными. TUnit стремится решить многие из этих проблем, или, по крайней мере, заявляет об этом. В этой серии рассмотрим, что может предложить TUnit.
Проблема существующих фреймворков
1. Накладные расходы на рефлексию
xUnit, NUnit и MSTest в значительной степени полагаются на рефлексию для обнаружения тестов, создания экземпляров фикстур и вызова методов тестирования. В больших наборах тестов накладные расходы на рефлексию могут значительно влиять на время выполнения.
Обнаружение тестов на основе рефлексии происходит во время выполнения, заставляя разработчиков ждать, прежде чем тесты начнут выполняться. Это особенно раздражает в конвейерах CI/CD.
2. Асинхронный подход был второстепенным
async/await был добавлен в существующие фреймворки тестирования. В результате иногда получаются неуклюжие утверждения, непоследовательная обработка асинхронных операций и не всегда понятный код.
3. Отсутствие поддержки AOT
Поддержка AOT становится необходимой для облачных приложений и контейнеризированных рабочих нагрузок. Интенсивное использование рефлексии в устаревших фреймворках затрудняет или делает невозможной поддержку AOT.
4. Ограниченный контроль параллелизации
Устаревшие фреймворки предлагают базовую параллелизацию, но контроль над порядком выполнения тестов, управлением зависимостями и распределением ресурсов минимален.
Заявления TUnit
Философия проектирования TUnit основана на скорости, современности, гибкости, простоте и лёгкости внедрения.
Ключевые концепции:
1. Производительность прежде всего — использование генерации кода во время компиляции вместо рефлексии, с параллельным выполнением тестов, включённым по умолчанию.
2. Совместимость с современным .NET — полная поддержка .NET 8 и более поздних версий, нативный AOT, тримминг и новые возможности среды выполнения.
3. Управление и гибкость — рабочие процессы на основе атрибутов и конфигурации, пользовательские источники данных, расширяемое поведение, цепочки зависимостей и тонкое управление планированием.
4. Широкая применимость — подходит не только для модульных тестов, но и для интеграционных, приёмочных и даже сквозных сценариев (включая поддержку таких библиотек, как Playwright).
5. Прочие отличительные особенности — асинхронные утверждения, Fluent API, различные источники данных (аргументы, методы, классы, матрицы), диагностика во время компиляции, скорость выполнения на 30% выше xUnit.
Как видно из этого списка, TUnit поддерживает множество функций, которых нет у других фреймворков тестирования и представляет ряд современных возможностей, которые значительно улучшают опыт разработчиков и проектирование тестов.
Далее подробнее рассмотрим функции, которые предлагает TUnit.
Продолжение следует…
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
TUnit – Новый Фреймворк Тестирования в .NET. Начало
xUnit, NUnit и MSTest многие годы хорошо служили командам для модульного, интеграционного и даже приёмочного тестирования. Однако по мере развития .NET с появлением новых версий среды выполнения, AOT-компиляции, требований кроссплатформенности, всё более крупных наборов тестов и более быстрых конвейеров CI/CD ограничения устаревших фреймворков стали более очевидными. TUnit стремится решить многие из этих проблем, или, по крайней мере, заявляет об этом. В этой серии рассмотрим, что может предложить TUnit.
Проблема существующих фреймворков
1. Накладные расходы на рефлексию
xUnit, NUnit и MSTest в значительной степени полагаются на рефлексию для обнаружения тестов, создания экземпляров фикстур и вызова методов тестирования. В больших наборах тестов накладные расходы на рефлексию могут значительно влиять на время выполнения.
Обнаружение тестов на основе рефлексии происходит во время выполнения, заставляя разработчиков ждать, прежде чем тесты начнут выполняться. Это особенно раздражает в конвейерах CI/CD.
2. Асинхронный подход был второстепенным
async/await был добавлен в существующие фреймворки тестирования. В результате иногда получаются неуклюжие утверждения, непоследовательная обработка асинхронных операций и не всегда понятный код.
3. Отсутствие поддержки AOT
Поддержка AOT становится необходимой для облачных приложений и контейнеризированных рабочих нагрузок. Интенсивное использование рефлексии в устаревших фреймворках затрудняет или делает невозможной поддержку AOT.
4. Ограниченный контроль параллелизации
Устаревшие фреймворки предлагают базовую параллелизацию, но контроль над порядком выполнения тестов, управлением зависимостями и распределением ресурсов минимален.
Заявления TUnit
Философия проектирования TUnit основана на скорости, современности, гибкости, простоте и лёгкости внедрения.
Ключевые концепции:
1. Производительность прежде всего — использование генерации кода во время компиляции вместо рефлексии, с параллельным выполнением тестов, включённым по умолчанию.
2. Совместимость с современным .NET — полная поддержка .NET 8 и более поздних версий, нативный AOT, тримминг и новые возможности среды выполнения.
3. Управление и гибкость — рабочие процессы на основе атрибутов и конфигурации, пользовательские источники данных, расширяемое поведение, цепочки зависимостей и тонкое управление планированием.
4. Широкая применимость — подходит не только для модульных тестов, но и для интеграционных, приёмочных и даже сквозных сценариев (включая поддержку таких библиотек, как Playwright).
5. Прочие отличительные особенности — асинхронные утверждения, Fluent API, различные источники данных (аргументы, методы, классы, матрицы), диагностика во время компиляции, скорость выполнения на 30% выше xUnit.
Как видно из этого списка, TUnit поддерживает множество функций, которых нет у других фреймворков тестирования и представляет ряд современных возможностей, которые значительно улучшают опыт разработчиков и проектирование тестов.
Далее подробнее рассмотрим функции, которые предлагает TUnit.
Продолжение следует…
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
👍10
День 2611. #Testing
TUnit – Новый Фреймворк Тестирования в .NET. Продолжение
Начало
Ключевые особенности TUnit
1. Нативная поддержка асинхронности
Утверждения ожидаются, обработчики инициализации асинхронны, и весь жизненный цикл теста учитывает, что современная .NET является асинхронной платформой.
xUnit:
TUnit:
Каждое утверждение ожидается. Это позволяет TUnit:
- Точно захватывать асинхронный контекст,
- Связывать утверждения с fluent-синтаксисом,
- Обрабатывать асинхронные утверждения без специального или пользовательского синтаксиса,
- Предоставлять более понятные и информативные сообщения об ошибках с полным контекстом выполнения.
2. Генерация кода и проверка во время компиляции
TUnit использует генераторы кода C# для обнаружения и компиляции тестов во время сборки, полностью исключая необходимость рефлексии во время выполнения. Такой подход позволяет выявлять многие ошибки во время компиляции, а не во время выполнения, и значительно сокращает время запуска тестов. Это также улучшает общее качество отладки, поскольку сгенерированный код обеспечивает более понятные пути выполнения и более предсказуемое поведение по сравнению с традиционными фреймворками, основанными на рефлексии.
3. Модель параллелизации
Справедливости ради, стоит заметить, что это не новая концепция, существующие тестовые фреймворки также могут выполнять тесты параллельно.
Продолжение следует…
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
TUnit – Новый Фреймворк Тестирования в .NET. Продолжение
Начало
Ключевые особенности TUnit
1. Нативная поддержка асинхронности
Утверждения ожидаются, обработчики инициализации асинхронны, и весь жизненный цикл теста учитывает, что современная .NET является асинхронной платформой.
xUnit:
[Fact]
public async Task TestAsync()
{
var result = await GetDataAsync();
Assert.Equal(5, result.Items.Count);
}
TUnit:
[Test]
public async Task TestAsync()
{
var result = await GetDataAsync();
await Assert.That(result.Items)
.Count()
.IsEqualTo(5);
}
Каждое утверждение ожидается. Это позволяет TUnit:
- Точно захватывать асинхронный контекст,
- Связывать утверждения с fluent-синтаксисом,
- Обрабатывать асинхронные утверждения без специального или пользовательского синтаксиса,
- Предоставлять более понятные и информативные сообщения об ошибках с полным контекстом выполнения.
2. Генерация кода и проверка во время компиляции
TUnit использует генераторы кода C# для обнаружения и компиляции тестов во время сборки, полностью исключая необходимость рефлексии во время выполнения. Такой подход позволяет выявлять многие ошибки во время компиляции, а не во время выполнения, и значительно сокращает время запуска тестов. Это также улучшает общее качество отладки, поскольку сгенерированный код обеспечивает более понятные пути выполнения и более предсказуемое поведение по сравнению с традиционными фреймворками, основанными на рефлексии.
[Test]
[Arguments(1, 2, 3)]
[Arguments(4, 5, 9)]
public async Task Add_WithVariousInputs(
int a, int b, int expected)
{
var result = Add(a, b);
await Assert.That(result).IsEqualTo(expected);
}
// Упрощённый сгенерированный код:
// [CompilerGenerated]
// public async Task Add_WithVariousInputs_1()
// {
// var result = Add(1, 2);
// await Assert.That(result).IsEqualTo(3);
// }
// [CompilerGenerated]
// public async Task Add_WithVariousInputs_2() { … }
3. Модель параллелизации
// Тесты по умолчанию распараллеливаются
[Test]
[Parallel] // Явно распараллелить
public async Task Test1() { }
// Последовательное выполнение при необходимости
[Test]
[Sequential]
public async Task Test2() { }
// Общие ресурсы для параллельных тестов [ClassDataSource<DatabaseFixture>(Shared = SharedType.PerClass)]
public class DatabaseTests
{
[Test]
public async Task Test1(DatabaseFixture db) { }
[Test]
public async Task Test2(DatabaseFixture db) { }
}
Справедливости ради, стоит заметить, что это не новая концепция, существующие тестовые фреймворки также могут выполнять тесты параллельно.
Продолжение следует…
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
👍10
День 2612. #Testing
TUnit – Новый Фреймворк Тестирования в .NET. Продолжение
Начало
Особенности 1-3
4. Передача данных в тесты
1) Аргументы уровня компиляции
2) Метод-источник (динамические данные)
3) Матричные тесты (комбинаторные)
4) Класс-источник
Как видите, TUnit поддерживает практически все функции, предлагаемые существующими фреймворками, часто усовершенствованные и модернизированные.
5. Жизненный цикл тестов и фикстур
Окончание следует…
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
TUnit – Новый Фреймворк Тестирования в .NET. Продолжение
Начало
Особенности 1-3
4. Передача данных в тесты
1) Аргументы уровня компиляции
[Test]
[Arguments(1, 2, 3)]
[Arguments(4, 5, 9)]
public async Task Addition(
int a, int b, int expected)
{
await Assert.That(a + b).IsEqualTo(expected);
}
2) Метод-источник (динамические данные)
[Test]
[MethodDataSource(nameof(TestCases))]
public async Task WithDynamicData(
int value, string expected)
{
var result = ProcessValue(value);
await Assert.That(result).IsEqualTo(expected);
}
public static
IEnumerable<(int, string)> TestCases()
{
yield return (1, "one");
yield return (2, "two");
yield return (3, "three");
}
3) Матричные тесты (комбинаторные)
[Test]
public async Task MatrixCombinations(
[Matrix(1, 2, 3)] int x,
[Matrix("a", "b")] string y,
[Matrix(true, false)] bool z)
{
// 3 × 2 × 2 = 12 комбинаций
await Assert.That(Validate(x, y, z)).IsTrue();
}
4) Класс-источник
[ClassDataSource<UserFixture>(Shared = SharedType.PerClass)]
public class UserServiceTests
{
[Test]
public async Task CreateUser(UserFixture fixture)
{
var user = await
fixture.Service.CreateAsync("John");
await Assert.That(user.Name).IsEqualTo("John");
}
}
public class UserFixture
{
public IUserService Service { get; }
= new UserService();
}
Как видите, TUnit поддерживает практически все функции, предлагаемые существующими фреймворками, часто усовершенствованные и модернизированные.
5. Жизненный цикл тестов и фикстур
public class TestLifecycleExample
{
private DatabaseConnection _conn;
// Перед каждым тестом
[Before(Test)]
public async Task SetupTest()
{
_conn = new DatabaseConnection();
await _conn.OpenAsync();
}
[Test]
public async Task DatabaseQuery()
{
var result =
await _conn.QueryAsync("SELECT * FROM Users");
await Assert.That(result).IsNotNull();
}
// После каждого теста
[After(Test)]
public async Task CleanupTest()
{
await _conn.CloseAsync();
_conn?.Dispose();
}
// Однажды на тестовый класс
[Before(Class)]
public static async Task SetupClass()
{
// Инициализация общих ресурсов
}
[After(Class)]
public static async Task CleanupClass()
{
// Очистка общих ресурсов
}
// Однажды на сборку
[Before(Assembly)]
public static async Task SetupAssembly()
{
// Инициализация данных уровня приложения
}
}
Окончание следует…
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
👍6
День 2613. #Testing
TUnit – Новый Фреймворк Тестирования в .NET. Окончание
Начало
Особенности 1-3
Особенности 4-5
6. Нативный Fluent API
TUnit поддерживает цепочку fluent утверждений «из коробки», без необходимости установки каких-либо дополнительных пакетов или настройки.
7. Нативная поддержка внедрения зависимостей
Для использования внедрения зависимостей не требуется сложная настройка, TUnit поддерживает его «из коробки».
Итого
Использовать ли TUnit?
TUnit - шаг вперёд в тестировании .NET. Существующие фреймворки остаются надёжными, стабильными и зрелыми, но они отражают проектные решения, принятые задолго до AOT, генераторов кода или современных ожиданий производительности.
TUnit стоит рассмотреть для новых проектов или оптимизации критически важных для производительности тестовых наборов, когда существующий тестовый набор становится узким местом в производительности или когда необходима поддержка AOT. Для устоявшихся кодовых баз со значительными инвестициями в тестирование существующий фреймворк, скорее всего, продолжит работать нормально, но вы всё равно можете попробовать TUnit и лично ощутить разницу.
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
TUnit – Новый Фреймворк Тестирования в .NET. Окончание
Начало
Особенности 1-3
Особенности 4-5
6. Нативный Fluent API
TUnit поддерживает цепочку fluent утверждений «из коробки», без необходимости установки каких-либо дополнительных пакетов или настройки.
[Test]
public async Task FluentAssertions()
{
var user = new { Name = "Alice",
Age = 30, Email = "alice@example.com" };
// Цепочка утверждений
await Assert.That(user.Name)
.IsNotNull()
.IsNotEmpty()
.StartsWith("Al");
// 'And' для логической группировки
await Assert.That(user.Age)
.IsGreaterThan(18)
.And.IsLessThan(65);
// Несколько утверждений в области
// (сообщение сразу о всех неудачах, а не о первой)
using var scope = Assert.Multiple();
await Assert.That(user.Name).IsEqualTo("Alice");
await Assert.That(user.Age).IsEqualTo(30);
await Assert.That(user.Email).IsNotNull();
}
7. Нативная поддержка внедрения зависимостей
Для использования внедрения зависимостей не требуется сложная настройка, TUnit поддерживает его «из коробки».
[Test]
public async Task WithDependencyInjection(
IUserService userService, ILogger logger)
{
var user = await userService.GetUserAsync(1);
logger.LogInformation($"Loaded user: {user.Name}");
await Assert.That(user).IsNotNull();
}
// Конфигурация через ServiceCollection
public void ConfigureServices(
IServiceCollection services)
{
services.AddScoped<IUserService, UserService>();
services.AddLogging();
}
Итого
Использовать ли TUnit?
TUnit - шаг вперёд в тестировании .NET. Существующие фреймворки остаются надёжными, стабильными и зрелыми, но они отражают проектные решения, принятые задолго до AOT, генераторов кода или современных ожиданий производительности.
TUnit стоит рассмотреть для новых проектов или оптимизации критически важных для производительности тестовых наборов, когда существующий тестовый набор становится узким местом в производительности или когда необходима поддержка AOT. Для устоявшихся кодовых баз со значительными инвестициями в тестирование существующий фреймворк, скорее всего, продолжит работать нормально, но вы всё равно можете попробовать TUnit и лично ощутить разницу.
Источник: https://trailheadtechnology.com/tunit-the-new-sheriff-in-town-for-net-testing/
👍11
День 2514. #Карьера #Оффтоп
Миф о «Хорошем Программисте»
Новичкам кажется, что быть хорошим программистом означает быть быстрым. Быстро печатать. Быстро решать задачи. Быстро отвечать. Но по мере накопления опыта оказывается, что все громко кричат о скорости, но молчат о глубине понимания. А глубина понимания — редкость.
Где-то в ИТ мы перепутали производительность с пониманием. Если кто-то решает 300 задач на структуры данных и алгоритмы, мы называем его сильным программистом. Если кто-то знает пять языков, мы называем его талантливым. Если кто-то может мгновенно объяснить временную сложность, мы называем его умным.
Но вот неприятная правда. Вы можете запоминать шаблоны, не понимая систем. А системы — это то, что действительно имеет значение. Проблема никогда не в синтаксисе. Никогда не в способности найти пропущенную точку с запятой. Проблема всегда в понимании:
- Почему это ломается?
- Почему эта логика ошибочна?
- Почему я не подумал об этом крайнем случае?
- Почему эта архитектура кажется неправильной?
Программирование перестаёт быть просто написанием строк кода. Оно становится проблемой ясности мышления. А ясность мышления — это сложно.
В интернете программирование выглядит как соревнование. Аккаунты на GitHub полные зелёных квадратиков. Люди хвастаются сериями успехов: «Решил 500 задач», «Освоил 8 языков». Но никто не пишет: «Я переделывал свою логику 6 раз, потому что она не масштабировалась». Никто не хвастается отладкой в течение четырёх часов подряд. Никто не радуется удалению 200 строк ненужного кода.
И всё же именно здесь происходит рост. Быть «хорошим программистом» — это не значит решать задачи быстрее всех. Это значит сохранять спокойствие, когда ничего не работает. Это значит разбивать большую, некрасивую проблему на более мелкие, понятные части. Это значит проектировать, прежде чем писать. Это значит понимать «почему» настолько глубоко, что даже если язык меняется, ваше мышление остаётся неизменным. Языки развиваются. Фреймворки меняются. Синтаксис обновляется. Ясное мышление остаётся.
То, чем по-настоящему стоит гордиться
Создание чего-то с нуля, что действительно работает. Не идеально. Не красиво. Но логично. А затем улучшение этого. Снова. И снова. И снова. Возможно, вопрос был задан неправильно. Не: «Хорошо ли я разбираюсь в программировании?», а: «Могу ли я создавать? Могу ли я мыслить? Могу ли я упорствовать, когда всё идёт наперекосяк?»
Потому что программирование — это не представление. Это архитектура мышления. А для этого требуется не только скорость. Требуется терпение.
Источник: https://medium.com/@shriya73spark2008/the-myth-of-being-good-at-coding-a9d15cbd689c
Миф о «Хорошем Программисте»
Новичкам кажется, что быть хорошим программистом означает быть быстрым. Быстро печатать. Быстро решать задачи. Быстро отвечать. Но по мере накопления опыта оказывается, что все громко кричат о скорости, но молчат о глубине понимания. А глубина понимания — редкость.
Где-то в ИТ мы перепутали производительность с пониманием. Если кто-то решает 300 задач на структуры данных и алгоритмы, мы называем его сильным программистом. Если кто-то знает пять языков, мы называем его талантливым. Если кто-то может мгновенно объяснить временную сложность, мы называем его умным.
Но вот неприятная правда. Вы можете запоминать шаблоны, не понимая систем. А системы — это то, что действительно имеет значение. Проблема никогда не в синтаксисе. Никогда не в способности найти пропущенную точку с запятой. Проблема всегда в понимании:
- Почему это ломается?
- Почему эта логика ошибочна?
- Почему я не подумал об этом крайнем случае?
- Почему эта архитектура кажется неправильной?
Программирование перестаёт быть просто написанием строк кода. Оно становится проблемой ясности мышления. А ясность мышления — это сложно.
В интернете программирование выглядит как соревнование. Аккаунты на GitHub полные зелёных квадратиков. Люди хвастаются сериями успехов: «Решил 500 задач», «Освоил 8 языков». Но никто не пишет: «Я переделывал свою логику 6 раз, потому что она не масштабировалась». Никто не хвастается отладкой в течение четырёх часов подряд. Никто не радуется удалению 200 строк ненужного кода.
И всё же именно здесь происходит рост. Быть «хорошим программистом» — это не значит решать задачи быстрее всех. Это значит сохранять спокойствие, когда ничего не работает. Это значит разбивать большую, некрасивую проблему на более мелкие, понятные части. Это значит проектировать, прежде чем писать. Это значит понимать «почему» настолько глубоко, что даже если язык меняется, ваше мышление остаётся неизменным. Языки развиваются. Фреймворки меняются. Синтаксис обновляется. Ясное мышление остаётся.
То, чем по-настоящему стоит гордиться
Создание чего-то с нуля, что действительно работает. Не идеально. Не красиво. Но логично. А затем улучшение этого. Снова. И снова. И снова. Возможно, вопрос был задан неправильно. Не: «Хорошо ли я разбираюсь в программировании?», а: «Могу ли я создавать? Могу ли я мыслить? Могу ли я упорствовать, когда всё идёт наперекосяк?»
Потому что программирование — это не представление. Это архитектура мышления. А для этого требуется не только скорость. Требуется терпение.
Источник: https://medium.com/@shriya73spark2008/the-myth-of-being-good-at-coding-a9d15cbd689c
👍44
День 2615. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
28. Методы оценки
«Можете ли вы описать методы оценки, которые вы использовали в своих проектах, и объяснить, как они помогли вам обеспечить выполнение проектов в установленные сроки?»
Хороший ответ
В моём опыте управления проектами .NET я использовал комбинацию методов оценки для обеспечения точного прогнозирования и эффективного управления проектом. Среди них экспертная оценка (Expert Judgment), покер планирования (Planning Poker) и анализ точек использования (Case Point Analysis).
1. Экспертная оценка предполагает консультации с опытными членами команды для получения оценок на основе их прошлого опыта. Например, при работе над веб-сервисом, включающим ASP.NET Core и Entity Framework Core, я обсуждал задачи со старшими разработчиками, имеющими аналогичный опыт работы над проектами, чтобы получить реалистичное представление о трудозатратах и сроках.
2. Покер планирования - метод оценки в Agile, использующий консенсус для оценки задач. Каждый член команды предоставляет оценку, используя пронумерованные карточки, и затем следуют обсуждения, пока команда не достигнет консенсуса. Этот метод особенно полезен для вовлечения всей команды в процесс оценки, что повышает вовлечённость и точность оценок. Суть метода:
- Каждый разработчик получает карточки с номерами, представляющими собой стори-пойнты.
- Владелец продукта описывает функцию.
- Разработчики выбирают карточку, представляющую их оценку, не раскрывая её.
- Все карточки раскрываются одновременно, и разногласия обсуждаются до достижения консенсуса.
3. Анализ вариантов использования - адаптирован для оценки трудозатрат, необходимых для пользовательских историй, включающих взаимодействие с пользователями. Он учитывает сложность вариантов использования и корректирует её с учётом технических и организационных факторов.
Суть метода в том, что каждый вариант использования классифицируется как простой, средний или сложный, а затем присваивается вес на основе этих категорий. Это особенно эффективно для проектов с чёткими функциональными требованиями, таких как веб-сервис с несколькими конечными точками.
Комбинация этих методов позволяет предоставить более надёжные оценки, учитывающие неопределённости и позволяющие лучше планировать и управлять рисками. Такой подход помогает гарантировать, что проекты будут реализованы в срок и в рамках заданного объёма, даже при возникновении непредвиденных сложностей.
Часто встречающийся плохой ответ
«Я примерно по опыту оцениваю время, которое потребуется на написание кода и добавляю к нему некоторый процент на непредвиденные проблемы. Обычно этого достаточно.»
Почему это неправильно
- Чрезмерное упрощение: Этот подход чрезмерно упрощён и не учитывает детальные аспекты выполняемых задач. Оценка — это не просто завышение необходимого времени, а понимание сложности и связанных с этим рисков.
- Неточность и неэффективность: Простое увеличение предполагаемого времени кодирования неточно отражает реальные необходимые усилия, особенно для задач, сложность или трудозатраты которых могут быть нелинейными. Этот метод может привести к неэффективному распределению ресурсов и либо к переоценке, либо к недооценке фактического необходимого времени.
- Отсутствие вовлечения заинтересованных сторон: Этот метод не предполагает вовлечения других членов команды и заинтересованных сторон, которые могут предложить ценные идеи для процесса оценки. Он не использует коллективный опыт и знания команды, что может привести к нарушению сроков проекта.
Эта ошибка часто возникает из-за недостатка опыта работы с формальными методами оценки или из-за работы в условиях, где детальное планирование не было приоритетом. Это подчёркивает необходимость структурированного подхода к оценке в управлении проектами разработки ПО, особенно для крупных или сложных проектов.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
28. Методы оценки
«Можете ли вы описать методы оценки, которые вы использовали в своих проектах, и объяснить, как они помогли вам обеспечить выполнение проектов в установленные сроки?»
Хороший ответ
В моём опыте управления проектами .NET я использовал комбинацию методов оценки для обеспечения точного прогнозирования и эффективного управления проектом. Среди них экспертная оценка (Expert Judgment), покер планирования (Planning Poker) и анализ точек использования (Case Point Analysis).
1. Экспертная оценка предполагает консультации с опытными членами команды для получения оценок на основе их прошлого опыта. Например, при работе над веб-сервисом, включающим ASP.NET Core и Entity Framework Core, я обсуждал задачи со старшими разработчиками, имеющими аналогичный опыт работы над проектами, чтобы получить реалистичное представление о трудозатратах и сроках.
2. Покер планирования - метод оценки в Agile, использующий консенсус для оценки задач. Каждый член команды предоставляет оценку, используя пронумерованные карточки, и затем следуют обсуждения, пока команда не достигнет консенсуса. Этот метод особенно полезен для вовлечения всей команды в процесс оценки, что повышает вовлечённость и точность оценок. Суть метода:
- Каждый разработчик получает карточки с номерами, представляющими собой стори-пойнты.
- Владелец продукта описывает функцию.
- Разработчики выбирают карточку, представляющую их оценку, не раскрывая её.
- Все карточки раскрываются одновременно, и разногласия обсуждаются до достижения консенсуса.
3. Анализ вариантов использования - адаптирован для оценки трудозатрат, необходимых для пользовательских историй, включающих взаимодействие с пользователями. Он учитывает сложность вариантов использования и корректирует её с учётом технических и организационных факторов.
Суть метода в том, что каждый вариант использования классифицируется как простой, средний или сложный, а затем присваивается вес на основе этих категорий. Это особенно эффективно для проектов с чёткими функциональными требованиями, таких как веб-сервис с несколькими конечными точками.
Комбинация этих методов позволяет предоставить более надёжные оценки, учитывающие неопределённости и позволяющие лучше планировать и управлять рисками. Такой подход помогает гарантировать, что проекты будут реализованы в срок и в рамках заданного объёма, даже при возникновении непредвиденных сложностей.
Часто встречающийся плохой ответ
«Я примерно по опыту оцениваю время, которое потребуется на написание кода и добавляю к нему некоторый процент на непредвиденные проблемы. Обычно этого достаточно.»
Почему это неправильно
- Чрезмерное упрощение: Этот подход чрезмерно упрощён и не учитывает детальные аспекты выполняемых задач. Оценка — это не просто завышение необходимого времени, а понимание сложности и связанных с этим рисков.
- Неточность и неэффективность: Простое увеличение предполагаемого времени кодирования неточно отражает реальные необходимые усилия, особенно для задач, сложность или трудозатраты которых могут быть нелинейными. Этот метод может привести к неэффективному распределению ресурсов и либо к переоценке, либо к недооценке фактического необходимого времени.
- Отсутствие вовлечения заинтересованных сторон: Этот метод не предполагает вовлечения других членов команды и заинтересованных сторон, которые могут предложить ценные идеи для процесса оценки. Он не использует коллективный опыт и знания команды, что может привести к нарушению сроков проекта.
Эта ошибка часто возникает из-за недостатка опыта работы с формальными методами оценки или из-за работы в условиях, где детальное планирование не было приоритетом. Это подчёркивает необходимость структурированного подхода к оценке в управлении проектами разработки ПО, особенно для крупных или сложных проектов.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍3
День 2616. #SQLServer
SQL Server Незаметно Переименовывает Пользователя
Автор оригинала: Bart Wullems
Учитывая кучу существующих ИИ-помощников, можно было бы ожидать, что мы больше не будем тратить время на глупые проблемы. К сожалению, до этого ещё далеко. Сегодня я потерял немало времени из-за поведения SQL Server, которое кажется очевидным, если вы об этом знаете, а если не знаете —ужасно раздражает.
У меня был скрипт, который должен был быть идемпотентным: создать пользователя БД, если его не существует, или обновить его, если существует. Стандартная процедура. Вот упрощённая версия:
Выглядит нормально. Запустил один раз — работает. Запустил второй раз, и SQL Server выдаёт ошибку, что не может найти пользователя
Что происходит на самом деле?
Когда вы запускаете
Таким образом, после первого запуска пользователя
Это одно из тех явлений, которое становится понятным, как только вы разберётесь в модели данных, но никаким образом не сообщает вам, что так происходит.
Решение
Явно укажите SQL Server сохранить имя пользователя как есть, добавив
Добавление
Почему SQL Server так делает?
SQL Server различает логины (субъекты уровня сервера) и пользователей (субъекты уровня БД). Когда вы связываете пользователя с логином с помощью команды
Источник: https://bartwullems.blogspot.com/2026/03/sql-server-silently-renames-your-user.html
SQL Server Незаметно Переименовывает Пользователя
Автор оригинала: Bart Wullems
Учитывая кучу существующих ИИ-помощников, можно было бы ожидать, что мы больше не будем тратить время на глупые проблемы. К сожалению, до этого ещё далеко. Сегодня я потерял немало времени из-за поведения SQL Server, которое кажется очевидным, если вы об этом знаете, а если не знаете —ужасно раздражает.
У меня был скрипт, который должен был быть идемпотентным: создать пользователя БД, если его не существует, или обновить его, если существует. Стандартная процедура. Вот упрощённая версия:
USE [ONT_SampleDB];
GO
IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'usr_DB_reader')
BEGIN
ALTER USER [usr_DB_reader] WITH LOGIN = [lg_DB_dev_reader];
END
ELSE
BEGIN
CREATE USER [usr_DB_reader] FOR LOGIN [lg_DB_dev_reader];
END
GO
ALTER ROLE [db_datareader] ADD MEMBER [usr_DB_reader];
GO
Выглядит нормально. Запустил один раз — работает. Запустил второй раз, и SQL Server выдаёт ошибку, что не может найти пользователя
usr_DB_reader. Пользователя, которого мы только что создали. В той же базе данных. Этим же скриптом.Что происходит на самом деле?
Когда вы запускаете
ALTER USER […] WITH LOGIN = […], SQL Server переименовывает пользователя в соответствии с логином — по умолчанию, без предупреждений.Таким образом, после первого запуска пользователя
usr_DB_reader больше не существует. Он переименован в lg_DB_dev_reader, чтобы соответствовать логину. При втором запуске проверка IF EXISTS ищет usr_DB_reader, ничего не находит и переходит в ELSE — где CREATE USER завершается с ошибкой, потому что такой логин уже сопоставлен с пользователем c другим именем.Это одно из тех явлений, которое становится понятным, как только вы разберётесь в модели данных, но никаким образом не сообщает вам, что так происходит.
Решение
Явно укажите SQL Server сохранить имя пользователя как есть, добавив
NAME = к оператору ALTER USER:ALTER USER [usr_DB_reader]
WITH NAME = [usr_DB_reader],
LOGIN = [VLM\lg_DB_dev_reader];
Добавление
WITH NAME = [usr_DB_reader] говорит SQL Server: да, измени логин, но не трогай имя пользователя. Теперь скрипт действительно идемпотентный.Почему SQL Server так делает?
SQL Server различает логины (субъекты уровня сервера) и пользователей (субъекты уровня БД). Когда вы связываете пользователя с логином с помощью команды
ALTER USER … WITH LOGIN, не указывая имя, SQL Server предполагает, что вы хотите синхронизировать их — поэтому он переименовывает пользователя в соответствии с логином. Это следует соглашениям, но это не то, чего вы ожидаете, если привыкли рассматривать имена пользователей как стабильные идентификаторы.Источник: https://bartwullems.blogspot.com/2026/03/sql-server-silently-renames-your-user.html
👍4