День 1310. #Карьера
С началом нового учебного года всех!
Лично для меня 1 сентября до сих пор остаётся днём старта чего-то нового. Стартует учебный год (теперь уже у детей), старт нового телесезона, старт многих осенне-весенних спортивных сезонов. В общем, повод выползать из отпускного настроения и приниматься за работу.
Поэтому сегодня поговорим о нашем злейшем враге – прокрастинации.
«По результатам многочисленных опросов, около 95% людей признают, что часто откладывают дела на потом.» (Остальные 5% просто врут).
- Пирс Стил «Уравнение прокрастинации»
Прокрастинация — увлекательная тема, и столь же увлекательной является наука, стоящая за ней. Исследования показывают, что у задачи есть шесть атрибутов, которые заставляют нас с большей вероятностью отложить её.
Мы гораздо более склонны откладывать на потом, когда задача:
1. Скучная (например, написание документации).
2. Разочаровывающая или рутинная (например, изучение нового навыка).
3. Сложная (например, дебаг плавающей ошибки).
4. Неоднозначная или неструктурированная (например, подготовка к марафону или реализация большого проекта).
5. Не содержащая в себе вознаграждения (например, всё то же написание документации, зная, что её никто не будет читать).
6. Не имеющая ценности для вас лично (например, уборка домашнего офиса).
Чем больше этих атрибутов имеет задача, тем больше вероятность, что мы её отложим.
Постараемся побороть каждый из этих атрибутов.
1. Делайте скучные задачи более увлекательными. Если нужно писать документацию, пойдите в любимое кафе и сделайте это за чашкой какого-нибудь экзотического кофе. Если выполнение задачи не требует умственных усилий, скачайте интересную аудиокнигу или подкаст.
2. Установите ограничение по времени для разочаровывающих задач. Занимайтесь задачей в течение 20-30 минут, а дальше – как пойдёт. Сделайте из этого игру. К примеру, Microsoft Learn имеет для этого очки опыта и бейджи за каждый изученный навык.
3. Разбейте сложную задачу на более мелкие и составьте план работы. Работайте над самыми сложными задачами во время вашего биологического прайм-тайма (подробнее о нём тут). Кроме того, не стесняйтесь просить помощи.
4. Составьте план неоднозначных и неструктурированных задач. Например, потратьте 20 минут на то, чтобы наметить следующие шаги по проекту. Вычёркивайте выполненные пункты. Поищите примеры того, как другие справлялись с такими задачами.
5. Побалуйте себя, выполняя задачи, которые не содержат в себе вознаграждения. Например, откладывайте доллар (или любой эквивалент) на какой-нибудь ваш каприз за каждые 10 минут работы (работы, а не прокрастинации) над задачей.
6. Ищите позитивные стороны в задачах, не имеющих ценности для вас лично. Например, убранное рабочее место позволяет чувствовать себя более спокойно, организованно и работать более продуктивно.
А вот ещё 3 совета:
1. Составьте список задач на случай, когда поймаете себя на прокрастинации. Главное, чтобы эти задачи имели хоть какую-нибудь пользу и ценность для вас. Это позволит вернуть чувство продуктивности, если основная задача никак не решается. Можно заняться хоть чем-то полезным, пусть это будет даже наведение порядка в папках на компьютере, обновление IDE или написания маленького скрипта для автоматизации ежедневных рутинных действий. Но не слишком увлекайтесь.
2. Составьте список негативных последствий. Простое перечисление и осознание негативных последствий от несделанного дела – отличный мотиватор взяться за работу.
3. Просто начните. Поставьте таймер на 15 минут, после чего позволите себе остановиться и заняться чем-то другим. Иногда задача не настолько неприятная, как вам изначально казалось. Если через 15 минут вы чувствуете в себе силы продолжать – продолжайте.
Прокрастинация — это человеческий феномен: все на планете откладывают дела. В следующий раз, когда вы заметите, что откладываете что-то, обратите внимание на то, что заставляет вас отложить задачу и составьте простой план противодействия этому. В результате вы сделаете намного больше.
Источник: https://alifeofproductivity.com/what-triggers-procrastination/
С началом нового учебного года всех!
Лично для меня 1 сентября до сих пор остаётся днём старта чего-то нового. Стартует учебный год (теперь уже у детей), старт нового телесезона, старт многих осенне-весенних спортивных сезонов. В общем, повод выползать из отпускного настроения и приниматься за работу.
Поэтому сегодня поговорим о нашем злейшем враге – прокрастинации.
«По результатам многочисленных опросов, около 95% людей признают, что часто откладывают дела на потом.» (Остальные 5% просто врут).
- Пирс Стил «Уравнение прокрастинации»
Прокрастинация — увлекательная тема, и столь же увлекательной является наука, стоящая за ней. Исследования показывают, что у задачи есть шесть атрибутов, которые заставляют нас с большей вероятностью отложить её.
Мы гораздо более склонны откладывать на потом, когда задача:
1. Скучная (например, написание документации).
2. Разочаровывающая или рутинная (например, изучение нового навыка).
3. Сложная (например, дебаг плавающей ошибки).
4. Неоднозначная или неструктурированная (например, подготовка к марафону или реализация большого проекта).
5. Не содержащая в себе вознаграждения (например, всё то же написание документации, зная, что её никто не будет читать).
6. Не имеющая ценности для вас лично (например, уборка домашнего офиса).
Чем больше этих атрибутов имеет задача, тем больше вероятность, что мы её отложим.
Постараемся побороть каждый из этих атрибутов.
1. Делайте скучные задачи более увлекательными. Если нужно писать документацию, пойдите в любимое кафе и сделайте это за чашкой какого-нибудь экзотического кофе. Если выполнение задачи не требует умственных усилий, скачайте интересную аудиокнигу или подкаст.
2. Установите ограничение по времени для разочаровывающих задач. Занимайтесь задачей в течение 20-30 минут, а дальше – как пойдёт. Сделайте из этого игру. К примеру, Microsoft Learn имеет для этого очки опыта и бейджи за каждый изученный навык.
3. Разбейте сложную задачу на более мелкие и составьте план работы. Работайте над самыми сложными задачами во время вашего биологического прайм-тайма (подробнее о нём тут). Кроме того, не стесняйтесь просить помощи.
4. Составьте план неоднозначных и неструктурированных задач. Например, потратьте 20 минут на то, чтобы наметить следующие шаги по проекту. Вычёркивайте выполненные пункты. Поищите примеры того, как другие справлялись с такими задачами.
5. Побалуйте себя, выполняя задачи, которые не содержат в себе вознаграждения. Например, откладывайте доллар (или любой эквивалент) на какой-нибудь ваш каприз за каждые 10 минут работы (работы, а не прокрастинации) над задачей.
6. Ищите позитивные стороны в задачах, не имеющих ценности для вас лично. Например, убранное рабочее место позволяет чувствовать себя более спокойно, организованно и работать более продуктивно.
А вот ещё 3 совета:
1. Составьте список задач на случай, когда поймаете себя на прокрастинации. Главное, чтобы эти задачи имели хоть какую-нибудь пользу и ценность для вас. Это позволит вернуть чувство продуктивности, если основная задача никак не решается. Можно заняться хоть чем-то полезным, пусть это будет даже наведение порядка в папках на компьютере, обновление IDE или написания маленького скрипта для автоматизации ежедневных рутинных действий. Но не слишком увлекайтесь.
2. Составьте список негативных последствий. Простое перечисление и осознание негативных последствий от несделанного дела – отличный мотиватор взяться за работу.
3. Просто начните. Поставьте таймер на 15 минут, после чего позволите себе остановиться и заняться чем-то другим. Иногда задача не настолько неприятная, как вам изначально казалось. Если через 15 минут вы чувствуете в себе силы продолжать – продолжайте.
Прокрастинация — это человеческий феномен: все на планете откладывают дела. В следующий раз, когда вы заметите, что откладываете что-то, обратите внимание на то, что заставляет вас отложить задачу и составьте простой план противодействия этому. В результате вы сделаете намного больше.
Источник: https://alifeofproductivity.com/what-triggers-procrastination/
👍6
Что мы говорим богу прокрастинации?
Anonymous Poll
30%
Не сегодня!
30%
Ещё 5 минуточек…
14%
Почему бы и нет?
26%
@#%*@#!, дедлайн!
👍12
День 1311. #ЗаметкиНаПолях #AsyncTips
Взаимодействие с другими системами отмены
Задача
Имеется внешний или унаследованный код с собственными концепциями отмены. Требуется управлять им с использованием стандартного объекта
Решение
У типа
Допустим, вы пишете обертку для
Метод
Помните о сроке существования регистрации обратных вызовов. Метод
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
Взаимодействие с другими системами отмены
Задача
Имеется внешний или унаследованный код с собственными концепциями отмены. Требуется управлять им с использованием стандартного объекта
CancellationToken
.Решение
У типа
CancellationToken
существует два основных способа реакции на запрос на отмену: периодический опрос и обратные вызовы. Периодический опрос обычно используется для кода, интенсивно использующего процессор, — например, циклов обработки данных; обратные вызовы обычно используются во всех остальных ситуациях. Регистрация обратного вызова для маркера осуществляется методом CancellationToken.Register
.Допустим, вы пишете обертку для
System.Net.NetworkInformation.Pingtype
и хотите предусмотреть возможность отмены тестового опроса. Класс Ping
уже имеет API на базе Task
, но не поддерживает CancellationToken
. Вместо этого тип Ping
содержит собственный метод SendAsyncCancel
, который может использоваться для отмены. Для этого зарегистрируйте обратный вызов, который активизирует этот метод:async Task<PingReply> PingAsync(
string host,
CancellationToken ct)
{
using var ping = new Ping();
var task = ping.SendPingAsync(host);
using CancellationTokenRegistration _ =
ct.Register(() => ping.SendAsyncCancel());
return await task;
}
Теперь при запросе на отмену CancellationToken
вызовет метод SendAsyncCancel
за вас, отменяя метод SendPingAsync
.Метод
CancellationToken.Register
может использоваться для взаимодействия с любой альтернативной системой отмены. Но следует помнить, что, если метод получает CancellationToken
, запрос отмены должен отменять только эту одну операцию. Некоторые альтернативные системы отмены реализуют отмену закрытием некоторого ресурса, что может привести к отмене нескольких операций; эта разновидность системы отмены плохо соответствует CancellationToken
. Если вы решите инкапсулировать такую разновидность отмены в CancellationToken
, следует документировать её необычную семантику отмены.Помните о сроке существования регистрации обратных вызовов. Метод
Register
возвращает отменяемый объект, который должен быть освобожден, когда обратный вызов перестанет быть нужным. Предыдущий пример использует команду using для выполнения очистки при завершении асинхронной операции. Если в коде отсутствует команда using, то при каждом вызове кода с тем же (долгосрочным) маркером CancellationToken
он будет добавлять новый обратный вызов (который, в свою очередь, будет поддерживать существование объекта Ping
). Чтобы избежать утечки памяти и ресурсов, очищайте регистрацию обратного вызова, когда он перестаёт быть нужным.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
👍8
День 1312. #CodeReview
Насколько Хорош Ваш Процесс Код-Ревью?
Если ваша команда считает код-ревью пустой тратой времени, то они правы. Те, кто не ценит проверки кода, откладывают их выполнение, часто мало чего находят, либо их комментарии носят чисто стилистический характер. В такой команде внедрение код-ревью может только ухудшить процесс разработки, замедлив его без улучшения качества кода.
Можно построить процесс проверки кода, который будет повышать эффективность, но нужно действовать целенаправленно. Во-первых, организация должна договориться о целях. Во-вторых, нужно регулярно отслеживать показатели проверки, чтобы убедиться, что цели достигнуты и процесс работает исправно.
Согласованность
Эффективный процесс код-ревью начинается с согласования цели - под какие результаты оптимизируется процесс? Выявление ошибок, улучшение сопровождаемости, повышение стилистической согласованности или обмен знаниями в команде? Определение приоритетов поможет команде сосредоточиться на том, какие отзывы оставлять и что искать.
Ключевые показатели
Метрики могут быть разными в зависимости от целей, но есть несколько общих, которые позволят быстро диагностировать и устранять проблемы, связанные с процессом проверки.
1. Скорость
«Время до первого отзыва» — среднее время ожидания отзыва отправителем. Когда этот показатель высок, отправители либо тратят время на ожидание, либо вынуждены делать что-то другое. Если это происходит, важно согласовать ожидания от проверки кода и то, как проверки могут быть лучше интегрированы в повседневные процессы. Определите, что для вас означает «низкое» время до первого отзыва. Относительно этого можно углубляться в индивидуальные и командные показатели: размер пул-реквестов, баланс рабочей нагрузки и скорость проверки. Важно снизить время до первого отзыва настолько, насколько это возможно, без ущерба для внимания и производительности рецензентов.
2. Покрытие
Если ваша цель — улучшить качество кода и выявить ошибки, важно сравнить количество файлов с комментариями в обзоре с количеством изменённых файлов в пул-реквесте. Это будет показателем тщательности проверки. Не существует оптимального числа, но вы должны убедиться, что результат соответствует ожиданиям. Чтобы рецензенты не просто проштамповывали любые изменения, но, и чтобы не сильно придирались и не замедляли процесс.
3. Влияние
Одно только покрытие отзывами не говорит о качестве кода. Важно посмотреть, все ли эти отзывы приводят к действиям? Для этого отслеживайте процент комментариев, которые приводят к ответным комментариям или изменениям в коде. Большое количество комментариев с низким «влиянием» указывает на то, что отзывы рецензентов не воспринимаются как ценные для отправителя. Это может потребовать перестройки того, как должны проводиться проверки кода.
4. Циклы
Пулл-реквесты, перескакивающие туда-сюда между автором и рецензентом, могут замедлять процесс. Если это происходит часто, процесс рецензирования может стать узким местом и источником демотивации для инженеров, пытающихся завершить свою работу.
Средний показатель может меняться по многим причинам. Привлечение новых разработчиков может вызвать всплеск. Однако такой всплеск в опытной команде часто является признаком рассогласованности представлений:
- о том, что значит «готово»,
- какие изменения ожидаются после комментария,
- как должно быть реализовано решение.
Если количество циклов проверки для определённого отправителя велико, это может означать, что он не понимает кодовую базу или имеет дело с нечёткими требованиями.
Проверка кода — один из самых сложных процессов в команде разработчиков ПО. В каждой команде существует свой идеальный баланс тщательности и скорости, и этот баланс может даже измениться для данной команды из-за изменения приоритетов. Менеджеры должны постоянно следить за процессом код-ревью, беседовать с командой, чтобы собрать информацию, необходимую для придания контекста метрикам проверки кода и придания им значимости.
Источник: https://thenewstack.io/how-good-is-your-code-review-process/
Насколько Хорош Ваш Процесс Код-Ревью?
Если ваша команда считает код-ревью пустой тратой времени, то они правы. Те, кто не ценит проверки кода, откладывают их выполнение, часто мало чего находят, либо их комментарии носят чисто стилистический характер. В такой команде внедрение код-ревью может только ухудшить процесс разработки, замедлив его без улучшения качества кода.
Можно построить процесс проверки кода, который будет повышать эффективность, но нужно действовать целенаправленно. Во-первых, организация должна договориться о целях. Во-вторых, нужно регулярно отслеживать показатели проверки, чтобы убедиться, что цели достигнуты и процесс работает исправно.
Согласованность
Эффективный процесс код-ревью начинается с согласования цели - под какие результаты оптимизируется процесс? Выявление ошибок, улучшение сопровождаемости, повышение стилистической согласованности или обмен знаниями в команде? Определение приоритетов поможет команде сосредоточиться на том, какие отзывы оставлять и что искать.
Ключевые показатели
Метрики могут быть разными в зависимости от целей, но есть несколько общих, которые позволят быстро диагностировать и устранять проблемы, связанные с процессом проверки.
1. Скорость
«Время до первого отзыва» — среднее время ожидания отзыва отправителем. Когда этот показатель высок, отправители либо тратят время на ожидание, либо вынуждены делать что-то другое. Если это происходит, важно согласовать ожидания от проверки кода и то, как проверки могут быть лучше интегрированы в повседневные процессы. Определите, что для вас означает «низкое» время до первого отзыва. Относительно этого можно углубляться в индивидуальные и командные показатели: размер пул-реквестов, баланс рабочей нагрузки и скорость проверки. Важно снизить время до первого отзыва настолько, насколько это возможно, без ущерба для внимания и производительности рецензентов.
2. Покрытие
Если ваша цель — улучшить качество кода и выявить ошибки, важно сравнить количество файлов с комментариями в обзоре с количеством изменённых файлов в пул-реквесте. Это будет показателем тщательности проверки. Не существует оптимального числа, но вы должны убедиться, что результат соответствует ожиданиям. Чтобы рецензенты не просто проштамповывали любые изменения, но, и чтобы не сильно придирались и не замедляли процесс.
3. Влияние
Одно только покрытие отзывами не говорит о качестве кода. Важно посмотреть, все ли эти отзывы приводят к действиям? Для этого отслеживайте процент комментариев, которые приводят к ответным комментариям или изменениям в коде. Большое количество комментариев с низким «влиянием» указывает на то, что отзывы рецензентов не воспринимаются как ценные для отправителя. Это может потребовать перестройки того, как должны проводиться проверки кода.
4. Циклы
Пулл-реквесты, перескакивающие туда-сюда между автором и рецензентом, могут замедлять процесс. Если это происходит часто, процесс рецензирования может стать узким местом и источником демотивации для инженеров, пытающихся завершить свою работу.
Средний показатель может меняться по многим причинам. Привлечение новых разработчиков может вызвать всплеск. Однако такой всплеск в опытной команде часто является признаком рассогласованности представлений:
- о том, что значит «готово»,
- какие изменения ожидаются после комментария,
- как должно быть реализовано решение.
Если количество циклов проверки для определённого отправителя велико, это может означать, что он не понимает кодовую базу или имеет дело с нечёткими требованиями.
Проверка кода — один из самых сложных процессов в команде разработчиков ПО. В каждой команде существует свой идеальный баланс тщательности и скорости, и этот баланс может даже измениться для данной команды из-за изменения приоритетов. Менеджеры должны постоянно следить за процессом код-ревью, беседовать с командой, чтобы собрать информацию, необходимую для придания контекста метрикам проверки кода и придания им значимости.
Источник: https://thenewstack.io/how-good-is-your-code-review-process/
👍7
День 1313. #TypesAndLanguages
Ваш Язык Влияет на то, Как Вы Думаете. Начало
Кажется очевидным, не так ли? Ваш язык диктует правила, и вам нужно играть по правилам. Однако последствия гораздо серьёзнее, чем вы думаете. Дело не только в том, что мы выбираем решения, которые просты в использовании на данном языке. Также мы считаем некоторые решения «плохими в целом», потому что они могут создавать некоторые проблемы на данном языке. Однако мы должны помнить, что концепции никогда не бывают хорошими или плохими. Именно то, как мы их используем, делает их таковыми.
Контейнеры внедрения зависимостей
Java-программисты часто заявляют, что DI-контейнеры — это плохо, и мы не должны их использовать. Вы можете найти сообщения в блогах, доклады на конференциях или дискуссии о том, почему мы не должны использовать DI и почему следует отказаться от Spring. В то же время Microsoft поддерживает DI-контейнер непосредственно в платформе .NET Core. Как так?
Дело не в том, что DI-контейнеры хороши или плохи. Дело в том, как мы их используем. Все методы экземпляра в Java являются виртуальными. Это делает переопределение очень простым и возможным почти всегда. Это привело к массовому использованию cglib для создания динамических прокси во время выполнения. Контейнеры DI в Java позволяют внедрять transient объекты в синглтоны — что является плохой практикой и отслеживается в .NET. То же самое касается серверов приложений — они гораздо популярнее и мощнее в мире Java, чем в .NET.
Поскольку проще использовать генерацию кода, проще делать более мощные и более опасные решения. А это приводит к проблемам: чтобы использовать мощные решения, нужно их понимать и уметь не навредить себе. А поскольку у нас не так много времени на изучение наших инструментов, мы часто вносим неправильные изменения в нашу кодовую базу. Это приводит к тонким проблемам с транзакциями, потерей данных и т.п. Java-программисты заметили это и решили не использовать эти возможности. Однако дело не в том, что «контейнеры DI плохи». Это «то, как мы используем DI-контейнеры в мире Java, слишком опасно и приводит к множеству проблем». Просто изучите свои инструменты, и вы будете в большей безопасности.
Частичные моки и виртуальные методы
То же самое происходит и в тестах. Java позволяет переопределить почти любой метод экземпляра, поэтому создание частичного мока разрешено и поддерживается по умолчанию. С другой стороны, вам нужно явно пометить свой метод виртуальным в C#, поэтому обычно вы этого не делаете. Если вы это сделаете, люди могут начать задавать вопросы в код-ревью вроде «почему он виртуальный? вы переопределяете его?». Таким образом, вы не делаете его виртуальным и не можете использовать частичные моки. Совершенно иначе, чем в Java.
Поскольку это разрешено в Java, оно используется чаще. Причина в том, что «если это разрешено по умолчанию, то это должно быть хорошо». Опять же, не стоит обобщать.
Множественное наследование
C++ допускал множественное наследование, и люди испугались проблемы алмаза. Java и C# решили полностью избежать этой проблемы, поэтому они множественное наследование запретили. Однако в то же время они заблокировали множественное наследование состояний и множественное наследование реализации. Единственной разрешённой формой было множественное наследование интерфейсов. К сожалению, проблема алмаза реально существует в языках C# и Java с самого начала.
Поэтому люди испугались наследования. В то же время такие языки, как Scala, допускают почти полное множественное наследование, и это не проблема. Даже Java и C# представили реализацию интерфейса по умолчанию, которую можно использовать для реализации миксинов и множественного наследования состояний. А что, теперь стало можно? Опять же, нельзя сказать, что множественное наследование хорошо или плохо само по себе. Проблема в том, как мы его используем.
Окончание следует…
Источник: https://blog.adamfurmanek.pl/2022/07/23/types-and-programming-languages-part-16/
Автор оригинала: Adam Furmanek
Ваш Язык Влияет на то, Как Вы Думаете. Начало
Кажется очевидным, не так ли? Ваш язык диктует правила, и вам нужно играть по правилам. Однако последствия гораздо серьёзнее, чем вы думаете. Дело не только в том, что мы выбираем решения, которые просты в использовании на данном языке. Также мы считаем некоторые решения «плохими в целом», потому что они могут создавать некоторые проблемы на данном языке. Однако мы должны помнить, что концепции никогда не бывают хорошими или плохими. Именно то, как мы их используем, делает их таковыми.
Контейнеры внедрения зависимостей
Java-программисты часто заявляют, что DI-контейнеры — это плохо, и мы не должны их использовать. Вы можете найти сообщения в блогах, доклады на конференциях или дискуссии о том, почему мы не должны использовать DI и почему следует отказаться от Spring. В то же время Microsoft поддерживает DI-контейнер непосредственно в платформе .NET Core. Как так?
Дело не в том, что DI-контейнеры хороши или плохи. Дело в том, как мы их используем. Все методы экземпляра в Java являются виртуальными. Это делает переопределение очень простым и возможным почти всегда. Это привело к массовому использованию cglib для создания динамических прокси во время выполнения. Контейнеры DI в Java позволяют внедрять transient объекты в синглтоны — что является плохой практикой и отслеживается в .NET. То же самое касается серверов приложений — они гораздо популярнее и мощнее в мире Java, чем в .NET.
Поскольку проще использовать генерацию кода, проще делать более мощные и более опасные решения. А это приводит к проблемам: чтобы использовать мощные решения, нужно их понимать и уметь не навредить себе. А поскольку у нас не так много времени на изучение наших инструментов, мы часто вносим неправильные изменения в нашу кодовую базу. Это приводит к тонким проблемам с транзакциями, потерей данных и т.п. Java-программисты заметили это и решили не использовать эти возможности. Однако дело не в том, что «контейнеры DI плохи». Это «то, как мы используем DI-контейнеры в мире Java, слишком опасно и приводит к множеству проблем». Просто изучите свои инструменты, и вы будете в большей безопасности.
Частичные моки и виртуальные методы
То же самое происходит и в тестах. Java позволяет переопределить почти любой метод экземпляра, поэтому создание частичного мока разрешено и поддерживается по умолчанию. С другой стороны, вам нужно явно пометить свой метод виртуальным в C#, поэтому обычно вы этого не делаете. Если вы это сделаете, люди могут начать задавать вопросы в код-ревью вроде «почему он виртуальный? вы переопределяете его?». Таким образом, вы не делаете его виртуальным и не можете использовать частичные моки. Совершенно иначе, чем в Java.
Поскольку это разрешено в Java, оно используется чаще. Причина в том, что «если это разрешено по умолчанию, то это должно быть хорошо». Опять же, не стоит обобщать.
Множественное наследование
C++ допускал множественное наследование, и люди испугались проблемы алмаза. Java и C# решили полностью избежать этой проблемы, поэтому они множественное наследование запретили. Однако в то же время они заблокировали множественное наследование состояний и множественное наследование реализации. Единственной разрешённой формой было множественное наследование интерфейсов. К сожалению, проблема алмаза реально существует в языках C# и Java с самого начала.
Поэтому люди испугались наследования. В то же время такие языки, как Scala, допускают почти полное множественное наследование, и это не проблема. Даже Java и C# представили реализацию интерфейса по умолчанию, которую можно использовать для реализации миксинов и множественного наследования состояний. А что, теперь стало можно? Опять же, нельзя сказать, что множественное наследование хорошо или плохо само по себе. Проблема в том, как мы его используем.
Окончание следует…
Источник: https://blog.adamfurmanek.pl/2022/07/23/types-and-programming-languages-part-16/
Автор оригинала: Adam Furmanek
👍7
День 1314. #TypesAndLanguages
Ваш Язык Влияет на то, Как Вы Думаете. Окончание
Начало
Наследование против композиции
Что из этого мы должны использовать? «Очевидно — композицию. Наследование — это плохо». Опять же, легко обобщать, но это не обязательно правильно.
Возможности ООП активно использовались на заре Java. Наследование было прорывом, глубокая классовая иерархия не удивляла. Как ни странно, божественные объекты также были популярны. Прошло время, и люди поняли, что помещать всё в класс длиной 8000 строк — не лучшая идея. Так что нам делать? «Запретить наследование, использовать композицию».
На самом деле дискуссия уходит гораздо глубже. Должны ли мы использовать сценарий транзакции и анемичную модель предметной области? Это хорошо? Или нам следует использовать классы с сохранением состояния и предметно-ориентированное проектирование?
Наследование не является ошибкой. Вам нужно понять концепцию и подумать, где она работает хорошо. Не запрещайте его только потому, что вы боитесь божественных классов.
Goto
Конечно, вы не можете использовать goto. Его надо запретить и убрать из языка. Теперь зайдите на GitHub и посмотрите варианты использования. Вы удивитесь.
Преждевременная оптимизация
Этим сильно злоупотребляют. Полная цитата гласит: «Мы должны забыть о неэффективности примерно в 97% случаев: преждевременная оптимизация — корень всех зол». Однако это относится к микрооптимизациям, таким как
В то же время не следует пренебрегать фактором оптимизации. Думайте об алгоритме, а не о циклах под капотом. Удалите ненужные коллекции и структуры данных, но не забивайте голову работой по выравниванию битов.
Однако очень легко снизить производительность, используя возможности языка. Отличным примером является LINQ в .NET — первое, что вы делаете для ускорения работы, — это избавляетесь от LINQ. Хотя по умолчанию он доступен.
Зелёные потоки
Зелёные потоки (если коротко, это потоки, управляемые средой выполнения, а не операционной системой) были популярны, но в какой-то момент подверглись жёсткой критике. В Microsoft написали об этом хорошую статью. C# представил асинхронность, которая позже была скопирована в другие языки (Python, JS, C++, Kotlin).
Однако Java реализовала асинхронность по-другому в своем проекте Loom. Они использовали виртуальные потоки под капотом. И тут в Microsoft внезапно решили поэкспериментировать с зелёными потоками в .NET.
Забавно, правда? Опять же, дело не в том, что концепция плоха. Дело в том, как мы это используем. Зелёные потоки также создают проблемы, особенно в отношении блокирующих операций, примитивов блокировки или interop-вызовов. Но это опять же о реализации, а не об идее.
Источник: https://blog.adamfurmanek.pl/2022/08/13/types-and-programming-languages-part-18/
Ваш Язык Влияет на то, Как Вы Думаете. Окончание
Начало
Наследование против композиции
Что из этого мы должны использовать? «Очевидно — композицию. Наследование — это плохо». Опять же, легко обобщать, но это не обязательно правильно.
Возможности ООП активно использовались на заре Java. Наследование было прорывом, глубокая классовая иерархия не удивляла. Как ни странно, божественные объекты также были популярны. Прошло время, и люди поняли, что помещать всё в класс длиной 8000 строк — не лучшая идея. Так что нам делать? «Запретить наследование, использовать композицию».
На самом деле дискуссия уходит гораздо глубже. Должны ли мы использовать сценарий транзакции и анемичную модель предметной области? Это хорошо? Или нам следует использовать классы с сохранением состояния и предметно-ориентированное проектирование?
Наследование не является ошибкой. Вам нужно понять концепцию и подумать, где она работает хорошо. Не запрещайте его только потому, что вы боитесь божественных классов.
Goto
Конечно, вы не можете использовать goto. Его надо запретить и убрать из языка. Теперь зайдите на GitHub и посмотрите варианты использования. Вы удивитесь.
Преждевременная оптимизация
Этим сильно злоупотребляют. Полная цитата гласит: «Мы должны забыть о неэффективности примерно в 97% случаев: преждевременная оптимизация — корень всех зол». Однако это относится к микрооптимизациям, таким как
i++
против ++i
. И да, такая оптимизация, вероятно, не нужна, так как наш код работает медленно из-за других вещей.В то же время не следует пренебрегать фактором оптимизации. Думайте об алгоритме, а не о циклах под капотом. Удалите ненужные коллекции и структуры данных, но не забивайте голову работой по выравниванию битов.
Однако очень легко снизить производительность, используя возможности языка. Отличным примером является LINQ в .NET — первое, что вы делаете для ускорения работы, — это избавляетесь от LINQ. Хотя по умолчанию он доступен.
Зелёные потоки
Зелёные потоки (если коротко, это потоки, управляемые средой выполнения, а не операционной системой) были популярны, но в какой-то момент подверглись жёсткой критике. В Microsoft написали об этом хорошую статью. C# представил асинхронность, которая позже была скопирована в другие языки (Python, JS, C++, Kotlin).
Однако Java реализовала асинхронность по-другому в своем проекте Loom. Они использовали виртуальные потоки под капотом. И тут в Microsoft внезапно решили поэкспериментировать с зелёными потоками в .NET.
Забавно, правда? Опять же, дело не в том, что концепция плоха. Дело в том, как мы это используем. Зелёные потоки также создают проблемы, особенно в отношении блокирующих операций, примитивов блокировки или interop-вызовов. Но это опять же о реализации, а не об идее.
Источник: https://blog.adamfurmanek.pl/2022/08/13/types-and-programming-languages-part-18/
👍6
День 1315. #ЧтоНовенького
Bulk-Операции в Entity Framework 7
В EF наконец завезут Bulk-Update и Bulk-Delete. Добавленные методы улучшают производительность. Теперь мы можем делать обновления и удаления с помощью всего одной операции, результатом которой будет одна команда SQL.
Рассмотрим использование этих операций. Допустим, у нас есть класс людей:
Чтобы массово удалить набор сущностей, отфильтруем их с помощью
ExecuteUpdate
Для обновления сущностей нам нужно использовать новый метод SetProperty. Первый аргумент SetProperty выбирает свойство, которое необходимо обновить с помощью лямбда-выражения, а второй аргумент — это новое значение этого свойства также с помощью лямбда-выражения, в котором мы также можем получать доступ к свойству. Например, здесь мы добавим префикс "New" к имени первой тысячи людей:
Bulk-Операции в Entity Framework 7
В EF наконец завезут Bulk-Update и Bulk-Delete. Добавленные методы улучшают производительность. Теперь мы можем делать обновления и удаления с помощью всего одной операции, результатом которой будет одна команда SQL.
Рассмотрим использование этих операций. Допустим, у нас есть класс людей:
public class PersonExecuteDelete
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Чтобы массово удалить набор сущностей, отфильтруем их с помощью
Where
(как раньше), а затем вызовем ExecuteDelete
. Помимо прочего, метод возвращает количество удалённых записей:var personsDeleted = context.PersonsВот какой код SQL он сгенерирует:
.Where(p => p.Name.Contains("L"))
.ExecuteDelete();
DELETE FROM [p]Как видите, он просто генерирует одну инструкцию SQL для удаления сущностей, соответствующих условию.
FROM [Persons] AS [p]
WHERE [p].[Name] LIKE N'%L%'
ExecuteUpdate
Для обновления сущностей нам нужно использовать новый метод SetProperty. Первый аргумент SetProperty выбирает свойство, которое необходимо обновить с помощью лямбда-выражения, а второй аргумент — это новое значение этого свойства также с помощью лямбда-выражения, в котором мы также можем получать доступ к свойству. Например, здесь мы добавим префикс "New" к имени первой тысячи людей:
var personsUpdated =В результате возвращается количество обновлённых записей, а SQL код получается таким:
context.Persons
.Where(p => p.PersonId <= 1_000)
.ExecuteUpdate(
p => p.SetProperty(
x => x.Name,
x => "New" + x.Name)
);
}
UPDATE [p]Чтобы обновить несколько свойств за раз, просто вызовите методы
SET [p].[Name] = N'New' + [p].[Name]
FROM [Persons] AS [p]
WHERE [p].[Id] <= CAST(1000 AS bigint)
SetProperty
в цепочке:….ExecuteUpdate(p =>Источник: https://timdeschryver.dev/blog/new-in-entity-framework-7-bulk-operations-with-executedelete-and-executeupdate
p.SetProperty(x => x.Name, x => "…")
.SetProperty(x => x.Age, x => 42)
);
}
👍21
День 1316. #ЗаметкиНаПолях
Неочевидные Различия в Regex
1. \d или [0-9]
В документации .NET про Regex,
- по умолчанию, без опции RegexOptions.ECMAScript,
- с опцией RegexOptions.ECMAScript
Категория цифр в Unicode содержит цифры 0, 1, 2, … но также цифры из других языков, вроде ٣, ٧, ൩ или ໓. Полный список состоит из 610 символов!
Поэтому
Добавление опции решает проблему:
2. [a-zA-Z] или [a-z] с IgnoreCase
Рассмотрим два регулярных выражения:
- «A» является ToLower() представлением «B»,
- оба символа являются представлением в нижнем регистре для одного и того же символа.
В этом случае
Источник: https://www.meziantou.net/regex-with-ignorecase-option-may-match-more-characters-than-expected.htm
Неочевидные Различия в Regex
1. \d или [0-9]
В документации .NET про Regex,
\d
означает любую цифру. Что означает термин «цифра», зависит от опций выражения:- по умолчанию, без опции RegexOptions.ECMAScript,
\d
означает \p{Nd}
, т.е. любой символ из категории «цифр» в Unicode;- с опцией RegexOptions.ECMAScript
\d
означает [0-9]
.Категория цифр в Unicode содержит цифры 0, 1, 2, … но также цифры из других языков, вроде ٣, ٧, ൩ или ໓. Полный список состоит из 610 символов!
Поэтому
Regex.IsMatch("०१२३४५६७८९", "[0-9]{10}");вернёт
False
, тогда какRegex.IsMatch("०१२३४५६७८९", "\\d{10}");вернёт
True
.Добавление опции решает проблему:
Regex.IsMatch("०१२३४५६७८९", "\\d{10}", RegexOptions.ECMAScript);вернёт
False
.2. [a-zA-Z] или [a-z] с IgnoreCase
Рассмотрим два регулярных выражения:
var regex1 = new Regex("^[a-zA-Z]+$");В большинстве случаев они работают одинаково, так, как мы и предполагаем:
var regex2 = new Regex("^[a-z]+$",
RegexOptions.IgnoreCase |
RegexOptions.CultureInvariant);
regex1.IsMatch("Test"); // TrueОднако, есть специальный символ K (U+212A), обозначающий температуру по Кельвину, и здесь всё интереснее:
regex2.IsMatch("Test"); // True
regex1.IsMatch("K"); // FalseКогда в регулярном выражении указан параметр
regex2.IsMatch("K"); // True
RegexOptions.IgnoreCase
, сравнение между входными данными и шаблоном будет выполняться без учёта регистра. Чтобы поддерживать это, Regex необходимо определить, какие отображения регистра будут использоваться для сравнений. Отображение регистра существует всякий раз, когда у вас есть два символа «A» и «B», где либо:- «A» является ToLower() представлением «B»,
- оба символа являются представлением в нижнем регистре для одного и того же символа.
В этом случае
char.ToLowerInvariant('K')
- это k (строчная латинская буква K). Поэтому второе выражение возвращает True
для знака Кельвина, однако он не входит в множество [a-zA-Z]
, поэтому первое выражение возвращает False
.Источник: https://www.meziantou.net/regex-with-ignorecase-option-may-match-more-characters-than-expected.htm
👍21
День 1317. #ЗаметкиНаПолях #ЧтоНовенького
Исправляем Предупреждение CS891
Если вы были одним из первых пользователей .NET 7, возможно, вы столкнулись со следующей ошибкой при компиляции существующего проекта .NET 6:
Warning CS8981: The type name only contains lower-cased ascii characters. Such names may become reserved for the language. (Имя типа содержит символы только в нижнем регистре. Такие имена могут быть зарезервированы под ключевые слова языка.)
Хотя предупреждение в принципе довольно подробное, в нём отсутствует пояснение, почему оно отображается. Особенно когда в .NET 6 код компилировался успешно. Рассмотрим на очень простой пример того, почему это предупреждение было добавлено.
Представим, что мы вернулись на много лет назад и пишем код C# в .NET 2.0. У нас есть код, который выглядит так:
Тут мы решаем обновиться до C# 5, а вместе с ним к нам пришли ключевые слова async/await. Теперь у нас проблемы, потому наш класс имеет конфликт имён.
Microsoft активно выпускает ежегодные выпуски .NET/C#, и само собой разумеется, что они могут добавить дополнительные зарезервированные ключевые слова в язык. Но до этого времени Microsoft, очевидно, не может зарезервировать все возможные комбинации ключевых слов, которые могут понадобиться в будущем.
Поэтому в Microsoft явно указали на тот факт, что все зарезервированные ключевые слова пишутся полностью строчными буквами. И, если вы следуете соглашениям об именовании, которые советуют не называть всё исключительно строчными буквами, то вы можете быть уверены, что в будущем у вас не будет конфликтов.
С другой стороны, это только предупреждение, вы можете его игнорировать, но на свой страх и риск.
Источник: https://dotnetcoretutorials.com/2022/08/10/fixing-cs891-the-type-name-only-contains-lower-cased-ascii-characters/
Исправляем Предупреждение CS891
Если вы были одним из первых пользователей .NET 7, возможно, вы столкнулись со следующей ошибкой при компиляции существующего проекта .NET 6:
Warning CS8981: The type name only contains lower-cased ascii characters. Such names may become reserved for the language. (Имя типа содержит символы только в нижнем регистре. Такие имена могут быть зарезервированы под ключевые слова языка.)
Хотя предупреждение в принципе довольно подробное, в нём отсутствует пояснение, почему оно отображается. Особенно когда в .NET 6 код компилировался успешно. Рассмотрим на очень простой пример того, почему это предупреждение было добавлено.
Представим, что мы вернулись на много лет назад и пишем код C# в .NET 2.0. У нас есть код, который выглядит так:
class async {В то время async/await не существовало в .NET, и вы могли бы создать класс, названный с использованием любого из этих ключевых слов, даже если они не соответствовали традиционным стандартам именования PascalCase.
}
Тут мы решаем обновиться до C# 5, а вместе с ним к нам пришли ключевые слова async/await. Теперь у нас проблемы, потому наш класс имеет конфликт имён.
Microsoft активно выпускает ежегодные выпуски .NET/C#, и само собой разумеется, что они могут добавить дополнительные зарезервированные ключевые слова в язык. Но до этого времени Microsoft, очевидно, не может зарезервировать все возможные комбинации ключевых слов, которые могут понадобиться в будущем.
Поэтому в Microsoft явно указали на тот факт, что все зарезервированные ключевые слова пишутся полностью строчными буквами. И, если вы следуете соглашениям об именовании, которые советуют не называть всё исключительно строчными буквами, то вы можете быть уверены, что в будущем у вас не будет конфликтов.
С другой стороны, это только предупреждение, вы можете его игнорировать, но на свой страх и риск.
Источник: https://dotnetcoretutorials.com/2022/08/10/fixing-cs891-the-type-name-only-contains-lower-cased-ascii-characters/
👍14
День 1318. #DevOps
6 Принципов Разработки Архитектуры ПО
В последнее время термин «непрерывный» (continuous) очень часто используется в речи поставщиков ПО и экспертов как программная архитектура, которую мы все должны и хотим иметь. Проблема в том, что многие считают, что «непрерывный» означает быструю доставку. Однако проектирование непрерывной программной архитектуры требует постоянной обратной связи от всех участников процесса: архитекторов, дизайнеров, разработчиков, операторов — и постоянного улучшения. Разработка архитектуры ПО больше не может быть разовым процессом.
Об этом на недавней конференции GOTO 2022 поговорили Пьер Пюрер, соавтор книги «Continuous Architecture in Practice», и Курт Биттнер, глава отдела корпоративных решений в Scrum.org.
«Проектирование и поддержка хорошо функционирующей непрерывной программной архитектуры требует, прежде всего, терпения,» - считает Пюрер. - «Cпешить с технологическим решением, прежде чем задать правильные вопросы, означает упускать возможности или функции, которые могут быть жизненно важными для бизнеса. Я видел команды, которые начинают с конца, и они знают, что хотят внедрить какую-то технологию. Кто-то сказал им: «Нам нужно быть в облаке Amazon». Ответом будет облако Amazon, а вы даже не задаёте этот вопрос.»
В течение многих лет проектирование архитектуры ПО означало проектирование чего-либо на начальном этапе, а затем переход к этапу развёртывания. Согласно традиционному представлению об архитектуре, «мы не пишем ни строчки кода, пока вся архитектура не будет собрана», — сказал Пюрер.
«Проблема с таким подходом, конечно, в том, что очень сложно знать всё сразу. Проектирование архитектуры, когда более половины ваших требований неверны, не даст вам хороших результатов. Трудно предсказать, как система будет эволюционировать."
Появились более гибкие подходы, что сделало процесс более итеративным. Тем не менее, это предполагает, что «вы пишете код, и архитектура каким-то образом появляется, как кит из воды». Но это приводит к необходимости «большого рефакторинга и перенастройки».
Гибкая разработка — это шаг в правильном направлении, но для непрерывной архитектуры проектировщики и разработчики ПО должны сделать ещё один шаг.
Им нужно задавать трудные вопросы: что нужно бизнесу? Что лучше сработает для пользователей или клиентов? Какие части бизнеса должны быть вовлечены в процесс проектирования?
По словам Пюрера, в основе успешной непрерывной архитектуры лежат шесть принципов. «Ни один из принципов не является новым или революционным, но вместе они имеют большой смысл».
Вот эти принципы:
1. Создавайте архитектуру продукта, а не проекта. Звучит очевидно, но многие об этом забывают.
2. Сосредоточьтесь на атрибутах качества, а не на обширности функционала. Да, функциональные требования важны, но, если качество не соответствует, у вас не получится эффективного продукта.
3. Откладывайте решения до тех пор, пока не будете уверены, что должны принять решение. У каждого решения есть цена. А если оно окажется неверным, будет и цена отката этого решения. Не принимайте решения слишком рано, пытаясь угадать, старайтесь основывать решение на фактах.
4. Планируйте изменения, потому что всё изменится — так что подумайте о «минималистичном дизайне». Хотя это не обязательно означает микросервисы.
5. Помните, тестирование сборки системы важно, но тестирование развёртывания системы едва ли не важнее.
6. Организуйте команду из людей, которые занимаются всеми аспектами системы. Да, может быть разделение на фронт и бэк, но все специалисты должны чётко представлять, какой продукт должен получиться.
«Люди думают об архитектуре как о чертежах, красивых диаграммах и т. д.», — говорит Пюрер. - «Да, у вас должны быть эти вещи, с помощью которых вы будете общаться, как часть архитектуры. Поскольку вы постоянно принимаете решения, вы будете учиться на своих ошибках, постоянно возвращаться и пересматривать свои решения».
Источник: https://www.zdnet.com/article/agile-alertness-6-principles-to-help-your-software-design-process-succeed/
6 Принципов Разработки Архитектуры ПО
В последнее время термин «непрерывный» (continuous) очень часто используется в речи поставщиков ПО и экспертов как программная архитектура, которую мы все должны и хотим иметь. Проблема в том, что многие считают, что «непрерывный» означает быструю доставку. Однако проектирование непрерывной программной архитектуры требует постоянной обратной связи от всех участников процесса: архитекторов, дизайнеров, разработчиков, операторов — и постоянного улучшения. Разработка архитектуры ПО больше не может быть разовым процессом.
Об этом на недавней конференции GOTO 2022 поговорили Пьер Пюрер, соавтор книги «Continuous Architecture in Practice», и Курт Биттнер, глава отдела корпоративных решений в Scrum.org.
«Проектирование и поддержка хорошо функционирующей непрерывной программной архитектуры требует, прежде всего, терпения,» - считает Пюрер. - «Cпешить с технологическим решением, прежде чем задать правильные вопросы, означает упускать возможности или функции, которые могут быть жизненно важными для бизнеса. Я видел команды, которые начинают с конца, и они знают, что хотят внедрить какую-то технологию. Кто-то сказал им: «Нам нужно быть в облаке Amazon». Ответом будет облако Amazon, а вы даже не задаёте этот вопрос.»
В течение многих лет проектирование архитектуры ПО означало проектирование чего-либо на начальном этапе, а затем переход к этапу развёртывания. Согласно традиционному представлению об архитектуре, «мы не пишем ни строчки кода, пока вся архитектура не будет собрана», — сказал Пюрер.
«Проблема с таким подходом, конечно, в том, что очень сложно знать всё сразу. Проектирование архитектуры, когда более половины ваших требований неверны, не даст вам хороших результатов. Трудно предсказать, как система будет эволюционировать."
Появились более гибкие подходы, что сделало процесс более итеративным. Тем не менее, это предполагает, что «вы пишете код, и архитектура каким-то образом появляется, как кит из воды». Но это приводит к необходимости «большого рефакторинга и перенастройки».
Гибкая разработка — это шаг в правильном направлении, но для непрерывной архитектуры проектировщики и разработчики ПО должны сделать ещё один шаг.
Им нужно задавать трудные вопросы: что нужно бизнесу? Что лучше сработает для пользователей или клиентов? Какие части бизнеса должны быть вовлечены в процесс проектирования?
По словам Пюрера, в основе успешной непрерывной архитектуры лежат шесть принципов. «Ни один из принципов не является новым или революционным, но вместе они имеют большой смысл».
Вот эти принципы:
1. Создавайте архитектуру продукта, а не проекта. Звучит очевидно, но многие об этом забывают.
2. Сосредоточьтесь на атрибутах качества, а не на обширности функционала. Да, функциональные требования важны, но, если качество не соответствует, у вас не получится эффективного продукта.
3. Откладывайте решения до тех пор, пока не будете уверены, что должны принять решение. У каждого решения есть цена. А если оно окажется неверным, будет и цена отката этого решения. Не принимайте решения слишком рано, пытаясь угадать, старайтесь основывать решение на фактах.
4. Планируйте изменения, потому что всё изменится — так что подумайте о «минималистичном дизайне». Хотя это не обязательно означает микросервисы.
5. Помните, тестирование сборки системы важно, но тестирование развёртывания системы едва ли не важнее.
6. Организуйте команду из людей, которые занимаются всеми аспектами системы. Да, может быть разделение на фронт и бэк, но все специалисты должны чётко представлять, какой продукт должен получиться.
«Люди думают об архитектуре как о чертежах, красивых диаграммах и т. д.», — говорит Пюрер. - «Да, у вас должны быть эти вещи, с помощью которых вы будете общаться, как часть архитектуры. Поскольку вы постоянно принимаете решения, вы будете учиться на своих ошибках, постоянно возвращаться и пересматривать свои решения».
Источник: https://www.zdnet.com/article/agile-alertness-6-principles-to-help-your-software-design-process-succeed/
👍10
День 1320. #ЗаметкиНаПолях #AsyncTips
Асинхронные интерфейсы и наследование
Задача: В интерфейсе или базовом классе имеется метод, который требуется сделать асинхронным.
Решение
Ключом к пониманию этой задачи и её решения станет понимание того, что async относится к подробностям реализации. Ключевое слово async может применяться только к методам с реализациями. Невозможно применить его к абстрактным методам или методам интерфейсов (если они не имеют реализации по умолчанию). Тем не менее вы можете определить метод с такой же сигнатурой, как у async-метода, но без ключевого слова async.
Ожидание допускают типы, а не методы. Вы можете использовать await с объектом Task, возвращённым методом, независимо от того, был метод реализован с ключевым словом async или нет. Таким образом, интерфейс или абстрактный метод может просто вернуть Task (или Task<T>), и это значение может ожидаться.
Следующий пример определяет интерфейс с асинхронным методом (без ключевого слова async), реализацию этого интерфейса (с async), и независимый метод, который потребляет метод этого интерфейса (посредством await):
Асинхронная сигнатура метода (возврат Task или Task<T>) означает лишь то, что реализация может быть асинхронной. Фактическая реализация может быть синхронной, если нет реальной асинхронной работы, которую нужно было бы выполнять. Например, тестовая заглушка может реализовать тот же интерфейс (без async), используя, например,
См. также: Возвращение завершённых задач
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 11.
Асинхронные интерфейсы и наследование
Задача: В интерфейсе или базовом классе имеется метод, который требуется сделать асинхронным.
Решение
Ключом к пониманию этой задачи и её решения станет понимание того, что async относится к подробностям реализации. Ключевое слово async может применяться только к методам с реализациями. Невозможно применить его к абстрактным методам или методам интерфейсов (если они не имеют реализации по умолчанию). Тем не менее вы можете определить метод с такой же сигнатурой, как у async-метода, но без ключевого слова async.
Ожидание допускают типы, а не методы. Вы можете использовать await с объектом Task, возвращённым методом, независимо от того, был метод реализован с ключевым словом async или нет. Таким образом, интерфейс или абстрактный метод может просто вернуть Task (или Task<T>), и это значение может ожидаться.
Следующий пример определяет интерфейс с асинхронным методом (без ключевого слова async), реализацию этого интерфейса (с async), и независимый метод, который потребляет метод этого интерфейса (посредством await):
interface ICountBytes…
{
Task<int> CountBytesAsync(
HttpClient hc, string url);
}
class Counter : ICountBytes
{
public async Task<int>
CountBytesAsync(HttpClient hc, string url)
{
var b = await hc.GetByteArrayAsync(url);
return b.Length;
}
}
async Task UseCounter(Этот паттерн работает и с абстрактными методами базовых классов.
HttpClient hc,
ICountBytes svc)
{
var res = await svc.CountBytesAsync(
hc,
"https://www.google.com");
Console.WriteLine(res);
}
Асинхронная сигнатура метода (возврат Task или Task<T>) означает лишь то, что реализация может быть асинхронной. Фактическая реализация может быть синхронной, если нет реальной асинхронной работы, которую нужно было бы выполнять. Например, тестовая заглушка может реализовать тот же интерфейс (без async), используя, например,
FromResult
:class CounterStub : ICountBytesАсинхронные методы интерфейсов и базовых классов встречаются всё чаще. Работать с ними не так уж сложно, если помнить, что ожидание должно применяться к возвращаемому типу (а не к методу), а определение асинхронного метода может быть реализовано как асинхронно, так и синхронно.
{
public Task<int> CountBytesAsync(
HttpClient hc, string url)
{
return Task.FromResult(13);
}
}
См. также: Возвращение завершённых задач
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 11.
👍7
День 1321. #ЗаметкиНаПолях
Получаем Согласие Пользователя Перед Выполнением Конфиденциального Кода
Перед выполнением конфиденциальных действий, таких как покупка чего-либо или показ конфиденциальных данных, необходимо получить согласие пользователя. Кроме того, необходимо убедиться, что фактический пользователь является тем, кто выполняет действие. Windows предоставляет API для получения согласия пользователя перед выполнением конфиденциальных действий.
Во-первых, нужно указать, что проект нацелен на Windows, установив свойство TargetFramework в файле .csproj:
Получаем Согласие Пользователя Перед Выполнением Конфиденциального Кода
Перед выполнением конфиденциальных действий, таких как покупка чего-либо или показ конфиденциальных данных, необходимо получить согласие пользователя. Кроме того, необходимо убедиться, что фактический пользователь является тем, кто выполняет действие. Windows предоставляет API для получения согласия пользователя перед выполнением конфиденциальных действий.
Во-первых, нужно указать, что проект нацелен на Windows, установив свойство TargetFramework в файле .csproj:
<Project Sdk="Microsoft.NET.Sdk">Теперь вы можете использовать специфический API для Windows, чтобы получить согласие:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0-windows10.0.17763.0</TargetFramework>
</PropertyGroup>
</Project>
using Windows.Security.Credentials.UI;Также можно использовать метод ConsentAsync перед выполнением действия:
async Task<bool> ConsentAsync(string reason)
{
var availability = await
UserConsentVerifier.CheckAvailabilityAsync();
if (availability ==
UserConsentVerifierAvailability.Available)
{
var result = await
UserConsentVerifier
.RequestVerificationAsync(reason);
return result ==
UserConsentVerificationResult.Verified;
}
return false;
}
if (await ConsentAsync("Confirm your identity"))Источник: https://www.meziantou.net/getting-user-consent-before-executing-sensitive-code.htm
Console.WriteLine("Cofirmed");
else
Console.WriteLine("Not confirmed");
👍10
День 1322. #ЧтоНовенького
Cборки в .NET 7 Обрезаются по Умолчанию
Все сборки в консольных приложениях в .NET 7 теперь обрезаются (trimmed) по умолчанию. Это изменение влияет только на приложения, опубликованные с параметром
Ранее обрезались только сборки с параметром
Начиная с .NET 7, по умолчанию обрезаются все сборки в приложении. Приложения, которые ранее могли работать с PublishTrimmed, могут не работать в .NET 7. Однако затронуты будут только приложения с предупреждениями о тримминге. Если ваше приложение ране не выдавало предупреждений о тримминге, изменение поведения не должно вызвать каких-либо неблагоприятных последствий и, скорее всего, лишь уменьшит размер приложения.
Если в вашем приложении были предупреждения о тримминге, вы можете увидеть изменения в поведении или исключения. Например, приложение, использующее Newtonsoft.Json или System.Text.Json без генерации исходного кода для сериализации и десериализации типов в пользовательском проекте, могло функционировать до изменения, поскольку типы в проекте полностью сохранялись. Выдавалось лишь одно или несколько предупреждений о тримминге (коды предупреждений ILxxxx). Теперь типы в пользовательском проекте обрезаются, и сериализация может завершиться ошибкой или привести к непредвиденным результатам.
Причина изменения
Это изменение помогает уменьшить размер приложения без явного согласия пользователей и соответствует ожиданиям пользователей, что всё приложение будет обрезаться, если не указано иное.
Рекомендованное действие
Лучшее решение — устранить все предупреждения о тримминге. Сведения об устранении предупреждений в ваших библиотеках можно посмотреть в разделе документации «Общие сведения о предупреждениях об обрезке».
В отношении сторонних библиотек, обратитесь к автору, чтобы попросить устранить предупреждения, или выберите другую библиотеку, которая уже поддерживает тримминг. Например, вместо Newtonsoft.Json можно переключиться на System.Text.Json с генерацией исходного кода.
Чтобы вернуться к предыдущему поведению, задайте для свойства TrimMode значение partial, которое было поведением по умолчанию до .NET 7:
Cборки в .NET 7 Обрезаются по Умолчанию
Все сборки в консольных приложениях в .NET 7 теперь обрезаются (trimmed) по умолчанию. Это изменение влияет только на приложения, опубликованные с параметром
PublishTrimmed=true
, и нарушит работу только тех приложений, для которых ранее выдавались предупреждения при тримминге. Это также влияет только на простые приложения .NET, которые не используют Windows Desktop, Android, iOS, WASM или ASP.NET SDK.Ранее обрезались только сборки с параметром
<IsTrimmable>true</IsTrimmable>
в файле проекта библиотеки.Начиная с .NET 7, по умолчанию обрезаются все сборки в приложении. Приложения, которые ранее могли работать с PublishTrimmed, могут не работать в .NET 7. Однако затронуты будут только приложения с предупреждениями о тримминге. Если ваше приложение ране не выдавало предупреждений о тримминге, изменение поведения не должно вызвать каких-либо неблагоприятных последствий и, скорее всего, лишь уменьшит размер приложения.
Если в вашем приложении были предупреждения о тримминге, вы можете увидеть изменения в поведении или исключения. Например, приложение, использующее Newtonsoft.Json или System.Text.Json без генерации исходного кода для сериализации и десериализации типов в пользовательском проекте, могло функционировать до изменения, поскольку типы в проекте полностью сохранялись. Выдавалось лишь одно или несколько предупреждений о тримминге (коды предупреждений ILxxxx). Теперь типы в пользовательском проекте обрезаются, и сериализация может завершиться ошибкой или привести к непредвиденным результатам.
Причина изменения
Это изменение помогает уменьшить размер приложения без явного согласия пользователей и соответствует ожиданиям пользователей, что всё приложение будет обрезаться, если не указано иное.
Рекомендованное действие
Лучшее решение — устранить все предупреждения о тримминге. Сведения об устранении предупреждений в ваших библиотеках можно посмотреть в разделе документации «Общие сведения о предупреждениях об обрезке».
В отношении сторонних библиотек, обратитесь к автору, чтобы попросить устранить предупреждения, или выберите другую библиотеку, которая уже поддерживает тримминг. Например, вместо Newtonsoft.Json можно переключиться на System.Text.Json с генерацией исходного кода.
Чтобы вернуться к предыдущему поведению, задайте для свойства TrimMode значение partial, которое было поведением по умолчанию до .NET 7:
<TrimMode>partial</TrimMode>Поведение по умолчанию в .NET 7+:
<TrimMode>full</TrimMode>Источник: https://docs.microsoft.com/en-us/dotnet/core/compatibility/deployment/7.0/trim-all-assemblies
👍7
День 1323. #Книги
По совету из здешнего чата прочитал книгу «Мой продуктивный год» (Крис Бэйли — М.: Альпина Паблишер, 2022).
«У многих людей списки дел настолько длинные, что невозможно переделать их все за имеющееся время. Первое, к чему прибегают в такой ситуации, чтобы высвободить время и успеть больше, - начинают заказывать еду в офис, накачиваются кофеином, забрасывают занятия спортом, работают до ночи и экономят на сне. Все эти жертвы способны ненадолго поддёрнуть продуктивность вверх, но в долгосрочной перспективе их влияние на продуктивность негативно.»
Автор в течение года пробовал на себе все возможные методы повышения продуктивности. В 26 главах книги он рассматривает каждый из методов, который действительно сработал для него. В итоге получается набор полезных советов, которые позволят сконцентрировано работать, выполнять задачи, которыми не хочется заниматься, и бороться с прокрастинацией.
Читается на одном дыхании и очень мотивирует. Некоторые из практик пробую применять.
По совету из здешнего чата прочитал книгу «Мой продуктивный год» (Крис Бэйли — М.: Альпина Паблишер, 2022).
«У многих людей списки дел настолько длинные, что невозможно переделать их все за имеющееся время. Первое, к чему прибегают в такой ситуации, чтобы высвободить время и успеть больше, - начинают заказывать еду в офис, накачиваются кофеином, забрасывают занятия спортом, работают до ночи и экономят на сне. Все эти жертвы способны ненадолго поддёрнуть продуктивность вверх, но в долгосрочной перспективе их влияние на продуктивность негативно.»
Автор в течение года пробовал на себе все возможные методы повышения продуктивности. В 26 главах книги он рассматривает каждый из методов, который действительно сработал для него. В итоге получается набор полезных советов, которые позволят сконцентрировано работать, выполнять задачи, которыми не хочется заниматься, и бороться с прокрастинацией.
Читается на одном дыхании и очень мотивирует. Некоторые из практик пробую применять.
👍22
День 1324. #ЗаметкиНаПолях
Как Получить Базовый URL в ASP.NET Core
Обычно это не нужно. По крайней мере, не из кода самого приложения. Однако существует ряд причин, по которым это всё ещё может быть актуально, например, если вы хотите сгенерировать и вывести абсолютный URL-адрес в контроллере MVC или на странице Razor.
Допустим, у нас есть адрес страницы:
https://example.com/path/document/?id=42
URL состоит из схемы (https), имени хоста (example.com), пути (path/document/), и строки запроса (id=42). Базовый адрес представляет собой комбинацию схемы, порта и имени хоста:
https://example.com
Номер порта можно не указывать, если веб-сервер прослушивает порт 443 для HTTPS или порт 80 для HTTP-запросов.
Насколько мне известно, в ASP.NET Core нет встроенных способов получить базовый URL, но запрос предоставляет достаточно информации, чтобы собрать его вручную:
Теперь для получения базового URL-адреса требуется всего одна строка:
Как Получить Базовый URL в ASP.NET Core
Обычно это не нужно. По крайней мере, не из кода самого приложения. Однако существует ряд причин, по которым это всё ещё может быть актуально, например, если вы хотите сгенерировать и вывести абсолютный URL-адрес в контроллере MVC или на странице Razor.
Допустим, у нас есть адрес страницы:
https://example.com/path/document/?id=42
URL состоит из схемы (https), имени хоста (example.com), пути (path/document/), и строки запроса (id=42). Базовый адрес представляет собой комбинацию схемы, порта и имени хоста:
https://example.com
Номер порта можно не указывать, если веб-сервер прослушивает порт 443 для HTTPS или порт 80 для HTTP-запросов.
Насколько мне известно, в ASP.NET Core нет встроенных способов получить базовый URL, но запрос предоставляет достаточно информации, чтобы собрать его вручную:
public IActionResult Index()Этот пример обычно предлагается на StackOverflow. Есть некоторые недостатки в использовании такой интерполяции строк. Очевидным является часть порта, которую мы в большинстве случаев не хотим включать. К счастью, в .NET есть встроенный класс для создания URL-адресов с именем UriBuilder. Немного отрефакторим код и включим его в метод расширения HttpRequest:
{
var base = $"{Request.Scheme}://{Request.Host}:{Request.Host.Port ?? 80}";
return View();
}
public static class HttpRequestExtensionsВ этом примере мы используем класс UriBuilder для добавления схемы и имени хоста, а порт добавляем только в том случае, если он есть в запросе. Значение -1 (как ни странно) не указывает на отсутствие порта в UriBuilder. Оператор if позволяет избежать отображения номера порта в базовом URL, используется порт по умолчанию для схемы. Т.е., если схема https и порт 443, нам просто нужен https://example.com, а не https://example.com:443.
{
public static string? BaseUrl(
this HttpRequest req)
{
if (req == null) return null;
var uriBuilder = new UriBuilder(
req.Scheme,
req.Host.Host,
req.Host.Port ?? -1);
if (uriBuilder.Uri.IsDefaultPort)
uriBuilder.Port = -1;
return uriBuilder.Uri.AbsoluteUri;
}
}
Теперь для получения базового URL-адреса требуется всего одна строка:
Request.BaseUrl();В Razor Pages у нас не будет доступа к HTTP-запросу, как в MVC. Здесь требуется внедрить HttpContextAccessor в файл Program.cs (Startup.cs):
var builder = WebApplication.CreateBuilder(args);После этого можно внедрить IHttpContextAccessor на страницу Razor:
builder.Services.AddHttpContextAccessor();
// ...
var app = builder.Build();
// ...
{Источник: https://blog.elmah.io/how-to-get-base-url-in-asp-net-core/
private readonly IHttpContextAccessor hCA;
public IndexModel(IHttpContextAccessor hCA)
{
this.hCA = hCA;
}
public void OnGet()
{
var baseUrl =
hCA.HttpContext?.Request.BaseUrl();
// ...
}
}
👍8
День 1325. #Оффтоп
Открытый Код и Случайные Инновации
Чем более открыта система для новых контрибуторов, тем больше шансов, что случайная встреча принесёт пользу всем участникам.
В конце 1970-х годов в разработке технологий доминировала горстка крупных компаний из Бостона, которые всё финансировали и привлекали в основном талантливых инженеров из Массачусетского технологического института.
В Кремниевой долине в 1990-х люди часто меняли работу и пользовались преимуществом растущего количества неформальных связей, созданных инженерами, бизнес-лидерами и венчурными капиталистами. Вместо культуры секретности была культура нетворкинга. Если бы вы были в Долине в 1990-х, вы могли бы почувствовать вокруг себя гул амбиций и технического голода. Каждая случайная встреча между игроками в индустрии ПО могла стать искрой, которая изменит то, как работает целая отрасль.
Сейчас, когда мы живем в 2020-х годах, произошло ещё одно важное событие, стимулирующее инновации, — это ПО с открытым исходным кодом. По мере того, как открытый код становился всё более популярным в 21 веке, темпы развития отрасли стремительно росли. В частности, это было обусловлено фреймворками ПО с открытым кодом, такими как LAMP или .NET Core, средами разработки и инновациями в базах данных, развитием CMS, поиска и других основных вычислительных функций. Разработка продвинулась «вверх по стеку», так что новым приложениям не нужно изобретать велосипед.
Это также привело к резкому росту экономической активности. Доступность децентрализованных инструментов разработки, таких как GIT, также экспоненциально расширила возможности технических работников по созданию неформальных сетей и совместной работе по всему миру. Не случайно в 2000-е почти все компании стали производителями ПО — от финансов до здравоохранения и образования. ПО управляет нашим миром, и ПО с открытым кодом является правилом, а не исключением в разработке.
Многие попадают в разработку ПО почти случайно. Услышав о программировании от знакомых, попробовав что-то написать самостоятельно или по статье или видеоуроку в сети. Эти случайности могли произойти только потому, что люди делятся своими знаниями, в основном неструктурированным образом. Этот неформальный обмен, который теперь может выходить за пределы географических, политических и бизнес-блоков, — вот что заставляет мир изобретать. Теперь мы наблюдаем ещё один сдвиг — к постгеографическому миру разработки программного обеспечения, великому «перераспределению» возможностей между городами и поселками, далекими от традиционных технологических центров.
Что читатель должен извлечь из этого поста? Что карьера зависит не только от случайности, но и от страстного намерения? Что местоположение может быть судьбоносным, но нельзя предсказать, где произойдет следующий прорыв?
Самый важный урок о случайных инновациях заключается в том, что они не являются транзакционными. На протяжении многих лет бизнес воспринимал использование открытого исходного кода как глупость, пустую трату времени и знаний, и как предоставление услуги бесплатно. Это потому, что они думали в стиле Бостонских компаний 1970-х, а не в стиле Кремниевой долины.
Обмен бизнес-информацией является услугой. Но случайные инновации требуют от нас отдавать, не получая, верить, что мы получим выгоду или просто смириться, с тем, что мы не получим непосредственной выгоды. Если вы поделитесь знаниями, кто-то воспользуется ими, но всё равно поделитесь. Независимо от того, делитесь ли вы открытым исходным кодом или своими знаниями иным образом, этот обмен ценен сам по себе. И он двигает всю отрасль вперёд.
Источник: https://stackoverflow.blog/2022/08/24/open-source-and-accidental-innovation/
Открытый Код и Случайные Инновации
Чем более открыта система для новых контрибуторов, тем больше шансов, что случайная встреча принесёт пользу всем участникам.
В конце 1970-х годов в разработке технологий доминировала горстка крупных компаний из Бостона, которые всё финансировали и привлекали в основном талантливых инженеров из Массачусетского технологического института.
В Кремниевой долине в 1990-х люди часто меняли работу и пользовались преимуществом растущего количества неформальных связей, созданных инженерами, бизнес-лидерами и венчурными капиталистами. Вместо культуры секретности была культура нетворкинга. Если бы вы были в Долине в 1990-х, вы могли бы почувствовать вокруг себя гул амбиций и технического голода. Каждая случайная встреча между игроками в индустрии ПО могла стать искрой, которая изменит то, как работает целая отрасль.
Сейчас, когда мы живем в 2020-х годах, произошло ещё одно важное событие, стимулирующее инновации, — это ПО с открытым исходным кодом. По мере того, как открытый код становился всё более популярным в 21 веке, темпы развития отрасли стремительно росли. В частности, это было обусловлено фреймворками ПО с открытым кодом, такими как LAMP или .NET Core, средами разработки и инновациями в базах данных, развитием CMS, поиска и других основных вычислительных функций. Разработка продвинулась «вверх по стеку», так что новым приложениям не нужно изобретать велосипед.
Это также привело к резкому росту экономической активности. Доступность децентрализованных инструментов разработки, таких как GIT, также экспоненциально расширила возможности технических работников по созданию неформальных сетей и совместной работе по всему миру. Не случайно в 2000-е почти все компании стали производителями ПО — от финансов до здравоохранения и образования. ПО управляет нашим миром, и ПО с открытым кодом является правилом, а не исключением в разработке.
Многие попадают в разработку ПО почти случайно. Услышав о программировании от знакомых, попробовав что-то написать самостоятельно или по статье или видеоуроку в сети. Эти случайности могли произойти только потому, что люди делятся своими знаниями, в основном неструктурированным образом. Этот неформальный обмен, который теперь может выходить за пределы географических, политических и бизнес-блоков, — вот что заставляет мир изобретать. Теперь мы наблюдаем ещё один сдвиг — к постгеографическому миру разработки программного обеспечения, великому «перераспределению» возможностей между городами и поселками, далекими от традиционных технологических центров.
Что читатель должен извлечь из этого поста? Что карьера зависит не только от случайности, но и от страстного намерения? Что местоположение может быть судьбоносным, но нельзя предсказать, где произойдет следующий прорыв?
Самый важный урок о случайных инновациях заключается в том, что они не являются транзакционными. На протяжении многих лет бизнес воспринимал использование открытого исходного кода как глупость, пустую трату времени и знаний, и как предоставление услуги бесплатно. Это потому, что они думали в стиле Бостонских компаний 1970-х, а не в стиле Кремниевой долины.
Обмен бизнес-информацией является услугой. Но случайные инновации требуют от нас отдавать, не получая, верить, что мы получим выгоду или просто смириться, с тем, что мы не получим непосредственной выгоды. Если вы поделитесь знаниями, кто-то воспользуется ими, но всё равно поделитесь. Независимо от того, делитесь ли вы открытым исходным кодом или своими знаниями иным образом, этот обмен ценен сам по себе. И он двигает всю отрасль вперёд.
Источник: https://stackoverflow.blog/2022/08/24/open-source-and-accidental-innovation/
👍11
День 1326. #CodeReview
Советы по Улучшению Обзоров Кода на GitHub
У большинства компаний и команд есть специальные стандарты, определяющие, как должен выглядеть обзор и сколько согласований вам нужно, прежде чем слить код в основную ветку. У GitHub есть специальные инструменты для поддержки обзоров кода в своих средах.
1. Защищённые ветки
Защитите основную ветку от случайных изменений. Push чего-либо непосредственно в основную ветку не должен быть возможным. К счастью, GitHub предлагает отличный механизм для защиты веток. Вы можете создать специальные правила, определив, например, что для слияния кода с основной веткой требуется пул-реквест и одобрение хотя бы одного рецензента.
Как это настроить?
- В репозитории на GitHub перейдите на вкладку Settings (Настройки).
- В меню слева нажмите Branches (Ветки).
- В разделе Branch protection rules (Правила защиты веток) нажмите Add rule (Добавить правило).
- Введите имя ветки или регулярное выражение для шаблона имени.
- Выберите один из пунктов, из списка правил и сохраните изменения.
2. Метки
Метки — это дополнительные, легко распознаваемые фрагменты информации, видимые в списках пул-реквестов. Вы можете использовать их, например, чтобы различать внутренние и внешние изменения, запросы на слияние, связанные с конкретными функциями вашего приложения, типом изменений или размером. Использование меток значительно упрощает управление слияниями.
Как создать новую метку?
- В репозитории на GitHub перейдите в раздел Pull Requests.
- Щёлкните на кнопку Labels (Метки) рядом с полем фильтра.
- Нажмите зелёную кнопку New label (Новая метка).
- Заполните все поля в форме и нажмите кнопку Create label (Создать метку).
- Теперь вы можете назначить её любому из ваших новых или существующих мерж-реквестов в форме создания пул-реквеста.
3. Автоматические проверки
Многие вещи, такие как синтаксис или выполнение тестов, могут выполняться автоматически. Вы можете использовать Jenkins/Github Actions/CircleCI или любой другой инструмент по вашему выбору, чтобы запускать автоматические тесты при каждом создании пул-реквеста. Добавьте правило для отказа в слиянии до тех пор, пока не будут пройдены все необходимые проверки. В один прекрасный день это может спасти ваш производственный код! Добавьте также способ лёгкого повторного запуска этих тестов вручную . Например, отправка специального сообщения в комментарии на GitHub. Это очень полезно при отладке.
4. Шаблон сообщения пул-реквеста с контрольным списком
Каждый запрос на слияние должен иметь хороший, короткий и говорящий сам за себя заголовок и некоторое описание, возможно ссылку на задачу в баг-трекере. Кроме того, некоторые вещи нельзя протестировать вручную, например, доступность или выполнение бизнес-требований. Со временем становится всё труднее помнить все те вещи, которые нужно указать в сообщении мерж-реквеста вам, как автору, и вещи, которые нужно проверить вам, как рецензенту. Вы можете легко решить эти проблемы, используя шаблоны для мерж-реквестов. Это черновик сообщения с контрольным списком вещей, которые нужно проверить вручную, когда вы создаёте запрос на слияние, и этого достаточно, чтобы заполнить форму необходимой информацией и отметить все пункты в контрольном списке как выполненные.
Как добавить шаблон?
- Откройте свой репозиторий в своем любимом редакторе кода.
- Добавьте файл pull_request_template.md в корень вашего репозитория или папку docs, расположенную в корне.
- Поместите свой шаблон внутрь файла (вы можете использовать синтаксис markdown для создания заголовков, контрольных списков и т. д.).
- Слейте изменения с основной веткой.
- Если вы хотите иметь более 1 шаблона сообщения, создайте каталог PULL_REQUEST_TEMPLATE (также в корне или в папке docs) и храните там файлы markdown. В этом случае пользователь сможет выбрать один из шаблонов, используя раскрывающееся меню во время создания запроса на слияние.
Источник: https://dev.to/this-is-learning/5-tips-to-improve-your-code-reviews-on-github-gja
Советы по Улучшению Обзоров Кода на GitHub
У большинства компаний и команд есть специальные стандарты, определяющие, как должен выглядеть обзор и сколько согласований вам нужно, прежде чем слить код в основную ветку. У GitHub есть специальные инструменты для поддержки обзоров кода в своих средах.
1. Защищённые ветки
Защитите основную ветку от случайных изменений. Push чего-либо непосредственно в основную ветку не должен быть возможным. К счастью, GitHub предлагает отличный механизм для защиты веток. Вы можете создать специальные правила, определив, например, что для слияния кода с основной веткой требуется пул-реквест и одобрение хотя бы одного рецензента.
Как это настроить?
- В репозитории на GitHub перейдите на вкладку Settings (Настройки).
- В меню слева нажмите Branches (Ветки).
- В разделе Branch protection rules (Правила защиты веток) нажмите Add rule (Добавить правило).
- Введите имя ветки или регулярное выражение для шаблона имени.
- Выберите один из пунктов, из списка правил и сохраните изменения.
2. Метки
Метки — это дополнительные, легко распознаваемые фрагменты информации, видимые в списках пул-реквестов. Вы можете использовать их, например, чтобы различать внутренние и внешние изменения, запросы на слияние, связанные с конкретными функциями вашего приложения, типом изменений или размером. Использование меток значительно упрощает управление слияниями.
Как создать новую метку?
- В репозитории на GitHub перейдите в раздел Pull Requests.
- Щёлкните на кнопку Labels (Метки) рядом с полем фильтра.
- Нажмите зелёную кнопку New label (Новая метка).
- Заполните все поля в форме и нажмите кнопку Create label (Создать метку).
- Теперь вы можете назначить её любому из ваших новых или существующих мерж-реквестов в форме создания пул-реквеста.
3. Автоматические проверки
Многие вещи, такие как синтаксис или выполнение тестов, могут выполняться автоматически. Вы можете использовать Jenkins/Github Actions/CircleCI или любой другой инструмент по вашему выбору, чтобы запускать автоматические тесты при каждом создании пул-реквеста. Добавьте правило для отказа в слиянии до тех пор, пока не будут пройдены все необходимые проверки. В один прекрасный день это может спасти ваш производственный код! Добавьте также способ лёгкого повторного запуска этих тестов вручную . Например, отправка специального сообщения в комментарии на GitHub. Это очень полезно при отладке.
4. Шаблон сообщения пул-реквеста с контрольным списком
Каждый запрос на слияние должен иметь хороший, короткий и говорящий сам за себя заголовок и некоторое описание, возможно ссылку на задачу в баг-трекере. Кроме того, некоторые вещи нельзя протестировать вручную, например, доступность или выполнение бизнес-требований. Со временем становится всё труднее помнить все те вещи, которые нужно указать в сообщении мерж-реквеста вам, как автору, и вещи, которые нужно проверить вам, как рецензенту. Вы можете легко решить эти проблемы, используя шаблоны для мерж-реквестов. Это черновик сообщения с контрольным списком вещей, которые нужно проверить вручную, когда вы создаёте запрос на слияние, и этого достаточно, чтобы заполнить форму необходимой информацией и отметить все пункты в контрольном списке как выполненные.
Как добавить шаблон?
- Откройте свой репозиторий в своем любимом редакторе кода.
- Добавьте файл pull_request_template.md в корень вашего репозитория или папку docs, расположенную в корне.
- Поместите свой шаблон внутрь файла (вы можете использовать синтаксис markdown для создания заголовков, контрольных списков и т. д.).
- Слейте изменения с основной веткой.
- Если вы хотите иметь более 1 шаблона сообщения, создайте каталог PULL_REQUEST_TEMPLATE (также в корне или в папке docs) и храните там файлы markdown. В этом случае пользователь сможет выбрать один из шаблонов, используя раскрывающееся меню во время создания запроса на слияние.
Источник: https://dev.to/this-is-learning/5-tips-to-improve-your-code-reviews-on-github-gja
👍6
День 1327. #ЧтоНовенького
.NET 7 SDK Поддерживает Создание Контейнерных Приложений
25 августа Microsoft объявили, что .NET 7 SDK будет включать поддержку создания контейнерных приложений в рамках процесса публикации сборки, минуя необходимость в явной фазе сборки Docker.
Обоснованием этого решения было упрощение стандартного кода Docker и снижение когнитивной нагрузки на разработчиков, что позволило создавать контейнерные приложения в .NET быстрее, чем раньше. Разработчики могут использовать сгенерированные контейнеры в локальной разработке или использовать их для создания образов в рамках конвейера CI/CD.
Чет Хаск, продукт-менеджер .NET SDK, объясняет, что для создания этой функции им пришлось добавить поддержку обработки файлов TAR непосредственно в .NET. Это позволило изменять и обновлять файлы образов Docker, которые упакованы как файлы TAR в соответствии со спецификацией Open Container Initiative, во время обычного процесса сборки .NET. Вся информация, необходимая для создания образа контейнера приложения .NET, уже имеется в момент сборки, а в пакет SDK для .NET был добавлен процесс сборки образа контейнера, написанный на C#.
Образ Docker может иметь множество параметров конфигурации. В процессе сборки образа .NET SDK эти конфигурации отображаются как свойства на уровне проекта. Например, проект ASP.NET Core имеет базовый образ контейнера по умолчанию из реестра контейнеров Azure. Если вы хотите заменить его на другой базовый образ, вам придётся изменить свойство
Основное ограничение заключается в том, что команды Dockerfile RUN не поддерживаются. По словам Хаска, нет возможности выполнять команды RUN с помощью .NET SDK. Команды Dockerfile RUN позволяют создавать промежуточные образы, запуская команды операционной системы в создаваемом образе, обычно для установки инструмента или изменения конфигурации системы. В качестве обходного пути Microsoft предлагает создать образ, использующий команды RUN, с помощью Docker, а затем указать этот образ в качестве базового при создании контейнеров в .NET SDK.
Чтобы попробовать эту новую функцию в .NET 7, вам необходимо установить Docker на вашем компьютере для разработки, по крайней мере, на данном этапе. Зависимость от Docker связана с тем, что SDK по-прежнему полагается на него для аутентификации в реестрах контейнеров. Также Docker по-прежнему необходим для запуска сгенерированного образа контейнера.
На данный момент эта функция поддерживается только для образов Linux. В Microsoft заявляют, что образы Windows и проверка подлинности реестра контейнеров будут готовы до выпуска .NET 7 наряду с другими возможностями настройки образов.
Источник: https://www.infoq.com/news/2022/09/dotnet-sdk-container-support/
.NET 7 SDK Поддерживает Создание Контейнерных Приложений
25 августа Microsoft объявили, что .NET 7 SDK будет включать поддержку создания контейнерных приложений в рамках процесса публикации сборки, минуя необходимость в явной фазе сборки Docker.
Обоснованием этого решения было упрощение стандартного кода Docker и снижение когнитивной нагрузки на разработчиков, что позволило создавать контейнерные приложения в .NET быстрее, чем раньше. Разработчики могут использовать сгенерированные контейнеры в локальной разработке или использовать их для создания образов в рамках конвейера CI/CD.
Чет Хаск, продукт-менеджер .NET SDK, объясняет, что для создания этой функции им пришлось добавить поддержку обработки файлов TAR непосредственно в .NET. Это позволило изменять и обновлять файлы образов Docker, которые упакованы как файлы TAR в соответствии со спецификацией Open Container Initiative, во время обычного процесса сборки .NET. Вся информация, необходимая для создания образа контейнера приложения .NET, уже имеется в момент сборки, а в пакет SDK для .NET был добавлен процесс сборки образа контейнера, написанный на C#.
Образ Docker может иметь множество параметров конфигурации. В процессе сборки образа .NET SDK эти конфигурации отображаются как свойства на уровне проекта. Например, проект ASP.NET Core имеет базовый образ контейнера по умолчанию из реестра контейнеров Azure. Если вы хотите заменить его на другой базовый образ, вам придётся изменить свойство
ContainerBaseImage
в файле проекта и выбрать для него новый образ. Процесс сборки также примет имя сборки проекта в качестве имени образа, которое также можно переопределить с помощью свойства проекта ContainerImageName
.Основное ограничение заключается в том, что команды Dockerfile RUN не поддерживаются. По словам Хаска, нет возможности выполнять команды RUN с помощью .NET SDK. Команды Dockerfile RUN позволяют создавать промежуточные образы, запуская команды операционной системы в создаваемом образе, обычно для установки инструмента или изменения конфигурации системы. В качестве обходного пути Microsoft предлагает создать образ, использующий команды RUN, с помощью Docker, а затем указать этот образ в качестве базового при создании контейнеров в .NET SDK.
Чтобы попробовать эту новую функцию в .NET 7, вам необходимо установить Docker на вашем компьютере для разработки, по крайней мере, на данном этапе. Зависимость от Docker связана с тем, что SDK по-прежнему полагается на него для аутентификации в реестрах контейнеров. Также Docker по-прежнему необходим для запуска сгенерированного образа контейнера.
На данный момент эта функция поддерживается только для образов Linux. В Microsoft заявляют, что образы Windows и проверка подлинности реестра контейнеров будут готовы до выпуска .NET 7 наряду с другими возможностями настройки образов.
Источник: https://www.infoq.com/news/2022/09/dotnet-sdk-container-support/
👍13
День 1328. #ЗаметкиНаПолях #AsyncTips
Асинхронное Создание Объектов: Фабрики
Задача: вы создаёте тип, который требует выполнения некоторой асинхронной работы в конструкторе.
Решение
Конструкторы не могут объявляться с async; кроме того, они не могут содержать ключевое слово await. Конечно, использование await в конструкторе могло бы быть полезным, но это привело бы к существенному изменению языка C#.
Одна из возможностей — использовать конструктор в паре с инициализирующим async-методом, чтобы тип использовался следующим образом:
Вот более качественное решение, которое основано на применении паттерна асинхронного фабричного метода:
Экземпляр может создаваться следующим образом:
К сожалению, в некоторых сценариях этот способ не работает — в частности, когда в коде используется провайдер внедрения зависимостей. Ни одна заметная библиотека внедрения зависимостей или инверсии управления не работает с async-кодом. Если вы окажетесь в одной из таких ситуаций, существует пара альтернатив, которые также стоит рассмотреть.
Если создаваемый экземпляр в действительности является общим ресурсом, можно использовать ленивую инициализацию. В противном случае можно воспользоваться паттерном асинхронной инициализации, который рассмотрим позже.
Пример того, как поступать не следует:
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 11.
Асинхронное Создание Объектов: Фабрики
Задача: вы создаёте тип, который требует выполнения некоторой асинхронной работы в конструкторе.
Решение
Конструкторы не могут объявляться с async; кроме того, они не могут содержать ключевое слово await. Конечно, использование await в конструкторе могло бы быть полезным, но это привело бы к существенному изменению языка C#.
Одна из возможностей — использовать конструктор в паре с инициализирующим async-методом, чтобы тип использовался следующим образом:
var instance = new MyAsyncClass();У такого подхода есть недостатки. Разработчик может забыть вызвать метод
await instance.InitAsync();
InitAsync
, а экземпляр не может использоваться сразу же после выполнения конструктора.Вот более качественное решение, которое основано на применении паттерна асинхронного фабричного метода:
class AsyncClassКонструктор и метод
{
private AsyncClass()
{
}
private async Task<AsyncClass> InitAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1));
return this;
}
public static Task<AsyncClass> CreateAsync()
{
var result = new AsyncClass();
return result.InitAsync();
}
}
InitAsync
объявлены приватными, чтобы они не могли использоваться в вызывающем коде; экземпляры могут создаваться только одним способом — статическим фабричным методом CreateAsync
. Вызывающий код не может обратиться к экземпляру до того, как инициализация будет завершена.Экземпляр может создаваться следующим образом:
var instance = await AsyncClass.CreateAsync();Главное преимущество этого паттерна заключается в том, что вызывающий код никак не сможет получить неинициализированный экземпляр
AsyncClass
.К сожалению, в некоторых сценариях этот способ не работает — в частности, когда в коде используется провайдер внедрения зависимостей. Ни одна заметная библиотека внедрения зависимостей или инверсии управления не работает с async-кодом. Если вы окажетесь в одной из таких ситуаций, существует пара альтернатив, которые также стоит рассмотреть.
Если создаваемый экземпляр в действительности является общим ресурсом, можно использовать ленивую инициализацию. В противном случае можно воспользоваться паттерном асинхронной инициализации, который рассмотрим позже.
Пример того, как поступать не следует:
class AsyncClassНа первый взгляд решение может показаться разумным: вы получаете обычный конструктор, который запускает асинхронную операцию; при этом у него есть ряд недостатков, обусловленных использованием async void. Первая проблема заключается в том, что при завершении конструктора экземпляр всё ещё продолжает асинхронно инициализироваться, и не существует очевидного способа определить, когда завершится асинхронная инициализация. Вторая проблема связана с обработкой ошибок: любые исключения, выданные из InitAsync, не могут быть перехвачены секциями catch, окружающими вызов конструктора объекта.
{
public AsyncClass()
{
InitAsync();
}
// ПЛОХОЙ КОД!!
private async void InitAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 11.
👍12