День 1015. #Карьера
Как Среднему Программисту Опережать Конкурентов
Код – это не вся моя жизнь. Я также не являюсь экспертом в структурах данных и алгоритмах. По сравнению с талантами в индустрии ПО я считаю себя средним программистом. Однако даже со средними навыками я никогда не прекращал расти. Быть средним программистом само по себе не мешает карьерному росту. Вы можете перерасти своих конкурентов, если будете готовы приложить усилия в правильном направлении.
1. Изучите домен компании
Хард скилы необходимы, чтобы быть разработчиком. Как средний программист, вы уже лучше многих. Всё, что нужно сделать, это добавить функциональные знания к своему инвентарю навыков. Интересуйтесь бизнес-целями каждого куска кода, который пишете. Знание примеров реального использования помогает писать наиболее простой код, отвечающий требованиям. Приложите максимум усилий для получения комплексных знаний о бизнес-логике.
Этого легко добиться, если вы работаете над приложением с первых дней. Если же вы присоединились к проекту по ходу, множество нюансов предметной области приходится изучать самостоятельно. База данных - лучшее место для начала (поскольку это наименее изменяющаяся часть). Следующим шагом будет понимание роли, которую данные играют в приложении и для компании. Вы будете поражены количеством бизнес-задач, которые можно эффективно решить, если вы знаете, что представляют собой функциональные сущности.
2. Постепенно укрепляйте уверенность
Уверенность в себе творит чудеса. Обучение, выполнение заданий, создание чего-то нового – всё это поможет вам укрепить веру в свои способности. Продолжайте искать возможности правильно использовать своё время.
Вам понадобится немного уверенности в себе, чтобы мотивировать вас, когда вы чувствуете себя плохо. Оно убедит вас в том, что вы можете делать всё, что вам нравится. Пет-проекты могут помочь вам отвлечься, когда работа в офисе становится слишком однообразной.
3. Будьте спасителем для других и привлекайте союзников
Помимо получения удовольствия от помощи ближнему, это даёт множество карьерных преимуществ. Во-первых, возможность узнать новое. Во-вторых, создание доверительных отношений внутри компании. Необязательно быть выдающимся программистом, чтобы быть полезным. Возможно, вы не сможете помочь всем. Но объяснение, почему вы не можете помочь лучше, чем просто отказ.
4. Предлагайте решения, а не просто озвучивайте проблемы
Ваше отношение к вызовам окажет гораздо более значительное влияние на ваш карьерный рост, чем навыки программирования. Люди ценят вовлечённость. Средний программист, преданный делу, может быть ценнее, чем отличный программист, который повсюду видит проблемы. Работая в команде, вы обязательно столкнётесь с проблемами: неэффективные рабочие процессы, коллеги, которые не выкладываются на полную, и т.п. Сосредоточьтесь на решении проблем, а не просто озвучивайте их. Однако имейте в виду, что, даже если есть разумные решения, не все проблемы можно решить в одночасье. Следовательно, разработчику нужно иметь много терпения, чтобы иметь дело с неэффективными людьми и процессами.
5. Сотрудничайте, чтобы расти быстрее
Совместная работа - отличный способ проявить себя в компании. Для этого не обязательно быть профессионалом. Если вы интроверт, то это может показаться довольно сложной задачей. Но самые конструктивные идеи обычно исходят от наименее заметных людей.
Идея в том, чтобы ваше присутствие ощущалось в вашей организации. Вы не просто пара рук, которые могут написать отличный код. Вы - инженер, который может внести свой вклад в развитие. Когда дело доходит до карьерного роста, восприятие имеет большое значение. Если люди не видят вас, значит, они вас не узнают. Станьте заметными за счёт сотрудничества.
Источник: https://betterprogramming.pub/how-to-stay-ahead-of-the-competition-as-an-average-programmer-f76853677490
Автор оригинала: Lokajit Tikayatray
Как Среднему Программисту Опережать Конкурентов
Код – это не вся моя жизнь. Я также не являюсь экспертом в структурах данных и алгоритмах. По сравнению с талантами в индустрии ПО я считаю себя средним программистом. Однако даже со средними навыками я никогда не прекращал расти. Быть средним программистом само по себе не мешает карьерному росту. Вы можете перерасти своих конкурентов, если будете готовы приложить усилия в правильном направлении.
1. Изучите домен компании
Хард скилы необходимы, чтобы быть разработчиком. Как средний программист, вы уже лучше многих. Всё, что нужно сделать, это добавить функциональные знания к своему инвентарю навыков. Интересуйтесь бизнес-целями каждого куска кода, который пишете. Знание примеров реального использования помогает писать наиболее простой код, отвечающий требованиям. Приложите максимум усилий для получения комплексных знаний о бизнес-логике.
Этого легко добиться, если вы работаете над приложением с первых дней. Если же вы присоединились к проекту по ходу, множество нюансов предметной области приходится изучать самостоятельно. База данных - лучшее место для начала (поскольку это наименее изменяющаяся часть). Следующим шагом будет понимание роли, которую данные играют в приложении и для компании. Вы будете поражены количеством бизнес-задач, которые можно эффективно решить, если вы знаете, что представляют собой функциональные сущности.
2. Постепенно укрепляйте уверенность
Уверенность в себе творит чудеса. Обучение, выполнение заданий, создание чего-то нового – всё это поможет вам укрепить веру в свои способности. Продолжайте искать возможности правильно использовать своё время.
Вам понадобится немного уверенности в себе, чтобы мотивировать вас, когда вы чувствуете себя плохо. Оно убедит вас в том, что вы можете делать всё, что вам нравится. Пет-проекты могут помочь вам отвлечься, когда работа в офисе становится слишком однообразной.
3. Будьте спасителем для других и привлекайте союзников
Помимо получения удовольствия от помощи ближнему, это даёт множество карьерных преимуществ. Во-первых, возможность узнать новое. Во-вторых, создание доверительных отношений внутри компании. Необязательно быть выдающимся программистом, чтобы быть полезным. Возможно, вы не сможете помочь всем. Но объяснение, почему вы не можете помочь лучше, чем просто отказ.
4. Предлагайте решения, а не просто озвучивайте проблемы
Ваше отношение к вызовам окажет гораздо более значительное влияние на ваш карьерный рост, чем навыки программирования. Люди ценят вовлечённость. Средний программист, преданный делу, может быть ценнее, чем отличный программист, который повсюду видит проблемы. Работая в команде, вы обязательно столкнётесь с проблемами: неэффективные рабочие процессы, коллеги, которые не выкладываются на полную, и т.п. Сосредоточьтесь на решении проблем, а не просто озвучивайте их. Однако имейте в виду, что, даже если есть разумные решения, не все проблемы можно решить в одночасье. Следовательно, разработчику нужно иметь много терпения, чтобы иметь дело с неэффективными людьми и процессами.
5. Сотрудничайте, чтобы расти быстрее
Совместная работа - отличный способ проявить себя в компании. Для этого не обязательно быть профессионалом. Если вы интроверт, то это может показаться довольно сложной задачей. Но самые конструктивные идеи обычно исходят от наименее заметных людей.
Идея в том, чтобы ваше присутствие ощущалось в вашей организации. Вы не просто пара рук, которые могут написать отличный код. Вы - инженер, который может внести свой вклад в развитие. Когда дело доходит до карьерного роста, восприятие имеет большое значение. Если люди не видят вас, значит, они вас не узнают. Станьте заметными за счёт сотрудничества.
Источник: https://betterprogramming.pub/how-to-stay-ahead-of-the-competition-as-an-average-programmer-f76853677490
Автор оригинала: Lokajit Tikayatray
День 1016. #ЗаметкиНаПолях
Основы DDD с Помощью Пиццы
Предметно-ориентированное проектирование (Domain Driven Design) не предоставляет практических способов реализации архитектуры ПО, но фокусируется на нескольких основных принципах, которые могут помочь в создании поддерживаемого ПО. Чтобы понять эти концепции, мы возьмем реальный пример пиццерии. Для начала рассмотрим несколько терминов.
Домен
Это предмет, вокруг которого построено наше приложение. Каждый компонент приложения выбран, запрограммирован и развёрнут с учетом потребностей домена. Домен в нашей пиццерии - пицца, и вокруг неё нужно строить всё. Повара, ингредиенты, меню, рекламные щиты и т.д.
Контекст
Окружение домена. В нашем случае магазин - это контекст. Всё, что требуется для удовлетворения потребностей, связанных с доменом, составляет контекст.
Модели
Строительные блоки домена. Различные части, которые объединяются для решения проблемы. В нашем случае это люди в их различных ролях, ингредиенты, пицца, мебель, машины и т.д.
Единый язык
Язык и терминология, которые используются при разговоре обо всём, что попадает в контекст.
Ограниченный контекст
Подсистема или разделение ответственности. У каждого сотрудника в магазине свой набор обязанностей. Маловероятно, что шеф-повар и кассир время от времени меняются ролями, поэтому им не нужно глубоко разбираться в работе друг друга.
Принципы DDD
1. ПО моделируется вокруг бизнес домена
Бизнес домен является основой всех архитектурных решений. Бизнес-модели и программные компоненты должны быть сопоставлены друг с другом. Независимо от того, используется ли термин разработчиком или руководителем компании, он должен означать одно и то же. Окончательная версия ПО - это отражение того, как работает бизнес.
Если владелец магазина использует термины маленькая, средняя и большая, рекомендуется, чтобы кассир использовал те же термины вместо размера пиццы в сантиметрах. Это упрощает понимание разговора для обеих сторон.
2. ПО развивается в ограниченном контексте
Ограниченный контекст описывает границы, в пределах которых подсистема должна развиваться. Подсистема не должна беспокоиться о том, как изменятся другие подсистемы, или пытаться решать их проблемы.
Доставка пиццы может развиваться без согласия поваров. Точно так же доставщик не диктует, какие ингредиенты нужно использовать на кухне.
3. Домены создаются, опираясь на мнение экспертов в предметной области
Команда разработчиков должна сначала понять требования с точки зрения бизнеса, прежде чем думать о технической стороне. Специалисты в предметной области несут ответственность за уточнение требований. Они фиксируют требования домена и разрешают любые спорные ситуации. Эксперты в предметной области не обязательно должны быть нетехническими. Это может быть любой, кто внимательно изучил предметную область и имеет опыт работы с ней.
Когда пиццерии нужен рекламный щит, владелец обращается к маркетологам и дизайнерам, а не создаёт дизайн сам.
Преимущества DDD
1. Облегчает общение – все разговоры ведутся экспертами в предметной области.
2. Повышает гибкость – возможность каждой подсистеме развиваться независимо.
3. Снижает недопонимание за счет использования единых формулировок и терминов.
4. Улучшает координацию в команде из-за сужения областей контекстов.
5. Способствует появлению более чистой архитектуры, поскольку разделение задач снижает риск раздувания программных компонентов.
DDD не следует использовать, когда:
1. Не ожидается быстрого роста системы.
2. Первоначальная стоимость должна быть низкой.
3. Время на разработку ограничено.
Источник: https://dev.to/abh1navv/understanding-domain-driven-design-with-some-pizza-4gkn
Основы DDD с Помощью Пиццы
Предметно-ориентированное проектирование (Domain Driven Design) не предоставляет практических способов реализации архитектуры ПО, но фокусируется на нескольких основных принципах, которые могут помочь в создании поддерживаемого ПО. Чтобы понять эти концепции, мы возьмем реальный пример пиццерии. Для начала рассмотрим несколько терминов.
Домен
Это предмет, вокруг которого построено наше приложение. Каждый компонент приложения выбран, запрограммирован и развёрнут с учетом потребностей домена. Домен в нашей пиццерии - пицца, и вокруг неё нужно строить всё. Повара, ингредиенты, меню, рекламные щиты и т.д.
Контекст
Окружение домена. В нашем случае магазин - это контекст. Всё, что требуется для удовлетворения потребностей, связанных с доменом, составляет контекст.
Модели
Строительные блоки домена. Различные части, которые объединяются для решения проблемы. В нашем случае это люди в их различных ролях, ингредиенты, пицца, мебель, машины и т.д.
Единый язык
Язык и терминология, которые используются при разговоре обо всём, что попадает в контекст.
Ограниченный контекст
Подсистема или разделение ответственности. У каждого сотрудника в магазине свой набор обязанностей. Маловероятно, что шеф-повар и кассир время от времени меняются ролями, поэтому им не нужно глубоко разбираться в работе друг друга.
Принципы DDD
1. ПО моделируется вокруг бизнес домена
Бизнес домен является основой всех архитектурных решений. Бизнес-модели и программные компоненты должны быть сопоставлены друг с другом. Независимо от того, используется ли термин разработчиком или руководителем компании, он должен означать одно и то же. Окончательная версия ПО - это отражение того, как работает бизнес.
Если владелец магазина использует термины маленькая, средняя и большая, рекомендуется, чтобы кассир использовал те же термины вместо размера пиццы в сантиметрах. Это упрощает понимание разговора для обеих сторон.
2. ПО развивается в ограниченном контексте
Ограниченный контекст описывает границы, в пределах которых подсистема должна развиваться. Подсистема не должна беспокоиться о том, как изменятся другие подсистемы, или пытаться решать их проблемы.
Доставка пиццы может развиваться без согласия поваров. Точно так же доставщик не диктует, какие ингредиенты нужно использовать на кухне.
3. Домены создаются, опираясь на мнение экспертов в предметной области
Команда разработчиков должна сначала понять требования с точки зрения бизнеса, прежде чем думать о технической стороне. Специалисты в предметной области несут ответственность за уточнение требований. Они фиксируют требования домена и разрешают любые спорные ситуации. Эксперты в предметной области не обязательно должны быть нетехническими. Это может быть любой, кто внимательно изучил предметную область и имеет опыт работы с ней.
Когда пиццерии нужен рекламный щит, владелец обращается к маркетологам и дизайнерам, а не создаёт дизайн сам.
Преимущества DDD
1. Облегчает общение – все разговоры ведутся экспертами в предметной области.
2. Повышает гибкость – возможность каждой подсистеме развиваться независимо.
3. Снижает недопонимание за счет использования единых формулировок и терминов.
4. Улучшает координацию в команде из-за сужения областей контекстов.
5. Способствует появлению более чистой архитектуры, поскольку разделение задач снижает риск раздувания программных компонентов.
DDD не следует использовать, когда:
1. Не ожидается быстрого роста системы.
2. Первоначальная стоимость должна быть низкой.
3. Время на разработку ограничено.
Источник: https://dev.to/abh1navv/understanding-domain-driven-design-with-some-pizza-4gkn
День 1017. #ЧтоНовенького
Изменения в Структурах в C# 10
C# 10 представляет функции для структур, которые обеспечивают лучшее соответствие структур и классов.
Конструкторы без параметров и инициализаторы полей
До C# 10 каждая структура имела неявный общедоступный конструктор без параметров, который устанавливал для полей структуры значения по умолчанию. Создание конструктора без параметров для структуры было ошибкой.
Теперь вы можете добавлять конструкторы структур без параметров. Они должны быть публичными и не могут быть частичными. Если вы его не добавите, будет предоставлен неявный конструктор без параметров, устанавливающий для всех полей значения по умолчанию.
Структуры-записи
Начиная с C# 10, записи можно определять как структуры:
Структуры и так сравниваются по значению. Структуры-записи добавляют поддержку
Также поддерживается позиционная запись:
Это упрощает преобразование кортежей в именованные типы. Изменение типов возвращаемых значений с кортежа, вроде
Чтобы создать неизменяемую структуру записи, добавьте
Теперь метод
Выражение with в структурах и анонимных типах
C# 10 поддерживает выражение with для всех структур, включая структуры-записи, а также для анонимных типов:
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Изменения в Структурах в C# 10
C# 10 представляет функции для структур, которые обеспечивают лучшее соответствие структур и классов.
Конструкторы без параметров и инициализаторы полей
До C# 10 каждая структура имела неявный общедоступный конструктор без параметров, который устанавливал для полей структуры значения по умолчанию. Создание конструктора без параметров для структуры было ошибкой.
Теперь вы можете добавлять конструкторы структур без параметров. Они должны быть публичными и не могут быть частичными. Если вы его не добавите, будет предоставлен неявный конструктор без параметров, устанавливающий для всех полей значения по умолчанию.
public struct Address {Можно инициализировать поля в конструкторе без параметров, как выше, либо через инициализаторы полей или свойств:
public Address() {
City = "<unknown>";
}
public string City { get; init; }
}
public struct Address {Структуры, созданные через ключевое слово
public string City { get; init; } = "<unknown>";
}
default
или при определении массива, игнорируют явные конструкторы без параметров и всегда устанавливают для членов значения по умолчанию.Структуры-записи
Начиная с C# 10, записи можно определять как структуры:
public record struct PersonВы можете продолжить определять записи как классы либо просто по слову
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
record
, либо через record class
для ясности.Структуры и так сравниваются по значению. Структуры-записи добавляют поддержку
IEquatable<T>
и оператор ==
, а также включают переопределение ToString()
.Также поддерживается позиционная запись:
public record struct Person (string FirstName, string LastName);Параметры первичного конструктора становятся публичными свойствами структуры-записи. В отличие от классов-записей, неявно созданные свойства доступны для чтения и записи.
Это упрощает преобразование кортежей в именованные типы. Изменение типов возвращаемых значений с кортежа, вроде
(string FirstName, string LastName)
, на именованный тип Person, может очистить ваш код и гарантировать согласованные имена членов.Чтобы создать неизменяемую структуру записи, добавьте
readonly
в определение структуры или отдельных свойств. Инициализаторы объектов являются частью этапа построения, на котором можно установить свойства только для чтения, поэтому следующая инициализация сработает и для readonly-структур:var person = new Person { FirstName = "Mads", LastName = "Torgersen"};Модификатор sealed для ToString() в классах-записях
Теперь метод
ToString()
может включать модификатор sealed
, который не позволит его переопределять в производных типах записей.Выражение with в структурах и анонимных типах
C# 10 поддерживает выражение with для всех структур, включая структуры-записи, а также для анонимных типов:
var person2 = person with {LastName = "Kristensen"};Выражение возвращает новый экземпляр с новым значением. Вы можете обновить любое количество полей. Поля, которые вы не установили, сохранят то же значение, что и исходный экземпляр.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Вы пользуетесь структурами?
Anonymous Poll
7%
Да, постоянно
38%
Да, но редко
38%
Знаю теоретически, на практике не доводилось
15%
Нет, мало о них знаю
2%
Другой ответ (в комментариях)
День 1018. #ProjectManagement
Почему Надо Выбирать Простую Веб-архитектуру
Координация команды разработчиков — тяжелая работа! Когда команда предлагает вам варианты, не всегда легко понять, что выбрать и почему.
Почему стоит выбрать более простой вариант?
1. Экономия. ПО требует денег на создание, улучшение и поддержку. Решения влияют на бюджет в долгосрочной перспективе. Чем сложнее веб-архитектура, тем больше нужно будет потратить в долгосрочной перспективе на запуск продукта, обеспечение безопасности и улучшения.
2. Обслуживаемость. У руководителей много различных забот и мало времени. Менее сложное ПО будет легче поддерживать в будущем, что сэкономит время и нервы.
3. Доступность. Более сложные архитектуры, такие как одностраничные приложения, могут быть менее доступны по умолчанию и требуют дополнительной работы для обеспечения доступности.
4. Производительность. Приложения, использующие сложные веб-архитектуры, зачастую дольше загружают даже относительно простые данные.
Более простой подход означает:
- Меньше уровней технологий
- Использование стабильных технологий вместо передовых
- По возможности меньше сложности
Ниже представлен план различных архитектур веб-приложений, от самых простых к более сложным.
1. Если можете, сделайте статический сайт
Содержание страниц статического сайта не меняется, пока владелец сайта не обновит его, например, опубликовав новую страницу.
Когда это хороший выбор: многим компаниям просто нужно публиковать информацию о себе в сети. Статические сайты проще всего создавать, поддерживать и размещать. Кроме того, они дешевле.
2. Если статического сайта недостаточно, сделайте серверное приложение
Здесь нужно подумать о создании приложения, базы данных и надёжном хранении пользовательской информации.
Когда это хороший выбор:
- нужна система регистрации и есть разные роли пользователей в приложении,
- нужна сложная логика или обработка данных.
3. Если требуется взаимодействие на стороне клиента, добавьте JavaScript
Веб-браузер может делать вычисления, анимацию и обрабатывать взаимодействия с пользователем. Интерактивность на стороне клиента означает отображение информации или обработку логики в самом браузере.
Когда это хороший выбор: «использование достаточного количества JS» можно рассматривать как способ добавить необходимую интерактивность, не добавляя ненужной сложности. Но нужно поставить вопрос, вводятся ли новые функции в ответ на требования пользователей и тестируются ли они на постоянной основе.
4. Если требуется сложная интерактивность на стороне клиента, может потребоваться одностраничное приложение (single-page application)
React, Angular, Vue.js или Blazor - все эти фреймворки используют JavaScript в браузере для предоставления пользователям функциональных возможностей. Для них часто требуются два набора приложений: на стороне клиента для интерактивности и на стороне сервера для доставки и хранения данных.
Когда это хороший выбор: одностраничные приложения предполагают компромиссы. Из-за нескольких уровней технологий их создание может быть более дорогостоящим и сложным в обслуживании. Часто требуется дополнительная работа, чтобы сделать приложение доступным. Безопасность может быть более сложной задачей. Одностраничные приложения могут быть правильным выбором, когда вы и ваша команда взвесили эти компромиссы и определили, что для предоставления основных функций приложения необходима интенсивная интерактивность на стороне клиента, автономность или отображение данных из публичного API.
Вот несколько вопросов, которые вы можете задать при выборе вариантов веб-архитектуры в проекте:
- Как эти варианты повлияют на доступность, пользовательский опыт и безопасность?
- Сколько разных языков программирования или наборов навыков понадобится, чтобы исправлять проблемы и развёртывать обновления?
- Есть ли пример успешного приложения на этой технологией в арсенале команды?
- Что будет, если команда сменится? Насколько легко или сложно будет нанять разработчиков, обладающих схожими навыками?
Источник: https://18f.gsa.gov/2021/04/05/why_simplicity_choosing_a_web_architecture/
Почему Надо Выбирать Простую Веб-архитектуру
Координация команды разработчиков — тяжелая работа! Когда команда предлагает вам варианты, не всегда легко понять, что выбрать и почему.
Почему стоит выбрать более простой вариант?
1. Экономия. ПО требует денег на создание, улучшение и поддержку. Решения влияют на бюджет в долгосрочной перспективе. Чем сложнее веб-архитектура, тем больше нужно будет потратить в долгосрочной перспективе на запуск продукта, обеспечение безопасности и улучшения.
2. Обслуживаемость. У руководителей много различных забот и мало времени. Менее сложное ПО будет легче поддерживать в будущем, что сэкономит время и нервы.
3. Доступность. Более сложные архитектуры, такие как одностраничные приложения, могут быть менее доступны по умолчанию и требуют дополнительной работы для обеспечения доступности.
4. Производительность. Приложения, использующие сложные веб-архитектуры, зачастую дольше загружают даже относительно простые данные.
Более простой подход означает:
- Меньше уровней технологий
- Использование стабильных технологий вместо передовых
- По возможности меньше сложности
Ниже представлен план различных архитектур веб-приложений, от самых простых к более сложным.
1. Если можете, сделайте статический сайт
Содержание страниц статического сайта не меняется, пока владелец сайта не обновит его, например, опубликовав новую страницу.
Когда это хороший выбор: многим компаниям просто нужно публиковать информацию о себе в сети. Статические сайты проще всего создавать, поддерживать и размещать. Кроме того, они дешевле.
2. Если статического сайта недостаточно, сделайте серверное приложение
Здесь нужно подумать о создании приложения, базы данных и надёжном хранении пользовательской информации.
Когда это хороший выбор:
- нужна система регистрации и есть разные роли пользователей в приложении,
- нужна сложная логика или обработка данных.
3. Если требуется взаимодействие на стороне клиента, добавьте JavaScript
Веб-браузер может делать вычисления, анимацию и обрабатывать взаимодействия с пользователем. Интерактивность на стороне клиента означает отображение информации или обработку логики в самом браузере.
Когда это хороший выбор: «использование достаточного количества JS» можно рассматривать как способ добавить необходимую интерактивность, не добавляя ненужной сложности. Но нужно поставить вопрос, вводятся ли новые функции в ответ на требования пользователей и тестируются ли они на постоянной основе.
4. Если требуется сложная интерактивность на стороне клиента, может потребоваться одностраничное приложение (single-page application)
React, Angular, Vue.js или Blazor - все эти фреймворки используют JavaScript в браузере для предоставления пользователям функциональных возможностей. Для них часто требуются два набора приложений: на стороне клиента для интерактивности и на стороне сервера для доставки и хранения данных.
Когда это хороший выбор: одностраничные приложения предполагают компромиссы. Из-за нескольких уровней технологий их создание может быть более дорогостоящим и сложным в обслуживании. Часто требуется дополнительная работа, чтобы сделать приложение доступным. Безопасность может быть более сложной задачей. Одностраничные приложения могут быть правильным выбором, когда вы и ваша команда взвесили эти компромиссы и определили, что для предоставления основных функций приложения необходима интенсивная интерактивность на стороне клиента, автономность или отображение данных из публичного API.
Вот несколько вопросов, которые вы можете задать при выборе вариантов веб-архитектуры в проекте:
- Как эти варианты повлияют на доступность, пользовательский опыт и безопасность?
- Сколько разных языков программирования или наборов навыков понадобится, чтобы исправлять проблемы и развёртывать обновления?
- Есть ли пример успешного приложения на этой технологией в арсенале команды?
- Что будет, если команда сменится? Насколько легко или сложно будет нанять разработчиков, обладающих схожими навыками?
Источник: https://18f.gsa.gov/2021/04/05/why_simplicity_choosing_a_web_architecture/
День 1019. #ЧтоНовенького
Улучшения Интерполяции Строк в C# 10
Продолжаем знакомиться с новинками в новой версии C#.
Интерполированные обработчики строк
Как известно, компилятор превращает интерполированные строки в вызов
В C# 10 добавили библиотечный шаблон, который позволяет API «брать на себя» обработку аргумента в виде интерполированной строки. Когда используется интерполированная строка, компилятор проверяет, назначена ли интерполированная строка типу, который удовлетворяет шаблону обработчика интерполированной строки. Обработчик интерполированной строки - это особый тип, который преобразует интерполированную строку в обычную строку. Он применяется в специализированных сценариях обычно по соображениям производительности.
Для примера рассмотрим
Авторы API проделали некоторую работу «под капотом» и добавили перегрузки с параметрами вида
Иногда вы хотите выполнить работу по построению строки только при определенных условиях. Примером является
Наконец, вот пример фактического изменения поведения строковой интерполяции.
Константные интерполированные строки
Если все замены в интерполированной строке являются константными строками, тогда результирующая строка также будет константой. Это позволяет использовать синтаксис интерполяции строк в большем количестве мест, например в атрибутах:
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Улучшения Интерполяции Строк в C# 10
Продолжаем знакомиться с новинками в новой версии C#.
Интерполированные обработчики строк
Как известно, компилятор превращает интерполированные строки в вызов
string.Format
. Это может привести к большому количеству аллокаций: упаковке аргументов, выделению массива аргументов и, конечно же, самой результирующей строки. Кроме того, он не оставляет места для манёвра в смысле самой интерполяции.В C# 10 добавили библиотечный шаблон, который позволяет API «брать на себя» обработку аргумента в виде интерполированной строки. Когда используется интерполированная строка, компилятор проверяет, назначена ли интерполированная строка типу, который удовлетворяет шаблону обработчика интерполированной строки. Обработчик интерполированной строки - это особый тип, который преобразует интерполированную строку в обычную строку. Он применяется в специализированных сценариях обычно по соображениям производительности.
Для примера рассмотрим
StringBuilder.Append
:var sb = new StringBuilder();До сих пор это вызывало перегрузку
sb.Append($"Привет, {args[0]}, как дела?");
Append(string? value)
, передавая туда аллоцированную и вычисленную строку, и добавляло её к StringBuilder
одним блоком. Однако теперь есть новая перегрузка Append(ref StringBuilder.AppendInterpolatedStringHandler handler)
, которая имеет приоритет над предыдущей, когда в качестве аргумента используется интерполированная строка.Авторы API проделали некоторую работу «под капотом» и добавили перегрузки с параметрами вида
[Something]InterpolatedStringHandler
, чтобы обрабатывать интерполированные строки более подходящим образом для своих целей. В нашем примере с добавлением строки " Привет, "
, args[0]
и ", как дела?"
будут по отдельности добавлены к StringBuilder
, что намного эффективнее, хотя имеет тот же результат.Иногда вы хотите выполнить работу по построению строки только при определенных условиях. Примером является
Debug.Assert
:Debug.Assert(condition, $"{КакойТоСложныйМетод()}");В большинстве случаев
condition
будет true
, и второй параметр не будет использоваться. Однако все аргументы вычисляются при каждом вызове, излишне замедляя выполнение. Debug.Assert
теперь имеет перегрузку с обработчиком интерполированных строк, который гарантирует, что второй аргумент даже не вычисляется, если условие истинно.Наконец, вот пример фактического изменения поведения строковой интерполяции.
String.Create()
позволяет вам указать IFormatProvider
, используемый для форматирования заменяемых выражений:String.Create(CultureInfo.InvariantCulture, $"Ответ: {result}");Значение
result
(число или дата) будет отформатировано в соответствии с переданной культурой.Константные интерполированные строки
Если все замены в интерполированной строке являются константными строками, тогда результирующая строка также будет константой. Это позволяет использовать синтаксис интерполяции строк в большем количестве мест, например в атрибутах:
[Obsolete($"Используйте {nameof(OtherMethod)}")]Обратите внимание, что замещаемые элементы должны быть заполнены константными строками. Другие типы, такие как числовые значения или значения даты, использовать нельзя, поскольку они чувствительны к культуре и не могут быть вычислены во время компиляции.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
День 1020. #ЗаметкиНаПолях #AsyncTips
Когда Использовать ValueTask. Начало
Простейший способ реализации метода, возвращающего
В следующем примере показана реализация
Окончание следует…
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Главы 2, 11.
Когда Использовать ValueTask. Начало
ValueTask<T>
используется как возвращаемый тип в ситуациях, в которых чаще всего может быть возвращён синхронный результат, а асинхронное поведение встречается реже. Обычно следует использовать Task<T>
, а не ValueTask<T>
. Рассматривать использование ValueTask<T>
в качестве возвращаемого типа следует только после профилирования, которое показывает, что это приведёт к повышению быстродействия.Простейший способ реализации метода, возвращающего
ValueTask<T>
, основан на использовании async
и await
, как и обычный async-метод. Нередко метод, возвращающий ValueTask<T>
, способен немедленно вернуть значение. В таких случаях можно применить оптимизацию для этого сценария с использованием конструктора ValueTask<T>
, и передавать управление медленному асинхронному методу только при необходимости:public ValueTask<int> MethodAsync()Возможны ситуации, в которых требуется реализовать метод, возвращающий
{
if (CanBehaveSynchronously)
return new ValueTask<int>(13);
return new ValueTask<int>(SlowMethodAsync());
}
private Task<int> SlowMethodAsync();
ValueTask<T>
. Например, при использовании интерфейса IAsyncDisposable
, метод DisposeAsync
которого возвращает ValueTask
. В C# 8.0 и .NET Core 3.0 появилось асинхронное освобождение ресурсов. В BCL появился новый интерфейс IAsyncDisposable
, который является асинхронным аналогом IDisposable
. Также была введена команда await using
— асинхронный аналог using
. Таким образом, типы, которые собирались выполнить асинхронную работу при освобождении, получили такую возможность. Возвращаемым типом DisposeAsync
является ValueTask
, а не Task
.В следующем примере показана реализация
IAsyncDisposable
, которая выполняет свою логику асинхронного освобождения однократно. При следующих вызовах метод DisposeAsync
завершается успешно и синхронно:class MyClass : IAsyncDisposableИспользование:
{
private Func<Task> _disposeLogic;
public ValueTask DisposeAsync()
{
if (_disposeLogic == null)
return default;
// Этот простой пример непотокобезопасный;
// если сразу несколько потоков вызовут DisposeAsync,
// логика может быть выполнена более одного раза.
Func<Task> logic = _disposeLogic;
_disposeLogic = null;
return new ValueTask(logic());
}
}
await using (var myClass = new MyClass())Большинство методов должно возвращать
{
...
} // Здесь вызывается DisposeAsync (с ожиданием)
Task<T>
, поскольку при потреблении Task<T>
возникает меньше скрытых ловушек, чем при потреблении ValueTask<T>
. Чаще всего при реализации интерфейсов, использующих ValueTask
или ValueTask<T>
, можно просто применять async
и await
.Окончание следует…
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Главы 2, 11.
День 1021. #ЗаметкиНаПолях #AsyncTips
Потребление ValueTask
Когда Использовать ValueTask
Задача
Требуется организовать потребление ValueTask<T>.
Решение
В большинстве случаев все, что необходимо сделать – добавить await:
Чтобы сделать что-то более сложное, преобразуйте ValueTask<T> в Task<T> вызовом AsTask:
Также возможны другие операции, например, асинхронное ожидание завершения нескольких операций:
Другие свойства ValueTask<T> предназначены для нетривиального использования. Обычно они работают не так, как другие известные свойства. В частности, для ValueTask<T>.Result действуют более жёсткие ограничения, чем для Task<T>.Result. Код, который синхронно получает результат от ValueTask<T>, может вызвать ValueTask<T>.Result или ValueTask<T>. GetAwaiter().GetResult(), но эти компоненты не должны вызываться до завершения ValueTask<T>. Синхронная загрузка результата из Task<T> блокирует вызывающий поток до завершения задачи; ValueTask<T> таких гарантий не даёт. Синхронное получение результатов от ValueTask или ValueTask<T> может быть выполнено только один раз, после завершения ValueTask, и это значение ValueTask уже не может использоваться для ожидания или преобразования в задачу. В противном случае вы получите непредсказуемый результат операции.
Итого
Когда ваш код вызывает метод, возвращающий ValueTask или ValueTask<T>, он должен либо немедленно выполнить await для этого ValueTask, либо немедленно вызвать AsTask для преобразования в Task. Возможно, эта простая рекомендация не исчерпывает все нетривиальные сценарии, но большинству приложений этого будет вполне достаточно.
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
Потребление ValueTask
Когда Использовать ValueTask
Задача
Требуется организовать потребление ValueTask<T>.
Решение
В большинстве случаев все, что необходимо сделать – добавить await:
ValueTask<int> MethodAsync();Также можно выполнить await после выполнения конкурентной операции, как в случае с Task<T>:
…
int value = await MethodAsync();
ValueTask<int> valueTask = MethodAsync();Однако следует помнить, что ValueTask или ValueTask<T> может ожидаться только один раз.
// Другая параллельная работа.
int value = await valueTask;
Чтобы сделать что-то более сложное, преобразуйте ValueTask<T> в Task<T> вызовом AsTask:
Task<int> task = MethodAsync().AsTask();Многократное ожидание Task<T> абсолютно безопасно.
// Другая параллельная работа.
int value = await task;
int anotherValue = await task;
Также возможны другие операции, например, асинхронное ожидание завершения нескольких операций:
Task<int> task1 = MethodAsync().AsTask();Тем не менее для каждого ValueTask<T> можно вызвать AsTask только один раз. Также вы не можете одновременно использовать await и вызвать AsTask для одного ValueTask<T>.
Task<int> task2 = MethodAsync().AsTask();
int[] results = await Task.WhenAll(task1, task2);
Другие свойства ValueTask<T> предназначены для нетривиального использования. Обычно они работают не так, как другие известные свойства. В частности, для ValueTask<T>.Result действуют более жёсткие ограничения, чем для Task<T>.Result. Код, который синхронно получает результат от ValueTask<T>, может вызвать ValueTask<T>.Result или ValueTask<T>. GetAwaiter().GetResult(), но эти компоненты не должны вызываться до завершения ValueTask<T>. Синхронная загрузка результата из Task<T> блокирует вызывающий поток до завершения задачи; ValueTask<T> таких гарантий не даёт. Синхронное получение результатов от ValueTask или ValueTask<T> может быть выполнено только один раз, после завершения ValueTask, и это значение ValueTask уже не может использоваться для ожидания или преобразования в задачу. В противном случае вы получите непредсказуемый результат операции.
Итого
Когда ваш код вызывает метод, возвращающий ValueTask или ValueTask<T>, он должен либо немедленно выполнить await для этого ValueTask, либо немедленно вызвать AsTask для преобразования в Task. Возможно, эта простая рекомендация не исчерпывает все нетривиальные сценарии, но большинству приложений этого будет вполне достаточно.
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
👍3
День 1022. #ЧтоНовенького
Улучшения Лямбда-Выражений в C# 10
Последний (по крайней мере пока) пост о новинках в новой версии C#. На всякий случай вот предыдущие посты о C# 10 и .NET 6:
- Улучшения в Асинхронности
- Улучшения в LINQ 1, 2
- PriorityQueue
- Статические абстрактные члены интерфейсов
- Обобщённая математика
- IEnumerable.Chunk()
- Глобальные Директивы Using
- Неявные Директивы Using
- Изменения в Структурах
- Улучшения Интерполяции Строк
Выведение типа в лябмдах
Лямбда-выражения теперь могут иметь «естественный» тип, то есть компилятор часто может самостоятельно определить тип лямбда-выражения. До сих пор лямбда-выражение приходилось преобразовывать в тип делегата или выражения. В большинстве случаев вы использовали один из перегруженных типов делегатов Func<…> или Action<…>:
Типы возврата для лямбда-выражений
В предыдущих примерах тип возвращаемого значения лямбда-выражения был очевиден и выводился. Это не всегда так:
Теперь вы можете помещать атрибуты в лямбда-выражения так же, как для методов и локальных функций. Cписок параметров при этом также должен быть заключен в круглые скобки:
Лямбда-выражения вызываются иначе, чем методы и локальные функции, и в результате атрибуты не имеют эффекта при вызове лямбда-выражения. Однако атрибуты лямбда-выражений по-прежнему полезны для анализа кода, и они также генерируются в методах, которые компилятор генерирует для лямбда-выражений, так что их можно обнаружить с помощью рефлексии.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Улучшения Лямбда-Выражений в C# 10
Последний (по крайней мере пока) пост о новинках в новой версии C#. На всякий случай вот предыдущие посты о C# 10 и .NET 6:
- Улучшения в Асинхронности
- Улучшения в LINQ 1, 2
- PriorityQueue
- Статические абстрактные члены интерфейсов
- Обобщённая математика
- IEnumerable.Chunk()
- Глобальные Директивы Using
- Неявные Директивы Using
- Изменения в Структурах
- Улучшения Интерполяции Строк
Выведение типа в лябмдах
Лямбда-выражения теперь могут иметь «естественный» тип, то есть компилятор часто может самостоятельно определить тип лямбда-выражения. До сих пор лямбда-выражение приходилось преобразовывать в тип делегата или выражения. В большинстве случаев вы использовали один из перегруженных типов делегатов Func<…> или Action<…>:
Func<string, int> parse = (string s) => int.Parse(s);Начиная с C# 10 компилятор может вывести тип за вас. Вы можете навести курсор на переменную и убедиться, что её тип всё так же
Func<string, int>
:var parse = (string s) => int.Parse(s);Обычно компилятор будет использовать доступный делегат
Func
или Action
, если подходящий существует. В противном случае он будет синтезировать тип делегата (например, если у вас есть ref-параметры или большое количество параметров). Не все лямбды имеют естественные типы - некоторым просто не хватает информации о типах. Например, если не указывать типы параметров, компилятор не сможет решить, какой тип делегата использовать, что приведёт к ошибке компиляции:var parse = s => int.Parse(s);Вывод естественного типа лямбды означает, что она может быть присвоена более базовому типу, например,
object
или Delegate
:Delegate parse = (string s) => int.Parse(s);В деревьях выражений используется комбинация «целевой» и «естественной» типизации. Если целевым типом является
LambdaExpression
или необобщённый Expression
(базовый тип для всех деревьев выражений), а лямбда имеет естественный тип делегата D
, будет выведен тип Expression<D>
:Expression parseExpr = (string s) => int.Parse(s);Здесь для
parseExpr
будет выведен тип Expression<Func<string, int>>
.Типы возврата для лямбда-выражений
В предыдущих примерах тип возвращаемого значения лямбда-выражения был очевиден и выводился. Это не всегда так:
var choose = (bool b) => b ? 1 : "two";В C# 10 вы можете указать явный тип возвращаемого значения для лямбда-выражения прямо перед параметрами. При этом параметры должны быть заключены в круглые скобки:
// Ошибка, т.к. тип результата непонятен
var choose = object (bool b) => b ? 1 : "two";Атрибуты лямбда-выражений
// Func<bool, object>
Теперь вы можете помещать атрибуты в лямбда-выражения так же, как для методов и локальных функций. Cписок параметров при этом также должен быть заключен в круглые скобки:
Func<string, int> parse =Как и для локальных функции, к лямбдам могут применяться только атрибуты, имеющие
[Example(1)] (s) => int.Parse(s);
var choose =
[Example(2)][Example(3)] object (bool b)
=> b ? 1 : "two";
AttributeTargets.Method
.Лямбда-выражения вызываются иначе, чем методы и локальные функции, и в результате атрибуты не имеют эффекта при вызове лямбда-выражения. Однако атрибуты лямбда-выражений по-прежнему полезны для анализа кода, и они также генерируются в методах, которые компилятор генерирует для лямбда-выражений, так что их можно обнаружить с помощью рефлексии.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Какую версию языка C# вы используете в вашей основной деятельности?
Anonymous Poll
13%
Уже 10 и .NET 6
41%
9 и .NET 5
22%
8 и .NET Core 3.x
3%
7 и .NET Core 2.x
16%
7 в .NET Framework
6%
Более старую версию (другую платформу)
День 1023. #Testing
Когда Использовать Mock-объекты
В тестировании можно пускаться в разные крайности относительно создания объектов-имитаций (mock-объектов). От имитации всего на свете до полного отказа их использовать. Обычно имитировать стоит только один конкретный тип зависимостей - неуправляемые зависимости: зависимости вне процесса, взаимодействия с которыми наблюдаются извне (SMTP-сервис, шина сообщений и т.д.).
Обычно существует несколько классов на пути от пользовательского ввода до вызова неуправляемой зависимости. Например, когда
Вам нужно имитировать акт отправки email (потому что SMTP-сервис является неуправляемой зависимостью), но какой именно класс имитировать?
Нужно имитировать самый последний класс в цепочке. Это позволяет использовать максимальное количество кода и улучшить защиту теста от ошибок.
Ещё один совет - имитировать только те типы, которыми вы владеете. Впервые он был представлен Стивом Фриманом и Натом Прайсом в их книге «Growing Object-Oriented Software, Guided by Tests».
Суть в написании собственных адаптеров поверх сторонних библиотек и имитации этих адаптеров вместо библиотечных типов. Это полезно, потому что:
1. Часто у вас нет глубокого понимания того, как работает сторонний код.
2. Даже если этот код уже предоставляет удобный интерфейс, имитировать этот интерфейс рискованно, потому что вы должны быть уверены, что поведение, которое вы имитируете, соответствует тому, что на самом деле делает внешняя библиотека.
3. Адаптеры абстрагируют несущественные технические детали стороннего кода и определяют отношения с библиотекой в условиях вашего приложения.
4. Если библиотека изменится, не придётся обновлять все тесты (и производственный код), которые с ней работают. Оболочка помогает ограничить такие изменения одним местом - самой оболочкой.
Обратите внимание, что правило имитации только тех типов, которыми вы владеете, не является на 100% строгим. Главное ограничение - ваше понимание того, как работает внешняя библиотека. Если эта библиотека тривиальна (до такой степени, что её поведение становится очевидным), то прямая имитация библиотеки становится приемлемой.
Гойко Аджич уточнил правило «Имитируйте только те типы, которые принадлежат вам», на «Имитируйте только те типы, которые вы понимаете».
Источник: https://enterprisecraftsmanship.com
Автор оригинала: Vladimir Khorikov
Когда Использовать Mock-объекты
В тестировании можно пускаться в разные крайности относительно создания объектов-имитаций (mock-объектов). От имитации всего на свете до полного отказа их использовать. Обычно имитировать стоит только один конкретный тип зависимостей - неуправляемые зависимости: зависимости вне процесса, взаимодействия с которыми наблюдаются извне (SMTP-сервис, шина сообщений и т.д.).
Обычно существует несколько классов на пути от пользовательского ввода до вызова неуправляемой зависимости. Например, когда
UserController
регистрирует пользователя, ему может потребоваться отправить email с подтверждением регистрации. Для этого контроллер может использовать вспомогательный класс, который сам использует другой класс и так далее, в конце концов вызывая SMTP-сервис.Вам нужно имитировать акт отправки email (потому что SMTP-сервис является неуправляемой зависимостью), но какой именно класс имитировать?
Нужно имитировать самый последний класс в цепочке. Это позволяет использовать максимальное количество кода и улучшить защиту теста от ошибок.
Ещё один совет - имитировать только те типы, которыми вы владеете. Впервые он был представлен Стивом Фриманом и Натом Прайсом в их книге «Growing Object-Oriented Software, Guided by Tests».
Суть в написании собственных адаптеров поверх сторонних библиотек и имитации этих адаптеров вместо библиотечных типов. Это полезно, потому что:
1. Часто у вас нет глубокого понимания того, как работает сторонний код.
2. Даже если этот код уже предоставляет удобный интерфейс, имитировать этот интерфейс рискованно, потому что вы должны быть уверены, что поведение, которое вы имитируете, соответствует тому, что на самом деле делает внешняя библиотека.
3. Адаптеры абстрагируют несущественные технические детали стороннего кода и определяют отношения с библиотекой в условиях вашего приложения.
4. Если библиотека изменится, не придётся обновлять все тесты (и производственный код), которые с ней работают. Оболочка помогает ограничить такие изменения одним местом - самой оболочкой.
Обратите внимание, что правило имитации только тех типов, которыми вы владеете, не является на 100% строгим. Главное ограничение - ваше понимание того, как работает внешняя библиотека. Если эта библиотека тривиальна (до такой степени, что её поведение становится очевидным), то прямая имитация библиотеки становится приемлемой.
Гойко Аджич уточнил правило «Имитируйте только те типы, которые принадлежат вам», на «Имитируйте только те типы, которые вы понимаете».
Источник: https://enterprisecraftsmanship.com
Автор оригинала: Vladimir Khorikov
День 1024. #ЧтоНовенького
Однофайловые Приложения в .NET 6
В .NET Core 3.0 мы познакомились с концепцией публикации приложения в виде одного exe-файла. Но в этом релизе было несколько вещей, которые не понравились людям. Основными проблемами были:
- Единственный файл exe на самом деле был самораспаковывающимся zip-архивом, который распаковывался во временное место и затем запускался. Иногда это создавало проблемы с точки зрения безопасности.
- Размер файла был астрономическим (70Мб для «Hello World»), хотя надо сказать, что он включает в себя всю среду исполнения .NET Core, поэтому на целевой машине не нужно было ничего устанавливать.
Давайте посмотрим, что изменилось в .NET 6.
Создадим простейшее консольное приложение:
Если открыть папку
Самораспаковывающегося архива, больше нет
В .NET 6 практика упаковки содержимого в большой архив была изменена на один настоящий исполняемый файл, который загружается в память, а не извлекается во временные папки. Хотя, сжатие можно по-прежнему включить с помощью флага:
.NET 6 имеет возможность убирать ненужные зависимости из вашего приложения. По умолчанию, когда вы публикуете автономное приложение, вы получаете всё. Но, используя функцию тримминга, вы можете удалить из среды исполнения зависимости, которые вы на самом деле не используете.
Заметьте, что это может привести к непредвиденным последствиям, поскольку компилятор не всегда может знать, какие зависимости вы используете, а какие нет (например, если вы используете рефлексию).
Попробуем:
Источник: https://dotnetcoretutorials.com/2021/11/10/single-file-apps-in-net-6/
Однофайловые Приложения в .NET 6
В .NET Core 3.0 мы познакомились с концепцией публикации приложения в виде одного exe-файла. Но в этом релизе было несколько вещей, которые не понравились людям. Основными проблемами были:
- Единственный файл exe на самом деле был самораспаковывающимся zip-архивом, который распаковывался во временное место и затем запускался. Иногда это создавало проблемы с точки зрения безопасности.
- Размер файла был астрономическим (70Мб для «Hello World»), хотя надо сказать, что он включает в себя всю среду исполнения .NET Core, поэтому на целевой машине не нужно было ничего устанавливать.
Давайте посмотрим, что изменилось в .NET 6.
Создадим простейшее консольное приложение:
Console.WriteLine("Hello, World!");Чтобы опубликовать это как единый исполняемый файл, выполним команду в терминале:
Console.ReadLine();
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained trueЗаметьте, что когда вы публикуете один файл, вы должны включать целевой тип ОС, так как exe поставляется специально для этой ОС.
Если открыть папку
MyProject\bin\Release\net6.0\win-x64\publish
, там будет один EXE-файл. Он довольно большой, ~60Мб, (хотя немного меньше, чем был раньше). Исполняемый файл с параметром --self-contained false
получается размером в 151Кб. Понятно, что размер – цена включения среды исполнения.Самораспаковывающегося архива, больше нет
В .NET 6 практика упаковки содержимого в большой архив была изменена на один настоящий исполняемый файл, который загружается в память, а не извлекается во временные папки. Хотя, сжатие можно по-прежнему включить с помощью флага:
-p:EnableCompressionInSingleFile=trueТримминг IL
.NET 6 имеет возможность убирать ненужные зависимости из вашего приложения. По умолчанию, когда вы публикуете автономное приложение, вы получаете всё. Но, используя функцию тримминга, вы можете удалить из среды исполнения зависимости, которые вы на самом деле не используете.
Заметьте, что это может привести к непредвиденным последствиям, поскольку компилятор не всегда может знать, какие зависимости вы используете, а какие нет (например, если вы используете рефлексию).
Попробуем:
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained true -p:PublishTrimmed=trueУ меня получился файл размером ~10Мб. Ещё раз замечу, что это всё приложение, включая среду исполнения. Неплохо!
Источник: https://dotnetcoretutorials.com/2021/11/10/single-file-apps-in-net-6/
День 1026. #ВопросыНаСобеседовании
Сегодня порекомендую вам очередное видео от Сергея Немчинского, в котором он отвечает на популярные вопросы про собеседования.
В какой одежде приходить? Что, если вы опоздали? Сколько времени длится собеседование? Нужно ли писать код на листочке? Почему спрашивают то, что не пригодится на конкретной позиции? Почему компании не дают фидбек в случае, если вы не подошли? И про многое другое.
Честно говоря, после просмотра очень хотелось прособеседоваться у Сергея. Жаль, что он не специализируется в .NET.
https://youtu.be/YeKmEmM7I2A
Сегодня порекомендую вам очередное видео от Сергея Немчинского, в котором он отвечает на популярные вопросы про собеседования.
В какой одежде приходить? Что, если вы опоздали? Сколько времени длится собеседование? Нужно ли писать код на листочке? Почему спрашивают то, что не пригодится на конкретной позиции? Почему компании не дают фидбек в случае, если вы не подошли? И про многое другое.
Честно говоря, после просмотра очень хотелось прособеседоваться у Сергея. Жаль, что он не специализируется в .NET.
https://youtu.be/YeKmEmM7I2A
День 1027. #Карьера
Софт-Скилы, Которые Вам Потребуются, Чтобы Добиться Успеха
При собеседовании на джуна в основном оценивают ваши навыки программирования и ничего больше. При собеседовании на более старшие вакансии эти навыки также важны, но требуется и кое-что ещё. Вот пять ключевых «софт»-навыков, которые действительно выделяют хорошего разработчика ПО из толпы.
1. Эффективная коммуникация
Умение хорошо объяснять ваши идеи другим.
Создание ПО - командный вид спорта. Команда состоит из людей с разным опытом, убеждениями, предубеждениями и знаниями. Если вы хотите создать хороший продукт, вы должны хорошо работать вместе. Система, которую вы разрабатываете, будет имитировать структуру коммуникации вашей организации: плохое общение между членами команды приведет к плохо спроектированным продуктам.
Лучшие разработчики грамотно доносят сложные технические концепции нетехническим людям или младшим специалистам. Вы далеко пойдёте как разработчик, если сможете эффективно общаться и учить других.
2. Эмпатия
Умение ставить себя на место пользователей.
Разработчик должен руководствоваться предназначением своего продукта. Конечно, интересно изучать новые технологии или копаться в последних инструментах разработки, но как насчёт того, почему именно важна наша работа?
Лучшие разработчики заботятся о цели, ради которой они создают ПО, и стремятся понять людей, которым помогают. Существует распространённое упражнение по управлению продуктом под названием «Сопоставление интересов», которое направлено на чёткое определение того, как пользователь думает, чувствует и взаимодействует с продуктом. Понимая поведение и чувства пользователей, мы можем создать продукт, который они будут действительно использовать по назначению.
Слишком часто продукты создаются без предварительного разговора с пользователями. Даже если вы разработчик в команде, понимание того, как думает ваш пользователь, приведёт к улучшению качества продукта.
3. Креативность
Умение искать решения.
Одна из величайших сверхспособностей любого разработчика - это способность гуглить. Когда появляется нерешаемая проблема, креативный разработчик знает, что решение, вероятно, уже существует. А когда этого не происходит, он не боится провести мозговой штурм по поиску нового решения.
Решение проблем требует обдумывания. Оно не приходит свыше, только чтобы бездумно его закодировать. Вы должны исследовать возможности, взвешивая различные технологии и навыки своей команды. После получения некоторого опыта, позволяющего понять, какие технологии существуют, придумать, как объединить эти решения становится проще.
4. Ответственность
Уверенность ваших коллег в том, что вы справитесь со своей работой.
В команде люди полагаются на то, что вы сделаете свою работу, особенно если вы пообещали выполнить задачу. Если вы надёжны, никому не нужно будет следить за вашими успехами, поскольку вы доказали, что можете брать на себя ответственность.
Руководителям нужны разработчики, которым не нужна няня. Им нужны подчиненные, которые соглашаются что-то делать, и выполняют то, за что берутся. Вы не поверите, но многие люди ненадёжны, поэтому ответственный разработчик никогда не пропадёт.
5. Любопытство
Умение задавать достаточно вопросов.
Есть люди, которые никогда не задают вопросов. Обычно это связано со стеснительностью, особенно в больших командах. Однако вопросы могут быть очень полезными, потому что они дают возможность учиться как вам, так и отвечающему.
В индустрии высоких технологий всегда есть чему поучиться. Любознательные разработчики ставят под сомнение существующие нормы, исследуют новые технологии и любят учиться. Задавать вопросы, чтобы бросить вызов устоявшемуся порядку, - отличный способ ускорить прогресс вашей команды. Вопросы - это возможность улучшить себя, свою команду и свой продукт.
Источник: https://betterprogramming.pub/5-soft-skills-you-need-to-succeed-as-a-developer-357f7eac3372
Автор оригинала: Marisa Hoenig
Софт-Скилы, Которые Вам Потребуются, Чтобы Добиться Успеха
При собеседовании на джуна в основном оценивают ваши навыки программирования и ничего больше. При собеседовании на более старшие вакансии эти навыки также важны, но требуется и кое-что ещё. Вот пять ключевых «софт»-навыков, которые действительно выделяют хорошего разработчика ПО из толпы.
1. Эффективная коммуникация
Умение хорошо объяснять ваши идеи другим.
Создание ПО - командный вид спорта. Команда состоит из людей с разным опытом, убеждениями, предубеждениями и знаниями. Если вы хотите создать хороший продукт, вы должны хорошо работать вместе. Система, которую вы разрабатываете, будет имитировать структуру коммуникации вашей организации: плохое общение между членами команды приведет к плохо спроектированным продуктам.
Лучшие разработчики грамотно доносят сложные технические концепции нетехническим людям или младшим специалистам. Вы далеко пойдёте как разработчик, если сможете эффективно общаться и учить других.
2. Эмпатия
Умение ставить себя на место пользователей.
Разработчик должен руководствоваться предназначением своего продукта. Конечно, интересно изучать новые технологии или копаться в последних инструментах разработки, но как насчёт того, почему именно важна наша работа?
Лучшие разработчики заботятся о цели, ради которой они создают ПО, и стремятся понять людей, которым помогают. Существует распространённое упражнение по управлению продуктом под названием «Сопоставление интересов», которое направлено на чёткое определение того, как пользователь думает, чувствует и взаимодействует с продуктом. Понимая поведение и чувства пользователей, мы можем создать продукт, который они будут действительно использовать по назначению.
Слишком часто продукты создаются без предварительного разговора с пользователями. Даже если вы разработчик в команде, понимание того, как думает ваш пользователь, приведёт к улучшению качества продукта.
3. Креативность
Умение искать решения.
Одна из величайших сверхспособностей любого разработчика - это способность гуглить. Когда появляется нерешаемая проблема, креативный разработчик знает, что решение, вероятно, уже существует. А когда этого не происходит, он не боится провести мозговой штурм по поиску нового решения.
Решение проблем требует обдумывания. Оно не приходит свыше, только чтобы бездумно его закодировать. Вы должны исследовать возможности, взвешивая различные технологии и навыки своей команды. После получения некоторого опыта, позволяющего понять, какие технологии существуют, придумать, как объединить эти решения становится проще.
4. Ответственность
Уверенность ваших коллег в том, что вы справитесь со своей работой.
В команде люди полагаются на то, что вы сделаете свою работу, особенно если вы пообещали выполнить задачу. Если вы надёжны, никому не нужно будет следить за вашими успехами, поскольку вы доказали, что можете брать на себя ответственность.
Руководителям нужны разработчики, которым не нужна няня. Им нужны подчиненные, которые соглашаются что-то делать, и выполняют то, за что берутся. Вы не поверите, но многие люди ненадёжны, поэтому ответственный разработчик никогда не пропадёт.
5. Любопытство
Умение задавать достаточно вопросов.
Есть люди, которые никогда не задают вопросов. Обычно это связано со стеснительностью, особенно в больших командах. Однако вопросы могут быть очень полезными, потому что они дают возможность учиться как вам, так и отвечающему.
В индустрии высоких технологий всегда есть чему поучиться. Любознательные разработчики ставят под сомнение существующие нормы, исследуют новые технологии и любят учиться. Задавать вопросы, чтобы бросить вызов устоявшемуся порядку, - отличный способ ускорить прогресс вашей команды. Вопросы - это возможность улучшить себя, свою команду и свой продукт.
Источник: https://betterprogramming.pub/5-soft-skills-you-need-to-succeed-as-a-developer-357f7eac3372
Автор оригинала: Marisa Hoenig
👍1
День 1028. #Microservices
Хватит Использовать Микросервисы. Создавайте Монолиты
Микросервисы могут показаться идеальным решением. Теоретически они увеличивают скорость разработки, позволяя независимо масштабировать различные части вашего приложения. Но на самом деле микросервисы сопряжены со скрытыми расходами. Трудно по-настоящему оценить их сложность, не попробовав создать приложение на микросервисах. Вот с чем приходится сталкиваться.
1. Управление данными превращается в кошмар
Синхронизация данных между микросервисами может быть сложной задачей.
База данных на микросервис - рекомендуемый шаблон. Он обеспечивает слабую связь и позволяет командам, специализирующимся на конкретных сервисах, работать независимо. Но что произойдёт, если один из микросервисов выйдет из строя? Например, один микросервис обновляет свою базу данных, а другой - нет. Подобные ситуации приводят к несогласованности данных. Поиск несоответствий данных между сервисами может быть болезненным. Придётся работать с несколькими сервисами, чтобы исправить ошибку. Это сразу сводит на нет одно из преимуществ – разделение на команды. Такую же ситуацию в монолитном приложении можно было бы легко предотвратить, заключив оба вызова БД в одну атомарную транзакцию. Слабая связь микросервисов усложняет задачу.
2. Больше времени на настройку
Создание архитектуры микросервисов занимает больше времени. Хотя отдельный сервис прост, набор взаимодействующих сервисов значительно сложнее сопоставимого монолита. Функции в монолите могут вызывать любые другие общедоступные функции. Но функции в микросервисе ограничены вызовом функций в том же микросервисе. Это требует создания системы связи между сервисами, что само по себе нетривиальная задача. Кроме того, сложнее избежать дублирования кода.
3. Микросервисы лучше всего подходят для больших команд
Хотя это одно из самых разрекламированных преимуществ микросервисов, вохможность выделить команду на микросервис есть только тогда, когда у вас достаточно специалистов, чтобы выделить несколько инженеров для каждого сервиса. Уменьшение объёма кода позволяет разработчикам лучше понимать код и увеличивает скорость разработки. Но у большинства стартапов этого нет. Тогда некоторым инженерам приходится работать со всеми сервисами. Это снижает производительность, из-за постоянного переключения контекста. А поиск ошибок в микросервисах, над которыми давно не работал, очень утомителен.
4. DevOps усложняется
Одна из наиболее веских причин для выбора микросервисов - это возможность запускать разные сервисы на разных типах серверов. Например, React имеет требования к памяти, процессору и времени безотказной работы отличные от сервиса машинного обучения. Это может значительно снизить затраты. Но тут есть свои проблемы. Например, можно потерять данные, просто забыв обновить один из сервисов. Настройка, обслуживание и мониторинг нескольких микросервисов требует больше усилий по сравнению с одним монолитным приложением. Теоретически «слабосвязанные» сервисы позволяют каждому сервису продолжать работу в случае отказа других. Но это принятие желаемого за действительное: истинная слабая связь редко возможна для сложного бизнеса.
В конце концов, архитектура вашего приложения настолько надежна, насколько надежна ее самая слабая часть. Чем больше движущихся частей, тем больше вероятность ошибки.
Итого
- Многие компании используют микросервисы, даже не нуждаясь в них. И, несмотря на популярность, микросервисы не для новичков.
- Большинству компаний было бы лучше построить монолит, а затем разделить его части на микросервисы, если это абсолютно необходимо.
- Оставьте создание микросервисной архитектуры с нуля для крупных технологических компаний с глубокими карманами.
- Ваш стартап, вероятно, ещё не готов. Это обычно так, и это приводит к большим затратам времени и энергии.
Источник: https://betterprogramming.pub/stop-using-microservices-build-monoliths-instead-9eac180ac908
Хватит Использовать Микросервисы. Создавайте Монолиты
Микросервисы могут показаться идеальным решением. Теоретически они увеличивают скорость разработки, позволяя независимо масштабировать различные части вашего приложения. Но на самом деле микросервисы сопряжены со скрытыми расходами. Трудно по-настоящему оценить их сложность, не попробовав создать приложение на микросервисах. Вот с чем приходится сталкиваться.
1. Управление данными превращается в кошмар
Синхронизация данных между микросервисами может быть сложной задачей.
База данных на микросервис - рекомендуемый шаблон. Он обеспечивает слабую связь и позволяет командам, специализирующимся на конкретных сервисах, работать независимо. Но что произойдёт, если один из микросервисов выйдет из строя? Например, один микросервис обновляет свою базу данных, а другой - нет. Подобные ситуации приводят к несогласованности данных. Поиск несоответствий данных между сервисами может быть болезненным. Придётся работать с несколькими сервисами, чтобы исправить ошибку. Это сразу сводит на нет одно из преимуществ – разделение на команды. Такую же ситуацию в монолитном приложении можно было бы легко предотвратить, заключив оба вызова БД в одну атомарную транзакцию. Слабая связь микросервисов усложняет задачу.
2. Больше времени на настройку
Создание архитектуры микросервисов занимает больше времени. Хотя отдельный сервис прост, набор взаимодействующих сервисов значительно сложнее сопоставимого монолита. Функции в монолите могут вызывать любые другие общедоступные функции. Но функции в микросервисе ограничены вызовом функций в том же микросервисе. Это требует создания системы связи между сервисами, что само по себе нетривиальная задача. Кроме того, сложнее избежать дублирования кода.
3. Микросервисы лучше всего подходят для больших команд
Хотя это одно из самых разрекламированных преимуществ микросервисов, вохможность выделить команду на микросервис есть только тогда, когда у вас достаточно специалистов, чтобы выделить несколько инженеров для каждого сервиса. Уменьшение объёма кода позволяет разработчикам лучше понимать код и увеличивает скорость разработки. Но у большинства стартапов этого нет. Тогда некоторым инженерам приходится работать со всеми сервисами. Это снижает производительность, из-за постоянного переключения контекста. А поиск ошибок в микросервисах, над которыми давно не работал, очень утомителен.
4. DevOps усложняется
Одна из наиболее веских причин для выбора микросервисов - это возможность запускать разные сервисы на разных типах серверов. Например, React имеет требования к памяти, процессору и времени безотказной работы отличные от сервиса машинного обучения. Это может значительно снизить затраты. Но тут есть свои проблемы. Например, можно потерять данные, просто забыв обновить один из сервисов. Настройка, обслуживание и мониторинг нескольких микросервисов требует больше усилий по сравнению с одним монолитным приложением. Теоретически «слабосвязанные» сервисы позволяют каждому сервису продолжать работу в случае отказа других. Но это принятие желаемого за действительное: истинная слабая связь редко возможна для сложного бизнеса.
В конце концов, архитектура вашего приложения настолько надежна, насколько надежна ее самая слабая часть. Чем больше движущихся частей, тем больше вероятность ошибки.
Итого
- Многие компании используют микросервисы, даже не нуждаясь в них. И, несмотря на популярность, микросервисы не для новичков.
- Большинству компаний было бы лучше построить монолит, а затем разделить его части на микросервисы, если это абсолютно необходимо.
- Оставьте создание микросервисной архитектуры с нуля для крупных технологических компаний с глубокими карманами.
- Ваш стартап, вероятно, ещё не готов. Это обычно так, и это приводит к большим затратам времени и энергии.
Источник: https://betterprogramming.pub/stop-using-microservices-build-monoliths-instead-9eac180ac908
👍1
День 1029. #ЗаметкиНаПолях #AsyncTips
Создание асинхронных потоков
Задача
Нужно вернуть несколько значений, при этом каждое значение может потребовать некоторой асинхронной работы.
Решение
Возвращение нескольких значений из метода может осуществляться командой yield return, а асинхронные методы используют async и await. Асинхронные потоки (асинхронные перечисления) объединяют эти два подхода. Используйте возвращаемый тип
Когда метод GetAsync начинает работу, он асинхронный запрашивает первую страницу данных, после чего производит первый элемент. Второй элемент выдаётся немедленно, потому что он содержится на той же странице данных. И т.д. 10 элементов. При запросе 11-го элемента цикл foreach завершится, выполнение цикла while продолжится. На следующей итерации цикла while выполнится асинхронный запрос второй страницы данных, после чего будет выдан 11-й элемент. И т.д…
В течение многих лет использовать async и await с yield return было невозможно, но асинхронные потоки ввели эту возможность. В примере выше стоит обратить внимание, что асинхронная работа нужна не для всех результатов. Здесь только приблизительно одному из каждых 10 элементов потребуется асинхронная работа. Если размер страницы равен 20, то асинхронная работа потребуется только одному из 20 элементов.
Это обычное поведение с асинхронными потоками. Для многих потоков большинство операций асинхронного перебора на самом деле синхронно; асинхронные потоки только позволяют асинхронно получить любой следующий элемент. Асинхронные потоки проектировались с учетом как асинхронного, так и синхронного кода; вот почему они построены на основе ValueTask<T>.
Когда вы реализуете асинхронные потоки, подумайте о поддержке отмены. Некоторые сценарии не требуют реальной отмены: потребляющий код всегда может отказаться от получения следующего элемента. Это абсолютно нормальный подход при отсутствии внешнего источника для отмены. Если вы хотите, чтобы асинхронный поток можно было отменить даже в процессе получения следующего элемента, то следует обеспечить поддержку отмены с использованием
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
Создание асинхронных потоков
Задача
Нужно вернуть несколько значений, при этом каждое значение может потребовать некоторой асинхронной работы.
Решение
Возвращение нескольких значений из метода может осуществляться командой yield return, а асинхронные методы используют async и await. Асинхронные потоки (асинхронные перечисления) объединяют эти два подхода. Используйте возвращаемый тип
IAsyncEnumerable<T>
. В следующем примере асинхронно перебираются результаты API, использующего параметры для страничной организации результатов:async IAsyncEnumerable<string> GetAsync(HttpClient client)
{
int off = 0;
const int lim = 10;
while (true)
{
// Получаем текущую страницу результатов
var result = await client.GetStringAsync(
$"{apiURL}/values?offset={off}&limit={lim}"
);
var values = result.Split('\n');
// Выдаём результаты с этой страницы
foreach (var value in values)
yield return value;
// Если последняя страница, выходим
if (values.Length != lim)
break;
// Переходим к следующей странице
off += lim;
}
}
Когда метод GetAsync начинает работу, он асинхронный запрашивает первую страницу данных, после чего производит первый элемент. Второй элемент выдаётся немедленно, потому что он содержится на той же странице данных. И т.д. 10 элементов. При запросе 11-го элемента цикл foreach завершится, выполнение цикла while продолжится. На следующей итерации цикла while выполнится асинхронный запрос второй страницы данных, после чего будет выдан 11-й элемент. И т.д…
В течение многих лет использовать async и await с yield return было невозможно, но асинхронные потоки ввели эту возможность. В примере выше стоит обратить внимание, что асинхронная работа нужна не для всех результатов. Здесь только приблизительно одному из каждых 10 элементов потребуется асинхронная работа. Если размер страницы равен 20, то асинхронная работа потребуется только одному из 20 элементов.
Это обычное поведение с асинхронными потоками. Для многих потоков большинство операций асинхронного перебора на самом деле синхронно; асинхронные потоки только позволяют асинхронно получить любой следующий элемент. Асинхронные потоки проектировались с учетом как асинхронного, так и синхронного кода; вот почему они построены на основе ValueTask<T>.
Когда вы реализуете асинхронные потоки, подумайте о поддержке отмены. Некоторые сценарии не требуют реальной отмены: потребляющий код всегда может отказаться от получения следующего элемента. Это абсолютно нормальный подход при отсутствии внешнего источника для отмены. Если вы хотите, чтобы асинхронный поток можно было отменить даже в процессе получения следующего элемента, то следует обеспечить поддержку отмены с использованием
CancellationToken
.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
👍1
День 1030. #ЗаметкиНаПолях #AsyncTips
Потребление асинхронных потоков
Создание асинхронных потоков
Задача: обработать результаты асинхронного потока.
Решение
Потребление асинхронного потока основано на объединении конструкций ожидания и перечисления в
На концептуальном уровне вызывается метод
Также можно выполнить асинхронную обработку каждого элемента:
В этом случае
В
Итого
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
Потребление асинхронных потоков
Создание асинхронных потоков
Задача: обработать результаты асинхронного потока.
Решение
Потребление асинхронного потока основано на объединении конструкций ожидания и перечисления в
await foreach
. Например, для асинхронного потока, который потребляет ответы API по страницам, можно организовать вывод элементов в консоль:public async Task ProcessAsync(HttpClient client)
{
await foreach (var value in GetAsync(client))
{
Console.WriteLine(value);
}
}
На концептуальном уровне вызывается метод
GetAsync
, который возвращает IAsyncEnumerable<T>
. Цикл foreach затем создаёт асинхронный перечислитель на базе асинхронного потока. Асинхронные перечислители на логическом уровне похожи на обычные перечислители, не считая того, что операция «получить следующий элемент» может быть асинхронной. Таким образом, await foreach
будет ожидать поступления следующего элемента или завершения асинхронного перечислителя. Если элемент поступил, то await foreach
выполнит тело цикла; если асинхронный перечислитель завершён, происходит выход из цикла.Также можно выполнить асинхронную обработку каждого элемента:
await foreach (var val in GetAsync(client))
{
// асинхронная работа
await Task.Delay(100);
Console.WriteLine(val);
}
В этом случае
await foreach
не переходит к следующему элементу до завершения тела цикла. Таким образом, await foreach
асинхронно получит первый элемент, после чего асинхронно выполнит тело цикла для первого элемента, затем асинхронно получит второй элемент, асинхронно выполнит тело цикла для второго элемента и т.д.В
await foreach
скрыта команда await: к операции «получить следующий элемент» применяется await
. С обычной командой await
можно обойти захват контекста с помощью ConfigureAwait(false)
. Асинхронные потоки также это поддерживают:await foreach (var val in
GetValuesAsync(client).ConfigureAwait(false))
{
await Task.Delay(100)
.ConfigureAwait(false);
Console.WriteLine(val);
}
Итого
await foreach
— самый логичный способ потребления асинхронных потоков. Язык поддерживает ConfigureAwait(false)
для предотвращения захвата контекста в await foreach
. Также возможен вариант с передачей маркеров отмены. Об этом позже.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
День 1031. #Карьера
Как Избежать Вредных Привычек, Работая Удалённо
Локдаун поспособствовал переходу многих разработчиков ПО на удалёнку. Но возникла проблема, как сохранить рабочий настрой дома? Ниже приведены пять вредных привычек, которые могут завести работающие дома, и советы, как их избежать.
1. Совмещение домашних и рабочих задач
Это может не показаться дурной привычкой. В конце концов, одновременное выполнение множества дел помогает сделать больше, не так ли? Так почему бы не помыть посуду, пока вы сидите на вебинаре, только не забыв отключить звук.
Некоторые люди склонны выполнять несколько задач одновременно, когда их руководители и коллеги не видят. Но одновременное выполнение двух или более дел, особенно когда вы выполняете домашние задачи в рабочее время или наоборот, приводит только к чрезмерному стрессу. Многозадачность никогда не бывает так же эффективна, как концентрация на одной задаче.
Делайте только одно дело за раз и в первую очередь беритесь за самые насущные проекты. Одновременное выполнение нескольких дел только помешает вам делать что-либо из них эффективно.
2. Работа круглосуточно
То, что вы можете работать с полуночи до 3 часов ночи, не означает, что вы должны это делать. На самом деле, наиболее продуктивные люди работают в обычное время, без выходных или сверхурочных. Кэл Ньюпорт - профессор вычислительной техники Джорджтаунского университета - в своей книге «В работу с головой» («Deep Work») помогает повысить продуктивность на работе.
Один из примеров - то, что он называет «продуктивностью по графику». Планирование всего рабочего дня по часам, заранее, при этом позволяя себе перемещать блоки при необходимости. По словам Ньюпорта, поддержание регулярного рабочего графика и отключение «домашнего офиса» в конце рабочего дня - это наиболее эффективный способ работы без стресса или выгорания. Если вы ограничиваете свой рабочий день, вам не нужно работать по ночам из-за того, что вы тратили рабочее время на социальные сети.
3. Проверка почты и «мелкая работа»
По словам Ньюпорта, важная работа требует умственного труда и большой концентрации. Не избегайте этого, заполняя время мелкой работой, которую Ньюпорт определяет как «когнитивно простые логистические задачи, которые часто выполняются в фоновом режиме». Это проверка почты, сотни мелких правок в вашей презентации и прочие слабо связанные с основной работой вещи.
Когда вы сохраняете свои умственные способности, чтобы по-настоящему сосредоточиться на поставленной задаче, вы сможете сделать её даже лучше, чем ожидали. Это потому, что, погрузившись в работу с головой, вы попадаете в состояние потока, когда время проходит незаметно.
4. Домашняя одежда
Возможно, вы шутили с друзьями о том, что весь день работаете в пижаме. Но, если вы действительно так делаете, самое время надеть соответствующую рабочую одежду. По словам Шэрон Койфман, президента кадрового агентства, которое нанимает удалённых сотрудников, между тем, что вы носите, и вашим настроением существует сильная связь. Вот почему рекомендуется вставать в установленное время и носить ту же одежду, что и в реальном офисе, вплоть до обуви. Профессиональная одежда способствует профессиональному отношению. С другой стороны, пижама может вселить в вас чувство неопрятности и дезорганизованности.
5. Экономия на инструментах
Домашний офис должен быть оснащён теми же инструментами и технологиями, которые используются в реальном офисе, или даже лучше. Удалённым сотрудникам нужен хороший микрофон, который экранирует фоновый шум (например, лай соседской собаки), и эргономичные офисные стол и кресло, чтобы избежать боли в спине, запястьях и т.п.
Есть ещё один бонусный совет: сохраняйте чувство юмора. Оно понадобится вам, когда дети шумят в соседней комнате, где-то на улице орёт автомобильная сигнализация, а вашему боссу нужно срочно провести онлайн конференцию.
Удалёнщики, какие у вас возникали плохие привычки, и как вы с ними боролись?
Источник: https://www.asme.org/topics-resources/content/five-tips-in-avoiding-bad-habits-when-working-remotely
Как Избежать Вредных Привычек, Работая Удалённо
Локдаун поспособствовал переходу многих разработчиков ПО на удалёнку. Но возникла проблема, как сохранить рабочий настрой дома? Ниже приведены пять вредных привычек, которые могут завести работающие дома, и советы, как их избежать.
1. Совмещение домашних и рабочих задач
Это может не показаться дурной привычкой. В конце концов, одновременное выполнение множества дел помогает сделать больше, не так ли? Так почему бы не помыть посуду, пока вы сидите на вебинаре, только не забыв отключить звук.
Некоторые люди склонны выполнять несколько задач одновременно, когда их руководители и коллеги не видят. Но одновременное выполнение двух или более дел, особенно когда вы выполняете домашние задачи в рабочее время или наоборот, приводит только к чрезмерному стрессу. Многозадачность никогда не бывает так же эффективна, как концентрация на одной задаче.
Делайте только одно дело за раз и в первую очередь беритесь за самые насущные проекты. Одновременное выполнение нескольких дел только помешает вам делать что-либо из них эффективно.
2. Работа круглосуточно
То, что вы можете работать с полуночи до 3 часов ночи, не означает, что вы должны это делать. На самом деле, наиболее продуктивные люди работают в обычное время, без выходных или сверхурочных. Кэл Ньюпорт - профессор вычислительной техники Джорджтаунского университета - в своей книге «В работу с головой» («Deep Work») помогает повысить продуктивность на работе.
Один из примеров - то, что он называет «продуктивностью по графику». Планирование всего рабочего дня по часам, заранее, при этом позволяя себе перемещать блоки при необходимости. По словам Ньюпорта, поддержание регулярного рабочего графика и отключение «домашнего офиса» в конце рабочего дня - это наиболее эффективный способ работы без стресса или выгорания. Если вы ограничиваете свой рабочий день, вам не нужно работать по ночам из-за того, что вы тратили рабочее время на социальные сети.
3. Проверка почты и «мелкая работа»
По словам Ньюпорта, важная работа требует умственного труда и большой концентрации. Не избегайте этого, заполняя время мелкой работой, которую Ньюпорт определяет как «когнитивно простые логистические задачи, которые часто выполняются в фоновом режиме». Это проверка почты, сотни мелких правок в вашей презентации и прочие слабо связанные с основной работой вещи.
Когда вы сохраняете свои умственные способности, чтобы по-настоящему сосредоточиться на поставленной задаче, вы сможете сделать её даже лучше, чем ожидали. Это потому, что, погрузившись в работу с головой, вы попадаете в состояние потока, когда время проходит незаметно.
4. Домашняя одежда
Возможно, вы шутили с друзьями о том, что весь день работаете в пижаме. Но, если вы действительно так делаете, самое время надеть соответствующую рабочую одежду. По словам Шэрон Койфман, президента кадрового агентства, которое нанимает удалённых сотрудников, между тем, что вы носите, и вашим настроением существует сильная связь. Вот почему рекомендуется вставать в установленное время и носить ту же одежду, что и в реальном офисе, вплоть до обуви. Профессиональная одежда способствует профессиональному отношению. С другой стороны, пижама может вселить в вас чувство неопрятности и дезорганизованности.
5. Экономия на инструментах
Домашний офис должен быть оснащён теми же инструментами и технологиями, которые используются в реальном офисе, или даже лучше. Удалённым сотрудникам нужен хороший микрофон, который экранирует фоновый шум (например, лай соседской собаки), и эргономичные офисные стол и кресло, чтобы избежать боли в спине, запястьях и т.п.
Есть ещё один бонусный совет: сохраняйте чувство юмора. Оно понадобится вам, когда дети шумят в соседней комнате, где-то на улице орёт автомобильная сигнализация, а вашему боссу нужно срочно провести онлайн конференцию.
Удалёнщики, какие у вас возникали плохие привычки, и как вы с ними боролись?
Источник: https://www.asme.org/topics-resources/content/five-tips-in-avoiding-bad-habits-when-working-remotely
👍1
День 1032. #юмор
А править прямо на проде. Ммм... непередаваемые ощущения.
А править прямо на проде. Ммм... непередаваемые ощущения.