StepOne | Степан Минин – Telegram
StepOne | Степан Минин
3.42K subscribers
245 photos
35 videos
6 files
310 links
StepOne by Степан Минин @ststphn

Твой первый шаг к успеху в программировании

Закрытый тг канал https://news.1rj.ru/str/tribute/app?startapp=slOA

По вопросам рекламы @Spiral_Yuri

Ютуб https://www.youtube.com/@steponeit
Download Telegram
AutoFixture killer feature

Разбираясь в библиотеке AutoFixture пришёл к выводу, что её главное назначение это минимизация Arrange этапа в тесте.

За счёт чего это достигается? Специальные атрибуты для интеграций с фреймворками xUnit и NUnit предоставляют всю необходимую магию.

Например, атрибут AutoData.
Допустим, у нас есть некоторая корзина, которую надо протестировать на добавление позиций.
Как бы выглядел тест без AutoFixture?
[Fact]
public void Cart_NotNullItem_NotEmpty()
{
var item = new Item();
var sut = new Cart();

sut.AddItem(item);

Assert.NotEmpty(sut.Items);
}


А после применения атрибута?
[Theory, AutoData]
public void Cart_NotNullItem_NotEmpty(Item item, [Frozen] Cart sut)
{
sut.AddItem(item);

Assert.NotEmpty(sut.Items);
}


Теперь весь Arrange лёг на плечи библиотеки и больше не надо волноваться по поводу template кода с инстанциированием!
Ну а расширять поведение под нужды валидаций или каких-то moq'ирований естественно можно, но об этом в другой раз.

Ставьте огонёчки, если хотели бы узнать о том, что такое Arrange и подход AAA в тестировании.
🔥62👍4
На пальцах про AAA

Как вы могли понять речь пойдёт не о батарейках или играх. Сегодняшний пост про юнит-тестирование.

Согласитесь, в таком сложном мире как программирование сложно ориентироваться, когда всё лежит где попало, не на своих местах.

Гораздо проще, когда всё структурировано, лежит, так сказать, по полочкам.
Однажды, умные разработчики подумали, и поняли, что и тесты можно структурировать и разложить на конкретные и понятные этапы.

Arrange

В этой секции находится код, ответственный за настройку теста. Создание объектов, подготовка данных, настройка моков и так далее.

Act

Затем идёт действие. То есть, непосредственно вызов тестируемого функционала.

Assert

Финальный этап - проверка. Проверяется всё что требуется проверить. Какие получились данные, состояние объектов, вызвалось ли то что нужно, была ли ошибка. В общем, есть где развернуться.

Вот и получается, что паттерн Arrange-Act-Assert за счёт своей простоты и эффективности в отношении организации и написания тестов стал де-факто стандартом индустрии.
👍25🔥5
Подписчик на канале спросил какие ещё есть де-факто стандарты индустрии по тестированию.

Он правильно написал про FIRST в юнит тестах, тестовую пирамиду, TDD, BDD и так далее.
Но хотелось бы рассказать про действительно устоявшуюся на 99,9% вещь.

Это конвенция по именованию тестов Roy Osherove, которая выглядит следующим образом:

UnitOfWork_StateUnderTest_ExpectedBehavior

Людям, владеющим английским языком, в целом, уже всё понятно.
То есть, в имени теста указываем:

▪️выполняемую единицу работы
▪️состояние, настраиваемое в тесте
▪️ожидаемое поведение

Чувствуете, на что похоже?
Если вы подумали про предыдущий пост, то суть точно уловили.

Таким образом, элементарное правило, очень лёгкое в реализации, кратно увеличивает структурированность проекта и лёгкость в навигации.
🔥17
StepOne | Степан Минин
Что такое .NET? .NET это фреймворк (платформа), написанный компанией Microsoft для создания множества разных типов приложений. Почему фреймворк назвали именно так, до сих пор до конца не ясно. .NET позволяет работать со множеством языков - C#, F#, Visual…
В комментариях к этому посту задали вопрос касательно ситуации C# vs Java на рынке труда.

Мой ответ не нужно воспринимать близко к сердцу, поскольку я всего лишь участник процесса найма, и не знаю многих ключевых данных: бюджеты, стратегии, распределение внутри компаний и прочее.
Далее, моё субъективное мнение.

Также, всё описанное касается только Российской Федерации.
Про то, что происходит за её пределами, не берусь утверждать.

Почему люди выбирают Java? Как мне кажется, так исторически сложилось.
Язык появился раньше, и, самое главное, сразу сделал возможным кроссплатформенную разработку, а не только около 8 лет назад.

Немаловажную роль сыграла и платформа Android. Ни у кого нет сомнения в её массовости.
Не стоит забывать, что до котлинов, дартов и флаттеров была джава.

