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

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

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

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

Ютуб https://www.youtube.com/@steponeit
Download Telegram
partial взрывает мне мозг 🤯

Недавно решил изучить такую возможность C#, как объявление типов данных в разных файлах с помощью ключевого слова partial.

В коммерческой практике не так часто это встречалось.

И я обнаружил, что с этой фичей можно делать просто супер странные вещи.

Например, у нас есть простенький интерфейс IConract:

public interface IContract
{
void Foo();
}


Сделаем раздробленный класс MyPartialClass:

public partial class MyPartialClass
{
// ...
}


И оказывается, что реализацию интерфейса этим классом можно написать вообще в другом файле, и если иметь перед глазами только первый, то об этом и не догадаешься!

public partial class MyPartialClass : IContract
{
public virtual void Foo()
{
throw new NotImplementedException();
}
}


При этом виртуальный метод Foo можно спокойно переопределять в той же манере в наследниках:

public partial class MyPartialClassDerived : MyPartialClass
{
public override void Foo()
{
Console.WriteLine(this);
base.Foo();
}
}


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

Злоупотреблять таким в командной работе конечно же не рекомендую.

Однако, подобный функционал будет полезен разработчикам решений на основе Source Generators.

Таким образом, можно докидывать компилятором различные бойлерплейты, которые не хочется писать руками.
💯9🤯3🙏2
StepOne | Степан Минин
Отлаживать код в Rider смогут даже младенцы 👶 JetBrains продолжают развивать лучшую IDE для C# разработчиков и удивлять их новыми обновлениями. В грядущей версии 2023.3 завезут, на мой взгляд, настоящую killer feature, которая называется Debugger Data Flow…
Релизнулся Rider 2023.3 😱

Завезли много всего интересного: поддержку .NET 8 SDK, одновременный запуск нескольких проектов, предиктивный дебаггинг, вытащили из превью AI ассистента и многое другое

Например, добавили отрисовку диаграм зависимостей типов 🎁

Теперь можно воочию увидеть архитектуру своего проекта, и убедиться, что её нужно переделать 😱

Короче говоря, побежали обновляться! 🏃‍♂️
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17😁31🤯1
Лучшая статья за прошедшую неделю 👍

Невольно закралась мысль о том, что все мои последние проекты могли прекрасно существовать в виде монолитов...

"Вопрос: Может ли монолит быть также эффективен как микросервисная архитектура?

Ответ: Нет, ему никогда не стать настолько же медленным
" 👏

https://habr.com/ru/articles/779362/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁8👏1💯1
Тут на днях разнесли в пух и прах первичные конструкторы в C# 12

В целом я согласен со многими поинтами, и поэтому хочется посмотреть, так сказать, bigger picture.

Подумайте: есть ли у вас такое ощущение, что последней крупной и продуманной до конца фичей была добавленная в C# 5 асинхронность?

Все последующие обновления чувствуются минорными - их спокойно можно было бы нумеровать 5.1, 5.2, 5.3 и так далее.

Даже обобщённую математику не доделали до конца!

Скорее всего, проблема в том, что Андерс Хейлсберг не занимается проектом, зато о TypeScript теперь кричат из каждого утюга 🤔

https://habr.com/ru/articles/779166/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8💯51🙏1
Контравариантность и ковариантность 🧠

В одном из профильных чатов видел сообщение о том, что упомянутая в заголовке тема даётся чуть ли не сложнее всего, что входит в основы C#.

Иногда, кажется проще запомнить наглядно, на примерах.

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

Контравариантность ⬆️

Возможность подставить более базовый тип на место формального типового параметра, которая используется для объявления аргументов функций:

interface IFooIn<in TInputType>
{
void Bar(TInputType input);
}


Пример из стандартной библиотеки - IComparable<>, где благодаря контравариантности можно сделать так:

IComparable<IEnumerable<char>> charEnumerableComparable = // ...;

// ...

IComparable<string> stringComparable = charEnumerableComparable;


Ковариантность ⬇️

Возможность подставить более производный тип на место формального типового параметра, которая используется для объявления возврата значений из функций:

