День 1179. #ЗаметкиНаПолях
Выделяем Подмассивы. Начало
Сегодня рассмотрим, различные способы выделения подмассива в C#.
Подмассив обычно определяется начальным индексом и количеством элементов, включаемых в него. В общем случае существует два логических способа это сделать:
- Создать новый массив и добавить к нему необходимые элементы.
- Создать оболочку вокруг массива, которая может содержать указатели на определенные элементы внутри массива без создания нового.
Допустим, у нас есть массив строк:
В LINQ есть методы
2. Использование метода Copy()
Тот же сценарий, но помощью метода массива
3. Оператор диапазона (x..y) в C# 8.0+
Начиная с C#8 появился новый оператор диапазона, который сделал выделение подмассива синтаксически очень простым. Он позволяет выделить элементы между индексом «x» и индексом «y», не включая элемент с индексом «y»:
Окончание следует…
Источник: https://code-maze.com/csharp-array-slicing/
Выделяем Подмассивы. Начало
Сегодня рассмотрим, различные способы выделения подмассива в C#.
Подмассив обычно определяется начальным индексом и количеством элементов, включаемых в него. В общем случае существует два логических способа это сделать:
- Создать новый массив и добавить к нему необходимые элементы.
- Создать оболочку вокруг массива, которая может содержать указатели на определенные элементы внутри массива без создания нового.
Допустим, у нас есть массив строк:
var posts = new string[] { "post1", "post2", "post3", "post4", "post5", "post6", "post7", "post8", "post9", "post10" };1. Использование LINQ
В LINQ есть методы
Skip()
и Take()
:var sliced = posts.Skip(0).Take(5);Мы передаем количество элементов, которые хотим пропустить, методу
// Элементы с post1 до post5
Skip()
- начальный индекс, и количество элементов, которые хотим включить, в метод Take()
. Операция возвращает новый IEnumerable
, который мы можем перечислить.2. Использование метода Copy()
Тот же сценарий, но помощью метода массива
Copy()
:var sliced = new string[5];Здесь мы инициализируем целевой массив, затем мы вызываем метод
Array.Copy(posts, 0, sliced, 0, 5);
Copy()
, который принимает исходный массив, начальный индекс, целевой массив, начальный целевой индекс (ноль, потому что мы копируем в новый массив) и количество элементов, которые мы хотим скопировать. Метод возвращает новый массив, содержащий скопированные элементы.3. Оператор диапазона (x..y) в C# 8.0+
Начиная с C#8 появился новый оператор диапазона, который сделал выделение подмассива синтаксически очень простым. Он позволяет выделить элементы между индексом «x» и индексом «y», не включая элемент с индексом «y»:
var s1 = posts[2..]; // co 2го до концаОператор диапазона также выделяет новый массив.
var s2 = posts[..2]; // с начала до 1го
var s3 = posts[1..3]; // с 1го до 2го
var s4 = posts[..]; // весь массив
var s5 = posts[3..^0]; // с 3го до предпоследнего
Окончание следует…
Источник: https://code-maze.com/csharp-array-slicing/
👍21
День 1180. #ЗаметкиНаПолях
Выделяем Подмассивы. Окончание
Начало
Теперь рассмотрим второй способ.
Для него рассмотрим новый сценарий. Допустим, мы создаем модель машинного обучения для благотворительной организации, которая будет предсказывать, сделает ли человек донат, в зависимости от его возраста. У нас есть куча данных, которые мы хотим разбить на две секции: обучающие данные, на которых будет обучаться модель, и тестовые данные, по которым мы будем тестировать модель.
4. Использование ArraySegment<T>
То же самое можно сделать с помощью метода
Замечание: мы должны быть осторожны, потому что это не новый массив, это на самом деле переменная типа-значения, содержащая указатели на позиции элементов в массиве, поэтому любое изменение значений в сегменте массива будет отражаться в исходном массиве.
5. Использование ReadOnlySpan<T> и Span<T>
Код, использующий
Сравнение быстродействия
На массиве из 10 строк быстродействие выделения подмассива из 5 элементов и их перечисления. Общий вид методов:
Источник: https://code-maze.com/csharp-array-slicing/
Выделяем Подмассивы. Окончание
Начало
Теперь рассмотрим второй способ.
Для него рассмотрим новый сценарий. Допустим, мы создаем модель машинного обучения для благотворительной организации, которая будет предсказывать, сделает ли человек донат, в зависимости от его возраста. У нас есть куча данных, которые мы хотим разбить на две секции: обучающие данные, на которых будет обучаться модель, и тестовые данные, по которым мы будем тестировать модель.
var data = new (int, bool)[] {Заметьте, что в примере у нас всего 5 элементов. В реальной же модели обучения их могут быть миллионы, поэтому выделять новый массив будет очень затратно.
(20, true),
(50, true),
(35, false),
(55, true),
(16, false)
};
4. Использование ArraySegment<T>
var train = new ArraySegment<(int, bool)>(data, 0, 3);Мы инициализируем новый экземпляр
var test = new ArraySegment<(int, bool)>(data, 3, 2);
ArraySegment
, передавая массив, который мы хотим разделить, начальный индекс и количество элементов. Это создает оболочку вокруг массива, которая ограничивает элементы между указанными позициями. Теперь мы можем выполнить итерацию по этому сегменту и прочитать его значения.То же самое можно сделать с помощью метода
ArraySegment<T>.Slice()
:var all = new ArraySegment<(int, bool)>(data);Мы создаем
var train = all.Slice(0, 3);
var test = all.Slice(3, 2);
ArraySegment
, который охватывает весь массив, затем вызываем метод Slice()
, который создает ещё один ArraySegment с указанными границами.Замечание: мы должны быть осторожны, потому что это не новый массив, это на самом деле переменная типа-значения, содержащая указатели на позиции элементов в массиве, поэтому любое изменение значений в сегменте массива будет отражаться в исходном массиве.
5. Использование ReadOnlySpan<T> и Span<T>
ReadOnlySpan<T>
предоставляет оболочку, которая позволяет только чтение из массива:var train = new ReadOnlySpan<(int, bool)>(data, 0, 3);
var test = new ReadOnlySpan<(int, bool)>(data, 3, 2);
ReadOnlySpan
очень похож на ArraySegment
. Он принимает массив, начальный индекс и количество элементов. Мы можем перечислить его, но, если мы попытаемся изменить какой-либо элемент через экземпляр ReadOnlySpan
, мы получим ошибку компиляции.Код, использующий
Span<T>
и его поведение аналогичны коду с ArraySegment<T>
. Их отличие в том, что Span<T>
можно использовать не только для массивов. Кроме того, ArraySegment<T>
реализует IEnumerable<T>
таким образом позволяет вернуть результат как IEnumerable<T>
, тогда как ReadOnlySpan<T>
и Span<T>
возвращают соответствующие типы, хотя оба имеют метод GetEnumerator()
, поэтому их также можно перечислить через foreach
.Сравнение быстродействия
На массиве из 10 строк быстродействие выделения подмассива из 5 элементов и их перечисления. Общий вид методов:
public int <Метод>()Результаты на картинке ниже.
{
// получение подмассива указанным методом
var slice = <подмассив>;
var cnt = 0;
foreach (var item in slice)
cnt++;
return cnt;
}
Источник: https://code-maze.com/csharp-array-slicing/
👍10
День 1181. #МоиИнструменты
Visual Studio 2022 Tweaks
Сегодня порекомендую вам расширение для Visual Studio 2022 от Мэдса Кристенсена Tweaks 2022. Оно содержит в себе множество мелких, но полезных улучшений (на основании предложений пользователей). Они упростят для вас те мелкие ненужные действия, которые нам приходится делать постоянно в повседневной работе. Подробное их описание ищите на странице расширения).
Стоит оговориться, что большинство из этого уже существует и это можно найти, покопавшись в настройках. Расширение позволяет сделать это быстро.
1. Общие
- Автоматическое сохранение документа, когда он теряет фокус. Также проект автоматически сохраняется при добавлении, удалении или переименовании файлов.
- Закрытие документа по
- Автоматический фокус на обозревателе решений после загрузки проекта (даже если он был скрыт).
- Пункт меню для очистки недавно открытых документов.
- Пункт всплывающего меню «Открыть сбоку» для файлов в обозревателе решений (открывает файл справа от текущего документа).
- Пункт всплывающего меню «Найти в обозревателе решений» для вкладок.
2. IDE
- Перезапуск VS в меню Файл (также возможно по
- Варианты запуска VS в безопасном режиме и в режиме презентации (доступны в выпадающем меню при правом клике на ярлыке VS).
- Отключение кнопок отладки
3. Сборка
- Выпадающий список уровня подробности сообщений сборки в окне Output.
- Сохранение решения при сборке.
- Удаление папок
- Отображение времени запуска и длительности сборки.
- Отображение актуальности файлов проекта (полезно знать, чтобы выяснить, почему проект пересобирается). Отображается даже на минимальном уровне подробностей в окне Output.
- Отображение порядка сборки проектов
4. Редактор
- Очистка кода при форматировании документа (
- Отмена копирования пустых строк. По умолчанию при нажатии
- Копирование без отступов (удаляет отступы у последующих строк, если первая скопирована без отступа).
- Форматирование при перемещении строк.
- Отмена зума по
- Возврат к стандартному зуму по
- Пункт «Настройки» во всплывающем меню документа, вызывающий настройки для языка документа.
- Пункт «Специальная вставка» во всплывающем меню документа.
- Возможность свернуть и скрыть несколько атрибутов.
- Выделение всей строки по
- Предупреждение при вставке больших объёмов текста.
Изменить все упомянутые настройки после установки расширения можно в меню Tools > Options > Environment > Tweaks 2022.
Visual Studio 2022 Tweaks
Сегодня порекомендую вам расширение для Visual Studio 2022 от Мэдса Кристенсена Tweaks 2022. Оно содержит в себе множество мелких, но полезных улучшений (на основании предложений пользователей). Они упростят для вас те мелкие ненужные действия, которые нам приходится делать постоянно в повседневной работе. Подробное их описание ищите на странице расширения).
Стоит оговориться, что большинство из этого уже существует и это можно найти, покопавшись в настройках. Расширение позволяет сделать это быстро.
1. Общие
- Автоматическое сохранение документа, когда он теряет фокус. Также проект автоматически сохраняется при добавлении, удалении или переименовании файлов.
- Закрытие документа по
Ctrl+W
.- Автоматический фокус на обозревателе решений после загрузки проекта (даже если он был скрыт).
- Пункт меню для очистки недавно открытых документов.
- Пункт всплывающего меню «Открыть сбоку» для файлов в обозревателе решений (открывает файл справа от текущего документа).
- Пункт всплывающего меню «Найти в обозревателе решений» для вкладок.
2. IDE
- Перезапуск VS в меню Файл (также возможно по
Shift+Alt+F4
).- Варианты запуска VS в безопасном режиме и в режиме презентации (доступны в выпадающем меню при правом клике на ярлыке VS).
- Отключение кнопок отладки
F10
/F11
(ох, сколько раз я промахивался мимо F12
).3. Сборка
- Выпадающий список уровня подробности сообщений сборки в окне Output.
- Сохранение решения при сборке.
- Удаление папок
bin
и obj
при очистке решения.- Отображение времени запуска и длительности сборки.
- Отображение актуальности файлов проекта (полезно знать, чтобы выяснить, почему проект пересобирается). Отображается даже на минимальном уровне подробностей в окне Output.
- Отображение порядка сборки проектов
4. Редактор
- Очистка кода при форматировании документа (
Ctrl+K,D
).- Отмена копирования пустых строк. По умолчанию при нажатии
Ctrl+C
, если ничего не выделено, копируется текущая строка. Теперь, если строка пустая, она не будет скопирована.- Копирование без отступов (удаляет отступы у последующих строк, если первая скопирована без отступа).
- Форматирование при перемещении строк.
Alt+стрелки
помогают переместить строку вверх/вниз. Теперь будет добавляться нужный отступ.- Отмена зума по
Ctrl+колёсико мыши
(из-за случайных срабатываний). Работает через Ctrl+Shift+колёсико мыши
.- Возврат к стандартному зуму по
Ctrl+0
(стандартный зум устанавливается в настройках).- Пункт «Настройки» во всплывающем меню документа, вызывающий настройки для языка документа.
- Пункт «Специальная вставка» во всплывающем меню документа.
- Возможность свернуть и скрыть несколько атрибутов.
- Выделение всей строки по
Shift+Alt+E
.- Предупреждение при вставке больших объёмов текста.
Изменить все упомянутые настройки после установки расширения можно в меню Tools > Options > Environment > Tweaks 2022.
👍8
День 1182. #Карьера
Как Разработчики Проваливаются
«Разработчики терпят неудачу по двум причинам: либо делают не так, либо делают не то».
Поразительно, что большинство разработчиков уделяют больше внимания первой части проблемы и забывают про вторую. Младшие программисты больше озабочены тем, как создать продукт. Есть техническая задача, и многим из нас нравится решать её, как головоломку. Но по мере накопления опыта вы обнаружите, что часто то, что вы создали, на самом деле не то, что хотел заказчик. А такой дефект труднее обнаружить, и часто дороже устранить.
Сделать не так
Определение намеренно расплывчато. Под неправильным в данном случае понимается любой технический дефект, в результате которого система не удовлетворяет потребностям пользователей. Критическая ошибка, архитектура не масштабируется, есть серьезные проблемы с производительностью, утечки памяти, может быть даже брешь в системе безопасности. Это все те вещи, о которых мы склонны думать, когда думаем о недостатках, дефектах или ошибках в приложениях.
Зачастую эти ошибки незначительны. Они могут быть обнаружены во время тестирования ещё до того, как их увидят конечные пользователи. В других случаях они могут быть довольно дорогими, и их нелегко исправить. Некоторые ошибки неизбежны, поэтому мы разрабатываем программные процессы таким образом, чтобы их можно было ожидать, обнаруживать и исправлять. Наша практика очень часто направлена на максимально быстрое обнаружение дефектов, поскольку мы знаем, что исправление дефекта сразу после его появления обходится на порядки дешевле, чем после его отправки в производственную среду. Предотвращение попадания дефектов в продукт — очень полезная деятельность для разработчиков ПО.
Ещё один способ создавать что-то неправильно связан с архитектурой или качеством. Некоторые решения, принятые на ранней стадии в отношении системной архитектуры, могут оказаться неправильными позже, когда они не позволят нам реагировать на запросы клиентов. Технический долг в виде костылей может иметь аналогичные последствия в перспективе. Хотя это и более коварно, чем выпуск видимых пользователями дефектов, это тоже примеры неправильного построения.
Сделать не то
Зачем мы делаем не то? Оказывается, общение – это трудно. Клиенты и пользователи не всегда чётко сообщают, чего они хотят. Мы не всегда хорошо слушаем или забываем. Или делаем то, что, как мы думаем, они хотят, или то, что хотели бы мы, вместо того, что требуется. Иногда это даже работает, но в большинстве случаев это пример того, как мы забываем, что мы не пользователи.
Часто пользователь хочет решить проблему, но, когда видит часть решения, это порождает новые идеи о том, как лучше её решить. Дело не в том, что они не знали, чего хотят, а в том, что итеративный процесс разработки решения выявил лучший подход. Худшее, что мы можем сделать как разработчики — это продавить посредственное решение, потому что мы не открыты для отличного, которое мы же нашли в процессе разработки. Поэтому важно часто обмениваться информацией, подтверждать наши предположения и позволять клиентам и заинтересованным сторонам реагировать на нашу работу по мере её продвижения. Будьте готовы изменить направление и быть открытыми для новых идей, чтобы максимизировать ценность предлагаемого вами решения.
Способность построить что-то правильно — это, как правило, вопрос технической компетентности. Как только вы достигнете определенного порога мастерства, вы будете уверены в своей способности сделать это. Создание правильной вещи требует дополнительных навыков и может зависеть от этой технической компетенции. Помимо правильного создания ПО, теперь вы должны иметь возможность быстро и эффективно общаться и изменять направление вашего решения по мере необходимости на основе актуальной информации. Только тогда вы можете быть уверены, что создаёте правильные вещи правильно.
Источник: https://weeklydevtips.com/episodes/how-developers-fail-ipx3u5cw?utm_sq=gg631te050
Автор оригинала: Steve "Ardalis" Smith
Как Разработчики Проваливаются
«Разработчики терпят неудачу по двум причинам: либо делают не так, либо делают не то».
Поразительно, что большинство разработчиков уделяют больше внимания первой части проблемы и забывают про вторую. Младшие программисты больше озабочены тем, как создать продукт. Есть техническая задача, и многим из нас нравится решать её, как головоломку. Но по мере накопления опыта вы обнаружите, что часто то, что вы создали, на самом деле не то, что хотел заказчик. А такой дефект труднее обнаружить, и часто дороже устранить.
Сделать не так
Определение намеренно расплывчато. Под неправильным в данном случае понимается любой технический дефект, в результате которого система не удовлетворяет потребностям пользователей. Критическая ошибка, архитектура не масштабируется, есть серьезные проблемы с производительностью, утечки памяти, может быть даже брешь в системе безопасности. Это все те вещи, о которых мы склонны думать, когда думаем о недостатках, дефектах или ошибках в приложениях.
Зачастую эти ошибки незначительны. Они могут быть обнаружены во время тестирования ещё до того, как их увидят конечные пользователи. В других случаях они могут быть довольно дорогими, и их нелегко исправить. Некоторые ошибки неизбежны, поэтому мы разрабатываем программные процессы таким образом, чтобы их можно было ожидать, обнаруживать и исправлять. Наша практика очень часто направлена на максимально быстрое обнаружение дефектов, поскольку мы знаем, что исправление дефекта сразу после его появления обходится на порядки дешевле, чем после его отправки в производственную среду. Предотвращение попадания дефектов в продукт — очень полезная деятельность для разработчиков ПО.
Ещё один способ создавать что-то неправильно связан с архитектурой или качеством. Некоторые решения, принятые на ранней стадии в отношении системной архитектуры, могут оказаться неправильными позже, когда они не позволят нам реагировать на запросы клиентов. Технический долг в виде костылей может иметь аналогичные последствия в перспективе. Хотя это и более коварно, чем выпуск видимых пользователями дефектов, это тоже примеры неправильного построения.
Сделать не то
Зачем мы делаем не то? Оказывается, общение – это трудно. Клиенты и пользователи не всегда чётко сообщают, чего они хотят. Мы не всегда хорошо слушаем или забываем. Или делаем то, что, как мы думаем, они хотят, или то, что хотели бы мы, вместо того, что требуется. Иногда это даже работает, но в большинстве случаев это пример того, как мы забываем, что мы не пользователи.
Часто пользователь хочет решить проблему, но, когда видит часть решения, это порождает новые идеи о том, как лучше её решить. Дело не в том, что они не знали, чего хотят, а в том, что итеративный процесс разработки решения выявил лучший подход. Худшее, что мы можем сделать как разработчики — это продавить посредственное решение, потому что мы не открыты для отличного, которое мы же нашли в процессе разработки. Поэтому важно часто обмениваться информацией, подтверждать наши предположения и позволять клиентам и заинтересованным сторонам реагировать на нашу работу по мере её продвижения. Будьте готовы изменить направление и быть открытыми для новых идей, чтобы максимизировать ценность предлагаемого вами решения.
Способность построить что-то правильно — это, как правило, вопрос технической компетентности. Как только вы достигнете определенного порога мастерства, вы будете уверены в своей способности сделать это. Создание правильной вещи требует дополнительных навыков и может зависеть от этой технической компетенции. Помимо правильного создания ПО, теперь вы должны иметь возможность быстро и эффективно общаться и изменять направление вашего решения по мере необходимости на основе актуальной информации. Только тогда вы можете быть уверены, что создаёте правильные вещи правильно.
Источник: https://weeklydevtips.com/episodes/how-developers-fail-ipx3u5cw?utm_sq=gg631te050
Автор оригинала: Steve "Ardalis" Smith
👍6
День 1183. #ЗаметкиНаПолях
Преимущества в Производительности Запечатанных Классов в .NET
По умолчанию классы не запечатаны. Это означает, что вы можете наследовать от них. Это неправильное поведение по умолчанию. Если класс не предназначен для наследования, он должен быть запечатан. Вы можете изменить это позже, при необходимости. Кроме того, это влияет на производительность. Когда класс запечатан, JIT может применить оптимизацию и немного повысить производительность приложения.
Вызов виртуальных методов
При вызове виртуальных методов фактический метод находится во время выполнения на основе фактического типа объекта. Каждый тип имеет таблицу виртуальных методов (vtable), которая содержит адреса всех виртуальных методов. Эти указатели используются во время выполнения для вызова соответствующих реализаций (динамическая диспетчеризация). Если JIT знает фактический тип объекта, он может пропустить виртуальную таблицу и напрямую вызвать правильный метод. Использование запечатанных типов помогает JIT в этом.
Приведение типов (is / as)
При приведении типов среда выполнения должна проверять тип объекта во время выполнения. При приведении к незапечатанному типу среда выполнения должна проверять наличие всех типов в иерархии. Однако при приведении к запечатанному типу среда выполнения должна проверять только тип объекта, поэтому оно выполняется быстрее.
Массивы
Массивы в .NET ковариантны. Это означает, что допустимо
Преобразование массивов в Span<T>
Вы можете преобразовать массивы в Span<T> или ReadOnlySpan<T>. По тем же причинам, что и в предыдущем разделе, JIT должен проверить тип объекта перед преобразованием массива в
Результаты теста быстродействия на картинке ниже.
Обнаружение недостижимого кода
При использовании запечатанного типа компилятор знает, что некоторые преобразования недействительны. Таким образом, он может сообщать о предупреждениях и ошибках. Это поможет уменьшить количество ошибок в вашем приложении, а также удалить недостижимый код.
Преимущества в Производительности Запечатанных Классов в .NET
По умолчанию классы не запечатаны. Это означает, что вы можете наследовать от них. Это неправильное поведение по умолчанию. Если класс не предназначен для наследования, он должен быть запечатан. Вы можете изменить это позже, при необходимости. Кроме того, это влияет на производительность. Когда класс запечатан, JIT может применить оптимизацию и немного повысить производительность приложения.
Вызов виртуальных методов
При вызове виртуальных методов фактический метод находится во время выполнения на основе фактического типа объекта. Каждый тип имеет таблицу виртуальных методов (vtable), которая содержит адреса всех виртуальных методов. Эти указатели используются во время выполнения для вызова соответствующих реализаций (динамическая диспетчеризация). Если JIT знает фактический тип объекта, он может пропустить виртуальную таблицу и напрямую вызвать правильный метод. Использование запечатанных типов помогает JIT в этом.
public class SealedBenchmarkЗдесь JIT не может знать тип
{
NonSealedType nonSealedType = new();
SealedType sealedType = new();
public void CallMethod_NonSealed()
=> nonSealedType.Method();
public void CallMethod_Sealed()
=> sealedType.Method();
}
nonSealedType
. Он мог быть установлен в производный тип другим методом. Поэтому должен быть виртуальный вызов. В отличие от следующего кода:var instance = new NonSealedType();Здесь JIT точно знает тип, поэтому делает прямой вызов.
instance.Method();
Приведение типов (is / as)
При приведении типов среда выполнения должна проверять тип объекта во время выполнения. При приведении к незапечатанному типу среда выполнения должна проверять наличие всех типов в иерархии. Однако при приведении к запечатанному типу среда выполнения должна проверять только тип объекта, поэтому оно выполняется быстрее.
Массивы
Массивы в .NET ковариантны. Это означает, что допустимо
BaseType[] value = new DerivedType[1];Ковариантность приводит к снижению производительности. JIT должен проверять тип объекта перед назначением элемента в массив. При использовании запечатанных типов JIT может удалить проверку.
Преобразование массивов в Span<T>
Вы можете преобразовать массивы в Span<T> или ReadOnlySpan<T>. По тем же причинам, что и в предыдущем разделе, JIT должен проверить тип объекта перед преобразованием массива в
Span<T>
. При использовании запечатанного типа можно избежать проверки.Результаты теста быстродействия на картинке ниже.
Обнаружение недостижимого кода
При использовании запечатанного типа компилятор знает, что некоторые преобразования недействительны. Таким образом, он может сообщать о предупреждениях и ошибках. Это поможет уменьшить количество ошибок в вашем приложении, а также удалить недостижимый код.
class SampleИсточник: https://www.meziantou.net/performance-benefits-of-sealed-class.htm
{
public void Foo(NonSealedType obj)
{
_ = obj as IMyInterface;
// ОК, т.к. производные класса
// могут реализовывать интерфейс
}
public void Foo(SealedType obj)
{
_ = obj is IMyInterface;
// ⚠️ Предупреждение CS0184
_ = obj as IMyInterface;
// ❌ Ошибка CS0039
}
}
👍19
День 1184. #Карьера
Сегодня порекомендую вам великолепный доклад Скотта Хансельмана «Building Teams Through Systems Thinking and Stories» на конференции NDC Porto.
«У вас есть конечное число нажатий на клавиши в течение вашей жизни.»
Цитата, характеризующая доклад. Скотт даёт множество разнообразных советов о том, как нам строить свою карьеру. С какими трудностями нам приходится сталкиваться и как он их решал для себя. Выгорание, удалёнка, «удача» в карьере, менторство, истории из карьеры и многое другое.
Всё это приправлено огромным количеством искромётных шуток!
«Знаете, как называет себя Тим Бернерс-Ли, создатель интернета? Web Developer. Так вот, вы, сеньоры, старшие веб-разработчики. Вы можете называть себя сеньорами, только тогда, когда Тим Бернерс-Ли назовёт себя Senior Web Developer. Не раньше!
Хотя, впрочем, ему скорей подойдёт другое слово: The Web Developer (Разработчик Веба).»
Наслаждайтесь!
https://youtu.be/VFIw0LlULyc
Кстати, насчёт конечного числа нажатий на клавиши. Смотрите сами https://keysleft.com/
PS: спасибо @fjod10199 за ссылку на доклад в нашем чате.
Сегодня порекомендую вам великолепный доклад Скотта Хансельмана «Building Teams Through Systems Thinking and Stories» на конференции NDC Porto.
«У вас есть конечное число нажатий на клавиши в течение вашей жизни.»
Цитата, характеризующая доклад. Скотт даёт множество разнообразных советов о том, как нам строить свою карьеру. С какими трудностями нам приходится сталкиваться и как он их решал для себя. Выгорание, удалёнка, «удача» в карьере, менторство, истории из карьеры и многое другое.
Всё это приправлено огромным количеством искромётных шуток!
«Знаете, как называет себя Тим Бернерс-Ли, создатель интернета? Web Developer. Так вот, вы, сеньоры, старшие веб-разработчики. Вы можете называть себя сеньорами, только тогда, когда Тим Бернерс-Ли назовёт себя Senior Web Developer. Не раньше!
Хотя, впрочем, ему скорей подойдёт другое слово: The Web Developer (Разработчик Веба).»
Наслаждайтесь!
https://youtu.be/VFIw0LlULyc
Кстати, насчёт конечного числа нажатий на клавиши. Смотрите сами https://keysleft.com/
PS: спасибо @fjod10199 за ссылку на доклад в нашем чате.
👍9
День 1185. #ЧтоНовенького
Превью Обновлений ASP.NET Core в .NET 7
Вышло уже 3 превью новинок в ASP.NET Core в новой версии .NET 7, которая должна выйти в ноябре. Вот самое интересное, на мой взгляд.
1. Внедрение сервисов в методах контроллера
Теперь не обязательно использовать атрибут
В минимальных API теперь можно добавить аннотации для спецификаций OpenAPI. Либо через методы расширения:
Теперь можно выполнять связывание из заголовков HTTPS и строки запроса в массивы примитивных типов, строк или в
Фильтры выполняются перед основной логикой обработчика маршрута и могут использоваться для проверки и изменения параметров обработчика или перехвата выполнения обработчика.
Подробнее про них рассказывает Ник Чапсас https://youtu.be/Kt9TiXrwIp4
5. Привязка с использованием TryParse
Теперь вы можете привязывать значения параметров действия контроллера с помощью метода
- https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-2/
- https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-3/
Превью Обновлений ASP.NET Core в .NET 7
Вышло уже 3 превью новинок в ASP.NET Core в новой версии .NET 7, которая должна выйти в ноябре. Вот самое интересное, на мой взгляд.
1. Внедрение сервисов в методах контроллера
Теперь не обязательно использовать атрибут
[FromServices]
, сервис будет подставляться автоматически:public class MyController : ControllerBaseЭто можно отключить в настройках:
{
public ActionResult Get(MyService service) => Ok();
}
Services.Configure<ApiBehaviorOptions>(opt =>2. Описания конечных точек
{
opt.DisableImplicitFromServicesParameters = true;
})
В минимальных API теперь можно добавить аннотации для спецификаций OpenAPI. Либо через методы расширения:
app.MapGet("/hello", () => ...)Либо через атрибуты:
.WithDescription("Hello request");
app.MapGet("/hello", [EndpointSummary("Hello request")]() => ...);3. Привязка массивов и StringValues
Теперь можно выполнять связывание из заголовков HTTPS и строки запроса в массивы примитивных типов, строк или в
StringValues
:// GET /tags?q=1&q=24. Фильтры обработчиков маршрутов
app.MapGet("/tags", (int[] q) => $"1:{q[0]}, 2:{q[1]}");
// GET /tags?names=john&names=jack
app.MapGet("/tags", (string[] names) => $"1:{names[0]}, 2:{names[1]}");
app.MapGet("/tags", (StringValues names) => $"1:{names[0]}, 2:{names[1]} ");
Фильтры выполняются перед основной логикой обработчика маршрута и могут использоваться для проверки и изменения параметров обработчика или перехвата выполнения обработчика.
app.MapGet("/hello/{name}", HelloName)Это похоже на фильтры промежуточного ПО. Но теперь их можно «навесить» на отдельные конечные точки.
.AddFilter(async (сontext, next) =>
{
return await next(сontext);
});
Подробнее про них рассказывает Ник Чапсас https://youtu.be/Kt9TiXrwIp4
5. Привязка с использованием TryParse
Теперь вы можете привязывать значения параметров действия контроллера с помощью метода
TryParse
. В примере ниже контроллер привязывает данные из строки запроса с помощью метода TryParse
в типе параметра:public class TryParseController : ControllerBaseИсточники:
{
// GET /tryparse?data=MyName
[HttpGet]
public ActionResult Get([FromQuery]CustomParse data)
{
…
}
public class CustomParse
{
public string? Name { get; set; }
public static bool TryParse(string s, out CustomParse result)
{
if (s is null)
{
result = default;
return false;
}
result = new CustomParse { Name = s };
return true;
}
}
}
- https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-2/
- https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-3/
👍2
День 1186. #ЗаметкиНаПолях
Код или Тесты: Что Рефакторить?
Сегодня рассмотрим, как рефакторить производственный код, если у вас нет достаточного покрытия тестами.
Все мы иногда работаем над устаревшими проектами. Фактически, они даже более распространены, чем разработка с нуля. Устаревшие проекты печально известны своим «качеством» кода, как производственного, так и тестового. Некоторые проекты могут вообще не иметь тестов. Как провести рефакторинг такого проекта?
Для безопасного рефакторинга у вас должны быть тесты, чтобы гарантировать, что ваш рефакторинг ничего не сломает. Но как внедрить тесты в проект с тесно связанным, не тестируемым кодом? Если бы код был хорошим и его можно было тестировать, вам не нужно было бы его рефакторить.
Это проблема курицы и яйца в старых проектах:
- Нужны тесты, чтобы убедиться, что рефакторинг прошёл успешно.
- Нужно провести рефакторинг кода, чтобы сделать его пригодным для тестирования.
Обойти эту проблему невозможно: тестовый и рабочий код неразрывно связаны; невозможно создать хорошие тесты, не вложив усилий в кодовую базу, которую они охватывают.
Чтобы преодолеть эту проблему, надо начать со сквозных и интеграционных тестов.
Сквозные тесты полностью имитируют конечного пользователя. Например, если ваше приложение представляет собой веб-сайт, сквозные тесты проверяют его через веб-интерфейс. Как правило, их мало, и они должны применяться только к наиболее важному функционалу: функциям, в которых вы никогда не хотите видеть каких-либо ошибок, и только если вы не можете получить такую же степень защиты с помощью модульных или интеграционных тестов.
Большую часть работы обычно выполняют модульные тесты, потому что их дешевле писать и поддерживать. Однако в устаревшем проекте сквозные тесты являются единственным доступным вариантом, потому что это единственный тип тестов, который не требует изменений в коде (поскольку они взаимодействуют с приложением, используя тот же интерфейс, что и обычные пользователи). Сквозные тесты также обладают наибольшей устойчивостью к рефакторингу и не вызывают ложных срабатываний из-за ваших действий по рефакторингу.
В некоторых устаревших проектах также есть золотая середина, где вы можете писать интеграционные тесты вместо сквозных. Это проекты, которые имеют хотя бы некоторую степень разделения ответственности. Например, API с беспорядочным кодом, в котором всё же есть контроллеры. Вы можете протестировать эти контроллеры вместо полноценного вызова конечных точек API из отдельного процесса. Полученные тесты будут интеграционными, и их будет легче поддерживать, чем сквозные тесты.
Хорошая новость, что большое количество сквозных и интеграционных тестов — временные. Как только вы начнёте рефакторинг, замените сквозные тесты интеграционными, а интеграционные - модульными.
Итак, путь к рефакторингу устаревшего кода таков:
1. Определите небольшую связную область в приложении, которую можно было бы отрефакторить относительно быстро и без разрушения остального кода.
2. Покройте эту область сквозными или интеграционными тестами.
3. Выполняйте рефакторинг, разделив бизнес-логику и обязанности по оркестровке.
4. Покройте бизнес-логику юнит-тестами; оркестровку - интеграционными тестами.
5. Удалите сквозные тесты (если они не обеспечивают дополнительного тестового покрытия).
6. Помните, что адекватное покрытие модульными тестами невозможно без качественной кодовой базы.
Источник: https://khorikov.org/posts/2022-01-17-production-test-code-refactor/
Код или Тесты: Что Рефакторить?
Сегодня рассмотрим, как рефакторить производственный код, если у вас нет достаточного покрытия тестами.
Все мы иногда работаем над устаревшими проектами. Фактически, они даже более распространены, чем разработка с нуля. Устаревшие проекты печально известны своим «качеством» кода, как производственного, так и тестового. Некоторые проекты могут вообще не иметь тестов. Как провести рефакторинг такого проекта?
Для безопасного рефакторинга у вас должны быть тесты, чтобы гарантировать, что ваш рефакторинг ничего не сломает. Но как внедрить тесты в проект с тесно связанным, не тестируемым кодом? Если бы код был хорошим и его можно было тестировать, вам не нужно было бы его рефакторить.
Это проблема курицы и яйца в старых проектах:
- Нужны тесты, чтобы убедиться, что рефакторинг прошёл успешно.
- Нужно провести рефакторинг кода, чтобы сделать его пригодным для тестирования.
Обойти эту проблему невозможно: тестовый и рабочий код неразрывно связаны; невозможно создать хорошие тесты, не вложив усилий в кодовую базу, которую они охватывают.
Чтобы преодолеть эту проблему, надо начать со сквозных и интеграционных тестов.
Сквозные тесты полностью имитируют конечного пользователя. Например, если ваше приложение представляет собой веб-сайт, сквозные тесты проверяют его через веб-интерфейс. Как правило, их мало, и они должны применяться только к наиболее важному функционалу: функциям, в которых вы никогда не хотите видеть каких-либо ошибок, и только если вы не можете получить такую же степень защиты с помощью модульных или интеграционных тестов.
Большую часть работы обычно выполняют модульные тесты, потому что их дешевле писать и поддерживать. Однако в устаревшем проекте сквозные тесты являются единственным доступным вариантом, потому что это единственный тип тестов, который не требует изменений в коде (поскольку они взаимодействуют с приложением, используя тот же интерфейс, что и обычные пользователи). Сквозные тесты также обладают наибольшей устойчивостью к рефакторингу и не вызывают ложных срабатываний из-за ваших действий по рефакторингу.
В некоторых устаревших проектах также есть золотая середина, где вы можете писать интеграционные тесты вместо сквозных. Это проекты, которые имеют хотя бы некоторую степень разделения ответственности. Например, API с беспорядочным кодом, в котором всё же есть контроллеры. Вы можете протестировать эти контроллеры вместо полноценного вызова конечных точек API из отдельного процесса. Полученные тесты будут интеграционными, и их будет легче поддерживать, чем сквозные тесты.
Хорошая новость, что большое количество сквозных и интеграционных тестов — временные. Как только вы начнёте рефакторинг, замените сквозные тесты интеграционными, а интеграционные - модульными.
Итак, путь к рефакторингу устаревшего кода таков:
1. Определите небольшую связную область в приложении, которую можно было бы отрефакторить относительно быстро и без разрушения остального кода.
2. Покройте эту область сквозными или интеграционными тестами.
3. Выполняйте рефакторинг, разделив бизнес-логику и обязанности по оркестровке.
4. Покройте бизнес-логику юнит-тестами; оркестровку - интеграционными тестами.
5. Удалите сквозные тесты (если они не обеспечивают дополнительного тестового покрытия).
6. Помните, что адекватное покрытие модульными тестами невозможно без качественной кодовой базы.
Источник: https://khorikov.org/posts/2022-01-17-production-test-code-refactor/
👍10
День 1187. #ЗаметкиНаПолях
Апкаст Записей
Интересную особенность записей обнаружил Фил Хаак. Вы не можете сделать апкаст, как для класса. Допустим, у нас есть следующие записи.
Базовая (она же DTO для обновления):
Фил спросил сообщество, как решить эту проблему. Предлагались разные варианты от использования маппера до сериализации/десериализации. Но решение нашлось довольно элегантное.
Апкаст Записей
Интересную особенность записей обнаружил Фил Хаак. Вы не можете сделать апкаст, как для класса. Допустим, у нас есть следующие записи.
Базовая (она же DTO для обновления):
public record PersonUpdate()Производная (с добавленным свойством
{
public string Name {get; init;}
//... остальные свойства
};
Id
):public record Person(int Id)Задача стандартная: получить
: PersonUpdate() {};
Person
из базы или API, создать PersonUpdate
с изменёнными свойствами и отправить его в метод UpdatePerson
. Код получается довольно простой:var person = GetPerson(42);Вроде всё должно работать. Но давайте посмотрим, что у нас получилось в
var updated = (PersonUpdate)person
with { Name = "New Name", …};
UpdatePerson(42, updated);
updated
:Console.WriteLine(updated);Свойство обновилось, но тип всё равно производный и содержит
// Вывод:
// Person { Name = New Name, Id = 42 }
Id
. Это, конечно, может не быть проблемой, но для Фила стало, т.к. API для обновления принимал объект без свойства Id
, а в этом случае выдавал ошибку.Фил спросил сообщество, как решить эту проблему. Предлагались разные варианты от использования маппера до сериализации/десериализации. Но решение нашлось довольно элегантное.
public record PersonUpdate()Статический метод принимает запись и выдаёт её копию. И действительно:
{
//... свойства
public static PersonUpdate
Copy(PersonUpdate updated) => new(updated);
};
var updated = PersonUpdate.Copy(person)Источник: https://gist.github.com/haacked/b47ed096201a47c9ebceb7397c09d28b
with { Name = "New Name"};
Console.WriteLine(updated);
// Вывод:
// PersonUpdate { Name = New Name }
👍16
Software Engineering at Google.pdf
9.2 MB
День 1188. #Книги
Наткнулся на книгу «Software Engineering at Google». Сам ещё не читал, но похоже, прочитать нужно обязательно.
Сегодня инженеры-программисты должны знать не только, как эффективно программировать, но и как разрабатывать правильные инженерные методы, чтобы сделать кодовую базу устойчивой и здоровой. Эта книга подчеркивает эту разницу между программированием и программной инженерией. Как программисты могут управлять кодовой базой, которая развивается и реагирует на меняющиеся требования на протяжении своей жизни? Инженеры-программисты из Google Титус Уинтерс, Хайрам Райт и Том Мэншрек представляют откровенный и проницательный взгляд на то, как некоторые из ведущих мировых специалистов создают и поддерживают ПО. В книге рассказывается об уникальной инженерной культуре, процессах и инструментах Google, а также о том, как эти аспекты влияют на эффективность инженерной организации.
Наткнулся на книгу «Software Engineering at Google». Сам ещё не читал, но похоже, прочитать нужно обязательно.
Сегодня инженеры-программисты должны знать не только, как эффективно программировать, но и как разрабатывать правильные инженерные методы, чтобы сделать кодовую базу устойчивой и здоровой. Эта книга подчеркивает эту разницу между программированием и программной инженерией. Как программисты могут управлять кодовой базой, которая развивается и реагирует на меняющиеся требования на протяжении своей жизни? Инженеры-программисты из Google Титус Уинтерс, Хайрам Райт и Том Мэншрек представляют откровенный и проницательный взгляд на то, как некоторые из ведущих мировых специалистов создают и поддерживают ПО. В книге рассказывается об уникальной инженерной культуре, процессах и инструментах Google, а также о том, как эти аспекты влияют на эффективность инженерной организации.
👍23
День 1189. #ЗаметкиНаПолях #AsyncTips
Неизменяемые словари
Задача: Нужна коллекция «ключ/значение», которая не слишком часто изменяется и допускает безопасные обращения из нескольких потоков. Например, в этой коллекции могут храниться данные состояния приложения в подстановочной (lookup) таблице; данные состояния редко изменяются, но они должны быть доступны для разных потоков.
Решение
Есть два типа неизменяемых словарей:
Несортированные и отсортированные словари обладают сходным быстродействием - O(log N) для всех типов операций, но рекомендуется использовать неупорядоченные словари, если только не требуется, чтобы элементы были отсортированы (они могут работать в целом немного быстрее). Кроме того, несортированные словари могут использоваться с любыми типами ключей, тогда как отсортированные словари требуют, чтобы тип ключей был сравнимым (например,
Словари являются полезным и общепринятым инструментом при работе с состоянием приложения. Они могут использоваться в любых сценариях, связанных с ключами/значениями или подстановками.
Неизменяемые словари, как и другие неизменяемые коллекции, поддерживают механизм для эффективного построения экземпляров, содержащих большое количество элементов. Например, если исходные данные загружаются в начале работы программы, вы сможете воспользоваться механизмом построителей для конструирования исходного неизменяемого словаря. С другой стороны, если данные строятся постепенно во время выполнения, вероятно, можно будет воспользоваться обычным методом
См. также:
- Неизменяемые стеки и очереди
- Неизменяемые списки
- Неизменяемые множества
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 9.
Неизменяемые словари
Задача: Нужна коллекция «ключ/значение», которая не слишком часто изменяется и допускает безопасные обращения из нескольких потоков. Например, в этой коллекции могут храниться данные состояния приложения в подстановочной (lookup) таблице; данные состояния редко изменяются, но они должны быть доступны для разных потоков.
Решение
Есть два типа неизменяемых словарей:
ImmutableDictionary<TKey, TValue>
и ImmutableSortedDictionary<TKey, TValue>
из пространства имён System.Collections.Immutable
, которые имеют очень похожие члены:var d = ImmutableDictionary<int, string>.Empty;Обратите внимание на использование
d = d.Add(10, "Ten");
d = d.Add(21, "Twenty-One");
d = d.SetItem(10, "Diez");
// Выводит "10Diez" и "21Twenty-One" в непредсказуемом порядке.
foreach (var item in d)
Console.WriteLine(item.Key + item.Value);
string ten = d[10];
// ten == "Diez"
d = d.Remove(21);
SetItem
. В изменяемом словаре можно было бы использовать конструкцию вида dictionary[key] = item
, но неизменяемые словари должны возвращать обновлённый неизменяемый словарь, поэтому вместо этого они должны использовать метод SetItem
.Несортированные и отсортированные словари обладают сходным быстродействием - O(log N) для всех типов операций, но рекомендуется использовать неупорядоченные словари, если только не требуется, чтобы элементы были отсортированы (они могут работать в целом немного быстрее). Кроме того, несортированные словари могут использоваться с любыми типами ключей, тогда как отсортированные словари требуют, чтобы тип ключей был сравнимым (например,
int
или реализующий IComparable
).Словари являются полезным и общепринятым инструментом при работе с состоянием приложения. Они могут использоваться в любых сценариях, связанных с ключами/значениями или подстановками.
Неизменяемые словари, как и другие неизменяемые коллекции, поддерживают механизм для эффективного построения экземпляров, содержащих большое количество элементов. Например, если исходные данные загружаются в начале работы программы, вы сможете воспользоваться механизмом построителей для конструирования исходного неизменяемого словаря. С другой стороны, если данные строятся постепенно во время выполнения, вероятно, можно будет воспользоваться обычным методом
Add
неизменяемых словарей.См. также:
- Неизменяемые стеки и очереди
- Неизменяемые списки
- Неизменяемые множества
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 9.
👍4
Какой тип ресурса рекомендуется подключить к Azure Function App для целей логирования и монтиторинга?
#Quiz #Azure
#Quiz #Azure
Anonymous Quiz
14%
Azure Event Hubs
47%
Azure Log Analytics
38%
Azure Application Insights
1%
Azure Container Instances
👍2
День 1190. #Testing
Тестировать Сначала или Потом
Когда писать тесты: до написания кода или после.
Сначала код
Это обычный подход, а также самый интуитивно понятный способ написания тестов. Сначала пишете код, а затем покрываете его тестами. Ничего сложного: это «нормальный» способ разработки ПО.
Сначала тесты
Противоположный подход: сначала вы пишете тест для функциональности, которую собираетесь разработать, а затем саму функциональность. Это наиболее важное отличие разработки через тестирование (TDD) от традиционного подхода.
Процесс TDD
1. Напишите тест
Так вы описываете требования к функциональности, которую скоро разработаете, и формулируете их в виде утверждений в тесте.
2. Убедитесь, что тест завершается неудачей по уважительной причине
Тест должен завершиться неудачей из-за проблем с тестируемой функциональностью, а не из-за какой-то несвязанной проблемы, типа исключения уровня приложения.
3. Сделайте так, чтобы тест прошёл
Реализуйте реальную функциональность, покрываемую тестом. Здесь качество кода не важно; цель в том, чтобы тест стал зеленым.
4. Рефакторинг
Если нужно, почистите код. Причина отделения этого шага в том, что легче рефакторить существующий беспорядочный код, чем писать чистый код с самого начала.
Преимущества TDD
Тесты проверяют код приложения, но кто проверяет тесты? Как убедиться, что тесты проверяют функциональность, а не просто бездействуют? Эту проблему решает TDD. Увидев, что тест проваливается из-за отсутствия функциональности (или из-за неправильной реализации), вы подтверждаете его правильность. Вы знаете, что, если код приложения перестанет работать должным образом, тест укажет на это. Эта практика снижает вероятность ложноотрицательных результатов (ложных зелёных тестов): вы уже видели, как тест провалился, и можете ожидать, что он сделает это снова. Поэтому шаг 2 так важен. Если тест терпит неудачу по несвязанной причине (например, неправильной настройке), вы не проверите этот тест и не можете знать, сработает ли он, если функциональность сломается.
При подходе «сначала код» эту проверку необходимо выполнять вручную: изменить код, чтобы сымитировать ошибку, убедиться, что тест падает, и изменить код обратно. Это утомительно, и многие пропускают этот шаг, что может привести к некорректным тестам. В TDD этот шаг встроен в сам процесс написания кода, т.е. не нужно выполнять какую-либо дополнительную работу.
Преимущества «тестов после»
Гибкость. Т.к. вам не нужно беспокоиться о тестах, вы можете легко менять код приложения: провести рефакторинг или даже полностью перепроектировать его. С тестами сделать это сложнее, потому что придётся исправлять тесты после каждого редизайна.
Когда использовать
Оба подхода нужно применять на нужном этапе вашего проекта. Можно выделить 2 этапа:
1. Делаем что надо
2. Делаем как надо
Сначала нужно наметить масштаб проекта, чтобы убедиться, что это правильное решение, и только потом создавать это решение. Первый этап включает эксперименты, наброски модели предметной области, рисование на доске и т. д. На этом этапе не нужны тесты: они будут только задерживать, и есть большая вероятность, что их придётся выбросить вместе с экспериментальным кодом.
Как только вы уверены, что делаете что надо, можно перейти к этапу 2. Здесь вы можете следовать TDD и получать все долгосрочные преимущества, такие как хорошее тестовое покрытие и качественные тесты.
Проблема с TDD заключается в том, что для того, чтобы быть продуктивным, вам нужно точно знать, что вы создаёте. Однако, как только вы это узнаете, вы сможете извлечь большую пользу из подхода «сначала тесты».
Еще одна область, где TDD полезен — исправление ошибок. Если вы нашли ошибку, не исправляйте ее сразу. Сначала напишите тест для воспроизведения этой ошибки, убедитесь, что он падает, а затем исправьте код. Таким образом, вам больше никогда не придется беспокоиться об этой ошибке.
Источник: https://khorikov.org/posts/2022-01-24-test-first-vs-test-last-approaches/
Тестировать Сначала или Потом
Когда писать тесты: до написания кода или после.
Сначала код
Это обычный подход, а также самый интуитивно понятный способ написания тестов. Сначала пишете код, а затем покрываете его тестами. Ничего сложного: это «нормальный» способ разработки ПО.
Сначала тесты
Противоположный подход: сначала вы пишете тест для функциональности, которую собираетесь разработать, а затем саму функциональность. Это наиболее важное отличие разработки через тестирование (TDD) от традиционного подхода.
Процесс TDD
1. Напишите тест
Так вы описываете требования к функциональности, которую скоро разработаете, и формулируете их в виде утверждений в тесте.
2. Убедитесь, что тест завершается неудачей по уважительной причине
Тест должен завершиться неудачей из-за проблем с тестируемой функциональностью, а не из-за какой-то несвязанной проблемы, типа исключения уровня приложения.
3. Сделайте так, чтобы тест прошёл
Реализуйте реальную функциональность, покрываемую тестом. Здесь качество кода не важно; цель в том, чтобы тест стал зеленым.
4. Рефакторинг
Если нужно, почистите код. Причина отделения этого шага в том, что легче рефакторить существующий беспорядочный код, чем писать чистый код с самого начала.
Преимущества TDD
Тесты проверяют код приложения, но кто проверяет тесты? Как убедиться, что тесты проверяют функциональность, а не просто бездействуют? Эту проблему решает TDD. Увидев, что тест проваливается из-за отсутствия функциональности (или из-за неправильной реализации), вы подтверждаете его правильность. Вы знаете, что, если код приложения перестанет работать должным образом, тест укажет на это. Эта практика снижает вероятность ложноотрицательных результатов (ложных зелёных тестов): вы уже видели, как тест провалился, и можете ожидать, что он сделает это снова. Поэтому шаг 2 так важен. Если тест терпит неудачу по несвязанной причине (например, неправильной настройке), вы не проверите этот тест и не можете знать, сработает ли он, если функциональность сломается.
При подходе «сначала код» эту проверку необходимо выполнять вручную: изменить код, чтобы сымитировать ошибку, убедиться, что тест падает, и изменить код обратно. Это утомительно, и многие пропускают этот шаг, что может привести к некорректным тестам. В TDD этот шаг встроен в сам процесс написания кода, т.е. не нужно выполнять какую-либо дополнительную работу.
Преимущества «тестов после»
Гибкость. Т.к. вам не нужно беспокоиться о тестах, вы можете легко менять код приложения: провести рефакторинг или даже полностью перепроектировать его. С тестами сделать это сложнее, потому что придётся исправлять тесты после каждого редизайна.
Когда использовать
Оба подхода нужно применять на нужном этапе вашего проекта. Можно выделить 2 этапа:
1. Делаем что надо
2. Делаем как надо
Сначала нужно наметить масштаб проекта, чтобы убедиться, что это правильное решение, и только потом создавать это решение. Первый этап включает эксперименты, наброски модели предметной области, рисование на доске и т. д. На этом этапе не нужны тесты: они будут только задерживать, и есть большая вероятность, что их придётся выбросить вместе с экспериментальным кодом.
Как только вы уверены, что делаете что надо, можно перейти к этапу 2. Здесь вы можете следовать TDD и получать все долгосрочные преимущества, такие как хорошее тестовое покрытие и качественные тесты.
Проблема с TDD заключается в том, что для того, чтобы быть продуктивным, вам нужно точно знать, что вы создаёте. Однако, как только вы это узнаете, вы сможете извлечь большую пользу из подхода «сначала тесты».
Еще одна область, где TDD полезен — исправление ошибок. Если вы нашли ошибку, не исправляйте ее сразу. Сначала напишите тест для воспроизведения этой ошибки, убедитесь, что он падает, а затем исправьте код. Таким образом, вам больше никогда не придется беспокоиться об этой ошибке.
Источник: https://khorikov.org/posts/2022-01-24-test-first-vs-test-last-approaches/
👍12
День 1191.
Подборка тегов, используемых в постах на канале, чтобы облегчить поиск. Не могу гарантировать, что все 1190 постов идеально и корректно помечены тегами, но всё-таки, эта подборка должна помочь.
Общие
Эти посты на совершенно разные темы, помечены этими тегами только с целью различать общую направленность поста.
#ЗаметкиНаПолях – технические посты. Краткие описания теории, особенности языка C# и платформы .NET, примеры кода, и т.п.
#Шпаргалка - примеры кода, команды для утилит и т.п.
#Юмор – шутки, комиксы и просто весёлые тексты или ссылки на видео.
#Оффтоп – всё прочее.
Специализированные
Эти теги более тематические, выделяют основную тему поста.
#Карьера – советы по повышению продуктивности, карьерному росту, прохождению собеседований и т.п.
#Книги – обзоры книг, которые (чаще всего) я лично прочитал, либо ещё нет, но советую прочитать.
#Курсы – обзоры и ссылки на онлайн курсы.
#МоиИнструменты – различные программы, утилиты и расширения IDE, которые я использую в работе.
#ЧтоНовенького – новости из мира .NET.
Узкоспециализированные
Эти теги относятся к определённой узкой теме.
#AsyncTips – серия постов из книги Стивена Клири “Конкурентность в C#”
#AsyncAwaitFAQ – серия постов “Самые Частые Ошибки при Работе с async/await.”
#BestPractices – советы по лучшим практикам, паттернам разработки.
#DesignPatterns – всё о паттернах проектирования, SOLID, IDEALS и т.п.
#DotNetAZ – серия постов с описанием терминов из мира .NET.
#GC – серия постов “Топ Вопросов о Памяти в .NET.” от Конрада Кокосы.
#MoreEffectiveCSharp – серия постов из книги Билла Вагнера “More Effective C#”.
#Testing – всё о тестировании кода.
#TipsAndTricks – советы и трюки, в основном по функционалу Visual Studio.
#Quiz - опросы в виде викторины.
#97Вещей – серия постов из книги “97 Вещей, Которые Должен Знать Каждый Программист”.
#ВопросыНаСобеседовании – тег говорит сам за себя, самые часто задаваемые вопросы на собеседовании по C#, ASP.NET и .NET.
#ЗадачиНаСобеседовании – похоже на вопросы, но здесь больше приводятся практические задачи. Чаще всего это 2 поста: собственно задача и ответ с разбором.
#КакСтатьСеньором – серия постов «Как Стать Сеньором» с советами о продвижении по карьерной лестнице.
Помимо этого, можно просто воспользоваться поиском по постам и попробовать найти то, что вам нужно.
Подборка тегов, используемых в постах на канале, чтобы облегчить поиск. Не могу гарантировать, что все 1190 постов идеально и корректно помечены тегами, но всё-таки, эта подборка должна помочь.
Общие
Эти посты на совершенно разные темы, помечены этими тегами только с целью различать общую направленность поста.
#ЗаметкиНаПолях – технические посты. Краткие описания теории, особенности языка C# и платформы .NET, примеры кода, и т.п.
#Шпаргалка - примеры кода, команды для утилит и т.п.
#Юмор – шутки, комиксы и просто весёлые тексты или ссылки на видео.
#Оффтоп – всё прочее.
Специализированные
Эти теги более тематические, выделяют основную тему поста.
#Карьера – советы по повышению продуктивности, карьерному росту, прохождению собеседований и т.п.
#Книги – обзоры книг, которые (чаще всего) я лично прочитал, либо ещё нет, но советую прочитать.
#Курсы – обзоры и ссылки на онлайн курсы.
#МоиИнструменты – различные программы, утилиты и расширения IDE, которые я использую в работе.
#ЧтоНовенького – новости из мира .NET.
Узкоспециализированные
Эти теги относятся к определённой узкой теме.
#AsyncTips – серия постов из книги Стивена Клири “Конкурентность в C#”
#AsyncAwaitFAQ – серия постов “Самые Частые Ошибки при Работе с async/await.”
#BestPractices – советы по лучшим практикам, паттернам разработки.
#DesignPatterns – всё о паттернах проектирования, SOLID, IDEALS и т.п.
#DotNetAZ – серия постов с описанием терминов из мира .NET.
#GC – серия постов “Топ Вопросов о Памяти в .NET.” от Конрада Кокосы.
#MoreEffectiveCSharp – серия постов из книги Билла Вагнера “More Effective C#”.
#Testing – всё о тестировании кода.
#TipsAndTricks – советы и трюки, в основном по функционалу Visual Studio.
#Quiz - опросы в виде викторины.
#97Вещей – серия постов из книги “97 Вещей, Которые Должен Знать Каждый Программист”.
#ВопросыНаСобеседовании – тег говорит сам за себя, самые часто задаваемые вопросы на собеседовании по C#, ASP.NET и .NET.
#ЗадачиНаСобеседовании – похоже на вопросы, но здесь больше приводятся практические задачи. Чаще всего это 2 поста: собственно задача и ответ с разбором.
#КакСтатьСеньором – серия постов «Как Стать Сеньором» с советами о продвижении по карьерной лестнице.
Помимо этого, можно просто воспользоваться поиском по постам и попробовать найти то, что вам нужно.
1👍59👎1
.NET Разработчик pinned «День 1191. Подборка тегов, используемых в постах на канале, чтобы облегчить поиск. Не могу гарантировать, что все 1190 постов идеально и корректно помечены тегами, но всё-таки, эта подборка должна помочь. Общие Эти посты на совершенно разные темы, помечены…»
День 1192. #Оффтоп
Сегодня порекомендую ещё одно очень крутое и познавательное выступление с NDC Conference Oslo, которая проходила в конце 2021 года. Доклад Дилана Бити называется «Plain Text».
Программное обеспечение – это сложно. Машинное обучение, архитектуры микросервисов, очереди сообщений... Каждые несколько месяцев появляется ещё одна революционная идея, которую нужно изучать, ещё одна инфраструктура. И в основе всех этих удивительных идей и абстракций лежит текст. Когда вы работаете с программным обеспечением, вы постоянно работаете с текстом. Некоторые из этих текстовых файлов являются исходным кодом, некоторые — конфигурационными файлами, некоторые — документацией. Редакторы, системы контроля версий, языки программирования — всё, от C# и HTML до Git и VS Code, основано на идее «простых текстовых файлов». Но не всё так просто.
Когда мы говорим, что что-то является «простым текстовым файлом», мы полагаемся на огромное количество предположений: об операционных системах, редакторах, форматах файлов, языке, культуре, истории… и в большинстве случаев это нормально. Но когда что-то идёт не так, «обычный текст» может привести к самым странным ошибкам, которые вы когда-либо видели. Почему в журналах событий Windows появляется китайский язык? Почему город Орхус находится не в том месте при упорядочивании по алфавиту? Что такое Kohuept? И почему у Магнуса Мортенссона всегда проблемы с въездом в США? Дилан Битти рассказывает о мире текстовых файлов: от истории механических телетайпов до кодировок, сопоставлений и кодовых страниц. Разбирает памятные баги и золотые правила работы с простым текстом. Кстати, кириллица в докладе разбирается довольно подробно.
Сегодня порекомендую ещё одно очень крутое и познавательное выступление с NDC Conference Oslo, которая проходила в конце 2021 года. Доклад Дилана Бити называется «Plain Text».
Программное обеспечение – это сложно. Машинное обучение, архитектуры микросервисов, очереди сообщений... Каждые несколько месяцев появляется ещё одна революционная идея, которую нужно изучать, ещё одна инфраструктура. И в основе всех этих удивительных идей и абстракций лежит текст. Когда вы работаете с программным обеспечением, вы постоянно работаете с текстом. Некоторые из этих текстовых файлов являются исходным кодом, некоторые — конфигурационными файлами, некоторые — документацией. Редакторы, системы контроля версий, языки программирования — всё, от C# и HTML до Git и VS Code, основано на идее «простых текстовых файлов». Но не всё так просто.
Когда мы говорим, что что-то является «простым текстовым файлом», мы полагаемся на огромное количество предположений: об операционных системах, редакторах, форматах файлов, языке, культуре, истории… и в большинстве случаев это нормально. Но когда что-то идёт не так, «обычный текст» может привести к самым странным ошибкам, которые вы когда-либо видели. Почему в журналах событий Windows появляется китайский язык? Почему город Орхус находится не в том месте при упорядочивании по алфавиту? Что такое Kohuept? И почему у Магнуса Мортенссона всегда проблемы с въездом в США? Дилан Битти рассказывает о мире текстовых файлов: от истории механических телетайпов до кодировок, сопоставлений и кодовых страниц. Разбирает памятные баги и золотые правила работы с простым текстом. Кстати, кириллица в докладе разбирается довольно подробно.
YouTube
Plain Text - Dylan Beattie - NDC Oslo 2021
Software is complicated. Machine learning, microservice architectures, message queues... every few months there's another revolutionary idea to consider, another framework to learn. And underneath so many of these amazing ideas and abstractions is text. When…
👍8
Нужна коллекция экземпляров типа Person, которая будет в основном использоваться для поиска людей по номеру паспорта. Вы знаете, что коллекция всегда будет содержать ровно 200 элементов. Какой тип коллекции будет наиболее подходящим?
#Quiz #CSharp
#Quiz #CSharp
Anonymous Quiz
24%
Массив
6%
Список
23%
HashSet
45%
Словарь
1%
Очередь
1%
Стек
👍18