Соответственно, есть огромное количество проектов, которые когда-то написали на джава (может даже и на коленке).
И теперь остаётся их либо поддерживать, либо переписывать.

В обоих случаях квалификация в джаве нужна. Особенно, эта история ощутима в финтехе, одной из самых крупных и развитых сфер нашего IT.

Полного расклада с детализированной статистикой не могу вам дать. Однако, есть простые вещи, достаточно правдоподобно отражающие общие тенденции.

Например, достаточно зайти на тот же HeadHunter (да-да, именно на него), и вбить в поиске сначала Java, потом C#. На момент создания поста получил 3014 вакансий против 1242.

В секретных чатах для разработчиков птички мне напели, что Сбер в ближайшее время планирует набрать 100 джазистов за месяц. Сто. За месяц.

Откройте любой подкаст с HR на ютубе, неважно с кем: Кира Кузьменко, Анна Атрошкина, или кто-то другой, и вы увидите, что в среднем Java вилки на 15-20% выше.

Я уже не говорю о специфике языков, принципиальных различиях платформ JVM и dotNET. Например, про async/await до сих пор пишут лонгриды, потому что никто ничего не понимает.

В каких компаниях сейчас есть C# в достаточном объёме?
В первую очередь, конечно это OzonTech, не могу не выделить их сильное сообщество.
Помимо этого: МТС, Kaspersky, Контур, Dodo, различные банки.
На галерах есть всё, про них я умолчу.

Реальность такова, какова она есть. Поэтому, всё, что можно сделать - принять её и жить дальше.
👍22🤔2🤯2
StepOne | Степан Минин
В комментариях к этому посту задали вопрос касательно ситуации C# vs Java на рынке труда. Мой ответ не нужно воспринимать близко к сердцу, поскольку я всего лишь участник процесса найма, и не знаю многих ключевых данных: бюджеты, стратегии, распределение…
Перечитав вчерашний пост, понял, что не хватило какого-то вывода.

Если с Java всё так хорошо, там больше денег и спроса, почему я пишу на C# и веду об этом канал?

Это вопрос выбора.
Во-первых, сишарп больше нравится.
Во-вторых, платформа dotNET кажется более перспективной.

Задумайтесь, Microsoft только начал набирать какие-то обороты, а имеющиеся результаты уже заставляют приятно удивиться.

Поймите, человечество сейчас живёт в эпоху перемен.
Чтобы обрести какую-то стабильность, надо не двигаться согласно массовым трендам, а последовательно поступать так, как считаешь нужным.

Просто не сходить со своего пути, двигаясь вперёд, подобно танку или бульдозеру. Тогда всё точно будет хорошо!
35👍11🔥4🤔2💯1
Факт дня про C# 11

Допустим, в проекте подключены nullable reference types.
Затем, объявляется некоторый класс с полем, у которого notnull ссылочный тип.
Чтобы не получить от компилятора warning CS8618, многие делают так:

public class Foo
{
public string Bar {get; set;} = null!;
}

В C# 11 появилось ключевое слово required, которое позволяет красиво обыграть эту ситуацию:

public class Foo
{
public required string Bar {get; set;}
}
🔥17👍12🤯6👌3
Признаться, очень люблю анекдоты.

Знаю анекдот про UDP, но не факт, что он до вас дойдёт...

На этот случай знаю анекдот про TCP.
И если он до вас не дойдёт, повторю его снова.
😁55🔥52👏1🤔1
Freeze/Inject/Register в AutoFixture

Давным-давно, в первых версиях библиотеки балом правил Register. Два других метода ещё не существовали.

Определён он был следующим образом:

public static void Register<T>(this IFixture fixture, T item)

Однако, была и перегрузка:

public static void Register<T>(this IFixture fixture, Func<T> creator)

Какое-то время казалось, что это нормально, впрочем, вскоре пользователи стали путаться. Например, можно было написать следующий код:

fixture.Register(() => universe.LightUp());

Поскольку делегат может получаться путём приведения ссылкой на метод, то валидной была и следующая запись:

fixture.Register(universe.LightUp);

Что если universe.LightUp это обращение к свойству, а не к методу? Тогда была бы выбрана первая перегрузка.

Но это крайне неочевидно.
Поэтому первая перегрузка превратилась в Inject<T>(this IFixture fixture, T item).

У метода Freeze несколько другая история.
В прошлом оказалось, что достаточно часто встречается следующее использование AutoFixture в императивном стиле:

var foo = fixture.Create<Foo>();
fixture.Inject(foo);

Тогда, автор библиотеки решил, что это так называемая концепция заморозки.
В итоге два вызова превратились в один метод Freeze.
🔥5🤯5👍2
Как скрыть от потребителя библиотеки лишние зависимости?

Недавно, я написал небольшую надстройку над AutoFixture, которая позволяет при создании объекта базового абстрактного класса получить экземпляр случайного наследника.

