Тут на днях разнесли в пух и прах первичные конструкторы в 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
StepOne | Степан Минин
Visitor NET. Уникальный проект Когда я начал рефакторинг своего интерпретатора, передо мной встал вопрос, как реализовывать паттерн Visitor. Его нужно было применить несколько раз, поскольку задач по работе с AST немало: многоэтапный статический анализ,…
Casting Performance 🤖
Потихоньку влился в рабочие процессы, и наконец готов выдать первый технический пост в этом году!
Сегодня мы поговорим о производительности приведения типов в разных сценариях, касающихся ковариантности и контравариантности.
Я написал простенький бенчмарк, чтобы проверить скорость работы с типами в 5 разных сценариях:
1️⃣ Direct - полное соответствие сигнатур
2️⃣ Implicit - неявное приведение благодаря особенностям вариантности
3️⃣ Explicit - использование оператора явного приведения типов
4️⃣ As - безопасное приведение через оператор
5️⃣ Dynamic - отключение статической типизации ключевым словом
Гипотеза: Dynamic самый медленный, Explicit и As чуть помедленнее, чем Implicit и Direct
Результаты на скрине её подтверждают!
Потихоньку влился в рабочие процессы, и наконец готов выдать первый технический пост в этом году!
Сегодня мы поговорим о производительности приведения типов в разных сценариях, касающихся ковариантности и контравариантности.
Я написал простенький бенчмарк, чтобы проверить скорость работы с типами в 5 разных сценариях:
as dynamicГипотеза: Dynamic самый медленный, Explicit и As чуть помедленнее, чем Implicit и Direct
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍5❤1👏1🤔1
Неочевидные проблемы
Недавно ко мне обратился подписчик с просьбой разобраться в проблеме.
Есть присланный фрагмент кода, на котором проверяется равенство строк.
Загвоздка в том, что при видимом одинаковом значении
Опытные могли догадаться, что дело в так называемых скрытых символах.
При обработке приложением строк, пришедших извне, надо быть готовым к такому сценарию.
Для начала можно посмотреть в дебаге на результат метода
Как с ними бороться, зависит от ваших потребностей и возможностей:
▪️Ожидаете их только по краям? Тогда сойдёт
▪️Когда хотите почистить внутри строки, можно прибегнуть к вызову
▪️При особых запросах на очистку лишних символов уже придётся прибегнуть к кастомным фильтрациям с помощью статических методов
Недавно ко мне обратился подписчик с просьбой разобраться в проблеме.
Есть присланный фрагмент кода, на котором проверяется равенство строк.
Загвоздка в том, что при видимом одинаковом значении
"5.1$1" проверка даёт false.Опытные могли догадаться, что дело в так называемых скрытых символах.
При обработке приложением строк, пришедших извне, надо быть готовым к такому сценарию.
Для начала можно посмотреть в дебаге на результат метода
ToCharArray(): он покажет весь массив символов, и врага можно будет увидеть в лицо.Как с ними бороться, зависит от ваших потребностей и возможностей:
▪️Ожидаете их только по краям? Тогда сойдёт
Trim▪️Когда хотите почистить внутри строки, можно прибегнуть к вызову
char.IsControl()▪️При особых запросах на очистку лишних символов уже придётся прибегнуть к кастомным фильтрациям с помощью статических методов
char (например, IsLetter || IsDigit) ну или регулярок👍28❤1🔥1
Строки и теоретико-множественные операции 🧠
Добро пожаловать в экспериментальную рубрику "сомнительно, но окЭй" 😅
Допустим, у нас есть некоторая строка и набор символов.
Надо решить две задачи:
1️⃣ Проверить содержит ли строка хотя бы один символ из набора. Для этого надо проверить пересечение двух множеств -
2️⃣ Проверить содержит ли строка все указанные символы. Тут налицо математическое определение
LINQ в C#, а также API интерфейса
Добро пожаловать в экспериментальную рубрику "сомнительно, но окЭй" 😅
Допустим, у нас есть некоторая строка и набор символов.
Надо решить две задачи:
строка & символы != пустое множествоподмножества.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🌭4❤1🥴1🍌1
Незамеченная фишка C# 12 😱
Уверен, вы могли упустить это нововведение в последней версии языка - лично я узнал о нём только благодаря подсказкам IDE😱
Теперь классы, структуры и интерфейсы с пустым телом можно объявлять без фигурных скобок, прямо как рекорды!
Соответственно, следующий фрагмент кода скомпилируется:
Уверен, вы могли упустить это нововведение в последней версии языка - лично я узнал о нём только благодаря подсказкам IDE
Теперь классы, структуры и интерфейсы с пустым телом можно объявлять без фигурных скобок, прямо как рекорды!
Соответственно, следующий фрагмент кода скомпилируется:
class MyClass;
abstract class MyAbstractClass;
struct MyStruct;
interface IMarkerInterface;
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18🤯6👍5❤1
Языком 2023 года по индексу TIOBE назван C#, который сохранил 5 место, но стал лидером по росту популярности (+1.43%) 🥳
Жаба уже одной в могиле, ведь она показала один из самых высоких спадов популярности (-4.34%) ☠️
https://www.tiobe.com/tiobe-index/
Жаба уже одной в могиле, ведь она показала один из самых высоких спадов популярности (-4.34%) ☠️
https://www.tiobe.com/tiobe-index/
👍23🔥3🍌3❤1
«Когда мера становится целью, она перестает быть хорошей мерой» - закон Гудхарта 🧠
Страшно подумать - принцип был сформулирован почти 50 лет назад, но много технических компаний и эффективных менеджеров продолжают его не понимать!
Если ваша цель снизить количество легаси - удалите кодовую базу и начните всё сначала.
Если ваша цель увеличить доход - покройте все экраны рекламой.
Если ваша цель писать больше кода - добавляйте бессмысленные комментарии.
Если ваша цель фиксить больше багов - чините самое простое.
Если ваша цель делать больше пулл реквестов - время вылизывать readme.
Если ваша цель увеличить вовлечённость - превратите всё в кликабельные кнопки.
Если ваша цель уменьшить количество отчётов об ошибке - усложните отправку отчёта.
Если ваша цель быстрая загрузка страницы - удалите всё мультимедиа, JavaScript и CSS с вашего сайта.
Страшно подумать - принцип был сформулирован почти 50 лет назад, но много технических компаний и эффективных менеджеров продолжают его не понимать!
Если ваша цель снизить количество легаси - удалите кодовую базу и начните всё сначала.
Если ваша цель увеличить доход - покройте все экраны рекламой.
Если ваша цель писать больше кода - добавляйте бессмысленные комментарии.
Если ваша цель фиксить больше багов - чините самое простое.
Если ваша цель делать больше пулл реквестов - время вылизывать readme.
Если ваша цель увеличить вовлечённость - превратите всё в кликабельные кнопки.
Если ваша цель уменьшить количество отчётов об ошибке - усложните отправку отчёта.
Если ваша цель быстрая загрузка страницы - удалите всё мультимедиа, JavaScript и CSS с вашего сайта.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24😁9💯5❤2🤔1🥱1
Рекомендую к прочтению
В прошлом году у меня возникла необходимость систематизировать в моменте свои знания об асинхронном программировании в C# и при этом иметь постоянную шпаргалку под рукой.
Собственно, эта книга идеально решила эту потребность - в ней описаны все необходимые аспекты, при чём очень доступно и концептуально, на уровне идеи, а не конкретного кода.
Вы даже узнаете, в чём преимущество
Бумажный вариант стоит недорого, сама книга имеет небольшой объём - всего 119 страниц.
Так что, однозначный лайк👍🏻
В прошлом году у меня возникла необходимость систематизировать в моменте свои знания об асинхронном программировании в C# и при этом иметь постоянную шпаргалку под рукой.
Собственно, эта книга идеально решила эту потребность - в ней описаны все необходимые аспекты, при чём очень доступно и концептуально, на уровне идеи, а не конкретного кода.
Вы даже узнаете, в чём преимущество
async / await для ASP NET приложений!Бумажный вариант стоит недорого, сама книга имеет небольшой объём - всего 119 страниц.
Так что, однозначный лайк👍🏻
👍40🔥7❤4
StepOne | Степан Минин
Год выходит на финишную прямую, как и контент в декабре на этом канале 🥶 Вот самые важные посты последнего месяца, которые можно перечитать ещё раз 🤔 ⚡️ Как растёт моя архитектурная компетенция на примере пет проекта ⚡️ Хитросделанные partial'ы ⚡️ Самое…
Как же летит время, январь почти всё 🤯
Надеюсь вы хорошо провели праздники, да и для канала месяц в целом прошёл неплохо
⚡️ Начал год со статьи про полиморфизм в DI на Хабре
⚡️ Сравниваем производительность разных способов приведения типов в ковариантном и контравариантных сценариях
⚡️ Пособие по борьбе со скрытыми символами
⚡️ Новый сахар в C# 12
Надеюсь вы хорошо провели праздники, да и для канала месяц в целом прошёл неплохо
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6⚡2🔥1
Какой сахар мне хотелось бы видеть в новых версиях C#
Вас не подвело зрение, мне действительно не хватает кое-какого синтаксического сахара)
Большинство разработчиков знакомы с оператором
Он делает эквивалентными две следующие строчки:
Однако, в моей практике часто встречалась ситуация, когда необходимо было сделать обратный процесс:
Хотелось бы сократить эту запись до одного оператора.
Не важно, как он будет называться, варианты:
Тогда, сокращение будет выглядеть так:
Вас не подвело зрение, мне действительно не хватает кое-какого синтаксического сахара)
Большинство разработчиков знакомы с оператором
??Он делает эквивалентными две следующие строчки:
return expr is null ? fallbackValue : expr
// ...
return expr ?? fallbackValue
Однако, в моей практике часто встречалась ситуация, когда необходимо было сделать обратный процесс:
return expr is null ? null : GetResult(expr)
Хотелось бы сократить эту запись до одного оператора.
Не важно, как он будет называться, варианты:
?!, ?:, ???Тогда, сокращение будет выглядеть так:
return expr ??? GetResult(expr)
🥴26👍12😁5🤯3👌1🕊1💯1