Task vs ValueTaskЧто такое
Task знают все C# разработчики - класс, олицетворяющий длительную операцию в асинхронном программировании.А вот в 7 версии языка появилась структура
ValueTask, и до сих пор не всем ясно её назначение.Из интересного в ней два поля - первое для хранения задачи, второе для хранения результата (при наличии).
Поскольку
Task это класс, то его экземпляр хранится в куче, а значит высвобождением памяти будет заниматься GC.ValueTask это структура, а значит вероятнее всего окажется на стеке, и расходов на высвобождение памяти будет потрачено существенно меньше.Соответственно, стоит использовать эту структуру, когда мы ожидаем, что задача будет выполняться синхронно большинство времени (например, закэшированный результат) или расходы на вызов и ожидание обычной задачи будут больше.
Однако, есть ряд ограничений, то есть, нельзя делать следующие вещи:
AsTask несколько раз.Result или .GetAwaiter().GetResult(), если задача не завершенаWhenAll() и WhenAny()Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤3👏3
StepOne | Степан Минин
Внедрение конкретной реализации в стандартном контейнере Допустим, у нас есть некоторый интерфейс, который имеет несколько реализаций: public interface IDependency {} public class DependencyImplOne : IDependency {} public class DependencyImplTwo : IDependency…
ASP NET 8 наконец-то добавит многообразие зависимостей 🥳
Реализовано это будет через ключи (например строковые).
Возвращаясь к старому примеру, он преобразится следующим образом:
Далее, использовать вот так, с помощью атрибута
Для меня, как поклонника ООП, это знаковая веха в развитии платформы 🔥
Считаю, что ради этой киллер фичи можно смело планировать переезд на новый LTS релиз!
Реализовано это будет через ключи (например строковые).
Возвращаясь к старому примеру, он преобразится следующим образом:
public interface IDependency {}
public class DependencyImplOne : IDependency {}
public class DependencyImplTwo : IDependency {}
builder.Services.AddKeyedSingleton<IDependency, DependencyImplOne>("one");
builder.Services.AddKeyedSingleton<IDependency, DependencyImplTwo>("two");Далее, использовать вот так, с помощью атрибута
[FromKeyedServices]:public class BarService : IBarService
{
public BarService([FromKeyedServices("one")] IDependency dependency) // DependencyImplOne
{
}
}
public class BazService : IBazService
{
public BazService([FromKeyedServices("two")] IDependency dependency) // DependencyImplTwo
{
}
}
Для меня, как поклонника ООП, это знаковая веха в развитии платформы 🔥
Считаю, что ради этой киллер фичи можно смело планировать переезд на новый LTS релиз!
Docs
What's new in ASP.NET Core in .NET 8
Learn about the new features in ASP.NET Core in .NET 8.
🔥24👍8🤯4😱2
Почему я всегда сообщаю рекрутеру зарплатные ожидания? 🤔
Есть распространённое мнение о зарплатных переговорах: «кто первый назвал цифру, тот и проиграл».
Однако это не совсем так.
Во-первых, сама культура подобных переговоров в РФ находится в достаточно зачаточном состоянии по сравнению с той же Америкой, например.
Во-вторых, разработчики это такие же рядовые сотрудники, как и другой персонал: для них существует вполне конкретный ФОТ.
То есть торги - это инструмент не растяжения мешка с деньгами, а прощупывания его границ.
И вот однажды я собеседовался в дом рф, попробовав всеми правдами и неправдами скрыть цифру💵
Изворачивался и уходил от ответа так, как никогда в жизни 🤯
При этом тех собес был очень приятный и даже нетипичный для индустрии, перспективный проект и интересными задачами, да и ребята показались вполне адекватными…
Но когда дело дошло до оффера, меня брали по верху вилки, но оказался таким, что смысл туда идти пропал абсолютно 🥵
Сказать, что чувствовал себя тогда идиотом - не сказать ничего😁
Да, мои зарплатные ожидания достаточно высокие, поэтому отвечаю на вопрос HR о деньгах, чтобы было понятно сразу - удовлетворит компания мои потребности или это пустая трата времени.
А терять время не хочет никто.
Есть распространённое мнение о зарплатных переговорах: «кто первый назвал цифру, тот и проиграл».
Однако это не совсем так.
Во-первых, сама культура подобных переговоров в РФ находится в достаточно зачаточном состоянии по сравнению с той же Америкой, например.
Во-вторых, разработчики это такие же рядовые сотрудники, как и другой персонал: для них существует вполне конкретный ФОТ.
То есть торги - это инструмент не растяжения мешка с деньгами, а прощупывания его границ.
И вот однажды я собеседовался в дом рф, попробовав всеми правдами и неправдами скрыть цифру
Изворачивался и уходил от ответа так, как никогда в жизни 🤯
При этом тех собес был очень приятный и даже нетипичный для индустрии, перспективный проект и интересными задачами, да и ребята показались вполне адекватными…
Но когда дело дошло до оффера, меня брали по верху вилки, но оказался таким, что смысл туда идти пропал абсолютно 🥵
Сказать, что чувствовал себя тогда идиотом - не сказать ничего
Да, мои зарплатные ожидания достаточно высокие, поэтому отвечаю на вопрос HR о деньгах, чтобы было понятно сразу - удовлетворит компания мои потребности или это пустая трата времени.
А терять время не хочет никто.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥4💯4
StepOne | Степан Минин
Почему я всегда сообщаю рекрутеру зарплатные ожидания? 🤔 Есть распространённое мнение о зарплатных переговорах: «кто первый назвал цифру, тот и проиграл». Однако это не совсем так. Во-первых, сама культура подобных переговоров в РФ находится в достаточно…
На просторах рунета этого не найти 🤫
Под вчерашним постом развернулась горячая дискуссия о переговорах по зарплате🔥
Поэтому делюсь с вами топом своих любимых материалов по этому вопросу⭐️
▪️https://www.kalzumeus.com/2012/01/23/salary-negotiation/
▪️https://bayareabelletrist.medium.com/how-i-negotiated-a-software-engineer-offer-in-silicon-valley-f11590f5c656
▪️https://faangpath.medium.com/how-to-negotiate-salary-offer-e9475ab11e3f
▪️https://www.freecodecamp.org/news/how-not-to-bomb-your-offer-negotiation-c46bb9bc7dea#.w30tfvb9r
Под вчерашним постом развернулась горячая дискуссия о переговорах по зарплате🔥
Поэтому делюсь с вами топом своих любимых материалов по этому вопросу
▪️https://www.kalzumeus.com/2012/01/23/salary-negotiation/
▪️https://bayareabelletrist.medium.com/how-i-negotiated-a-software-engineer-offer-in-silicon-valley-f11590f5c656
▪️https://faangpath.medium.com/how-to-negotiate-salary-offer-e9475ab11e3f
▪️https://www.freecodecamp.org/news/how-not-to-bomb-your-offer-negotiation-c46bb9bc7dea#.w30tfvb9r
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍6🔥4
StepOne | Степан Минин
В Москве уже успело выпасть 7 сантиметров снежного покрова, а я успел собрать для вас самые важные посты октября 🤩 💎 Запись моего спикерского дебюта на Стачке 💎 История о том, как этот дебют состоялся 💎 Самое простое объяснение примитивов синхронизации…
Завтра начнётся последний месяц 2023 года, а значит пора подвести итоги ноября 🤩
В этом месяце постарался выдать побольше эксклюзивных материалов🤫
🔥 Уникальный гайд по акклиматизации на новой работе
🔥 Разоблачение стагнации процессов собеседования OZON
🔥 Запись доклада на MskDotNet Meetup
🔥 Личная история о важности открытости в зарплатных переговорах
🔥 Эффективные секретные материалы о зарплатных переговорах впервые в telegram
В этом месяце постарался выдать побольше эксклюзивных материалов
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6🥱2❤🔥1⚡1
StepOne | Степан Минин
Немного о pet project В прошлом посте я написал про то, как опыт коммерческой разработки повлиял на мой стиль его ведения. Однако, может возникнуть закономерный вопрос: «Так чем ты там занимаешься?» Отвечаю. Сейчас мой основной open source contribute -…
Правильность архитектуры проверяется при внедрении нового функционала
Кажется, написал что-то очевидное, но столкнулся с этим лично на своём pet project.
В рамках него я пишу интерпретатор TypeScript подобного языка.
Этот проект родился, как дипломная работа в бакалавриате бауманки.
Но поскольку сроки были сильно сжаты, то изначально всё сделано на скорую руку.
Год назад хотел добавить в язык аналог выражения
Одно из самых неправильных решений в проекте - обработка абстрактного синтаксического дерева интрузивным методом.
Подсветить то, насколько важно перейти на паттерн Visitor, помогла моя попытка внедрить DDD и выделить домен системы.
Сейчас, когда рефакторинг близится к концу, все детали пазла собираются в одну картину, новые фичи собираются на глазах за счёт правильной траектории архитектурной эволюции.
При этом стали видны новые точки роста - ошибки в реализации «Посетителя», изоляция домена, изменение знания одних частей системы о других и так далее.
Кажется, написал что-то очевидное, но столкнулся с этим лично на своём pet project.
В рамках него я пишу интерпретатор TypeScript подобного языка.
Этот проект родился, как дипломная работа в бакалавриате бауманки.
Но поскольку сроки были сильно сжаты, то изначально всё сделано на скорую руку.
Год назад хотел добавить в язык аналог выражения
with из C#, но столкнулся с тем, что из-за спешки сделать это будет больно.Одно из самых неправильных решений в проекте - обработка абстрактного синтаксического дерева интрузивным методом.
Подсветить то, насколько важно перейти на паттерн Visitor, помогла моя попытка внедрить DDD и выделить домен системы.
Сейчас, когда рефакторинг близится к концу, все детали пазла собираются в одну картину, новые фичи собираются на глазах за счёт правильной траектории архитектурной эволюции.
При этом стали видны новые точки роста - ошибки в реализации «Посетителя», изоляция домена, изменение знания одних частей системы о других и так далее.
👍10🔥4👏2❤1
В EF Core 8 узаконили Value Object 🤩
Одно из тех обновлений, которое не следует пропускать😱
Например, есть следующая сущность заказа
Кажется, что уже существует семантика работы с типами значениями, ведь никто не отменял атрибут [Owned].
Однако, при попытке сохранить сущность, которая использует один инстанс на несколько полей возникнет ошибка:
Кажется, что всё будет хорошо, но получим исключение
«
При этом он может быть иммутабельным!
Соответственно, такое обновление сущности:
Сгенерирует следующий SQL:
То есть, это собственный тип на стероидах💉
Одно из тех обновлений, которое не следует пропускать
Например, есть следующая сущность заказа
Order вместе с сущностью клиента Customer:public class Customer
{
public int Id { get; set; }
public required string Name { get; set; }
public required Address Address { get; set; }
public List<Order> Orders { get; } = new();
}
public class Order
{
public int Id { get; set; }
public required string Contents { get; set; }
public required Address ShippingAddress { get; set; }
public required Address BillingAddress { get; set; }
public Customer Customer { get; set; } = null!;
}
Кажется, что уже существует семантика работы с типами значениями, ведь никто не отменял атрибут [Owned].
Однако, при попытке сохранить сущность, которая использует один инстанс на несколько полей возникнет ошибка:
var address = GetAddress();
customer.Orders.Add(
new Order { Contents = "Tesco Tasty Treats", BillingAddress = address, ShippingAddress = address, });
await context.SaveChangesAsync();
Кажется, что всё будет хорошо, но получим исключение
InvalidOperationException с сообщением«
Cannot save instance of 'Order.ShippingAddress#Address' because it is an owned entity without any reference to its owner. Owned entities can only be saved as part of an aggregate also including the owner entity.
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.PrepareToSave()»
Теперь, достаточно разметить тип данных атрибутом [ComplexType].При этом он может быть иммутабельным!
[ComplexType]
public record Address(string Line1, string? Line2, string City, string Country, string PostCode);
Соответственно, такое обновление сущности:
customer.Address = customer.Address with { Line1 = "Peacock Lodge" };
await context.SaveChangesAsync();
Сгенерирует следующий SQL:
UPDATE [Customers] SET [Address_Line1] = @p0
OUTPUT 1
WHERE [Id] = @p1;
То есть, это собственный тип на стероидах
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍2🎉1🤣1🏆1
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 ассистента и многое другое
Например, добавили отрисовку диаграм зависимостей типов🎁
Теперь можно воочию увидеть архитектуру своего проекта, и убедиться, что её нужно переделать😱
Короче говоря, побежали обновляться!🏃♂️
Завезли много всего интересного: поддержку .NET 8 SDK, одновременный запуск нескольких проектов, предиктивный дебаггинг, вытащили из превью AI ассистента и многое другое
Например, добавили отрисовку диаграм зависимостей типов
Теперь можно воочию увидеть архитектуру своего проекта, и убедиться, что её нужно переделать
Короче говоря, побежали обновляться!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17😁3❤1🤯1
Лучшая статья за прошедшую неделю 👍
Невольно закралась мысль о том, что все мои последние проекты могли прекрасно существовать в виде монолитов...
"Вопрос: Может ли монолит быть также эффективен как микросервисная архитектура?
Ответ: Нет, ему никогда не стать настолько же медленным"👏
https://habr.com/ru/articles/779362/
Невольно закралась мысль о том, что все мои последние проекты могли прекрасно существовать в виде монолитов...
"Вопрос: Может ли монолит быть также эффективен как микросервисная архитектура?
Ответ: Нет, ему никогда не стать настолько же медленным"
https://habr.com/ru/articles/779362/
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Смерть от тысячи микросервисов
пролог и ссылка на оригинал Это перевод-адаптация https://renegadeotter.com/2023/09/10/death-by-a-thousand-microservices с вкраплениями моих собственных мыслей. Я не профессиональный переводчик,...
👍9😁8👏1💯1
Тут на днях разнесли в пух и прах первичные конструкторы в C# 12
В целом я согласен со многими поинтами, и поэтому хочется посмотреть, так сказать, bigger picture.
Подумайте: есть ли у вас такое ощущение, что последней крупной и продуманной до конца фичей была добавленная в C# 5 асинхронность?
Все последующие обновления чувствуются минорными - их спокойно можно было бы нумеровать 5.1, 5.2, 5.3 и так далее.
Даже обобщённую математику не доделали до конца!
Скорее всего, проблема в том, что Андерс Хейлсберг не занимается проектом, зато о TypeScript теперь кричат из каждого утюга🤔
https://habr.com/ru/articles/779166/
В целом я согласен со многими поинтами, и поэтому хочется посмотреть, так сказать, 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
Хабр
1000 и 1 способ инициализации типов в C# 12.0
Среди нововведений C# 12 было достаточно больше количество по-настоящему качественных и крутых фич (например дефолтные параметры лямбд). Но речь сегодня пойдет о ложке дёгтя в бочке мёда - Primary...
👍8💯5❤1🙏1
Контравариантность и ковариантность 🧠
В одном из профильных чатов видел сообщение о том, что упомянутая в заголовке тема даётся чуть ли не сложнее всего, что входит в основы C#.
Иногда, кажется проще запомнить наглядно, на примерах.
Также, стоит упомянуть, что всё нижеописанное актуально именно в дженериках.
Контравариантность ⬆️
Возможность подставить более базовый тип на место формального типового параметра, которая используется для объявления аргументов функций:
Пример из стандартной библиотеки -
Ковариантность ⬇️
Возможность подставить более производный тип на место формального типового параметра, которая используется для объявления возврата значений из функций:
Пример из стандартной библиотеки -
Дополнительно 🤓
Во-первых, первое и второе можно совмещать в рамках одного типа:
Во-вторых, это очень мощный инструмент на стыке параметрического полиморфизма и полиморфизма подтипов, который позволяет строить мощные расширяемые и универсальные системы типов.
В-третьих, самый смак этой фичи в том, что кастинг, который был показан выше, в силу своей неявности по перфомансу равен отсутствию кастинга, поскольку в результирующем IL отсутствуют инструкции
В одном из профильных чатов видел сообщение о том, что упомянутая в заголовке тема даётся чуть ли не сложнее всего, что входит в основы 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👍5❤2
StepOne | Степан Минин
Правильность архитектуры проверяется при внедрении нового функционала Кажется, написал что-то очевидное, но столкнулся с этим лично на своём pet project. В рамках него я пишу интерпретатор TypeScript подобного языка. Этот проект родился, как дипломная работа…
Visitor NET. Уникальный проект
Когда я начал рефакторинг своего интерпретатора, передо мной встал вопрос, как реализовывать паттерн Visitor.
Его нужно было применить несколько раз, поскольку задач по работе с AST немало: многоэтапный статический анализ, вывод типов, кодогенерация и так далее.
Поэтому, во мне сразу проснулось желание сделать некий гибкий и универсальный мини-фреймворк, чтобы штамповать посетителей в условиях меняющейся и расширяющейся иерархии узлов синтаксического дерева.
Ну а появляющаяся система типов выглядела слишком самодостаточной, чтобы стать частью домена моего приложения.
Так было принято решение выделить контракты для реализации паттерна в отдельную сборку, которая потом подключалась через NuGet.
Изначально, хотелось сделать ациклический вариант шаблона - он был гибким в том плане, что конечный посетитель строился из "кубиков" - возможностей посещать какие-либо элементы:
Соответственно сам визитор выглядел примерно так:
Сам посещаемый элемент должен уметь вызвать
Классический ациклический вариант предлагает следующую реализацию метода
Однако, прибегать к явному даункастингу в такой ситуации очень не хочется, потому что это лишает код полиморфности.
Попытка провалилась - циклическую зависимость всё-таки пришлось оставить, поскольку во избежание явного кастинга посещаемому элементу приходилось знать о конкретном посетителе:
Такая реализация нарушала OCP и LSP, поскольку в посещаемом элементе отсутствовала единая точка входа для любого посетителя, независимая от результата обработки.
Получается нужно было обобщить сам метод
Ну и конечно правило отсутствия явного приведения типов сохраняется - язык и шаблон объектно-ориентированные, а компилятор должен работать на программиста.
Всего этого удалось добиться с помощью контравариантности и паттерна CRTP:
Тогда, в самом посещаемом элементе приходится писать два метода
С написанием этих двух методов можно не заморачиваться, так как я создал incremental source generator, который автоматизирует написание кода.
Таким образом, удалось решить нетривиальную задачу по созданию ациклической, универсальной, расширяемой и типобезопасной реализации шаблона Visitor без применения явного даункастинга.
При этом, подобного решения не найти на просторах интернета - осмелюсь заявить, что вы видите подобное впервые.
Поэтому, давайте поддержим мой проект звездой на гитхаб⭐️
https://github.com/Stepami/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
GitHub
GitHub - Stepami/visitor-net: First-ever acyclic generic extensible typesafe implementation of Visitor pattern for .NET without…
First-ever acyclic generic extensible typesafe implementation of Visitor pattern for .NET without any usage of dynamic cast. Implementation powered by Source Generators - Stepami/visitor-net
🔥16👍7❤2🕊2
Как вы заработали свою первую 1000 рублей в IT?
Первые деньги мне принёс заказ на создание Telegram бота на Python!
Первые деньги мне принёс заказ на создание 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 - выход из строя отдельных узлов системы не влияет на её общую работоспособность
Ставь 🐳 если тебя это спрашивали на собесе
Правильный ответ:
Пояснение:
Consistency - данные между узлами системы согласованы и не противоречат друг другу
Availability - любой request к системе завершается response
Partition Tolerance - выход из строя отдельных узлов системы не влияет на её общую работоспособность
Ставь 🐳 если тебя это спрашивали на собесе
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳24👍13😱4❤1👌1
Forwarded from Сеньор Юникорн | Владимир Маслов
Слово вкатуна. Харды на собесе
Криминальная драма, основанная на реальных событиях, все совпадения - случайны.
Отчаявшись попасть на стажировку в😀 после соревнования Контеста, 16-летний Андрей возвращается домой и случайно видит, как пацаны за гаражами решают литкод.
Он присоединяется к пацанами, и работяги-джейсоноукладчики знакомят Андрея с учением Назрана. Благодаря им он узнает, что учить алгоритмы не обязательно (этим занимаются только стажеры-"чушпаны") - достаточно солгать в резюме про 3 года опыта, придумать 2-3 фейковых места работы - и можно будет "вкатиться" в Сбер нананосеки 200к/месяц.
Андрей крадет заначку у матери и поступает в академию Вкатышей. Но со временем Андрей понимает, что обучение в академии - это скам, где вместо реальных знаний его натаскивают на вопросы на собеседованиях. Ему обещают выдать куратора, который будет шептать в наушник ему ответы на вопросы и поможет пройти испытательный, а взамен он должен будет несколько лет отдавать половину своей зарплаты.
И когда Андрей пытается «соскочить», выясняется, что теперь он должен заплатить штраф размером в полмиллиона рублей…
#пятничное от @senior_unicorn
Криминальная драма, основанная на реальных событиях, все совпадения - случайны.
Отчаявшись попасть на стажировку в
Он присоединяется к пацанами, и работяги-джейсоноукладчики знакомят Андрея с учением Назрана. Благодаря им он узнает, что учить алгоритмы не обязательно (этим занимаются только стажеры-"чушпаны") - достаточно солгать в резюме про 3 года опыта, придумать 2-3 фейковых места работы - и можно будет "вкатиться" в Сбер на
Андрей крадет заначку у матери и поступает в академию Вкатышей. Но со временем Андрей понимает, что обучение в академии - это скам, где вместо реальных знаний его натаскивают на вопросы на собеседованиях. Ему обещают выдать куратора, который будет шептать в наушник ему ответы на вопросы и поможет пройти испытательный, а взамен он должен будет несколько лет отдавать половину своей зарплаты.
И когда Андрей пытается «соскочить», выясняется, что теперь он должен заплатить штраф размером в полмиллиона рублей…
#пятничное от @senior_unicorn
Please open Telegram to view this post
VIEW IN TELEGRAM
😁23🔥4❤3🥱2👍1
StepOne | Степан Минин
Завтра начнётся последний месяц 2023 года, а значит пора подвести итоги ноября 🤩 В этом месяце постарался выдать побольше эксклюзивных материалов 🤫 🔥 Уникальный гайд по акклиматизации на новой работе 🔥 Разоблачение стагнации процессов собеседования OZON…
Год выходит на финишную прямую, как и контент в декабре на этом канале 🥶
Вот самые важные посты последнего месяца, которые можно перечитать ещё раз🤔
⚡️ Как растёт моя архитектурная компетенция на примере пет проекта
⚡️ Хитросделанные partial'ы
⚡️ Самое понятное объяснение ковариантности и контравариантности
⚡️ Новое и абсолютно уникальное прочтение паттерна Visitor в моём исполнении
Вот самые важные посты последнего месяца, которые можно перечитать ещё раз
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍3⚡1❤1
Дорогие подписчики StepOne 🎄
От всей души поздравляю вас с наступающим 2024 годом!
Желаю как можно меньше красноглазить с залипанием в устройства, и как можно больше проводить времени с семьёй, друзьями и близкими ❤️
Пусть у вас всё будет хорошо!
В следующем году будет много интересного...😈
От всей души поздравляю вас с наступающим 2024 годом!
Желаю как можно меньше красноглазить с залипанием в устройства, и как можно больше проводить времени с семьёй, друзьями и близкими ❤️
Пусть у вас всё будет хорошо!
В следующем году будет много интересного...😈
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉39❤8🥰2👍1
StepOne | Степан Минин
ASP NET 8 наконец-то добавит многообразие зависимостей 🥳 Реализовано это будет через ключи (например строковые). Возвращаясь к старому примеру, он преобразится следующим образом: public interface IDependency {} public class DependencyImplOne : IDependency…
Собрал для вас все посты канала про полиморфное поведение DI в одной статье на Хабр!
Прочитать и поставить плюсик➕ можно по ссылке:
https://habr.com/ru/companies/ruvds/articles/776768/
P.S. Kandinsky продолжает выручать - на этот раз попробовал 3.0 версию 🤯
Прочитать и поставить плюсик
https://habr.com/ru/companies/ruvds/articles/776768/
P.S. Kandinsky продолжает выручать - на этот раз попробовал 3.0 версию 🤯
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Dependency Injection контейнеры .NET, допускающие полиморфное поведение
Иногда случается так, что при разработке приложения на платформе .NET с внедрением зависимостей и сервисами от контейнера требуется поддержка полиморфного поведения. Когда, например, у интерфейса есть...
👍16❤5🔥5
Программисты на Си такие:
О да, valgrind 🤩
Please open Telegram to view this post
VIEW IN TELEGRAM
😁10🍌4🤯2👍1🤩1