#оффтоп Тут Хабр разжёг выкатил исследование зарплат в ИТ, что вызвало немало споров в различных сообществах. Вот и я решил поинтересоваться. Опрос ниже.
Получаете ли вы медианную зарплату по региону (ближайший город из картинки выше) и по специализации?
Anonymous Poll
24%
Да, и по региону, и по специализации вцелом
22%
Только больше медианной по региону
54%
Меньше медианной по региону
День пятьсот тридцать девятый. #ЧтоНовенького #CSharp9
C#9: Новые Ключевые слова and, or и not для Сопоставления по Шаблону
Хотя это может звучать как первоапрельская шутка, в C#9 хотят добавить
Чтобы сделать сопоставление по шаблону более гибким и мощным, хотят добавить концепцию конъюнктивных, дизъюнктивных и отрицательных шаблонов. Внешне они выглядят как логические операции, в которых вы хотите выполнить сопоставление с обоими шаблонами (конъюнктивный), с любым из шаблонов (дизъюнктивный), либо не совпадающее с шаблоном (отрицательный).
В этом и проблема. Если вы работаете с логическими значениями, то операторы
Если бы мы использовали операторы
Поэтому необходимы новые ключевые слова, чтобы избежать двусмысленности. Подробнее они обсуждаются в этом предложении на GitHub.
Источник: https://www.infoq.com/news/2020/07/CSharp-And-Or-Not/
C#9: Новые Ключевые слова and, or и not для Сопоставления по Шаблону
Хотя это может звучать как первоапрельская шутка, в C#9 хотят добавить
and
, or
и not
в список ключевых слов для использования в сопоставлении по шаблону.Чтобы сделать сопоставление по шаблону более гибким и мощным, хотят добавить концепцию конъюнктивных, дизъюнктивных и отрицательных шаблонов. Внешне они выглядят как логические операции, в которых вы хотите выполнить сопоставление с обоими шаблонами (конъюнктивный), с любым из шаблонов (дизъюнктивный), либо не совпадающее с шаблоном (отрицательный).
В этом и проблема. Если вы работаете с логическими значениями, то операторы
&&
и ||
будут неоднозначными. Компилятор не сможет определить, относятся они к значениям или к шаблонам. Чтобы проиллюстрировать эту идею, рассмотрим дизъюнктивный шаблон:if (myBool is true or false)Это будет интерпретировано как «истина, если myBool равно true или если myBool равно false».
Если бы мы использовали операторы
&&
и ||
для объединения шаблонов, получился бы следующий код:if (myBool is true || false)Но это буквально означает «истина, если myBool равняется результату логического выражения (true или false)», что можно упростить до «истина, если myBool равняется true». А это совершенно не то, что мы хотели бы получить в дизъюнктивном шаблоне.
Поэтому необходимы новые ключевые слова, чтобы избежать двусмысленности. Подробнее они обсуждаются в этом предложении на GitHub.
Источник: https://www.infoq.com/news/2020/07/CSharp-And-Or-Not/
День пятьсот сороковой. #MoreEffectiveCSharp
14. Различайте Интерфейсные и Абстрактные Методы
На первый взгляд реализация интерфейса выглядит так же, как и переопределение абстрактной функции. Но есть различия:
- Реализация абстрактного члена базового класса должна быть виртуальной; реализация члена интерфейса – не обязательно.
- Интерфейсы могут быть реализованы явно, что скроет их реализацию от открытого интерфейса класса.
Рассмотрим варианты реализации простого интерфейса в иерархии классов:
Также можно реализовать интерфейс без фактической реализации его методов:
Можно реализовать паттерн Шаблонный метод:
Реализация интерфейсов дает больше возможностей, чем создание и переопределение виртуальных функций. Вы можете точно решить, как и когда производные классы могут изменять поведение по умолчанию членов интерфейса. Методы интерфейса - это не виртуальные методы, а отдельный контракт.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 15.
14. Различайте Интерфейсные и Абстрактные Методы
На первый взгляд реализация интерфейса выглядит так же, как и переопределение абстрактной функции. Но есть различия:
- Реализация абстрактного члена базового класса должна быть виртуальной; реализация члена интерфейса – не обязательно.
- Интерфейсы могут быть реализованы явно, что скроет их реализацию от открытого интерфейса класса.
Рассмотрим варианты реализации простого интерфейса в иерархии классов:
interface IMessage {Метод
void Message();
}
public class MyClass : IMessage {
public void Message() => WriteLine(nameof(MyClass));
}
Message()
является частью публичного интерфейса MyClass
, а также может быть вызван через приведение к IMessage
. Теперь добавим производный класс:public class MyDerivedClass : MyClass {Нам пришлось добавить ключевое слово
public new void Message() =>
WriteLine(nameof(MyDerivedClass));
}
new
. MyClass.Message()
не является виртуальным, его нельзя переопределить. Класс MyDerived
создаёт новый метод Message
, который не переопределяет MyClass.Message
, а скрывает его. Однако MyClass.Message
по-прежнему доступен через IMessage
:MyDerivedClass d = new MyDerivedClass();Приведение к
d.Message(); // выведет "MyDerivedClass"
IMessage m = d as IMessage;
m.Message(); // выведет "MyClass"
IMessage
вызывает базовую реализацию. Если доступа к базовому классу нет, можно реализовать интерфейс и в производном классе:public class MyDerivedClass : MyClass, IMessage {…}Тогда поведение изменится:
m.Message(); // выведет "MyDerivedClass"Ключевое слово new всё равно придётся использовать. Базовая реализация будет доступна через апкаст:
MyClass b = d;Если доступ к базовому классу есть, объявите интерфейсный метод виртуальным, а в производных классах используйте ключевое слово override. Тогда переопределённая версия метода будет вызываться всегда: и из производного класса, и после приведения как к базовому классу, так и к интерфейсу.
b.Message(); // выведет "MyClass"
Также можно реализовать интерфейс без фактической реализации его методов:
public abstract class MyClass : IMessage {Тогда все конкретные производные типы должны переопределить и предоставить собственную реализацию
public abstract void Message();
}
Message()
. Интерфейс IMessage
является частью объявления MyClass
, но реализация методов откладывается до каждого конкретного производного класса.Можно реализовать паттерн Шаблонный метод:
public class MyClass : IMessage {Любой производный класс может переопределить
protected virtual void OnMessage() {}
public void Message() {
OnMessage();
WriteLine(nameof(MyClass));
}
}
OnMessage()
и добавить свой код в реализацию контракта IMessage
.Реализация интерфейсов дает больше возможностей, чем создание и переопределение виртуальных функций. Вы можете точно решить, как и когда производные классы могут изменять поведение по умолчанию членов интерфейса. Методы интерфейса - это не виртуальные методы, а отдельный контракт.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 15.
День пятьсот сорок первый. #Оффтоп
Сегодня расскажу про классную серию видео на ютуб от Shawn Wildermuth. Серия называется Maintainers (Сопровождающие). Это видео о людях, которые сделали внушительный вклад в развитие открытого кода. В первом видео серии Jimmy Bogard описывает историю создания знаменитого AutoMapper. Как он создавался, почему было принято решение сделать его открытым, как появлялись первые контрибьюторы и почему довольно сложно сразу применять изменения сделанные контрибьюторами.
А поскольку это видео всего на 9 минут, вот вам ещё одно от Jimmy Bogard. Это его выступление на онлайн конференции NDC в апреле, где он рассказывает про «Архитектуру Вертикальных Слоёв» (Vertical Slice Architecture).
Проблема стандартной n-слойной архитектуры приложений, состоящей из UI, домена, бизнес-логики и слоя доступа к данным, в том, что чтобы сделать даже небольшое изменение (например, добавить поле в форму), приходится изменять огромное количество файлов и классов во всех слоях приложения.
Почему бы не разделить приложение по слоям вариантов использования. Фактически вариантов использования веб-приложения всего два:
GET:
В общем, гораздо более подробно это описано в видео. Энджой)))
Сегодня расскажу про классную серию видео на ютуб от Shawn Wildermuth. Серия называется Maintainers (Сопровождающие). Это видео о людях, которые сделали внушительный вклад в развитие открытого кода. В первом видео серии Jimmy Bogard описывает историю создания знаменитого AutoMapper. Как он создавался, почему было принято решение сделать его открытым, как появлялись первые контрибьюторы и почему довольно сложно сразу применять изменения сделанные контрибьюторами.
А поскольку это видео всего на 9 минут, вот вам ещё одно от Jimmy Bogard. Это его выступление на онлайн конференции NDC в апреле, где он рассказывает про «Архитектуру Вертикальных Слоёв» (Vertical Slice Architecture).
Проблема стандартной n-слойной архитектуры приложений, состоящей из UI, домена, бизнес-логики и слоя доступа к данным, в том, что чтобы сделать даже небольшое изменение (например, добавить поле в форму), приходится изменять огромное количество файлов и классов во всех слоях приложения.
Почему бы не разделить приложение по слоям вариантов использования. Фактически вариантов использования веб-приложения всего два:
GET:
Запрос (Query) – Обработчик (Handler) – Ответ (Response)POST:
Команда (Command) – Обработчик (Handler) – Ответ (Response)Тогда можно использовать принцип CQRS и разделить приложение на соответствующие слои. Если совсем упрощённо, то в MVC, Модель – это Запрос/Команда, логика Контроллера помещается в Обработчик, а Ответ передаётся в Представление, либо в качестве ответа API.
В общем, гораздо более подробно это описано в видео. Энджой)))
День пятьсот сорок второй. #ЧтоНовенького #CSharp9
C#9: Операторы Диапазона в Конструкциях Switch и Сопоставлениях по Шаблону
С момента первого выхода C# разработчики жаловались на отсутствие операторов диапазона в конструкциях
Следующие шаблоны будут разрешены после ключевых слов
-
-
-
-
Шаблоны всё ещё ограничены только константами. Это становится проблемой, когда вы имеете дело с датой, временем или другими аналогичными структурами, поскольку они не имеют константного представления в C#.
В обсуждении предложения на GitHub Нил Гафтер написал по этому поводу:
«Смысл этой функциональности был в расширении сопоставления по шаблону. В частности, ограничение только константами сделано, чтобы компилятор мог проанализировать и оптимизировать весь набор операций сопоставления по шаблону. Если компилятор не знает значения, с которым он сопоставляет, он не сможет этого сделать. В конце концов, чем плохи обычные выражения?»
Мариуш Павельски отвечает, почему ограничение может стать проблемой:
«Я просто думаю, что будет много людей, которые захотят использовать ключевые слова is, and и or просто как ещё один способ написания логических выражений. Ещё одна небольшая функция C#, которая делает код более лаконичным. Они не будут знать, что это часть большой функциональности сопоставления по шаблону, которая «была разработана для работы с константами». Они будут просто сбиты с толку, когда вместо константы будут использовать имя переменной и получат ошибку «CS0150: A constant value is expected» (Ожидается константное значение).»
Как бы то ни было, операторы and, or и not также могут быть использованы в сочетании с диапазонами. Например,
Это немного трудно читать, поэтому в выражениях можно использовать круглые скобки:
Источник: https://www.infoq.com/news/2020/07/CSharp-9-Range-Patterns/
C#9: Операторы Диапазона в Конструкциях Switch и Сопоставлениях по Шаблону
С момента первого выхода C# разработчики жаловались на отсутствие операторов диапазона в конструкциях
switch
. Как часть улучшений сопоставлений по шаблону в C#9, это ограничение было устранено.Следующие шаблоны будут разрешены после ключевых слов
case
или is
:-
< константа
-
> константа
-
<= константа
-
>= константа
Шаблоны всё ещё ограничены только константами. Это становится проблемой, когда вы имеете дело с датой, временем или другими аналогичными структурами, поскольку они не имеют константного представления в C#.
В обсуждении предложения на GitHub Нил Гафтер написал по этому поводу:
«Смысл этой функциональности был в расширении сопоставления по шаблону. В частности, ограничение только константами сделано, чтобы компилятор мог проанализировать и оптимизировать весь набор операций сопоставления по шаблону. Если компилятор не знает значения, с которым он сопоставляет, он не сможет этого сделать. В конце концов, чем плохи обычные выражения?»
Мариуш Павельски отвечает, почему ограничение может стать проблемой:
«Я просто думаю, что будет много людей, которые захотят использовать ключевые слова is, and и or просто как ещё один способ написания логических выражений. Ещё одна небольшая функция C#, которая делает код более лаконичным. Они не будут знать, что это часть большой функциональности сопоставления по шаблону, которая «была разработана для работы с константами». Они будут просто сбиты с толку, когда вместо константы будут использовать имя переменной и получат ошибку «CS0150: A constant value is expected» (Ожидается константное значение).»
Как бы то ни было, операторы and, or и not также могут быть использованы в сочетании с диапазонами. Например,
bool IsLetter(char c) =>
c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';
Это немного трудно читать, поэтому в выражениях можно использовать круглые скобки:
bool IsLetter(char c) =>
c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');
Источник: https://www.infoq.com/news/2020/07/CSharp-9-Range-Patterns/
День пятьсот сорок третий. #DotNetAZ
Dotnet A-Z. 4
В этой серии постов рассмотрим наиболее распространённые понятия в .NET в алфавитном порядке.
implementation of .NET (реализация .NET)
Реализация .NET включает в себя:
- Одну или несколько сред исполнения: CLR, CoreCLR, CoreRT.
- Библиотеку классов, которая реализует версию .NET Standard и может включать дополнительные API: .NET Framework Base Class Library, .NET Core Base Class Library.
- Необязательно: один или несколько фреймворков приложений: ASP.NET, Windows Forms и WPF включены в .NET Framework.
- Необязательно: инструменты разработки. Некоторые инструменты разработки используются несколькими реализациями.
Примеры реализаций .NET:
- .NET Framework – Реализация .NET, которая работает только в Windows.
- .NET Core – Кроссплатформенная, высокопроизводительная реализация .NET с открытым исходным кодом.
- Universal Windows Platform (UWP) – Реализация .NET, которая используется для создания современных приложений с сенсорным управлением и для ПО Интернета вещей (IoT).
Library (библиотека)
Коллекция API, которая может быть вызвана из приложений или других библиотек. Библиотека .NET состоит из одной или нескольких сборок.
Термины библиотека и фреймворк часто используются взаимозаменяемо.
Metapackage (метапакет)
Пакет NuGet, это пакет, который не содержит сборок, но содержит список зависимостей. Используется для лёгкого добавления заданного набора библиотек в проект, т.к. достаточно установить только метапакет и все его зависимости будут автоматически загружены и подключены.
Например, метапакет
Источник: https://docs.microsoft.com/en-us/dotnet/standard/glossary
Dotnet A-Z. 4
В этой серии постов рассмотрим наиболее распространённые понятия в .NET в алфавитном порядке.
implementation of .NET (реализация .NET)
Реализация .NET включает в себя:
- Одну или несколько сред исполнения: CLR, CoreCLR, CoreRT.
- Библиотеку классов, которая реализует версию .NET Standard и может включать дополнительные API: .NET Framework Base Class Library, .NET Core Base Class Library.
- Необязательно: один или несколько фреймворков приложений: ASP.NET, Windows Forms и WPF включены в .NET Framework.
- Необязательно: инструменты разработки. Некоторые инструменты разработки используются несколькими реализациями.
Примеры реализаций .NET:
- .NET Framework – Реализация .NET, которая работает только в Windows.
- .NET Core – Кроссплатформенная, высокопроизводительная реализация .NET с открытым исходным кодом.
- Universal Windows Platform (UWP) – Реализация .NET, которая используется для создания современных приложений с сенсорным управлением и для ПО Интернета вещей (IoT).
Library (библиотека)
Коллекция API, которая может быть вызвана из приложений или других библиотек. Библиотека .NET состоит из одной или нескольких сборок.
Термины библиотека и фреймворк часто используются взаимозаменяемо.
Metapackage (метапакет)
Пакет NuGet, это пакет, который не содержит сборок, но содержит список зависимостей. Используется для лёгкого добавления заданного набора библиотек в проект, т.к. достаточно установить только метапакет и все его зависимости будут автоматически загружены и подключены.
Например, метапакет
Microsoft.AspNetCore.App
предоставляет набор API по умолчанию для создания приложения ASP.NET Core.Источник: https://docs.microsoft.com/en-us/dotnet/standard/glossary
День пятьсот сорок четвёртый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
52. Дайте Проекту Голос
Ваш проект скорее всего использует систему контроля версий. Возможно, он подключен к серверу непрерывной интеграции, который проверяет правильность кода с помощью автоматических тестов. Это замечательно.
Вы можете добавить инструменты статического анализа кода на сервере непрерывной интеграции для сбора метрик кода. Эти метрики предоставляют обратную связь о конкретных аспектах вашего кода, а также об их изменении с течением времени. Если вы устанавливаете метрики кода, всегда будет некоторая граница, которую вы не захотите пересекать. Предположим, вы начали с 20% покрытия тестами и никогда не хотите падать ниже 15%. Непрерывная интеграция помогает отслеживать все эти цифры, но вам всё равно придётся регулярно их проверять. Но представьте, что вы могли бы делегировать эту задачу самому проекту, позволив ему сообщать, когда метрики ухудшаются.
Вам нужно дать право голоса вашему проекту. Информирование разработчиков может быть сделано по электронной почте или с помощью мгновенных сообщений. Но ещё эффективнее будет использование в вашем офисе устройства экстремальной обратной связи (XFD).
Идея XFD заключается в том, чтобы управлять физическим устройством: лампой, фонтанчиком, игрушечным роботом или даже ракетной установкой, - на основе результатов автоматического анализа. Всякий раз, когда ваши ограничения нарушаются, устройство будет менять своё состояние. Например, загорится лампа. Вы не сможете пропустить это сообщение, даже если вы спешите домой.
В зависимости от типа устройства XFD вы сможете услышать о неудачной сборке, увидеть «красный свет» или даже почувствовать запах плохого кода. Устройства могут быть установлены в разных местах, если вы работаете в распределённой команде. Вы можете разместить светофор в офисе менеджера проекта, указывающий на текущее состояние проекта. Он это оценит.
Только ваша фантазия может ограничить вас в выборе устройства. Вы можете набить офис команды радиоуправляемыми игрушками, а если хотите выглядеть более профессионально, приобретите стильные дизайнерские светильники. Всё, что имеет подключение к электричеству или пульт дистанционного управления, потенциально может быть использовано в качестве устройства экстремальной обратной связи.
Устройства XFD играют роль голосовых связок вашего проекта. С его помощью проект критикует или хвалит разработчиков в соответствии с правилами, выбранными командой. Вы можете пойти дальше, применив ПО для синтеза речи и пару динамиков. Тогда ваш проект действительно станет говорить.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Daniel Lindner.
97 Вещей, Которые Должен Знать Каждый Программист
52. Дайте Проекту Голос
Ваш проект скорее всего использует систему контроля версий. Возможно, он подключен к серверу непрерывной интеграции, который проверяет правильность кода с помощью автоматических тестов. Это замечательно.
Вы можете добавить инструменты статического анализа кода на сервере непрерывной интеграции для сбора метрик кода. Эти метрики предоставляют обратную связь о конкретных аспектах вашего кода, а также об их изменении с течением времени. Если вы устанавливаете метрики кода, всегда будет некоторая граница, которую вы не захотите пересекать. Предположим, вы начали с 20% покрытия тестами и никогда не хотите падать ниже 15%. Непрерывная интеграция помогает отслеживать все эти цифры, но вам всё равно придётся регулярно их проверять. Но представьте, что вы могли бы делегировать эту задачу самому проекту, позволив ему сообщать, когда метрики ухудшаются.
Вам нужно дать право голоса вашему проекту. Информирование разработчиков может быть сделано по электронной почте или с помощью мгновенных сообщений. Но ещё эффективнее будет использование в вашем офисе устройства экстремальной обратной связи (XFD).
Идея XFD заключается в том, чтобы управлять физическим устройством: лампой, фонтанчиком, игрушечным роботом или даже ракетной установкой, - на основе результатов автоматического анализа. Всякий раз, когда ваши ограничения нарушаются, устройство будет менять своё состояние. Например, загорится лампа. Вы не сможете пропустить это сообщение, даже если вы спешите домой.
В зависимости от типа устройства XFD вы сможете услышать о неудачной сборке, увидеть «красный свет» или даже почувствовать запах плохого кода. Устройства могут быть установлены в разных местах, если вы работаете в распределённой команде. Вы можете разместить светофор в офисе менеджера проекта, указывающий на текущее состояние проекта. Он это оценит.
Только ваша фантазия может ограничить вас в выборе устройства. Вы можете набить офис команды радиоуправляемыми игрушками, а если хотите выглядеть более профессионально, приобретите стильные дизайнерские светильники. Всё, что имеет подключение к электричеству или пульт дистанционного управления, потенциально может быть использовано в качестве устройства экстремальной обратной связи.
Устройства XFD играют роль голосовых связок вашего проекта. С его помощью проект критикует или хвалит разработчиков в соответствии с правилами, выбранными командой. Вы можете пойти дальше, применив ПО для синтеза речи и пару динамиков. Тогда ваш проект действительно станет говорить.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Daniel Lindner.
👍1
День пятьсот сорок пятый. #ЧтоНовенького #CSharp9
C#9: Незначительные Улучшения в Лямбдах
В C#9 лямбда-функции получат два обновления. Ни одно из них не изменит способ написания кода, но они помогут разработчику прояснить свои намерения.
Дискард-Параметры Лямбда Функций
Позволят разработчикам явно указать, что некоторые параметры не нужны, что предотвратит ошибочные предупреждения компилятора о неиспользуемых параметрах. Это может быть полезно, например, в обработчиках событий, когда не нужны параметры
Будут использоваться, чтобы обозначить, что лямбда или анонимная функция не может захватывать локальные переменные (включая параметры). Вот пример из оригинального предложения функционала:
Чтобы избежать случайного захвата любого локального состояния при предоставлении лямбда-функций в качестве аргумента метода, предлагается добавить к лямбда-объявлению ключевое слово
- может ссылаться на статические члены из окружающего кода;
- может ссылаться на определения констант из окружающего кода;
- не может захватывать состояние из окружающего кода, т.е. локальные объекты, параметры и
- не может ссылаться на экземплярные члены окружающего её класса;
-
Источник: https://www.infoq.com/news/2020/07/CSharp-Lambdas/
C#9: Незначительные Улучшения в Лямбдах
В C#9 лямбда-функции получат два обновления. Ни одно из них не изменит способ написания кода, но они помогут разработчику прояснить свои намерения.
Дискард-Параметры Лямбда Функций
Позволят разработчикам явно указать, что некоторые параметры не нужны, что предотвратит ошибочные предупреждения компилятора о неиспользуемых параметрах. Это может быть полезно, например, в обработчиках событий, когда не нужны параметры
sender
и eventArgs
:button1.Click += (s, e) => ShowDialog();Замена параметров, как показано ниже, позволит явно указать, что они не используются:
button1.Click += (_, _) => ShowDialog();При необходимости могут быть использованы типы:
var handler = (object _, EventArgs _) => ShowDialog();Статические Анонимные Функции
Будут использоваться, чтобы обозначить, что лямбда или анонимная функция не может захватывать локальные переменные (включая параметры). Вот пример из оригинального предложения функционала:
int y = 10;Проблема в том, что это неявно приводит к увеличению времени жизни локальной переменной, т.к. анонимная функция может существовать дольше, чем окружающий её метод.
someMethod(x => x + y);
//захватывает 'y', приводя к неявному выделению памяти
Чтобы избежать случайного захвата любого локального состояния при предоставлении лямбда-функций в качестве аргумента метода, предлагается добавить к лямбда-объявлению ключевое слово
static
. Это сделает лямбда-функцию похожей на статический метод, который не может захватывать локальные объекты и не имеет доступа к this
или base
:int y = 10;Чтобы исправить эту ошибку, переменная y должна быть изменена на константу или статическое поле:
someMethod(static x => x + y); //ошибка!
const int y = 10;Вот основные правила для статических анонимных функций:
someMethod(static x => x + y);
- может ссылаться на статические члены из окружающего кода;
- может ссылаться на определения констант из окружающего кода;
- не может захватывать состояние из окружающего кода, т.е. локальные объекты, параметры и
this
из окружающего кода недоступны;- не может ссылаться на экземплярные члены окружающего её класса;
-
nameof()
внутри статической анонимной функции может ссылаться на локальные объекты, параметры, this
или base
из окружающего кода.Источник: https://www.infoq.com/news/2020/07/CSharp-Lambdas/
День пятьсот сорок шестой.
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Начало 1-2
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
1. Непонимание Отложенного Исполнения
Опытные разработчики хорошо осведомлены об этой функции .NET, но она может испортить жизнь тем, кто о ней не знает. Если коротко, методы/операторы, возвращающие
Рассмотрим следующее выдуманное модульное тестирование:
2. Предположение о Порядке Элементов в Словаре
Элементы в
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Начало 1-2
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
1. Непонимание Отложенного Исполнения
Опытные разработчики хорошо осведомлены об этой функции .NET, но она может испортить жизнь тем, кто о ней не знает. Если коротко, методы/операторы, возвращающие
IEnumerable<T>
через yield
, выполняются не на строке вызова метода/оператора, а когда к результирующей коллекции обращаются каким-либо образом. То же относится к большинству методов LINQ.Рассмотрим следующее выдуманное модульное тестирование:
[TestMethod]Оба теста не пройдут. Первый, потому что к
[ExpectedException(typeof(ArgumentNullException))]
public void Ensure_Null_Exception_Is_Thrown() {
var result = RepeatString5Times(null);
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void Ensure_Invalid_Operation_Exception_Is_Thrown() {
var result = RepeatString5Times("test");
var firstItem = result.First();
}
private IEnumerable<string> RepeatString5Times(string toRepeat) {
if (toRepeat == null)
throw new ArgumentNullException(nameof(toRepeat));
for (int i = 0; i < 5; i++) {
if (i == 3)
throw new InvalidOperationException("3 ужасное число");
yield return $"{toRepeat} - {i}";
}
}
result
ни разу не обращаются и тело метода не вызывается. Второй, т.к. механизм отложенного выполнения выйдет из метода, когда это необходимо (т.е. после выдачи первого элемента), поэтому i == 3
никогда не выполнится.2. Предположение о Порядке Элементов в Словаре
Элементы в
List<T>
сохраняются в том же порядке, в котором вы их добавляете. Но иногда нужно иметь объект, связанный с элементом списка, и очевидным ответом является использование Dictionary<TKey, TValue>
, который позволяет указать связанное значение для ключа. Вы можете выполнить итерацию по словарю, используя foreach
, и большую часть времени он будет вести себя так, как ожидалось: вы будете получать доступ к элементам в порядке их добавления. Однако порядок элементов словаря не определён, т.е. это счастливое совпадение, и на это поведение не стоит полагаться. Это объясняется в документации Microsoft, но кто ж её читает))) Следующий код:var dict = new Dictionary<string, object>();Выведет:
dict.Add("first", new object());
dict.Add("second", new object());
dict.Remove("first");
dict.Add("third", new object());
foreach (var entry in dict)
Console.WriteLine(entry.Key);
thirdПродолжение следует…
second
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
День пятьсот сорок седьмой.
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Продолжение 3-4
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
Начало 1-2.
3. Игнорирование Безопасности Потоков
Многопоточность великолепна. При правильной реализации может произойти значительное улучшение производительности вашего приложения. Однако вы должны быть осторожны с объектами, которые вы изменяете, потому что могут возникать, на первый взгляд, случайные ошибки.
Многие классы библиотеки .NET не являются потокобезопасными, т.е. Microsoft не даёт никаких гарантий правильной работы класса при использовании параллельно из нескольких потоков. Это не было бы большой проблемой, если бы можно было сразу отлавливать возникающие проблемы, но природа многопоточности предполагает, что проблемы изменчивы и возникают непредсказуемо: скорее всего, каждое выполнение кода будет приводить к иному результату.
В качестве примера возьмем этот блок кода, который использует простой, но не потокобезопасный
Так получается, потому что метод
4. Неправильное Округление
Теперь о чём-то более простом. .NET имеет прекрасный статический метод
Продолжение следует…
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Продолжение 3-4
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
Начало 1-2.
3. Игнорирование Безопасности Потоков
Многопоточность великолепна. При правильной реализации может произойти значительное улучшение производительности вашего приложения. Однако вы должны быть осторожны с объектами, которые вы изменяете, потому что могут возникать, на первый взгляд, случайные ошибки.
Многие классы библиотеки .NET не являются потокобезопасными, т.е. Microsoft не даёт никаких гарантий правильной работы класса при использовании параллельно из нескольких потоков. Это не было бы большой проблемой, если бы можно было сразу отлавливать возникающие проблемы, но природа многопоточности предполагает, что проблемы изменчивы и возникают непредсказуемо: скорее всего, каждое выполнение кода будет приводить к иному результату.
В качестве примера возьмем этот блок кода, который использует простой, но не потокобезопасный
List<T>
:var items = new List<int>();Мы добавляем числа от 0 до 4 в список по 10000 раз каждое, т.е. мы должны получить список в 50000 элементов, верно? Ну, есть небольшой шанс, что так и получится, но ниже мои результаты 5 выполнений:
var tasks = new List<Task>();
for (int i = 0; i < 5; i++) {
tasks.Add(Task.Run(() => {
for (int k = 0; k < 10000; k++)
items.Add(i);
}));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine(items.Count);
28191Попробуйте сами
23536
44346
40007
40476
Так получается, потому что метод
Add
не является атомарным, т.е. поток может «прервать» исполнение метода. То есть размер массива может измениться, в то время как другой поток находится в процессе добавления элемента, либо два потока могут добавлять элементы с одним индексом. Иногда могут возникать исключения IndexOutOfRange
или ArgumentException
, вероятно, потому что размер массива изменился во время добавления к нему элемента. Что делать? Мы могли бы использовать ключевое слово lock
, чтобы гарантировать, что только один поток может добавлять элемент в список одновременно, но это может значительно повлиять на производительность. Microsoft любезно предоставляет несколько потрясающих коллекций, которые безопасны для потоков и оптимизированы для производительности.4. Неправильное Округление
Теперь о чём-то более простом. .NET имеет прекрасный статический метод
Round
в классе Math
, который принимает числовое значение и округляет до заданного десятичного знака. Работает обычно идеально, но что делать, когда вам нужно округлить 2.25
до десятых? Math.Round(2.25, 1);Вероятно, вы ожидаете, что это округлится до
2.3
– ведь нас так учили в школе. Однако, похоже, .NET использует «округление банкиров» и округляет приведенный пример до 2.2
! Банкиры в таком случае округляют до ближайшей чётной цифры. К счастью, это можно легко переопределить в методе Math.Round
:Math.Round(2.25, 1, MidpointRounding.AwayFromZero);По умолчанию используется
MidpointRounding.ToEven
.Продолжение следует…
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
День пятьсот сорок восьмой.
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Продолжение 5-6
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
Начало 1-2
Продолжение 3-4
5. Ужасный Класс "DBNull"
У некоторых это может вызвать неприятные воспоминания, т.к. ORM скрывает это зло от нас, но если вы используете чистый ADO.NET (
Я не уверен на 100%, почему в Microsoft решили представить
Разница может показаться незначительной, но значения
Единственное преимущество этого - вы не получите
6. Злоупотребление ленивой загрузкой в LINQ
Ленивая загрузка - это отличная функция как LINQ to SQL, так и LINQ to Entities (Entity Framework), которая позволяет загружать связанные данные таблицы по требованию. Допустим, у нас есть таблицы
Когда нужно получить данные определённого модуля, но не нужны относящиеся к нему результаты, Entity Framework достаточно умён, чтобы запросить данные только для модуля, а для получения результатов выполнить отдельный запрос, только когда они потребуются. Таким образом, приведенный ниже код будет выполнять как минимум 2 запроса: один для получения модуля, а другой для получения результатов (для каждого модуля).
Окончание следует…
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Продолжение 5-6
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
Начало 1-2
Продолжение 3-4
5. Ужасный Класс "DBNull"
У некоторых это может вызвать неприятные воспоминания, т.к. ORM скрывает это зло от нас, но если вы используете чистый ADO.NET (
SqlDataReader
и т.п.), вы рано или поздно столкнётесь с DBNull.Value
.Я не уверен на 100%, почему в Microsoft решили представить
NULL
в виде специального типа DBNull
со статическим полем Value
. Возможно, причина в обратной совместимости. Так было в Visual Basic в эпоху до .NET. VB6 не имеет унифицированной объектной модели (когда всё наследуется от System.Object
) или концепции «null». Существует Nothing
, но это скорее default
из C#, чем null
. Таким образом, в VB6 и ADO, у вас есть значение DBNull
для представления null
из БД.Разница может показаться незначительной, но значения
DBNull
и null
имеют разную семантику. Например, в строках. В VB нулевая строка равна пустой строке. Нет никакого способа разделить эти две концепции как в VB6, так и VB7+ (VB.NET).Единственное преимущество этого - вы не получите
NullReferenceException
при доступе к полю базы данных, равному NULL
. Однако при этом вы не только должны поддерживать отдельный способ проверки значений на NULL
(о чём можно легко забыть, и что может привести к серьезным ошибкам), но также вы теряете прекрасные возможности языка C#. Например, вместо:reader.GetString(0) ?? "NULL";придётся использовать:
reader.GetString(0) != DBNull.Value ? reader.GetString(0) : "NULL";Ужас!
6. Злоупотребление ленивой загрузкой в LINQ
Ленивая загрузка - это отличная функция как LINQ to SQL, так и LINQ to Entities (Entity Framework), которая позволяет загружать связанные данные таблицы по требованию. Допустим, у нас есть таблицы
Modules
и Results
с отношением «один ко многим» (модуль может иметь много результатов).Когда нужно получить данные определённого модуля, но не нужны относящиеся к нему результаты, Entity Framework достаточно умён, чтобы запросить данные только для модуля, а для получения результатов выполнить отдельный запрос, только когда они потребуются. Таким образом, приведенный ниже код будет выполнять как минимум 2 запроса: один для получения модуля, а другой для получения результатов (для каждого модуля).
using (var db = new DBEntities()) {Однако, если у нас много модулей, отдельный SQL запрос к результатам будет выполняться для каждого модуля. Очевидно, что это лишняя и ненужная нагрузка на сервер. Но в Entity Framework решить проблему очень легко, просто запросив включение результатов в исходный запрос:
var modules = db.Modules;
foreach (var module in modules) {
var moduleType = module.Results;
//Обработка модуля
}
}
var modules = db.Modules.Include(b => b.Results);В этом случае выполнится всего один SQL запрос, который будет включать все модули и все результаты для каждого модуля, что Entity Framework потом корректно транслирует в объекты модели.
Окончание следует…
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
День пятьсот сорок девятый.
Хороших выходных вам, дорогие подписчики. И вот вам видосик скрасить досуг первого дня авгрусти (запасайтесь двумя часами). На этот раз (большая редкость) видео на русском. Андрея Акиньшина в мире .NET лишний раз представлять не нужно. Его (по крайней мере, в русскоязычном сообществе) должны знать примерно как Рихтера или Скита. Впрочем, авторы видео его и не представляют, поэтому, если вы таки не знаете, кто это, сначала погуглите)))
В интервью каналу «Мы обречены» он рассказывает о своей книге «Pro .NET Benchmarking», про производительность и красоту кода, про хобби программистов и многое другое. В общем, лично мне очень понравилось.
Хороших выходных вам, дорогие подписчики. И вот вам видосик скрасить досуг первого дня авгрусти (запасайтесь двумя часами). На этот раз (большая редкость) видео на русском. Андрея Акиньшина в мире .NET лишний раз представлять не нужно. Его (по крайней мере, в русскоязычном сообществе) должны знать примерно как Рихтера или Скита. Впрочем, авторы видео его и не представляют, поэтому, если вы таки не знаете, кто это, сначала погуглите)))
В интервью каналу «Мы обречены» он рассказывает о своей книге «Pro .NET Benchmarking», про производительность и красоту кода, про хобби программистов и многое другое. В общем, лично мне очень понравилось.
YouTube
Андрей Акиньшин — бенчмарки, перфоманс, производительный код — Мы обречены #12
Супер-курс Влада Тена по Алгоритмам!
https://t.iss.one/tribute/app?startapp=sjGY-5jAPwCjfRH3
Чат подкаста в Телеграме — https://t.iss.one/myobrecheny
Телеграм канал — https://t.iss.one/myobrechenychannel
Твиттер — https://twitter.com/myobrecheny
VK — https://vk.com/myobrecheny…
https://t.iss.one/tribute/app?startapp=sjGY-5jAPwCjfRH3
Чат подкаста в Телеграме — https://t.iss.one/myobrecheny
Телеграм канал — https://t.iss.one/myobrechenychannel
Твиттер — https://twitter.com/myobrecheny
VK — https://vk.com/myobrecheny…
День пятьсот пятидесятый.
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Окончание 7
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
Начало 1-2
Продолжение 3-4
Продолжение 5-6
7. Непонимание Того как LINQ to SQL/Entity Framework Генерирует Запросы
Продолжая тему из пункта 6, стоит упомянуть, насколько по-разному будет выполняться ваш код, если он находится внутри запроса LINQ. Если коротко, весь код внутри запроса LINQ транслируется в SQL. Это кажется очевидным, но очень легко забыть контекст, в котором вы находитесь и допустить ошибку. Ниже приведён список некоторых типичных проблем, с которыми вы можете столкнуться.
Большинство методов не будут работать
Представьте, что вы используете следующий запрос, чтобы разделить имя модулей по двоеточию и захватить вторую часть:
Методы, которые всё же сработают, могут дать неожиданные результаты…
Рассмотрим следующее выражение LINQ (понятия не имею, зачем это делать на практике, но просто допустим, что надо):
Знайте, когда надо просто использовать старый добрый SQL.
Если вы выполняете чрезвычайно сложный запрос в LINQ, то автоматически сгенерированный SQL запрос может выглядеть как что-то, что съели, выплюнули, снова съели и снова выплюнули. К сожалению, конкретных примеров у меня нет, но, по опыту, использование сложных запросов к нескольким связанным таблицам превращает их поддержку в кошмар. Кроме того, могут появиться проблемы с производительностью, которые будет сложно решить, не имея прямого контроля над сгенерированным SQL. Поэтому либо напишите запрос сразу на SQL, либо доверьте эту работу администратору базы данных (если он у вас есть).
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
7 Опасных Ошибок, Которые Легко Совершить в C#/.NET. Окончание 7
В каждом языке есть ловушки, в которые легко попасть и ошибочные представления об ожидаемом поведении языка. Вот некоторые из них.
Начало 1-2
Продолжение 3-4
Продолжение 5-6
7. Непонимание Того как LINQ to SQL/Entity Framework Генерирует Запросы
Продолжая тему из пункта 6, стоит упомянуть, насколько по-разному будет выполняться ваш код, если он находится внутри запроса LINQ. Если коротко, весь код внутри запроса LINQ транслируется в SQL. Это кажется очевидным, но очень легко забыть контекст, в котором вы находитесь и допустить ошибку. Ниже приведён список некоторых типичных проблем, с которыми вы можете столкнуться.
Большинство методов не будут работать
Представьте, что вы используете следующий запрос, чтобы разделить имя модулей по двоеточию и захватить вторую часть:
var modules = from m in db.ModulesЭто вызовет исключение в большинстве провайдеров LINQ: для метода
select m.Name.Split(':')[1];
Split
нет перевода в SQL. Могут поддерживаться некоторые методы, например, добавление дней к дате, но всё зависит от провайдера.Методы, которые всё же сработают, могут дать неожиданные результаты…
Рассмотрим следующее выражение LINQ (понятия не имею, зачем это делать на практике, но просто допустим, что надо):
int modules = db.Modules.Sum(a => a.ID);Если строки в таблице Modules есть, то выражение выдаст сумму значений идентификаторов. Вроде всё правильно. Но что, если применить это выражение к LINQ to Objects? Мы можем сделать это, преобразовав коллекцию модулей в список перед вызовом метода
Sum
:int modules = db.Modules.ToList().Sum(a => a.ID);И ВНЕЗАПНО!… мы получим тот же ответ. Однако, если строк в таблице не будет, то LINQ to Objects вернёт
0
, а версия для Entity Framework/LINQ to SQL выдаст исключение InvalidOperationException
, сообщающее, что невозможно преобразовать int?
в int
. Это связано с тем, что вызов SUM
в SQL на пустом наборе вместо 0
возвращает NULL
. Следовательно, вместо этого он пытается вернуть обнуляемый тип int
. Поэтому…Знайте, когда надо просто использовать старый добрый SQL.
Если вы выполняете чрезвычайно сложный запрос в LINQ, то автоматически сгенерированный SQL запрос может выглядеть как что-то, что съели, выплюнули, снова съели и снова выплюнули. К сожалению, конкретных примеров у меня нет, но, по опыту, использование сложных запросов к нескольким связанным таблицам превращает их поддержку в кошмар. Кроме того, могут появиться проблемы с производительностью, которые будет сложно решить, не имея прямого контроля над сгенерированным SQL. Поэтому либо напишите запрос сразу на SQL, либо доверьте эту работу администратору базы данных (если он у вас есть).
Источник: https://chrisstclair.co.uk/7-dangerous-mistakes-in-c-net-that-are-easy-to-make/
День пятьсот пятьдесят первый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
53. Модульные тесты - пустая трата времени?
Модульные тесты - пустая трата времени: вы всегда будете тратить больше усилий на их поддержку, чем на написание кода.
- Кто-то, в какой-то момент вашей карьеры
Я слышал это десятки раз. Обычно веб-разработчики более склонны так думать, чем их бэкенд-коллеги. И на то есть веская причина: юнит-тестам фронтэнда ещё есть куда расти. В последние годы мне посчастливилось запустить большое количество новых проектов, больших и малых, и, оглядываясь назад, я чувствую, что написание тестов всегда экономило время (или могло бы сэкономить). Но мне потребовалось много времени, чтобы по-настоящему понять их преимущества и изменить свои привычки. Есть много тех, кто до сих пор скептически относится к юнит-тестам, но вот что лично я бы сказал молодому себе: «Забудь про фразу "не хватает времени для написания модульных тестов"».
Вы никогда не напишите их «позже», вам нужна дисциплина, чтобы сделать это, и если у вас их нет по мере написания кода, у вас наверняка не будет их никогда, поскольку проект становится больше и больше. Ни один проект не может быть слишком мал, чтобы его не тестировать. По своему опыту скажу, что для всего, что длиннее 5 строк кода, тестирование вручную всегда будет дороже автоматизированного.
Со временем вы обнаружите, что, когда вы делаете свой код тестируемым, вы также повышаете его внутреннее качество. Помните тот момент, когда вы тратили несколько часов, чтобы воспроизвести какую-нибудь странную ошибку? Программные системы сложны и требуют идеального взаимодействия многих элементов, некоторые из которых находятся вне вашего контроля. Если что-то идёт не так только в редком случае, когда какой-то внешний модуль возвращает что-то неожиданное, отладка становится практически невозможной. Поскольку модульные тесты позволяют вам контролировать состояние вашего приложения в мельчайших деталях, воспроизведение такой проблемы становится намного проще.
Модульное тестирование - это не какая-то дополнительная фича, которую хорошо бы иметь. Это обязательный шаг в процессе разработки программного обеспечения. Как команда инженеров, вы можете пропустить их, но это рано или поздно отбросит вас назад и будет стоить вам кучу времени. В конце концов, а какие есть другие варианты?
1. Не тестировать вообще. Излишне говорить, что полученный продукт будет бесполезным дерьмом. Вы должны будете исправлять его исключительно на основании отзывов пользователей, что приведёт к непостижимым затратам и поиску другой работы.
2. Отдать продукт на ручное тестирование другой команде. Достаточно скоро вы обнаружите, что проблемы, которые в противном случае вы могли бы обнаружить довольно быстро, будут продолжать возникать между вами и тестерами. Это уже лучше: по крайней мере ваши пользователи больше не проводят тестирование за вас. Тем не менее, постоянный пинг-понг тикетами с тестировщиками отнимает много времени, плюс с каждой итерацией вам придётся перезапускать весь процесс.
3. Вы вручную тестируете свой код перед тем, как передать его по дальше. Это, наверное, самый распространенный сценарий (по крайней мере, я на это надеюсь). Вы наверняка думаете, что как разработчик вы хорошо знаете, где найти проблему и быстро её исправить. Однако, учитывая, насколько сложным может быть состояние приложения и насколько долго иногда приходится воссоздавать все необходимые условия для репликации проблемы, в конце концов вы потратите уйму времени, не на исправление ошибки, а тыкая по кнопкам, воспроизводя путь пользователя.
Да, модульное тестирование в любом случае отнимает много времени, особенно если у вас плохо спроектирована кодовая база. Но вам всё равно придётся тестировать свой код. Единственный выбор, который перед вами стоит, - тратить время, выполняя тесты вручную, или инвестировать некоторые усилия в обучение правильному написанию модульных тестов и получать выгоду позже.
Источник: https://hackernoon.com/are-unit-tests-a-waste-of-your-time-ftw3umv
97 Вещей, Которые Должен Знать Каждый Программист
53. Модульные тесты - пустая трата времени?
Модульные тесты - пустая трата времени: вы всегда будете тратить больше усилий на их поддержку, чем на написание кода.
- Кто-то, в какой-то момент вашей карьеры
Я слышал это десятки раз. Обычно веб-разработчики более склонны так думать, чем их бэкенд-коллеги. И на то есть веская причина: юнит-тестам фронтэнда ещё есть куда расти. В последние годы мне посчастливилось запустить большое количество новых проектов, больших и малых, и, оглядываясь назад, я чувствую, что написание тестов всегда экономило время (или могло бы сэкономить). Но мне потребовалось много времени, чтобы по-настоящему понять их преимущества и изменить свои привычки. Есть много тех, кто до сих пор скептически относится к юнит-тестам, но вот что лично я бы сказал молодому себе: «Забудь про фразу "не хватает времени для написания модульных тестов"».
Вы никогда не напишите их «позже», вам нужна дисциплина, чтобы сделать это, и если у вас их нет по мере написания кода, у вас наверняка не будет их никогда, поскольку проект становится больше и больше. Ни один проект не может быть слишком мал, чтобы его не тестировать. По своему опыту скажу, что для всего, что длиннее 5 строк кода, тестирование вручную всегда будет дороже автоматизированного.
Со временем вы обнаружите, что, когда вы делаете свой код тестируемым, вы также повышаете его внутреннее качество. Помните тот момент, когда вы тратили несколько часов, чтобы воспроизвести какую-нибудь странную ошибку? Программные системы сложны и требуют идеального взаимодействия многих элементов, некоторые из которых находятся вне вашего контроля. Если что-то идёт не так только в редком случае, когда какой-то внешний модуль возвращает что-то неожиданное, отладка становится практически невозможной. Поскольку модульные тесты позволяют вам контролировать состояние вашего приложения в мельчайших деталях, воспроизведение такой проблемы становится намного проще.
Модульное тестирование - это не какая-то дополнительная фича, которую хорошо бы иметь. Это обязательный шаг в процессе разработки программного обеспечения. Как команда инженеров, вы можете пропустить их, но это рано или поздно отбросит вас назад и будет стоить вам кучу времени. В конце концов, а какие есть другие варианты?
1. Не тестировать вообще. Излишне говорить, что полученный продукт будет бесполезным дерьмом. Вы должны будете исправлять его исключительно на основании отзывов пользователей, что приведёт к непостижимым затратам и поиску другой работы.
2. Отдать продукт на ручное тестирование другой команде. Достаточно скоро вы обнаружите, что проблемы, которые в противном случае вы могли бы обнаружить довольно быстро, будут продолжать возникать между вами и тестерами. Это уже лучше: по крайней мере ваши пользователи больше не проводят тестирование за вас. Тем не менее, постоянный пинг-понг тикетами с тестировщиками отнимает много времени, плюс с каждой итерацией вам придётся перезапускать весь процесс.
3. Вы вручную тестируете свой код перед тем, как передать его по дальше. Это, наверное, самый распространенный сценарий (по крайней мере, я на это надеюсь). Вы наверняка думаете, что как разработчик вы хорошо знаете, где найти проблему и быстро её исправить. Однако, учитывая, насколько сложным может быть состояние приложения и насколько долго иногда приходится воссоздавать все необходимые условия для репликации проблемы, в конце концов вы потратите уйму времени, не на исправление ошибки, а тыкая по кнопкам, воспроизводя путь пользователя.
Да, модульное тестирование в любом случае отнимает много времени, особенно если у вас плохо спроектирована кодовая база. Но вам всё равно придётся тестировать свой код. Единственный выбор, который перед вами стоит, - тратить время, выполняя тесты вручную, или инвестировать некоторые усилия в обучение правильному написанию модульных тестов и получать выгоду позже.
Источник: https://hackernoon.com/are-unit-tests-a-waste-of-your-time-ftw3umv
День пятьсот пятьдесят второй. #ЧтоНовенького
Новые Функции в Visual Studio для Повышения Продуктивности. Начало
Команда Roslyn представляет новые функции для повышения продуктивности в Visual Studio 2019.
1. Автодополнения IntelliSense для форматов DateTime и TimeSpan. Эта обещает быть чрезвычайно полезным, потому что мы все знаем, как сложно запоминать форматы даты и времени. Поместите курсор в строковый литерал
2. Добавление заголовка файла позволяет легко добавлять заголовки к существующим файлам, проектам и решениям с помощью EditorConfig. Добавьте правило
3. Диалоговое окно изменения сигнатуры метода теперь позволит добавлять параметры. Поместите курсор на сигнатуру метода и
Источник: https://devblogs.microsoft.com/dotnet/learn-about-the-latest-net-productivity-features/
Новые Функции в Visual Studio для Повышения Продуктивности. Начало
Команда Roslyn представляет новые функции для повышения продуктивности в Visual Studio 2019.
1. Автодополнения IntelliSense для форматов DateTime и TimeSpan. Эта обещает быть чрезвычайно полезным, потому что мы все знаем, как сложно запоминать форматы даты и времени. Поместите курсор в строковый литерал
DateTime
или TimeSpan
и нажмите (Ctrl+Пробел
). Вы увидите варианты завершения и объяснение, что означает каждый символ. См. рис.1 ниже.2. Добавление заголовка файла позволяет легко добавлять заголовки к существующим файлам, проектам и решениям с помощью EditorConfig. Добавьте правило
file_header_template
в файл .editorconfig
и установите нужный текст заголовка. Затем поместите курсор в первую строку любого файла C#. Нажмите Ctrl+.
, чтобы вызвать меню «Быстрые действия и рефакторинг», и выберите «Добавить заголовок файла» («Add file header»). См. рис.2 ниже.3. Диалоговое окно изменения сигнатуры метода теперь позволит добавлять параметры. Поместите курсор на сигнатуру метода и
Ctrl+.
, чтобы вызвать меню «Быстрые действия и рефакторинг», и выберите «Изменить сигнатуру» («Change signature»). Откроется окно, где вы можете нажать «Добавить» («Add») для добавления параметра. При этом откроется новое диалоговое окно «Добавить Параметр» («Add Parameter»). См. рис.3 ниже. Оно позволяет задать тип и имя параметра, а также сделать параметр обязательным или необязательным со значением по умолчанию. Кроме того, вы можете задать значение в вызывающем коде (по желанию использовав именованный аргумент для этого значения), либо ввести переменную TODO. Переменная TODO поместит «TODO
» в вызывающий код, чтобы вы могли обойти все вызовы метода и передать нужное значение в каждом случае. Для необязательных параметров есть возможность пропустить изменения в вызывающем коде.Источник: https://devblogs.microsoft.com/dotnet/learn-about-the-latest-net-productivity-features/
День пятьсот пятьдесят третий. #юмор
Примерно так же надо задавать вопрос на Stackoverflow)))
Примерно так же надо задавать вопрос на Stackoverflow)))
День пятьсот пятьдесят четвёртый. #ЧтоНовенького
Новые Функции в Visual Studio для Повышения Продуктивности. Окончание
Начало
Исправления и рефакторинг кода - это предложения по изменению кода, которые компилятор предоставляет с помощью значков лампочки и отвертки. Чтобы вызвать меню быстрых действий и рефакторинга, нажмите Ctrl+. или Alt+Enter. Команда Roslyn представляет новые возможности исправления и рефакторинга кода в Visual Studio 2019:
- Добавление явного приведения (Add explicit cast). Позволяет добавить оператор явного приведения, если неявное приведение выражения невозможно. См. рис. 1 ниже.
- Упрощение условного выражения (Simplify conditional expression). Делает условные выражения более чёткими и краткими. См. рис. 2 ниже.
- Преобразование в дословную/обычную строку (Convert To Verbatim/Regular String). Позволяет в одно нажатие преобразовать строку из обычной в дословную и наоборот. См. рис. 3 ниже.
- Добавление атрибута «DebuggerDisplay» (Add ‘DebuggerDisplay’ attribute). Предложение появляется, если поместить курсор на имя класса. Позволяет программно закреплять свойства в отладчике кода. Добавляет атрибут отображения в отладчике в начало класса и генерирует автоматический метод, который возвращает
- Генерация операторов сравнения (Generate comparison operators). Генерирует шаблонный код с операторами сравнения для типов, реализующих
- Генерация операторов IEquatable (Generate Equals(object)). Добавляет реализацию
- Генерация конструктора со свойствами (Generate constructor in <QualifiedName> (with properties)). Предложение появляется, если поместить курсор на экземпляр типа. Позволяет добавить в соответствующий тип конструктор нужной сигнатуры и необходимые свойства. См. рис. 7 ниже.
- Исправление случайных присвоений и сравнений (Assign/Compare to '<QualifiedName>.value'). Позволяет исправить операцию присвоения или сравнения, когда имена поля класса и параметра конструктора совпадают. Исправление добавляет “
Источник: https://devblogs.microsoft.com/dotnet/learn-about-the-latest-net-productivity-features/
Новые Функции в Visual Studio для Повышения Продуктивности. Окончание
Начало
Исправления и рефакторинг кода - это предложения по изменению кода, которые компилятор предоставляет с помощью значков лампочки и отвертки. Чтобы вызвать меню быстрых действий и рефакторинга, нажмите Ctrl+. или Alt+Enter. Команда Roslyn представляет новые возможности исправления и рефакторинга кода в Visual Studio 2019:
- Добавление явного приведения (Add explicit cast). Позволяет добавить оператор явного приведения, если неявное приведение выражения невозможно. См. рис. 1 ниже.
- Упрощение условного выражения (Simplify conditional expression). Делает условные выражения более чёткими и краткими. См. рис. 2 ниже.
- Преобразование в дословную/обычную строку (Convert To Verbatim/Regular String). Позволяет в одно нажатие преобразовать строку из обычной в дословную и наоборот. См. рис. 3 ниже.
- Добавление атрибута «DebuggerDisplay» (Add ‘DebuggerDisplay’ attribute). Предложение появляется, если поместить курсор на имя класса. Позволяет программно закреплять свойства в отладчике кода. Добавляет атрибут отображения в отладчике в начало класса и генерирует автоматический метод, который возвращает
ToString()
. Метод можно отредактировать, чтобы вернуть значение свойства, которое вы хотите закрепить в отладчике. См. рис. 4 ниже.- Генерация операторов сравнения (Generate comparison operators). Генерирует шаблонный код с операторами сравнения для типов, реализующих
IComparable
. См. рис. 5 ниже.- Генерация операторов IEquatable (Generate Equals(object)). Добавляет реализацию
IEquatable
, а также операторы равенства и не равенства для структур. См. рис. 6 ниже.- Генерация конструктора со свойствами (Generate constructor in <QualifiedName> (with properties)). Предложение появляется, если поместить курсор на экземпляр типа. Позволяет добавить в соответствующий тип конструктор нужной сигнатуры и необходимые свойства. См. рис. 7 ниже.
- Исправление случайных присвоений и сравнений (Assign/Compare to '<QualifiedName>.value'). Позволяет исправить операцию присвоения или сравнения, когда имена поля класса и параметра конструктора совпадают. Исправление добавляет “
this.
” в нужную часть операции. См. рис. 8 ниже.Источник: https://devblogs.microsoft.com/dotnet/learn-about-the-latest-net-productivity-features/