Допустим, у нас есть подобная иерархия:

abstract class A { }
class B : A { }
class C : A { }


Если написать fixture.Create<A>(), то мы получим исключение, поскольку вызывать new для абстрактных классов запрещено.
Ожидается, что мы получим случайным образом либо new B(), либо new C().

Однако, базовый функционал библиотеки не даёт такого поведения из коробки.
С помощью моего NuGet пакета можно настроить fixture таким образом, и всё заработает:

fixture.CustomizePolymorphism<A>()
.WithDerivedType<B>()
.WithDerivedType<C>()
.BuildCustomization();


Так вот при создании библиотеки возникла проблема.
В связи с тем, что она создана как дополнение к AutoFixture, присутствует зависимость, которая потом попадает к потребителю в раздел Implicitly Installed Packages.
Согласитесь, неприятно.

Решается проблема очень просто, достаточно пометить зависимость атрибутом PrivateAssets со значением all в конфигурации файла проекта:

<PackageReference Include="AutoFixture" Version="4.18.0" PrivateAssets="all"/>
🔥12👍2
Работаю в Rider и не знаю проблем)
👍22😁8🤔2😢1🥴1🏆1
Ставь ❤️, если было
22❤‍🔥6🤣3🔥2
Какой длины должны быть функции?

Если обратиться к такой классике, как «Чистый Код» Роберта С. Мартина, то можно увидеть следующее:

Первое правило функций — они должны быть маленькими. Второе правило функций заключается в том, что они должны быть еще меньше

То есть, кажется, что это означает примерно следующее:

1️⃣ Функции должны быть короткими — не длиннее 20 строк и в большинстве случаев менее 10 строк.

2️⃣ Функции должны иметь как можно меньше аргументов, желательно ни одного.

Стоит придерживаться стратегии «разделяй и властвуй».
Попробовать разделить метод на несколько логических шагов, определить что от чего зависит.

Затем, разбить это на минимальные модули, которые соединяются в единый механизм, например, с помощью внедрения зависимостей.

Такие действия, безусловно, помогут начертить границы ответственностей, сделают код чище и читабельнее.

Однако, практика показывает, что в любом проекте можно найти большой объём кода под рефакторинг с методами и на 100, 200, 300 строк с десятком параметров.

Как вы думаете, стоит их распиливать и переписывать?
🤔11👍7🔥1
Как генерировать валидные данные?

Активные читатели моего канала могут подумать, что сейчас будет очередной пост про какую-нибудь кастомизацию AutoFixture, ведь все знают, как библиотека генерирует строки и числа.

А вот и нет! В сегодняшнем разговоре о генерации данных ключевое слово валидные.

Ответ на вопрос в заголовке: Bogus.

Да, для C# существует не один генератор данных.
Но разница проявляется как в назначении, так и в устройстве.

AutoFixture - это скорее некоторое подобие DI контейнера с CQRS архитектурой.
Bogus - инструмент, больше похожий на FluentValudation.

Для каждой модельки создаётся специальный генератор.
В нём с помощью fluent interface api всем полям прописываются правила по заполнению значений.

public class OrderFaker : Faker<Order>
{
public OrderFaker()
{
RuleFor(o => o.OrderId, f => f.Guid.NewGuid());
RuleFor(o => o.Item, f => f.Lorem.Sentence());
RuleFor(o => o.Quantity, f => f.Random.Number(1, 10));
}
}

var orderFaker = new OrderFaker();
var order = orderFaker.Generate();

Таким образом, данные получаются осмысленными.
В арсенале богуса есть адреса, имена, различные локали, схемы генерации, расширяемость и многое другое.
🔥27👍53
Хочу поделиться с вами радостной новостью.
Наконец-то получил свой долгожданный платёжный стикер МТС🤩

Вот так аккуратно он выглядит, будучи прикреплённым сбоку от айфоновской камеры. Не знаю будут ли обновлять дизайн в новых партиях в связи с ребрендингом, но у моего ещё есть яйцо😁

Оплачивая через Apple Pay, покупатели выработали определённый пользовательский опыт. Своеобразный жест, характеризующийся тем, как подносится телефон к терминалу, какой частью и так далее. Эту историю получилось перенести практически безболезненно на мой взгляд.

МТС Pay Tag поддерживает привязку нескольких карт от разных банков, что очень удобно. А к релизу добавили несколько новых, например, мой любимый райф😍

Работает исправно, впечатления только позитивные. Одним словом, молодцы! Не то что какой-то там тинькофф или прости Господи сбер. Наклепали маленьких карточек и думают, что прокатит🤡
🔥7🤣3👍21
Топ-3 места, куда бы я пошёл учиться на программиста в 2023 году

Естественно, речь идёт о направлении подготовки «прикладная математика и информатика» (01.03.02), другое рассматривать смысла нет.

