День 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
День 1193. #ЗаметкиНаПолях #TipsAndTricks
Временно Изменяем CurrentCulture
Иногда для тестирования некоторых функций вам требуется изменить культуру потока, в котором работает приложение. Текущая культура определяется в глобальном свойстве
Создадим класс, который реализует интерфейс
Например, проверим символ валюты:
Итого
Использование класса, реализующего
Источник: https://dev.to/bellonedavide/c-tip-how-to-temporarily-change-the-currentculture-2bp7
Временно Изменяем CurrentCulture
Иногда для тестирования некоторых функций вам требуется изменить культуру потока, в котором работает приложение. Текущая культура определяется в глобальном свойстве
Thread.CurrentThread.CurrentCulture
.Создадим класс, который реализует интерфейс
IDisposable
, чтобы иметь ограниченный блок кода, в котором будет использоваться новая культура:public class TempCulture : IDisposableВ конструкторе сохраняем текущую культуру в приватном поле. Затем, когда мы вызываем метод Dispose (который неявно вызывается при закрытии блока using), мы используем это значение для восстановления исходной культуры.
{
CultureInfo _old;
public TempCulture(CultureInfo culture)
{
_old = CultureInfo.CurrentCulture;
Thread.CurrentThread.CurrentCulture = culture;
}
public void Dispose()
{
Thread.CurrentThread.CurrentCulture = _old;
}
}
Например, проверим символ валюты:
Thread.CurrentThread.CurrentCulture =Сначала мы устанавливаем культуру текущего потока на японскую, и получаем символ валюты – йену ¥. Затем временно переходим на русскую культуру и в консоль выводится рубль ₽. Наконец, когда мы выходим за пределы блока using, мы снова получаем йену.
new CultureInfo("ja-jp");
Console.WriteLine(
Thread.CurrentThread.CurrentCulture
.NumberFormat.CurrencySymbol
);
//¥
using (new TempCulture(new CultureInfo("ru-ru")))
{
Console.WriteLine(
Thread.CurrentThread.CurrentCulture
.NumberFormat.CurrencySymbol
);
//₽
}
Console.WriteLine(
Thread.CurrentThread.CurrentCulture
.NumberFormat.CurrencySymbol
);
//¥
Итого
Использование класса, реализующего
IDisposable
, — хороший способ создать временную среду с характеристиками, отличными от характеристик основной среды.Источник: https://dev.to/bellonedavide/c-tip-how-to-temporarily-change-the-currentculture-2bp7
👍21
День 1194. #Testing
Стоимость Кода
Сегодняшний пост посвящён долгосрочным последствиям наших решений в процессе разработки программного обеспечения.
Вопрос
Простые однострочные свойства слишком тривиальны. Стоит ли их тестировать? Ведь в крупных или долгосрочных проектах кто-то может изменить их. Правильно ли предполагать, что их поведение никогда не изменится? Написать тест для них просто и займёт всего минуту.
Разве уверенность в том, что никто случайно не сломает ваш код, подправив сеттеры и геттеры, не оправдывает написание чрезвычайно простых модульных тестов?
Этот вопрос стоит разделить его на две части.
1. Правильно ли предположить, что поведение «однострочников» никогда не изменится?
Нет необходимости это предполагать. Вы можете протестировать этот код, как только он станет достаточно сложным. Именно здесь становятся полезными инструменты покрытия кода. Покрытие кода - недостаточный показатель для определения качества ваших тестов. Но эти метрики всё же полезны в некоторых сценариях. Один из них — видеть, какие части вашего кода тестируются, а какие нет.
Инструменты анализа покрытия кода позволяют увидеть добавление сложности (например, ветвления) в эти простые свойства. И вы заметите, что часть этой сложности не проверена.
2. Долгосрочная и краткосрочная стоимость кода
Написание модульных тестов для этих однострочников тривиально и занимает всего минуту для каждого.
Написать такие тесты действительно легко. Но это не главная проблема. Стоимость здесь состоит из двух частей:
- Написание такого теста
- Поддержание его на протяжении всего жизненного цикла проекта
И вторая часть гораздо важнее первой.
Написание кода — это одноразовое действие, вам нужно сделать это только один раз. С другой стороны, чтение и сопровождение кода — непрерывный процесс. Затраты на этот процесс со временем увеличиваются. Рассмотрим все действия, которые становятся более затратными по мере добавления новых тестов:
- Рефакторинг тестов при рефакторинге тестируемого кода
- Запуск дополнительных тестов при каждом изменении кода
- Обработка ложных срабатываний
- Затраты времени на чтение тестов, когда вы пытаетесь понять, как ведет себя тестируемый код
Если это кажется слишком трудоёмким – это потому, что так оно и есть. Следовательно, вы должны уделять очень пристальное внимание тому, какие тесты вы добавляете в свой набор тестов. Лучше вообще не писать тест, чем писать малоценный тест, даже если сам этот тест простой.
Обратите внимание, что это правило верно для всего вашего кода, а не только для тестов. Вы читаете код гораздо чаще, чем пишете его, поэтому весь ваш код должен быть оптимизирован для чтения, а не для написания.
Источник: https://khorikov.org/posts/2021-09-27-cost-of-code/
Стоимость Кода
Сегодняшний пост посвящён долгосрочным последствиям наших решений в процессе разработки программного обеспечения.
Вопрос
Простые однострочные свойства слишком тривиальны. Стоит ли их тестировать? Ведь в крупных или долгосрочных проектах кто-то может изменить их. Правильно ли предполагать, что их поведение никогда не изменится? Написать тест для них просто и займёт всего минуту.
Разве уверенность в том, что никто случайно не сломает ваш код, подправив сеттеры и геттеры, не оправдывает написание чрезвычайно простых модульных тестов?
Этот вопрос стоит разделить его на две части.
1. Правильно ли предположить, что поведение «однострочников» никогда не изменится?
Нет необходимости это предполагать. Вы можете протестировать этот код, как только он станет достаточно сложным. Именно здесь становятся полезными инструменты покрытия кода. Покрытие кода - недостаточный показатель для определения качества ваших тестов. Но эти метрики всё же полезны в некоторых сценариях. Один из них — видеть, какие части вашего кода тестируются, а какие нет.
Инструменты анализа покрытия кода позволяют увидеть добавление сложности (например, ветвления) в эти простые свойства. И вы заметите, что часть этой сложности не проверена.
2. Долгосрочная и краткосрочная стоимость кода
Написание модульных тестов для этих однострочников тривиально и занимает всего минуту для каждого.
Написать такие тесты действительно легко. Но это не главная проблема. Стоимость здесь состоит из двух частей:
- Написание такого теста
- Поддержание его на протяжении всего жизненного цикла проекта
И вторая часть гораздо важнее первой.
Написание кода — это одноразовое действие, вам нужно сделать это только один раз. С другой стороны, чтение и сопровождение кода — непрерывный процесс. Затраты на этот процесс со временем увеличиваются. Рассмотрим все действия, которые становятся более затратными по мере добавления новых тестов:
- Рефакторинг тестов при рефакторинге тестируемого кода
- Запуск дополнительных тестов при каждом изменении кода
- Обработка ложных срабатываний
- Затраты времени на чтение тестов, когда вы пытаетесь понять, как ведет себя тестируемый код
Если это кажется слишком трудоёмким – это потому, что так оно и есть. Следовательно, вы должны уделять очень пристальное внимание тому, какие тесты вы добавляете в свой набор тестов. Лучше вообще не писать тест, чем писать малоценный тест, даже если сам этот тест простой.
Обратите внимание, что это правило верно для всего вашего кода, а не только для тестов. Вы читаете код гораздо чаще, чем пишете его, поэтому весь ваш код должен быть оптимизирован для чтения, а не для написания.
Источник: https://khorikov.org/posts/2021-09-27-cost-of-code/
👍10
День 1195. #Карьера
6 Вещей, Которым я Научилась за Полгода Работы Тимлидом
"Не прошло и полугода, как я заняла должность руководителя группы. Я пришла из небольшой компании, где неофициально руководила проектом. Вот 6 главных вещей, которые я лично усвоила, став тимлидом на крупном проекте."
1. Больше встреч, меньше времени на разработку - это неизбежно
Несмотря на то, что меня заверили, что я по-прежнему буду выполнять большую часть работы по разработке, это вскоре прекратилось, поскольку увеличились затраты времени на другие обязанности. Особенно в периоды, когда мы нанимали сотрудников, и мне приходилось часами просматривать резюме и сидеть на собеседованиях. В среднем я бы сказала, что практическое время на разработку сократилось до 50% или даже меньше.
2. Повседневный менеджмент требует много времени и усилий
Повседневное управление — это не только приём заявок на отпуск или ответы на странные вопросы — обычно это гораздо больше. В моей компании мы проводим встречи один на один раз в две недели. С командой из 5 человек это оказалось неожиданно много! И в них мне приходилось помогать с постановкой целей и следить за тем, чтобы все были довольны, не упуская из виду рабочую нагрузку коллег и их цели.
Кроме того, адаптация новичков тоже занимает много времени — я не тот человек, который хочет бросать людей в пекло без поддержки, поэтому я не тороплюсь, помогаю им, чтобы убедиться, что у всех всё в порядке.
3. Не все сразу признают ваше лидерство
В самом деле, кажется, некоторые до сих пор не признают меня как начальника! Одно дело получить повышение, а другое — заслужить уважение окружающих. Особенно, когда вы относительно новичок в компании, а коллеги могут работать там уже некоторое время, поэтому вы, вероятно, не так хорошо знаете процессы и продукт.
Добавьте к этому тот факт, что я довольно молода для этой должности, плюс женщина. Так что мне пришлось много работать, чтобы доказать, что я достойна и способна руководить командой.
4. Твоя задача не в том, чтобы быть лучшим в команде
Это важно, но это не то же самое, что быть сеньором. Раньше меня считали техническим экспертом, и я давала советы по дизайну и реализации. Мне нравился процесс обсуждения решений с другими разработчиками. Однако теперь, когда я занимаю руководящую роль, я вместо этого должна признавать сильные стороны членов моей команды и создавать среду, которая поощряет членов команды вносить свой вклад. В противном случае вы столкнётесь с неприятным ярлыком «микроменеджера» или «диктатора»!
Это не значит, что вы не можете иметь своё мнение или быть экспертом, но вы не должны заставлять всех делать что-то по-вашему только потому, что вы главный.
5. Не все хотят, чтобы ими «управляли»
Некоторым людям не нужен менеджер, некоторые не хотят, чтобы их тренировали или наставляли. Вы просто не можете заставить их участвовать в процессе. И это нормально. Однако, если они активно сопротивляются вам или проявляют неуважение, это не нормально. Должно присутствовать взаимное уважение.
6. Я реально ненавижу конфронтацию
В трудные времена мне приходилось набираться смелости, чтобы противостоять людям и брать ответственность на себя. Это то, над чем мне придётся продолжать работать, потому что это не было естественно для меня!
Конфронтация не означает проявления агрессии или жарких споров, но если вы менеджер, вы не можете избежать её, если кто-то не справляется, ведёт себя грубо или ещё каким-то образом создаёт проблему. Вы, как руководитель группы, несёте ответственность за разрешение конфликтов.
Однако иногда это действительно отстой! Я хочу хороших рабочих отношений с людьми, с которыми я работаю, и чтобы окружающая среда была дружелюбной и веселой. Однако, как менеджер, я просто не могу всегда всем нравиться.
Источник: https://katycodesstuff.hashnode.dev/the-top-6-things-ive-learnt-after-6-months-as-a-team-lead
Автор оригинала: Katy A
6 Вещей, Которым я Научилась за Полгода Работы Тимлидом
"Не прошло и полугода, как я заняла должность руководителя группы. Я пришла из небольшой компании, где неофициально руководила проектом. Вот 6 главных вещей, которые я лично усвоила, став тимлидом на крупном проекте."
1. Больше встреч, меньше времени на разработку - это неизбежно
Несмотря на то, что меня заверили, что я по-прежнему буду выполнять большую часть работы по разработке, это вскоре прекратилось, поскольку увеличились затраты времени на другие обязанности. Особенно в периоды, когда мы нанимали сотрудников, и мне приходилось часами просматривать резюме и сидеть на собеседованиях. В среднем я бы сказала, что практическое время на разработку сократилось до 50% или даже меньше.
2. Повседневный менеджмент требует много времени и усилий
Повседневное управление — это не только приём заявок на отпуск или ответы на странные вопросы — обычно это гораздо больше. В моей компании мы проводим встречи один на один раз в две недели. С командой из 5 человек это оказалось неожиданно много! И в них мне приходилось помогать с постановкой целей и следить за тем, чтобы все были довольны, не упуская из виду рабочую нагрузку коллег и их цели.
Кроме того, адаптация новичков тоже занимает много времени — я не тот человек, который хочет бросать людей в пекло без поддержки, поэтому я не тороплюсь, помогаю им, чтобы убедиться, что у всех всё в порядке.
3. Не все сразу признают ваше лидерство
В самом деле, кажется, некоторые до сих пор не признают меня как начальника! Одно дело получить повышение, а другое — заслужить уважение окружающих. Особенно, когда вы относительно новичок в компании, а коллеги могут работать там уже некоторое время, поэтому вы, вероятно, не так хорошо знаете процессы и продукт.
Добавьте к этому тот факт, что я довольно молода для этой должности, плюс женщина. Так что мне пришлось много работать, чтобы доказать, что я достойна и способна руководить командой.
4. Твоя задача не в том, чтобы быть лучшим в команде
Это важно, но это не то же самое, что быть сеньором. Раньше меня считали техническим экспертом, и я давала советы по дизайну и реализации. Мне нравился процесс обсуждения решений с другими разработчиками. Однако теперь, когда я занимаю руководящую роль, я вместо этого должна признавать сильные стороны членов моей команды и создавать среду, которая поощряет членов команды вносить свой вклад. В противном случае вы столкнётесь с неприятным ярлыком «микроменеджера» или «диктатора»!
Это не значит, что вы не можете иметь своё мнение или быть экспертом, но вы не должны заставлять всех делать что-то по-вашему только потому, что вы главный.
5. Не все хотят, чтобы ими «управляли»
Некоторым людям не нужен менеджер, некоторые не хотят, чтобы их тренировали или наставляли. Вы просто не можете заставить их участвовать в процессе. И это нормально. Однако, если они активно сопротивляются вам или проявляют неуважение, это не нормально. Должно присутствовать взаимное уважение.
6. Я реально ненавижу конфронтацию
В трудные времена мне приходилось набираться смелости, чтобы противостоять людям и брать ответственность на себя. Это то, над чем мне придётся продолжать работать, потому что это не было естественно для меня!
Конфронтация не означает проявления агрессии или жарких споров, но если вы менеджер, вы не можете избежать её, если кто-то не справляется, ведёт себя грубо или ещё каким-то образом создаёт проблему. Вы, как руководитель группы, несёте ответственность за разрешение конфликтов.
Однако иногда это действительно отстой! Я хочу хороших рабочих отношений с людьми, с которыми я работаю, и чтобы окружающая среда была дружелюбной и веселой. Однако, как менеджер, я просто не могу всегда всем нравиться.
Источник: https://katycodesstuff.hashnode.dev/the-top-6-things-ive-learnt-after-6-months-as-a-team-lead
Автор оригинала: Katy A
👍12
Объявлен следующий массив:
var allReports = new Report[20];
Вы не знаете, является ли Report ссылочным типом или структурой. Какое из следующих утверждений верно? #Quiz #CSharp
var allReports = new Report[20];
Вы не знаете, является ли Report ссылочным типом или структурой. Какое из следующих утверждений верно? #Quiz #CSharp
Anonymous Quiz
72%
allReports - ссылочного типа
17%
allReports - ссылочного типа, только если Report - ссылочного типа
9%
allReports - типа значения
3%
allReports - типа dynamic
👍6
День 1196. #ЗаметкиНаПолях
Правила Кода
Roslyn имеет очень большой набор анализаторов для проверки качества вашего кода, но вы должны включить эти анализаторы, прежде чем они начнут что-то делать. Сегодня рассмотрим краткую информацию о том, почему важно включать эти анализаторы в ваши проекты C#, как это сделать и как их настроить.
Правила кода — это правила, которые компилятор или инструмент анализа кода применяет на уровне сборки. Они обеспечивают соблюдение соглашений о кодировании, выявляют ошибки и предоставляют инструменты для исправлений. Roslyn и другие инструменты .NET/C# используют статический анализ кода, чтобы проверить, где в вашем коде есть нарушения. Rider и Resharper предоставляют инструменты статического анализа кода поверх существующего анализа кода от Roslyn.
У команд, которые используют правила кода, возникает меньше проблем. Вот некоторые из преимуществ использования анализа кода:
- Уменьшает количество ошибок
- Уменьшает количество претензий к вашему коду в пул-реквестах
- Заставляет использовать новые конструкции кода вместо старых
- Изменяет вредные привычки
- Одинаковый стиль кода уменьшает количество несущественных различий в Git
- Удаляет ненужный код
- Уменьшает количество ненужных путей кода
Без правил кода этот код компилируется нормально:
Правила кода включаются на уровне csproj, а затем можно изменить файл editorconfig для отдельных правил. Нужно добавить Nuget пакет Microsoft.CodeAnalysis.NetAnalyzers (Roslyn Analysers). Это самый распространённый набор анализаторов. Они работают на всех IDE и платформах и внутри конвейеров CI/CD. Вы также можете добавить другие пакеты Nuget для дополнительных анализаторов.
Если в вашем решении несколько проектов, нужно переместить конфигурацию в файл Directory.Build.props. Это позволит совместно использовать параметры проекта для нескольких проектов в вашем решении.
Гораздо проще начать со всеми включенными правилами и собрать решение с полным анализом кода. Однако вы можете настроить каждое правило отдельно. Добавьте файл editorconfig в своё решение. Можно настраивать правила как в визуальном редакторе, так и отредактировать файл напрямую как текст. Справочник по конфигурации можно найти здесь.
Рекомендуется включить все правила кода и постепенно исправлять ошибки, с которыми вы сталкиваетесь в своём решении. Существуют инструменты массового исправления, которые помогут вам решить многие проблемы. Команда CLI dotnet format применит множество исправлений, но чаще бывает безопаснее применять исправления для правил по одному вручную. Устранение всех проблем может занять некоторое время. Однако не нужно исправлять все нарушения правил кода за один раз.
Итого
Добавляйте правила кода в каждый новый проект, над которым вы работаете, и пытайтесь довести существующий код до идеала, применяя правила кода. Некоторым этот процесс покажется неприятным, и я признаю, что система конфигурации довольно запутана, но в долгосрочной перспективе это того стоит. Анализ кода действительно улучшает его качество, и вы улучшаете свои привычки кодирования. Вы также улучшите навыки кодирования в команде и будете реже спорить из-за мелких деталей в пулл-реквестах. Если в вашей команде есть люди, которые сопротивляются этому, пойдите на некоторые уступки, отключив правила, которые они считают особенно надоедливыми.
Источник: https://christianfindlay.com/2022/04/24/code-rules/
Правила Кода
Roslyn имеет очень большой набор анализаторов для проверки качества вашего кода, но вы должны включить эти анализаторы, прежде чем они начнут что-то делать. Сегодня рассмотрим краткую информацию о том, почему важно включать эти анализаторы в ваши проекты C#, как это сделать и как их настроить.
Правила кода — это правила, которые компилятор или инструмент анализа кода применяет на уровне сборки. Они обеспечивают соблюдение соглашений о кодировании, выявляют ошибки и предоставляют инструменты для исправлений. Roslyn и другие инструменты .NET/C# используют статический анализ кода, чтобы проверить, где в вашем коде есть нарушения. Rider и Resharper предоставляют инструменты статического анализа кода поверх существующего анализа кода от Roslyn.
У команд, которые используют правила кода, возникает меньше проблем. Вот некоторые из преимуществ использования анализа кода:
- Уменьшает количество ошибок
- Уменьшает количество претензий к вашему коду в пул-реквестах
- Заставляет использовать новые конструкции кода вместо старых
- Изменяет вредные привычки
- Одинаковый стиль кода уменьшает количество несущественных различий в Git
- Удаляет ненужный код
- Уменьшает количество ненужных путей кода
Без правил кода этот код компилируется нормально:
public static class ProgramОднако, когда мы включаем правила кода, анализатор сообщит нам, что есть ошибка. Если мы правильно настроим правила кода, мы не сможем собрать приложение. Эту ошибку удастся предотвратить ещё до того, как мы запустим тесты. Бесчисленные правила могут помочь вам улучшить качество кода, производительность, удобочитаемость и найти более простые способы написания кода.
{
public static void Main() =>
Console.WriteLine(
string.Format(new CultureInfo("en-US"),
"Hello {0}{1}!", "World")
);
}
Правила кода включаются на уровне csproj, а затем можно изменить файл editorconfig для отдельных правил. Нужно добавить Nuget пакет Microsoft.CodeAnalysis.NetAnalyzers (Roslyn Analysers). Это самый распространённый набор анализаторов. Они работают на всех IDE и платформах и внутри конвейеров CI/CD. Вы также можете добавить другие пакеты Nuget для дополнительных анализаторов.
Если в вашем решении несколько проектов, нужно переместить конфигурацию в файл Directory.Build.props. Это позволит совместно использовать параметры проекта для нескольких проектов в вашем решении.
Гораздо проще начать со всеми включенными правилами и собрать решение с полным анализом кода. Однако вы можете настроить каждое правило отдельно. Добавьте файл editorconfig в своё решение. Можно настраивать правила как в визуальном редакторе, так и отредактировать файл напрямую как текст. Справочник по конфигурации можно найти здесь.
Рекомендуется включить все правила кода и постепенно исправлять ошибки, с которыми вы сталкиваетесь в своём решении. Существуют инструменты массового исправления, которые помогут вам решить многие проблемы. Команда CLI dotnet format применит множество исправлений, но чаще бывает безопаснее применять исправления для правил по одному вручную. Устранение всех проблем может занять некоторое время. Однако не нужно исправлять все нарушения правил кода за один раз.
Итого
Добавляйте правила кода в каждый новый проект, над которым вы работаете, и пытайтесь довести существующий код до идеала, применяя правила кода. Некоторым этот процесс покажется неприятным, и я признаю, что система конфигурации довольно запутана, но в долгосрочной перспективе это того стоит. Анализ кода действительно улучшает его качество, и вы улучшаете свои привычки кодирования. Вы также улучшите навыки кодирования в команде и будете реже спорить из-за мелких деталей в пулл-реквестах. Если в вашей команде есть люди, которые сопротивляются этому, пойдите на некоторые уступки, отключив правила, которые они считают особенно надоедливыми.
Источник: https://christianfindlay.com/2022/04/24/code-rules/
👍10
День 1198. #ЧтоНовенького
Обновления ASP.NET Core в .NET 7 Превью 4. Начало
Недавно вышедший превью 4 .NET 7 включает много отличных обновлений в ASP.NET Core.
1. Улучшения производительности HTTP/2
Значительно переработана обработка сервером Kestrel запросов HTTP/2. HTTP/2 позволяет параллельно выполнять до 100 запросов по TCP-соединению. Это называется мультиплексированием. До превью 4 мультиплексирование HTTP/2 в Kestrel основывалось на блокировке через ключевое слово lock для управления тем, какой запрос может записывать в TCP-соединение. Хотя блокировка — это простое решение для написания безопасного многопоточного кода, она неэффективна при высокой конкуренции потоков.
Профилирование и бенчмаркинг Kestrel показывали:
- Высокую конкуренцию за поток, когда соединение занято.
- Пустую трату циклов ЦП из-за запросов, борющихся за блокировку записи.
- Бездействующие ядра ЦП, поскольку запросы ожидали блокировки записи.
- Производительность Kestrel, для других серверов в сценариях с загруженным соединением.
Решение состоит в том, чтобы переписать, как запросы HTTP/2 в Kestrel получают доступ к TCP-соединению. Потокобезопасная очередь заменяет блокировку записи. Вместо того, чтобы бороться за то, кто может использовать блокировку записи, теперь запросы выстраиваются в очередь, и их обрабатывает выделенный потребитель. Ресурсы ЦП, которые ранее тратились впустую, теперь доступны остальной части приложения.
Эти улучшения видны в gRPC, популярной среде RPC, использующей HTTP/2.
2. Типизированные результаты для минимальных API
В .NET 6 представили интерфейс
В .NET 7 типы, реализующие
Новый статический класс
Тогда пример выше можно переписать с использованием
Источник: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-4/
Обновления ASP.NET Core в .NET 7 Превью 4. Начало
Недавно вышедший превью 4 .NET 7 включает много отличных обновлений в ASP.NET Core.
1. Улучшения производительности HTTP/2
Значительно переработана обработка сервером Kestrel запросов HTTP/2. HTTP/2 позволяет параллельно выполнять до 100 запросов по TCP-соединению. Это называется мультиплексированием. До превью 4 мультиплексирование HTTP/2 в Kestrel основывалось на блокировке через ключевое слово lock для управления тем, какой запрос может записывать в TCP-соединение. Хотя блокировка — это простое решение для написания безопасного многопоточного кода, она неэффективна при высокой конкуренции потоков.
Профилирование и бенчмаркинг Kestrel показывали:
- Высокую конкуренцию за поток, когда соединение занято.
- Пустую трату циклов ЦП из-за запросов, борющихся за блокировку записи.
- Бездействующие ядра ЦП, поскольку запросы ожидали блокировки записи.
- Производительность Kestrel, для других серверов в сценариях с загруженным соединением.
Решение состоит в том, чтобы переписать, как запросы HTTP/2 в Kestrel получают доступ к TCP-соединению. Потокобезопасная очередь заменяет блокировку записи. Вместо того, чтобы бороться за то, кто может использовать блокировку записи, теперь запросы выстраиваются в очередь, и их обрабатывает выделенный потребитель. Ресурсы ЦП, которые ранее тратились впустую, теперь доступны остальной части приложения.
Эти улучшения видны в gRPC, популярной среде RPC, использующей HTTP/2.
2. Типизированные результаты для минимальных API
В .NET 6 представили интерфейс
IResult
для предоставления значений, возвращаемых из минимальных API, которые не используют неявную поддержку сериализации JSON возвращённого объекта в ответ HTTP. Статический класс Results
используется для создания различных объектов IResult
, представляющих различные типы ответов, от простой установки кода ответа до перенаправления на другой URL-адрес. Однако типы инфраструктуры, реализующие IResult
, возвращаемые этими методами, были внутренними, что затрудняло проверку конкретного типа IResult
, возвращаемого методами API, в модульных тестах.В .NET 7 типы, реализующие
IResult
в ASP.NET Core, стали общедоступными, что позволяет использовать простые утверждения при тестировании. Пусть у нас есть следующий метод API:public async Task<IResult> GetTodos(TodoDb db)Тогда проверить результат метода можно следующим образом:
{
return Results.Ok(
await db.Todos.ToArrayAsync()
);
}
var db = CreateDbContext();Обратите внимание, что тип результата —
var result = await api.GetTodos(db);
Assert.IsType<Ok<object>>(result);
Ok<object>
, поскольку метод Results.Ok(object? value = null)
принимает значение как объект, а не как исходный тип. Чтобы решить эту проблему, введён новый фабричный класс для создания «типизированных» результатов.Новый статический класс
Microsoft.AspNetCore.Http.TypedResults
является «типизированным» эквивалентом существующего класса Microsoft.AspNetCore.Http.Results
. Вы можете использовать TypedResults
в минимальных API для создания экземпляров типов, реализующих IResult
, c сохранением информации о конкретном типе.Тогда пример выше можно переписать с использованием
TypedResults
:public async Task<IResult> GetTodos(TodoDb db)И протестировать уже типизированный результат:
{
return TypedResults.Ok(
await db.Todos.ToArrayAsync()
);
}
var db = CreateDbContext();Продолжение следует…
var result = await todosApi.GetTodos(db);
Assert.IsType<Ok<Todo[]>>(result);
Источник: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-4/
👍7
День 1199. #Testing
Тестирование в Реальной Жизни. Начало
Коротко о различных нестандартных типах тестов и о том, что нужно иметь в виду при их использовании.
1. Тесты бизнес-логики
Эти тесты включают в себя всё, что подтверждает, что ваша бизнес-логика работает: модульные тесты, интеграционные тесты, сквозные тесты и т. д. Конкретная их реализация может варьироваться, но суть в том, что они должны проверять бизнес-цели кода, а не его техническую структуру. Здесь нас не заботят приватные методы, вызываются ли методы в правильном порядке, правильность параметров или что-либо ещё техническое. Просто нужно убедиться, что вывод соответствует вашим ожиданиям.
Избегайте любых непроизводственных компонентов (имитаций). Используйте реальные базы данных, реальные конечные точки и т. д. Имитируйте их, только если вам нужно сделать тесты более надёжными или быстрыми. Не имеет значения, что тесты проходят, если приложение не работает. Убедитесь, что вы проверяете все уровни вашего ПО, включая сетевые рукопожатия, авторизацию/аутентификацию, разрешения и т. д. В идеале используйте инфраструктуру как код для создания новой среды тестирования каждый раз.
2. Сравнительные тесты и тесты производительности
Призваны убедиться, что ваше приложение работает в реальных сценариях. Можно взять производственные журналы, извлечь запросы, а затем запустить их для нового и старого кода, чтобы сравнить, совпадают ли выходные данные. Таким образом, вы можете убедиться, что приложение действительно работает. Здесь нужно помнить о нескольких вещах.
Во-первых, если ваше приложение не сохраняет состояния, то запустить его таким образом несложно, поскольку оно просто принимает входные данные и возвращает выходные данные. Это математические операции, системы рекомендаций и т. д. Однако вы можете сделать все приложения фактически не сохраняющими состояние, если будете всегда логировать ввод и вывод всех внешних вызовов: сетевых запросов, запросов к БД, чтения файлов и т. д. Очевидно, что это может быть возможно не во всех случаях.
Во-вторых, законы о защите персональных данных (GDPR, CCPA и т. п.). Возможно, вашей тестовой среде не разрешено обрабатывать производственные данные, поэтому необходимо анонимизировать их (как в журналах, так и при передаче между приложениями). Кроме того, необходимо правильно обрабатывать географическую безопасность - если вашим данным запрещено покидать пределы ЕС, вы не сможете проводить тесты в другой стране.
В-третьих, нагрузочные тесты. Как правило, не стоит брать логи нагрузочных тестов и запускать на них сравнительные тесты. Поэтому важно уметь отличить в производственной среде реальный запрос от поддельного тестового.
Когда у вас есть логи для сравнительных тестов, вы достигаете ещё двух вещей: корректности кэша и базы данных в тестовой среде. После исполнения сравнительных тестов ваш тестовый кэш готов обслуживать трафик на полной скорости. Это очень важно, поскольку кэш должен быть масштабирован, чтобы поддерживать стабильное соотношение попаданий, чего может быть трудно достичь с поддельными запросами. Кроме того, теперь тестовая база данных заполнена достаточным количеством данных и, что более важно, реальными записями из реальной жизни.
Имея эти две вещи, можно начать выполнять тесты производительности. Можно просто продолжить воспроизведение производственного трафика в тестовой среде, но на этот раз для измерения производительности. Необходимо реплицировать производственную инфраструктуру, поэтому, если у вас есть кэши на внешних хостах в производственном кластере, нужно организовать их таким же образом в тестовой среде. То же самое относится к базам данных, сетевым вызовам и т. д. Имейте в виду, что это может стать дорогостоящим: в вашей лаборатории тестирования необходимо иметь характеристики аналогичные производственной среде. Тут придётся найти баланс между бизнес-требованиями и количеством денег, которые можно потратить на содержание лаборатории тестирования и проведение тестов.
Окончание следует…
Источник: https://blog.adamfurmanek.pl/2022/02/19/types-and-programming-languages-part-9/
Тестирование в Реальной Жизни. Начало
Коротко о различных нестандартных типах тестов и о том, что нужно иметь в виду при их использовании.
1. Тесты бизнес-логики
Эти тесты включают в себя всё, что подтверждает, что ваша бизнес-логика работает: модульные тесты, интеграционные тесты, сквозные тесты и т. д. Конкретная их реализация может варьироваться, но суть в том, что они должны проверять бизнес-цели кода, а не его техническую структуру. Здесь нас не заботят приватные методы, вызываются ли методы в правильном порядке, правильность параметров или что-либо ещё техническое. Просто нужно убедиться, что вывод соответствует вашим ожиданиям.
Избегайте любых непроизводственных компонентов (имитаций). Используйте реальные базы данных, реальные конечные точки и т. д. Имитируйте их, только если вам нужно сделать тесты более надёжными или быстрыми. Не имеет значения, что тесты проходят, если приложение не работает. Убедитесь, что вы проверяете все уровни вашего ПО, включая сетевые рукопожатия, авторизацию/аутентификацию, разрешения и т. д. В идеале используйте инфраструктуру как код для создания новой среды тестирования каждый раз.
2. Сравнительные тесты и тесты производительности
Призваны убедиться, что ваше приложение работает в реальных сценариях. Можно взять производственные журналы, извлечь запросы, а затем запустить их для нового и старого кода, чтобы сравнить, совпадают ли выходные данные. Таким образом, вы можете убедиться, что приложение действительно работает. Здесь нужно помнить о нескольких вещах.
Во-первых, если ваше приложение не сохраняет состояния, то запустить его таким образом несложно, поскольку оно просто принимает входные данные и возвращает выходные данные. Это математические операции, системы рекомендаций и т. д. Однако вы можете сделать все приложения фактически не сохраняющими состояние, если будете всегда логировать ввод и вывод всех внешних вызовов: сетевых запросов, запросов к БД, чтения файлов и т. д. Очевидно, что это может быть возможно не во всех случаях.
Во-вторых, законы о защите персональных данных (GDPR, CCPA и т. п.). Возможно, вашей тестовой среде не разрешено обрабатывать производственные данные, поэтому необходимо анонимизировать их (как в журналах, так и при передаче между приложениями). Кроме того, необходимо правильно обрабатывать географическую безопасность - если вашим данным запрещено покидать пределы ЕС, вы не сможете проводить тесты в другой стране.
В-третьих, нагрузочные тесты. Как правило, не стоит брать логи нагрузочных тестов и запускать на них сравнительные тесты. Поэтому важно уметь отличить в производственной среде реальный запрос от поддельного тестового.
Когда у вас есть логи для сравнительных тестов, вы достигаете ещё двух вещей: корректности кэша и базы данных в тестовой среде. После исполнения сравнительных тестов ваш тестовый кэш готов обслуживать трафик на полной скорости. Это очень важно, поскольку кэш должен быть масштабирован, чтобы поддерживать стабильное соотношение попаданий, чего может быть трудно достичь с поддельными запросами. Кроме того, теперь тестовая база данных заполнена достаточным количеством данных и, что более важно, реальными записями из реальной жизни.
Имея эти две вещи, можно начать выполнять тесты производительности. Можно просто продолжить воспроизведение производственного трафика в тестовой среде, но на этот раз для измерения производительности. Необходимо реплицировать производственную инфраструктуру, поэтому, если у вас есть кэши на внешних хостах в производственном кластере, нужно организовать их таким же образом в тестовой среде. То же самое относится к базам данных, сетевым вызовам и т. д. Имейте в виду, что это может стать дорогостоящим: в вашей лаборатории тестирования необходимо иметь характеристики аналогичные производственной среде. Тут придётся найти баланс между бизнес-требованиями и количеством денег, которые можно потратить на содержание лаборатории тестирования и проведение тестов.
Окончание следует…
Источник: https://blog.adamfurmanek.pl/2022/02/19/types-and-programming-languages-part-9/
👍4