interface IFooOut<out TOutputType>
{
TOutputType Baz();
}


Пример из стандартной библиотеки - IEnumerable<>, где благодаря ковариантности можно сделать так:

IEnumerable<Task<object>> tasksWithResults = // ...;

// ...

IEnumerable<Task> tasks = tasksWithResults;


Дополнительно 🤓

Во-первых, первое и второе можно совмещать в рамках одного типа:

interface IFooInOut<in TInputType, out TOutputType>
{
TOutputType Foo(TInputType input);
}


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

В-третьих, самый смак этой фичи в том, что кастинг, который был показан выше, в силу своей неявности по перфомансу равен отсутствию кастинга, поскольку в результирующем IL отсутствуют инструкции castclass.
🤯9🔥7👍52
StepOne | Степан Минин
Правильность архитектуры проверяется при внедрении нового функционала Кажется, написал что-то очевидное, но столкнулся с этим лично на своём pet project. В рамках него я пишу интерпретатор TypeScript подобного языка. Этот проект родился, как дипломная работа…
Visitor NET. Уникальный проект

Когда я начал рефакторинг своего интерпретатора, передо мной встал вопрос, как реализовывать паттерн Visitor.

Его нужно было применить несколько раз, поскольку задач по работе с AST немало: многоэтапный статический анализ, вывод типов, кодогенерация и так далее.

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

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

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

Изначально, хотелось сделать ациклический вариант шаблона - он был гибким в том плане, что конечный посетитель строился из "кубиков" - возможностей посещать какие-либо элементы:

public interface IVisitor<in TVisitable, out T> : IVisitor
where TVisitable : IVisitable
{
T Visit(TVisitable visitable);
}


Соответственно сам визитор выглядел примерно так:

public class TypeSystemLoader :
IVisitor<ScriptBody>,
IVisitor<AbstractSyntaxTreeNode>,
IVisitor<TypeDeclaration>
{
// ...
}


Сам посещаемый элемент должен уметь вызвать visitor.Visit(this) и для этого ему нужно знать, что у типа есть правильная перегрузка метода.

Классический ациклический вариант предлагает следующую реализацию метода Accept:

public class ScriptBody : AbstractSyntaxTreeNode
{
public override void Accept(IVisitor visitor)
{
if (visitor is IVisitor<ScriptBody> typed)
typed.Visit(this);
}
}


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

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

public interface IVisitable<in TVisitor, out T> : IVisitable
where TVisitor : IVisitor
{
T Accept(TVisitor visitor);
}


Такая реализация нарушала OCP и LSP, поскольку в посещаемом элементе отсутствовала единая точка входа для любого посетителя, независимая от результата обработки.

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

Ну и конечно правило отсутствия явного приведения типов сохраняется - язык и шаблон объектно-ориентированные, а компилятор должен работать на программиста.

Всего этого удалось добиться с помощью контравариантности и паттерна CRTP:

public interface IVisitor<in TVisitable, out TReturn>
where TVisitable : IVisitable<TVisitable>
{
TReturn Visit(TVisitable visitable);
}

public interface IVisitable<out TVisitable>
where TVisitable : IVisitable<TVisitable>
{
TReturn Accept<TReturn>(IVisitor<TVisitable, TReturn> visitor);
}


Тогда, в самом посещаемом элементе приходится писать два метода Accept: первый для корня иерархии, который будет вызывать посетитель; а второй уже для того, чтобы под капотом вызвался нужный Visit:

public record Operation(
char Symbol,
BinaryTreeNode Left,
BinaryTreeNode Right) : BinaryTreeNode, IVisitable<Operation>
{
public override TReturn Accept<TReturn>(
IVisitor<BinaryTreeNode, TReturn> visitor) =>
Accept(visitor);

public TReturn Accept<TReturn>(
IVisitor<Operation, TReturn> visitor) =>
visitor.Visit(this);
}


С написанием этих двух методов можно не заморачиваться, так как я создал incremental source generator, который автоматизирует написание кода.

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

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