🥇Бауманка (кафедра ИУ-9)

Это моя альма-матер. История обучения заслуживает не одного поста. Путь был трудным, но ни о чём не жалею.

Огромное количество практической подготовки - нон-стоп кодинг все 4 года.
Разнообразные компании-партнёры, которые позволяют уже в стенах ВУЗа стать востребованным специалистом.
Почти двухсотлетняя история и уникальные традиции, которые не оставят равнодушным ни одного студента.

🥈Физтех (школа ФПМИ)

Лучшая физико-математическая школа за пределами МКАД.
Один из тех немногих университетов (кроме того, что на 1 месте), который до последнего сопротивлялся введению разрушительного для образования дистанционного формата.
Осилит не каждый, место не для слабонервных.

🥉МГУ (факультет ВМК)

Старейший университет России, определивший облик русского образования.
Преподаватели именно отсюда обогащают другие университеты своими уникальными методиками, знаниями и опытом.
🔥14👍32🥱2
Что общего между математиком и программистом?

В IT сфере популярен тезис о том, что математика программистам не нужна.
Не могу согласиться с этим утверждением, но об этом в другой раз.

Интересно наблюдать, как совершались важнейшие математические открытия.
Взять для примера доказательство великой теоремы Ферма.

Сначала были пифагоровы тройки, затем изобрели теорию колец, рассматривали гауссовы числа.
Только в конце XX века удалось доказать теорему, используя многолетний опыт предыдущих попыток.

С другой стороны, C# разработчик видит три следующих интерфейса:

interface IShowableString
{
string Show(string s);
}

interface IShowableBoolean
{
string Show(bool b);
}

interface IShowableInteger
{
string Show(int i);
}

Готов поспорить, первая мысль, которая придёт ему в голову, это сделать следующее:

interface IShowable<T>
{
string Show(T item);
}

Чувствуете, куда веду?
Нас объединяет искусство обобщать. Ведь взаимодействие с неизвестным происходит по одному алгоритму в обоих случаях:

▪️Встреча частного случая некоторой общей задачи

▪️Поиск частного решения

▪️Вероятная встреча другого частного случая той же задачи

▪️Обобщение

▪️Поиск общего решения
🔥20👍4🥴1😍1
Выступаю на конференции

В сентябре, неожиданно для себя, поеду в Ульяновск, чтобы поучаствовать в международной IT конференции Стачка в качестве спикера.

Так что всех желающих жду на своём докладе, поговорим про полиморфные контракты.

https://nastachku.ru/vnedrenie-polimorfnyh-kontraktov-v-servisy-na-.net-7
🔥12👍4🤬1🥴1
Самый редко используемый цикл в C#

Цикл do while редко используется, но важно помнить о его существовании, чтобы понимать возможные случаи применения.

Его синтаксис таков:

do
{
// тело цикла
} while (condition)


Этот цикл всегда исполняет своё тело как минимум один раз, даже если условие не выполнено.

Из этой особенности, отличающей do while от других видов циклов, вытекают его основные сценарии использования.

А как часто вы используете do while?
👍14🤯4😢2🏆2😁1🤬1🌭1
Вопрос от подписчика: "Стоит ли использовать foreach, если for быстрее?"

Здесь важно понимать, чем отличаются эти циклы.

▪️for - это классический управляющий оператор, который транслируется в +/- одинаковый IR или машинный код практически во всех языках программирования согласно блок-схеме выше.

Принцип его работы одинаков везде:
for (выражение1; выражение2; выражение3)
оператор


▪️foreach - это синтаксический сахар над итераторами, который ещё и работает согласно принципам утиной типизации.
Перебираемому объекту даже не обязательно реализовывать IEnumerable.

Разворачивается такой цикл примерно в следующее:
var enumerator = enumerable.GetEnumerator();
while (enumerator.MoveNext())
{
var item = enumerator.Current;
// ...
}

Невооружённым глазом видно, что здесь происходит вызов через VMT, возможен cast, выделение памяти и так далее.
Обслуживание foreach очевидно дороже, потому что это абстракция.

Так что использование везде for вместо foreach - скорее микрооптимизация.
🔥11🥴4👍31🥱1
Возможно вы не знали этот метод LINQ

С 6-ой версии в .NET присутствует метод Chunk, который позволяет дробить коллекцию на одинаковые кусочки, так называемые "чанки".

// получаем итерируемый объект
var enumerable = Enumerable.Range(1, 999);

// дробим на чанки
var chunks = enumerable.Chunk(29);

// итерируем по чанкам
foreach(var chunk in chunks) // для каждого чанка
{
foreach(var item in chunk) // для каждого элемента в чанке
{
Console.WriteLine(item);
}
}

Пользуйтесь на здоровье!
👍47🤯5🕊3🐳32🥱1