Поэтому, давайте поддержим мой проект звездой на гитхаб ⭐️
https://github.com/Stepami/visitor-net

Нейросеть так не сможет.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👍72🕊2
Как вы заработали свою первую 1000 рублей в IT?

Первые деньги мне принёс заказ на создание Telegram бота на Python!
Anonymous Poll
11%
Оплачиваемая стажировка
48%
Работа
6%
Репетиторство / наставничество / менторство
20%
Фриланс
11%
Всё ещё нищук (
4%
Другое (пишите в комментариях)
🤔2👍1🤯1😱1🙏1🐳1🌭1
Что означает «CAP» в CAP теореме?

1️⃣ Consistency, Availability, Partition Tolerance

2️⃣ Control, Allocation, Process

3️⃣ Code, Architecture, Pipeline

4️⃣ Connection Access Protocol

Правильный ответ: 1️⃣

Пояснение:

CAP теорема утверждает, что в любой распределённой системе можно добиться только 2 из 3 гарантий.

Consistency - данные между узлами системы согласованы и не противоречат друг другу

Availability - любой request к системе завершается response

Partition Tolerance - выход из строя отдельных узлов системы не влияет на её общую работоспособность


Ставь 🐳 если тебя это спрашивали на собесе
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳24👍13😱41👌1
Слово вкатуна. Харды на собесе

Криминальная драма, основанная на реальных событиях, все совпадения - случайны.

Отчаявшись попасть на стажировку в 😀 после соревнования Контеста, 16-летний Андрей возвращается домой и случайно видит, как пацаны за гаражами решают литкод.

Он присоединяется к пацанами, и работяги-джейсоноукладчики знакомят Андрея с учением Назрана. Благодаря им он узнает, что учить алгоритмы не обязательно (этим занимаются только стажеры-"чушпаны") - достаточно солгать в резюме про 3 года опыта, придумать 2-3 фейковых места работы - и можно будет "вкатиться" в Сбер на наносеки 200к/месяц.

Андрей крадет заначку у матери и поступает в академию Вкатышей. Но со временем Андрей понимает, что обучение в академии - это скам, где вместо реальных знаний его натаскивают на вопросы на собеседованиях. Ему обещают выдать куратора, который будет шептать в наушник ему ответы на вопросы и поможет пройти испытательный, а взамен он должен будет несколько лет отдавать половину своей зарплаты.

И когда Андрей пытается «соскочить», выясняется, что теперь он должен заплатить штраф размером в полмиллиона рублей…

#пятничное от @senior_unicorn
Please open Telegram to view this post
VIEW IN TELEGRAM
😁23🔥43🥱2👍1
Дорогие подписчики StepOne 🎄

От всей души поздравляю вас с наступающим 2024 годом!

Желаю как можно меньше красноглазить с залипанием в устройства, и как можно больше проводить времени с семьёй, друзьями и близкими ❤️

Пусть у вас всё будет хорошо!

В следующем году будет много интересного...😈
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉398🥰2👍1
Программисты на Си такие:

О да, valgrind 🤩
Please open Telegram to view this post
VIEW IN TELEGRAM
😁10🍌4🤯2👍1🤩1
Backlog senior разработчика be like:
😁26🤣3🤯2💯2😢1
StepOne | Степан Минин
Visitor NET. Уникальный проект Когда я начал рефакторинг своего интерпретатора, передо мной встал вопрос, как реализовывать паттерн Visitor. Его нужно было применить несколько раз, поскольку задач по работе с AST немало: многоэтапный статический анализ,…
Casting Performance 🤖

Потихоньку влился в рабочие процессы, и наконец готов выдать первый технический пост в этом году!

Сегодня мы поговорим о производительности приведения типов в разных сценариях, касающихся ковариантности и контравариантности.

Я написал простенький бенчмарк, чтобы проверить скорость работы с типами в 5 разных сценариях:

1️⃣ Direct - полное соответствие сигнатур

2️⃣ Implicit - неявное приведение благодаря особенностям вариантности

3️⃣ Explicit - использование оператора явного приведения типов

4️⃣ As - безопасное приведение через оператор as

5️⃣ Dynamic - отключение статической типизации ключевым словом dynamic

Гипотеза: Dynamic самый медленный, Explicit и As чуть помедленнее, чем Implicit и Direct

Результаты на скрине её подтверждают!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍51👏1🤔1
Неочевидные проблемы

Недавно ко мне обратился подписчик с просьбой разобраться в проблеме.

Есть присланный фрагмент кода, на котором проверяется равенство строк.

Загвоздка в том, что при видимом одинаковом значении "5.1$1" проверка даёт false.

Опытные могли догадаться, что дело в так называемых скрытых символах.

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

Для начала можно посмотреть в дебаге на результат метода ToCharArray(): он покажет весь массив символов, и врага можно будет увидеть в лицо.

Как с ними бороться, зависит от ваших потребностей и возможностей:

▪️Ожидаете их только по краям? Тогда сойдёт Trim

▪️Когда хотите почистить внутри строки, можно прибегнуть к вызову char.IsControl()

▪️При особых запросах на очистку лишних символов уже придётся прибегнуть к кастомным фильтрациям с помощью статических методов char (например, IsLetter || IsDigit) ну или регулярок
👍281🔥1
Строки и теоретико-множественные операции 🧠

Добро пожаловать в экспериментальную рубрику "сомнительно, но окЭй" 😅

Допустим, у нас есть некоторая строка и набор символов.

Надо решить две задачи:

1️⃣Проверить содержит ли строка хотя бы один символ из набора. Для этого надо проверить пересечение двух множеств - строка & символы != пустое множество

2️⃣Проверить содержит ли строка все указанные символы. Тут налицо математическое определение подмножества.

LINQ в C#, а также API интерфейса ISet<> даёт все возможности для лаконичного программирования указанных решений:

public static class StringExtensions
{
public static bool ContainsAnySymbol(
this string str,
IEnumerable<char> symbols) =>
str.Intersect(symbols).Any();

public static bool ContainsAllSymbols(
this string str,
IEnumerable<char> symbols) =>
symbols.ToHashSet().IsSubsetOf(str.ToHashSet());
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🤔9🌭41🥴1🍌1
Незамеченная фишка C# 12 😱

Уверен, вы могли упустить это нововведение в последней версии языка - лично я узнал о нём только благодаря подсказкам IDE 😱

Теперь классы, структуры и интерфейсы с пустым телом можно объявлять без фигурных скобок, прямо как рекорды!

Соответственно, следующий фрагмент кода скомпилируется:

class MyClass;

abstract class MyAbstractClass;

struct MyStruct;

interface IMarkerInterface;
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18🤯6👍51
Языком 2023 года по индексу TIOBE назван C#, который сохранил 5 место, но стал лидером по росту популярности (+1.43%) 🥳

Жаба уже одной в могиле, ведь она показала один из самых высоких спадов популярности (-4.34%) ☠️

https://www.tiobe.com/tiobe-index/
👍23🔥3🍌31
Узнали? Согласны?
😁18🔥12🥴54💯4🥱3
«Когда мера становится целью, она перестает быть хорошей мерой» - закон Гудхарта 🧠

Страшно подумать - принцип был сформулирован почти 50 лет назад, но много технических компаний и эффективных менеджеров продолжают его не понимать!

Если ваша цель снизить количество легаси - удалите кодовую базу и начните всё сначала.

Если ваша цель увеличить доход - покройте все экраны рекламой.

Если ваша цель писать больше кода - добавляйте бессмысленные комментарии.

Если ваша цель фиксить больше багов - чините самое простое.

Если ваша цель делать больше пулл реквестов - время вылизывать readme.

Если ваша цель увеличить вовлечённость - превратите всё в кликабельные кнопки.

Если ваша цель уменьшить количество отчётов об ошибке - усложните отправку отчёта.

Если ваша цель быстрая загрузка страницы - удалите всё мультимедиа, JavaScript и CSS с вашего сайта.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24😁9💯52🤔1🥱1