Тёмный

10 худших моментов языка C#, которые прочувствуют только профи 

Dev Jungles - Andrii Podkolzin
Подписаться 12 тыс.
Просмотров 14 тыс.
50% 1

#DevJungles #dotnet #csharp
Telegram канал Dev Jungles - t.me/DevJungles
Поддержать канал можно:
- Спонсорством на RU-vid
- Переводом на карту или пополнением банки монобанка:
Dev Jungles RU-vid Channel Fund
send.monobank.ua/jar/7iAP3sZkm9
Номер карты банки:
5375 4112 0230 1466
- Или криптой:
Binance Id: 479881646
BTC - 18C3jsFYwviN5FvzpAt4uMWRfUeVKvdWxy
ETH - 0x2903f63ba9009732272e91a299053b9d7b623216
USDT on ERC20 - 0x2903f63ba9009732272e91a299053b9d7b623216
USDT on TRC20 - TSmS5RzQKbWdxZkoM2oRo9HK8FYBaq744T
LTC - LN3CkrnvZLZTXDUhqTy1gUKMVpLjEPA4G2
DOGE - DPwon439jf3axVSBwyuXso6z7CivuJF655
AAVE - 0x2903f63ba9009732272e91a299053b9d7b623216
Waves - 3P8D57Zw7CrqW2o7dHpvZR2UzAzQRFA2kZd
Наш родной С# почти всегда прекрасен и вытягивал нас из разных переплетов.
Но и он не свят и в нем есть недостатки.
Есть те, разговоры о которых уже набили всем оскомину: как то, например то, что все по умолчанию изменяемо и нужно делать дополнительные манипуляции, что бы сделать объект immutable, хотя работа в эту сторону идет(те же record).
Или еще много было сказано, про старый синтаксис делегатов. Он и правда ужасен, но давайте по-честному: вы когда его последний раз видели?
Сегодня я хочу обстоятельно поговорить о том, что регулярно отстреливает нам на реальных проектах! Что делает их сложнее там, где этого можно и нужно было бы избежать. Но скажу не только о проблемах, но и предложу для них решения, а еще накидаю контекста почему так было сделано, потому погнали!
Сегодня:
record struct внезапно оказались mutable!
event subscribtion/unsubscribtion просто ужасны!
default parameters отстреливают в ногу каждому второму!
Нужно перевернуть половину проекта, когда передаешь параметры в base constructor
И многое другое!
Тайм-коды:
00:00 - Вступление
02:30 - 10 место
04:50 - 9 место
10:00 - 8 место
13:17 - 7 место
17:12 - 6 место
19:50 - 5 место
21:36 - 4 место
24:59 - 3 место
27:56 - 2 место
31:08 - Достойны упоминания
34:59 - 1 место
37:49 - Вывод

Опубликовано:

 

25 июл 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 256   
@rogiawos8737
@rogiawos8737 Год назад
Чел, хорош , контент вообще в кайф!! Можно вот этого вот всего почаще❤❤❤
@K1llRay64
@K1llRay64 Год назад
с языка)) всем маслятам маслят )))
@tyomios
@tyomios Год назад
Вы перепутали канал)
@MrNachosVIDEOS
@MrNachosVIDEOS Год назад
Замечательное видео) Внесу свою лепту (как человек что много лет пишет на чистом С/Ассемблере, а сейчас пишу этот комеет как С# фулстек) 1) модификаторы доступа - это годнота. Если не нужно, то не используешь "лишнее". У С\C++ вместо internal вообще static (это при том, что там есть external) Я выступаю за то, чтобы был максимально гибкий контроль за областью видимости, потому как много раз видел, как сужение области видимости просто "схлопывает" тонны кода на выхлопе компилятора. И таких инструментов, которые несут смысл как для программиста, так и для компилятора очень мало, если так подумать 2) Мне очень нравится, что вложенные типы видят приватные поля тех, что выше по иерархии. Благодаря этому можно очень красиво делать реализации Строителей. Если делать как по науке, то нужно подводить желаемый тип под интерфейс, в котором можно менять значения полей. И сам интерфейс хорошо бы спрятать, чтобы уши не торчали... а так, вложил один тип в другой и всё готово. Потому как руки всё равно потянтся проверить, а не будет ли у типа фабричного метода, если конструктор приватный Про путаницу с модификаторами доступа по умолчанию -- полностью солидарен 3) Дженерики - это прям беда. Столько раз себя ловил на мысли, что это какой-то кастрат плюсовых шаблонов, что аж неловко становилось Они ну слишком базовые. Есть попытки в метапрограммирование (те же where и всякие контр/ко/ин-вариантности), но пользоваться ими очень неудобно, когда нужно работать с иерархией этих типов Спасаемся базовыми типами, как и было упомянуто в видео) Но лично моя боль №1 -- поведение структуры с интерфейсами Это прямо дичь. Моментально рушится вся идея строго значимого типа. Плюс к тому очень много странных ограничений (нельзя давать полям значения по умолчанию, вне конструктора без аргументов, но как только ты этот самый конструктор определяешь, то ты рушишь целую вереницу оптимизаций, что заботливо для тебя выстроили авторы языка) А те же readonly ref struct я смог применть только в паттерне итератор. И работает это только из-за костылей с утиной типизацией... вне этого как только у тебя появляется хоть маломальски выстроенная иерархия типов и ты хочешь внести "перформанса" , то ты быстро обнаруживаешь, насколько же у тебя связаны руки. Либо рефлексия, либо переписывать всё в совсем другой парадигме Я бы добавил интерфейсу гарантию, что он представляет только значимый тип (с синтаксисом для такого поведения). По сути легальный и чистый способ для утиной типизации С# получился очень удобным прикладным языком И он может решать целый спектр задач Потому его сейчас как лебедь/рак/щука тянут в сторону обратной совместимости, рядом новые и модные практики с функциональщиной, а особняком системные программисты, которым нужон High Performance Ещё раз выражаю благодарность за видео и труд! Смотрю тебя с большим удовольствием)
@DevJungles
@DevJungles Год назад
1.2. согласен) 3. Я вот и рад, что не стали брать шаблоны из плюсов целиком: уж очень они сложны, но то, что затянули явно недостаточно, это тоже факт
@hel2x
@hel2x Год назад
Невероятно интересный видос. Большое тебе спасибо ❤
@user-jd2kx9nb1t
@user-jd2kx9nb1t Год назад
Мне пришлось перейти с C# на Java, ребят. Как же вы счастливы, ребят, вы не понимаете, насколько C# кажется прекрасным после перехода на джаву!
@DevJungles
@DevJungles Год назад
О дааа! Помню на первой работе иногда нужно было лазить в сорсы ANTLR, а он на старехонькой Java. И я прямо страдал без var и LINQ... Но это и была совсем старая Java..
@valiantsinm
@valiantsinm Год назад
В Java самая попоболь это отсутствие единого стандарта. Всякие там спринги, груви и прочий заопарк. 90% процентов Java чатика на проекте забито вопросами типо "вот я обновил версию библиотеки с х на y и вот тут у меня всё сломалось" или "взял последнюю версиюю исходников из репозитория и уменя всё сломалось". И вот когда видишь советы типа "надо взять вот эту весию либы X и вот эту версию либы Y. а вот этот код откатить/закоментить/переписать" волосы на голове шевелятся.
@pfff-doh
@pfff-doh Год назад
зачем вообще жаба, если есть котлин
@daitedve1984
@daitedve1984 Год назад
Жаба - лютое говнищще из прошлого века, зачем на него переходить?? Котлина мало что ли?
@user-jd2kx9nb1t
@user-jd2kx9nb1t Год назад
@@ruslooob лямбды, не умеющие менять значения переменных, недогенерики, отсутствие await, операторы перегружать нельзя, поэтому упаси вас бог создавать через new и сравнивать стринги через ==, прекрасное совершенно поведение типа long с недооптимизацией, странные моменты с уборкой мусора, и т.д., всего не упомнишь. Больше всего конечно трогают лямбды, await и недогенерики, 2023 год на дворе, остальное реже.
@ppc2012
@ppc2012 Год назад
Хаха, я смог заполнить switch expression. Буквально всего то пара лет прошло) Теперь осталось запомнить синтаксис его паттерн матчингов.
@DevJungles
@DevJungles Год назад
О дааааааа.... На канале, кстати, есть ролик про pattern matching... Я там тоже немного горю от синтаксиса)
@WisdomHacks
@WisdomHacks Год назад
Очень интересно! Спасибо)
@redice8928
@redice8928 Год назад
очень хорошее видео, благодарю за труд
@user-zd6di5mq9z
@user-zd6di5mq9z Год назад
Не знал о некоторых проблемах даже, повезло-повезло. Спасибо, интересный формат!
@user-qp8bt7gq4b
@user-qp8bt7gq4b Год назад
Крутое видео. Спасибо за воркэраунды для некоторых проблем!
@maximkonoplyanik9155
@maximkonoplyanik9155 Год назад
Отличный ролик 👍
@native-nature-video
@native-nature-video 11 месяцев назад
Спасибо за видос!!!
@kkk-tk6gq
@kkk-tk6gq Год назад
Классный видос, лайк
@Speed-Run-Facts
@Speed-Run-Facts Год назад
Крутое видео)
@evg12345
@evg12345 Год назад
Спасибо
@gnchrtd
@gnchrtd Год назад
Ух, про switch прямо в точку. Помню сходил на неделю в отпуск и напрочь забыл его синтаксис. Дело было года два назад, когда он только входил в обиход. По части модификаторов доступа - там еще file завезли) а где internal, там и InternalsVisibleTo, так сказать) P.S. На фразе «С деструктором все еще хуже. Во-первых, он у нас… есть» заржал и подавился своим смузи
@DevJungles
@DevJungles Год назад
😁😅😅😅
@endemic3401
@endemic3401 Год назад
Читаешь такой книжочку/статейку по сишарп, встречаешь слово "деструктор", реакция: "А, че? точно.."))
@GamDevRus
@GamDevRus Год назад
Крут!!!
@grant1118
@grant1118 Год назад
Спасибо за очередное полезное!) Никак не пойму как до такого уровня подняться. Ты не рассказывал про свой путь, что надо сделать? Не поступать в вуз, сразу стартапы, куча пет проектов и потом куча ком. проектов, не жениться (чтобы не отвлекали), с друзьями никуда не ходит и пр. Поделись лайф хаком, очень интересно!)
@DevJungles
@DevJungles Год назад
Ахахаха)) Да фиг его: ничего такого вроде не было. Мне кажется тут сыграло просто время движения: если 10 лет заниматься разработкой постоянно стараясь узнать что-то новое и сделать что-то новое, без экстрима в плане темпа, но и без длинных пропусков, то все сработает)
@grant1118
@grant1118 Год назад
Отлично, выглядит как план!) Надо будет такой roadmap и транслировать подрастающим разработчикам.👍
@independentexpert8349
@independentexpert8349 Год назад
я десь рік тому стикнувся з 10-ю проблемою, тоді теж мало не здурів і майже постарів на 50 років поки дебажив, в кінці в мені щось перегоріло і я просто змирився що це так не працює, розбиратись в причинах вже не було ні часу ні моральних сил, просто переробив і забув. Ти зараз прям витяг на "світ божий" коварне зло приховане в пітьмі, яке паскудить життя багатьом. Вважай - ти рятуєш людям нерви і час для чогось більш прекрасного, так тримати👍
@DevJungles
@DevJungles Год назад
Крутий комент) Радий, що відео сподобалося)
@denys-p
@denys-p Год назад
У меня как-то было веселье с перегрузкой методов. Уже не помню деталей, но идея была в том что было 2 версии метода и одна принимала энум, а вторая инт. В итоге я передаю энум, а вызывается версия с интом.
@HOSTRASOKYRA
@HOSTRASOKYRA Год назад
Дуже дякую. Корисне відео. Реквест на налаштування статичних аналізаторів. Тільки в студії, а не в цих ваших джетбрейнах!
@DevJungles
@DevJungles Год назад
А там нащастя як MS став розвивати команд лайн і compiler as a service, воно стало більш-менш універсально, бо працює рівнем нижче за IDE
@nanvlad
@nanvlad Год назад
Добротний відос. Тепер по пунктах 10) Все правильно, так влаштовані інтерфейси - я не хочу знати внутрішню імплементацію (вона взагалі може бути в іншій інтернал френдлі ассемблі, або замокана в тестах), а працювати лише з публічним контрактом, тому x і має бути 10 9) Теж логічно, але неочевидно - лише на досвіді трекаєш таке. 8) void - зло, a async void - ще більше зло :) 7) event - в топку, застаріло, краще юзати Rx. Конкатенація делегатів може бути корисною в маппері, наприклад, коли накидуєш на маппінг одного проперті декілька делегатів 5) Type inference - це біль C# та аналізаторів синтаксису. F# в цьому плані дуже органічний 4) protected - це біч ООП, коли писали все на Rich Domain Model, де дані та поведінка інкапсулювалися в самому класі і для модифікації функціональності лишалося засабкласитися з оверрайдами (привіт Template Method pattern). Pubilc модифікатор в інерфейсах юзаю лише тоді, коли далі йде дефолт імплементація - це дозволяє візуально відрізняти вже імплементовані методи від тих, які треба імплементувати в нащадках 2) Конструктор ще не можна передати як посилання на метод, типу .Select(Myobj.ctor) і доводиться писати .Select(_ => new Myobj()) 1) Вітаю, ти віднайшов property injection :) В Blazor є відповідний атрибут [Inject], де можна врізати свій сервіс без зміни всіх нащадків
@DevJungles
@DevJungles Год назад
10. Згоден, але кейс муторний и хотів би щоб мова якось уберігала від таких пострілів собі у ногу. 8. Так там навіть не було про async void... Там скоріше про те, що навіть Task біда, тому що він не Task 7. Чи можна було б у мапері реалізувати так без конкатенацїї делегатів? Так. Тому все ще вважаю, що конкатенація делегатів дуже стрьомна штука, що була додана у мову помилково. 2. Доречі цікавий кейс. 1. Property injection став більш прийнятним як на мене після введення слова required. До цього: стрьомна штука.
@DevJungles
@DevJungles Год назад
Дяка за крутий і розгорнутий комент)
@Ivolution091
@Ivolution091 Год назад
К обходу 7-й проблемы в пример можно ещё библиотеку System.Reactive привести. Там тоже логика помещения подписки в IDisposable используется. Также есть механизмы адаптации классических событий. Но, с другой стороны, это уже не Subscriber/Puslisher, а Observable/Observer получается.
@DevJungles
@DevJungles Год назад
Если честно, несколько раз пытался вкатится в System.Reactive, но как-то все время задачи выглядили слишком простыми, не стоящими того, что бы разбираться в этой технологией... ..в общем сложновата она на вход в чем-то.
@Ivolution091
@Ivolution091 Год назад
@@DevJungles Да, сложная вещь, объемная. Я с WPF в основном работаю, там неплохо весьма приживается эта технология. А вот WEB, например, сложно представить, как её использовать.
@mierce
@mierce Год назад
Не понятно,но очень интересно)
@vladrega6862
@vladrega6862 Год назад
Хорошее видео, насчёт конструкторов с абстрактными классами полностью согласен, а так же с асинхронными и не асинхронными перегрузками. Как по мне уже давненько пора отказаться от явного применения Task с асинхронными методами и отдать это на вотчину компилятора, т.к. нам, как правило, нужен дженерик объект таска, а не сам таск,🤘
@edwardfreedom
@edwardfreedom Год назад
сделай свой обьект или касти внутри как нибудь
@DevJungles
@DevJungles Год назад
С одной стороны согласен, с другой асинхронность тоже важная часть сигнатуры и ее хотелось бы видеть... Не знаю. Не простой вопрос.
@vladrega6862
@vladrega6862 Год назад
@@DevJungles ну, такое, я бы предпочел асинхронные методы суффиксом отмечать, и, возможно, чтобы явный тип был указан при наведении на метод. С var же так работает, почему бы не сделать что-то подобное. А возвращаемый тип, на самом деле не всегда говорит о том, что метод асинхронный, не знаю, доводилось ли ковыряться в либах к sql различным, там можно часто встретить методы, которые возвращают таск, но при этом прям параметром принимаю булевый флаг async и если ты выбрал false, то у тебя будет синхронный метод беспантово завернут в таск, такое..
@mudrecsalimkhanov329
@mudrecsalimkhanov329 Год назад
Хорошее видео, Новый switch case конечно же это ужас. + в последних версиях шарпа очень много сахара, это не очень радует.!
@user-pn9rm2xr7x
@user-pn9rm2xr7x Год назад
На счёт конструкторов: можно сгенерировать пачку паршл классов в которых определяется конструктор. Либо иньектить зависимости в свойства. Ну а 50 тестов всё ровно придётся изменить.
@DjonNIK777
@DjonNIK777 Год назад
По поводу последней проблемы: в Rider есть удобная функциональность, добавляющая аргументы в функцию, если в одном из мест вызова дописать этот аргумент. Это же применяю и при добавлении нового параметра в базовый класс. Так же можно через меню рефакторинга это же сделать - в popup окне вписываешь название и типа аргумента, и он появляется во всех наследниках. Не знаю, как там в VS - давно не использовал
@DevJungles
@DevJungles Год назад
Дада Есть, иногда даже пользуюсь, иногда забываю. Но там большой и сложный диалог открывается, пока все прокдикаешь уже злой будешь
@DjonNIK777
@DjonNIK777 Год назад
Диалог да, а когда фактически изменил конструктор (или любой другой метод), то прям из контекстного меню можно добавить новый параметр во все наследники (или реализации)
@DjonNIK777
@DjonNIK777 Год назад
Кстати, я про IEnumerable/IQuerible всегда факаплю сам, но в приведенном примере еще большее зло - ToList(). Я даже долгое время думал, что для листа ToList вернет тот же самы инстанц, но в реализации увидел, что всегда создается новый экземпляр
@Kitulous
@Kitulous Год назад
@@DjonNIK777 уточню: когда прописываешь новый аргумент, он выделяется такой белой рамочкой, и если в этот момент нажать Альт+Энтер или какая у вас комбинация для квик фиксов, то там первым пунктом будет применение рефакторинга
@user-me6ey7gq4j
@user-me6ey7gq4j Год назад
У меня проблема, которая на первом месте, была в ts'e, только там в конструкторе было 17 сервисов, в родитель я передавал 10, у того был еще один родитель с 4 параметрами. И к этим четырём параметрам надо было добавить пятый... Энивей у свитч экспрешена первое место у меня
@radiosh66
@radiosh66 Год назад
Слушайте, а в райдере (или любой другой IDE от JB) это проблема не решается простым рефакторингом сигнатуры конструктора?
@EugeneS88-RU
@EugeneS88-RU Год назад
с парой проблем сталкивался,решения такие же были,как и ты предложил. но давайте посмотрим правде в глаза - многие из новых фич языка (вообще) крайне сомнительны и спорны( те же интерфейсы с реализацией по умолчанию)
@antonkaster
@antonkaster Год назад
11:47 Плачу на этом моменте. Сколько часов было убито в борьбе с этим!
@user-fy3dv8em6o
@user-fy3dv8em6o 2 месяца назад
1. В С++ если констуктор наследника будет по аргументам повторять базовый + без тела (только вызов конструктора базового класса), то можно написать внутри класса наследника class Derived : public BaseClass { using BaseClass::BaseClass; }
@DevJungles
@DevJungles 2 месяца назад
Неплохая фича, но, наверное, не работает если добавить аргументы в наследнике...
@user-fy3dv8em6o
@user-fy3dv8em6o 2 месяца назад
@@DevJungles да, это уже не сработает, но в видео было так, что набор аргументов одинаковый)
@alvkn
@alvkn Год назад
топ1 проблему прочувствовал буквально на днях, согласен с ее нахождением в топ1
@user-wj7er2go9d
@user-wj7er2go9d Год назад
На счет первого пункта. Если я не ошибаюсь , то можно вместо класса агрегатора и использовать атрибут , наподобие инжект в ангуляр, я недавно натыкался на статью. Суть в том что тебе вообще не надо писать зависимости в наследниках , а лишь указать аттрибут в базовом и он будет применять все di в наследниках
@DevJungles
@DevJungles Год назад
Дада! Есть такое: особенно с модификатором required и get/init свойствами это становится прямо вменяемо.
@pispis3617
@pispis3617 Год назад
Чет так заслушался на вступлении, что показалось, что начала какого-нибудь фильма от Гая Ричи)))
@PsiHamster
@PsiHamster Год назад
Насчет конструкторов вариантов не особо много, средствами языка сейчас, как вариант, только добавлять вторым конструктором, и вызывать из первого с созданием нужного класса. Но если нужно какую-то зависимость протаскивать, то тут без изменений никак не обойтись. Жаль райдер не умеет сигнатуры всех зависимых конструкторов обновлять. С языковой конструкцией не хватает какого-то наследования конструкторов, возможно. Так, чтобы если есть класс A с недефолтным конструкторов, то в классе B : A, он сразу был бы доступен, с возможностью переопределения через override. Так, если бы в наследниках не было бы специализированных конструкторов, тогда кода пришлось бы меньше лопатить. (Но если в наследниках есть дополнительные параметры, то всё равно фигачить придется) По-моему тут особо вариантов нет, если появляется необходимость какую-то чувствительную часть кода подергать, то к этому надо быть готовым. Вариант с моделькой с сервисами в приведенном примере считаю перебором. Если у базового класса много зависимостей, которые ещё и часто меняются, и не нужны наследникам, то это скорее всего признаки плохой архитектуры.
@DevJungles
@DevJungles Год назад
По поводу плохой архитектуры согласен, впрочем это не значит, что с такой архитектурой не приходится работать.
@user-qq9hw2cz6l
@user-qq9hw2cz6l Год назад
Использовали сложение делегатов в продакшене. Был парсер документов, который менял состояние в зависимости от положения в документе, и на разных состояниях нужно было обрабатывать токены одним или несколькими анализаторами. Соответственно был словарь состояние-делегат, где делагат не обязательно один анализатор, а может быть несколько с разной логикой. И не то чтобы это было бы сложно сделать без суммирующихся делегатов, но если они уже есть, то почему бы их не заюзать.
@DevJungles
@DevJungles Год назад
Проблемы начинаются если есть взвешенные значения) Не понятно: как получить все, какое именно ты получил итд.
@shkippitor1895
@shkippitor1895 Год назад
про гит в точку
@ivanvoyager
@ivanvoyager Год назад
Половина проблем просто надуманы. А насчёт массивов и генериков и общего кода что мешает использовать интерфейсы? У массива спокойно есть генериковый интерфейс IReadOnlyList`T, например.
@DevJungles
@DevJungles Год назад
Да, есть способы выкрутится. Но, если работаешь в уровня рефлексии и пишешь какой-то обощенный код, то GetType().IsGenericType нужно помнить, что массивы туда не попадают.
@user-qg6fn3qx9m
@user-qg6fn3qx9m Год назад
Речь конечно про с# но добавлю по поводу косяков, в entity framework 7 завезли column json, только нельзя чтобы классы в этих колонках имели поле с названием id, будет вылетать ошибка при запросах , так как конфликтует как я понял с ихним десерелизатооом .
@DevJungles
@DevJungles Год назад
Ух.. Не знал этой штуки.
@Mnogoznaal_
@Mnogoznaal_ Год назад
Первое место жиза, но только не понятно как настроить его для DI. Есть видосы на эту тему? Еще тоже бесит что он автоматом не указывает дженерик, я думаю это могут добавить IDEшках как авто заполнение.
@stanislavpetrov6124
@stanislavpetrov6124 Год назад
Гугл: YourDiContainerName property injection
@joresso
@joresso Год назад
Смотря каким DI пользуетесь. В MicrosoftDI Add(Singleton/Scoped/Transient)(provider=>/*тут выбираете из провайдера что надо и конструируете экземпляр класса*/)... посмотрите повнимательнее методы регистрации типов в вашем DI должно быть что-то похожее
@DevJungles
@DevJungles Год назад
Сделаю видео где-то в мае)
@Dread2607
@Dread2607 Год назад
А можна лінк на оригінальну статтю ? Чи на презентацію, якою ти користуєшся ?
@DevJungles
@DevJungles Год назад
Оригінальної статті не існує, все для цього відео створював ексклюзивно. Лінку на презентацію та сценарій виклав для спонсорів та патронів каналу.
@denys-p
@denys-p Год назад
А первая проблема у меня чаще решается практически полным отсутствием наследования, если честно. Если там какая-то общая логика, то её можно вывести в какой-нибудь класс-хелпер. С наследованием в принципе очень легко отстрелить себе ногу не в одном месте, так в другом. Была весёлая история, когда переопределили то ли Equals то ли GetHashCode в базовом классе сущности и у нас то ли работа с базой, то ли какие-то вычисления взорвались от этого в совсем другом месте
@alexlightweight
@alexlightweight Год назад
" у меня чаще решается практически полным отсутствием наследования, если честно." сейчас тебе мамкины архитекторы и мамкины тимлиды накидают г...внеца на вентилятор в комментах ))) А если серьезно, то я согласен, лепить где попало наследование что бы казаться умным бред, его надо применять там где действительно есть общая логика которую копипастить не стоит в классах, но любителей что то поменять в базовом классе всегда можно ткнуть носом в SOLID, а точнее в Open/Closed, но на практике лучше конечно применять наследование там где это РЕАЛЬНО нужно, а не потому что "мы же умные программисты". Последнее время вообще наблюдаю тенденцию что сейчас код пишется не для решения бизнес задач, а для применения паттернов, архитектур, "умных идей из книжек" и т.д., то есть сейчас не принято думать при написании кода, главное написать код "поумнее" и главное чем сложнее тем лучше, что бы не выглядеть идиотом, потому что забыли про главный принцип программирования KISS, который я считаю поважнее будет чем SOLID и ООП вместе взятые. )))
@user-kk7ib8hu3v
@user-kk7ib8hu3v Год назад
ну да, ну да, особенно на 10 летних проектах вообще нету наследования, и статиков и классов на 10000 строк)
@denys-p
@denys-p Год назад
Ну, там где классы по 10000 строк, там поможет только мучительный рефакторинг или переписывание начисто
@DevJungles
@DevJungles Год назад
Сложные многоуровневые разветвленные иерархии точно могут быть злом и доставлять огромное количество проблем. Иерархии в 1 уровень, вполне часто могут быть неплохим решением: базовый репозиторий и пару десятков наследников и подобные варианты. Вот на таких вариантах первая боль и отстреливает часто.
@alexlightweight
@alexlightweight Год назад
​@@DevJungles да, согласен, 1 уровень, максимум 2 это норм. У нас в проекте TL является "архитектурным астронавтом" (загуглите термин кому интересно что это за тип программистов), так вот у нас иерархия в 20-30 бессмысленных классов, черт ногу сломит, а главное что необходимости в этом вообще нет, но у нас в конторе главное написать "код позамудренее" и чем больше он непонятный и сложный тем ты круче. Так что согласен с @Dev Jungles - Andrii Podkolzin на все сто процентов, 1 уровень вообще идеально, 2 допустимо но нужно точно иметь на это обоснование. 🙂
@Robit666
@Robit666 Год назад
На счёт 6го места... default там не впихуемый т.к. в этом случае будет сравнение на значение по умолчанию
@dimaaannn1
@dimaaannn1 Год назад
Вот женерики да, прям иногда хочется хитрых проверок навернуть, и так чтобы "оно само" потом работало при использовании. А в итоге получаются костыли с кучей наследований. А на счёт конструкторов - у меня была идея, что если бы на вход можно было передавать какой то класс (или анонимный тип) который может деконструктиться в нужный список аргументов прямо при передаче в конструктор. var arguments = new SomeClassArgsRecord(a, b, c); var someClass = new SomeClass(arguments.Deconstruct()); // new SomeClass(a, b, c)
@DevJungles
@DevJungles Год назад
На самом деле: мы все реже пишем оператор new, все чаще объекты создаются контейнром, потому именно передача параметров редко отстреливает прямо так серьезно.
@bulsond
@bulsond Год назад
По поводу массивов (их необобщенности) и конструктора - это же следствие истории создания шарпа, как сводного брата Java.
@DevJungles
@DevJungles Год назад
Ага... Но разве оно от этого меньше болит?)
@joresso
@joresso Год назад
При просмотре подумал что прсто дженерики появились в netFramework 2. И не свящано с историей создания... создатели специально отказались от дженериков?
@endemic3401
@endemic3401 Год назад
1ое место. Был такой случай на первой самой работе. Был самым зеленым джуном среди сеньоров. И потел каждый раз, когда в процессе багфикса приходилось трогать "то что работает" и было написано опытными программистами. Но в один прекрасный день попался баг, в качестве решения которого, было необходимо добавить в конструктор базового класса некий объект. Как сейчас помню, звоню наставнику и несколько раз уточняю, что "пук среньк надо вот в базу добавить вот это, но там наследование 5> потомков и типа мне надо каждому из них в ктор пробросить этот тип..???" "- Да"....
@DevJungles
@DevJungles Год назад
Дада) Первое место прямо в самое сердечко. Где-то пол года выписывал проблемы для этого видео. За это время сам в работе столкнулся с проблемой раза 4
@joresso
@joresso Год назад
Обычно с коллегами обсуждаем новые фичи... и часть просто не используем))) чтоб не бесили. Как в шутке - "если вам не нравятся гейпарады, прекратите в них участвовать"
@DevJungles
@DevJungles Год назад
Обычно, если команда большая, то провернуть такое довольно сложно)
@native-nature-video
@native-nature-video 11 месяцев назад
Имхо косяк #1 - это неудобство отписки от ивентов. Особенно с анонимными методами
@DevJungles
@DevJungles 11 месяцев назад
Мне кажется мы их слишком редко используем последнее время, чтобы это было проблем. Все меньше и меньше АПИ работают с ивентами.
@dualitysolify
@dualitysolify Год назад
Насчет свитча орнул) Пока мы - джсеры, страдаем от того что из нашего языка пытаются сделать шарп постоянной копипастой паттернов от туда, то шарписты страдают от того к ним завозят паттерны из джса))) З.Ы. Для тех кто не въехал, в джс свитч кейс как он выглядит в плюсах или хексе это антипаттерн, который заменяют объектом, каждый из свойств которого является кейсом, который стрелочной функцией возвращает результат для кондишена
@DevJungles
@DevJungles Год назад
Хех))
@Hafune
@Hafune Год назад
С дженериками конечно боль, особенно после котлина где можно сказать "тут у меня интерфейс с неважно каким дженериком IMyInterface".
@DevJungles
@DevJungles Год назад
Да да да! Я вот примерно это и хотел бы иметь
@ka4ep
@ka4ep Год назад
Кому как, у меня каждый раз болят дженерики из 3-го места, ну и с ними всё время паровозиком идут массивы из 1-го места. Это массив, список, словарь, как их понимать? И каждый раз либо изобретаешь с нуля, либо тащишь свою библиотеку с решением. Создаёшь в каждой библиотеке модуль Autofac, автоматчески регистрируешь вот это всё... а под капотом боль от "а класс реализует дженерик интерфейс", а "интерфейс наследует этот дженерик интерфейс"? А атрибут? А как из этого безобразия создать инстанцию?... 🤯
@DevJungles
@DevJungles Год назад
Массивы были всего лишь в упоменаниях)
@kOPOBkAAA
@kOPOBkAAA Год назад
решение на топ1 крутое!
@alfany6252
@alfany6252 Год назад
Есть ещё реализация интерфейсов по умолчанию. Когда на это первый раз смотришь вообще мозг ломается
@DevJungles
@DevJungles Год назад
О да!) Но потом привыкаешь и далее подсаживаешься 😂😂😂
@ever-modern
@ever-modern Год назад
про 9: Правильным решением будет использование асинхронных методов у IQueryable. У IEnumerable таких нет.
@DevJungles
@DevJungles Год назад
Не совсем так. WhereAsync, SelectAsync нету и там. Там есть лишь "финализирующие" методы... SingleAsync, ToListAsync итд
@vasiliylu8054
@vasiliylu8054 Год назад
Я не очень понял про 9 пункт, вроде это же можно запомнить, почти как "жи-ши", не тащи тонны данных через enumerable, юзай силу, Люк.
@DevJungles
@DevJungles Год назад
Ну да, но это нужно постоянно помнить А ещё легко сделать классный метод для работы с IEnumrrable, а потом "случайно" его заюзать для какого-то Queryable
@user-ll2fo1vf2n
@user-ll2fo1vf2n 9 месяцев назад
Проблему с 1 места мне доводилось решать похожим способом, но со временем я понял, что лучше будет сделать отдельный класс RepoMappedEntittiesBase, который собственно и добавляет новый функционал и будет требовать уже для новых наследников передачу нужных данных. Тем самым мы и не нарушаем Open-Closed принцип. Как по мне оба подхода имеют смысл, т.к. все зависит от контекста того, какие изменения вы планируете внести.
@user-ll2fo1vf2n
@user-ll2fo1vf2n 9 месяцев назад
Из всех перечисленных моментов, считаю худшими только с 10 места. Довольно часто сталкивался с проблемой из 7 места, из-за которой приходилось писать кучу костылей, однако спасибо тебе за её решение, ведь действительно запомнить disposables при подписке упрощает решение этой проблемы.
@DevJungles
@DevJungles 9 месяцев назад
Немного запутался в обоих Ваших комментариях, если честно.
@6trica1a3
@6trica1a3 Год назад
Разложил сисярп по фактам, так ему 😅👍
@jarogor
@jarogor Год назад
По поводу первого места. Мне не понятно, по какой причине нужно постоянно переопределять конструкторы. Этой проблемы могло бы не быть, если бы не пришлось этого делать. При этом они не обязательно что-то делают, они просто перебрасывают параметры и просто существуют. Возможно есть этому объяснение, которое я не знаю и это всё оправдано. Но например в php такого нету, конструктор можно сделать один раз в родителе и иметь кучу наследников, которые будут пользоваться уже существующим конструктором. В тайпскрипте тоже
@DevJungles
@DevJungles Год назад
Согласен. Кейс, когда конструктор не меняется можно было бы запросто решить. Более сложный кейс, когда наследники имеют больше зависимостей все равно бы остался, но уже стало бы легче.
@denys-p
@denys-p Год назад
А в целом - да, вроде косяков хватает, но с многими или вообще не сталкиваешься или они лишь чуточку портят жизнь. А потом садишься за Питон или того хуже Джаваскрипт и стреляешь себе в ногу на пустом месте. Например в Питоне свойства объекта в конструкторе надо писать через self., иначе это будут статические свойства. Я разок так выстрелил себе в ногу. Вон стильно-модно-молодёжный Rust из коробки не имеет yield, пользуйтесь библиотеками :( Подозреваю что если пописать на нём подольше, то тоже можно всякого найти
@KLNHOMEALONE
@KLNHOMEALONE Год назад
Андрей, а тебе еще не говорили, что ты реально крут? :)
@DevJungles
@DevJungles Год назад
Спасибо))
@volan4ik.
@volan4ik. Год назад
А як же record class, який може бути positional (immutable) або звичайним (mutable). Здавалося б, навіщо?
@DevJungles
@DevJungles Год назад
Тут може щось упустив, бо не зрозумів про що це(
@volan4ik.
@volan4ik. Год назад
@@DevJungles positional record це такий: public record MyRecord(string Var1, int Var2); Він генерується у клас з конструктором, з додатковою логікою на порівняння типів. Звичайний record наступний: public record MyRecord { public string Var1 { get; init; } ... } Він генерується як звичайний клас, взагалі без нічого. Тож незрозуміло, який в ньому сенс. }
@64narayan
@64narayan Год назад
По девятому пункту (IQueryable и IEnumerable): если такая проблема появляется на продакшене, то у вас большие проблемы с тестированием своей работы и язык тут не при чем. Подобные проблемы у вас будет при использовании любого языка
@DevJungles
@DevJungles Год назад
И с одной стороны я согласен, но с другой это лишнее место, где частые ошибки случаются. Язык или API могли быть задизайнены чуть иначе.
@Diyozen
@Diyozen Год назад
Тоже отмечу жуткую боль от дженериков. Они вроде бы неплохие, но не хватает кучи инструментов (по типу усилений ограничений по иерархии интерфейсов, например, и других). Тему самой главной проблемы (№1), честно говоря, не очень понял. Как изначальную проблему (наследование реализаций в программировании бьёт по рукам ещё со времён множественного наследования), так и решение-костыль (оно же усложняет чтение класса и параметров конструктора). Не совсем понимаю контекста, но разве использование Type Object паттерна не излечит от этой проблемы? Или декоратор, опять же.
@DevJungles
@DevJungles Год назад
Если честно не вижу как декоратор или тайп объект может решить эту проблему...
@Diyozen
@Diyozen Год назад
@@DevJungles нет наследования - нет проблем протягивания зависимостей через всю иерархию. Что-то в этом роде)) Но это, наверное, я просто изначальную проблему не так понял.
@user-oi9vo7xk4x
@user-oi9vo7xk4x 3 месяца назад
По поводу 8. Про void это не конкретно шарпа беда, а вообще всех языков, генеалогическм восходящих к Си. Поэтому в си возвращают 0, что значит, что процедура выполнена успешно.
@Kitulous
@Kitulous Год назад
30:00 а ещё я в райдере когда копирую файл с классом, вставляю, меняю ему имя, и оно не меняет имя класса внутри! и его приходится менять в двух местах!
@DevJungles
@DevJungles Год назад
Ага
@Alex-qt9oo
@Alex-qt9oo Год назад
спасибі за роботу. А можна приклад як навчити DI створювати об'єкти як в топовій проблемі 🙃🙃🤗🤗
@DevJungles
@DevJungles Год назад
Буде відео. У травні, сподіваюсь)
@user-zf7ue6uv9d
@user-zf7ue6uv9d Год назад
Немалую часть проблем фиксят линтеры и копайлот. Лично мне не нравится, что когда у меня есть интерфейс с синхронным методом, я подключаю асинхронную реализацию (хз, например перехожу на новую бд, к которой драйвер предоставляет возможность делать асинхронные вызовы), так вот теперь эти таски пронизывают код полностью. Придётся переписать все вфункции, чтобы они работали с тасками. И это прям вымораживает. Какого чёрта вообще моя бизнес логика должна знать синхронный или асинхронный вызов порта она должна вызывать (например в гексагональной архитектуре)? Бл не должна зависеть от инфра уровня. А тут язык подсовывает явную зависимость.
@DevJungles
@DevJungles Год назад
1. Мне кажется, эти проблемы копайлот не фиксит вообще никак. 2. Вполне реально выстроить слой бизнес логики без тасок и асинхронности. В том примере, что приводите судя по всему бизнес логика вызывает слой данных. Это ок в трехслойке, но не ок в гексагональной. Там бизнес модель в центре и не зависит ни от чего.
@rechw769
@rechw769 Год назад
там ещё модификатор доступа file завезли в 11 шарпе)))
@DevJungles
@DevJungles Год назад
Ох.. Точно. Забыл про него. И он еще и со своим особым контекстом применения)
@rechw769
@rechw769 Год назад
@@DevJungles спасибо за контент, делаешь крутейшие ролики)
@MrCommanderKid
@MrCommanderKid Год назад
Чем опытней разработчик тем грандиозней ляпы он совершает.
@DevJungles
@DevJungles Год назад
1000%))
@stanislavsh6582
@stanislavsh6582 Год назад
Ну. Большая часть это не проблемы языка. Но с чем согласен, это с войдом. Войд - это реально боль, если тебе нужно библиотеку для команды делать. Приходится либо одинаковую логику мутить, либо вводить какое-то извращение в духе Unit, Empty, Nothing и всем говорить, что оно есть. И проблема со вторым подходом, в том что шарп начинает ворнинги сыпать, дескать ты результат не используешь, а ну как сделай Nothing _ = Lib.Execute();
@user-tx8lw5ti9m
@user-tx8lw5ti9m Год назад
На счёт 8го места. Видел затычку с классом Void с приватном конструктором, а методы с таким типом просто возвращают null
@DevJungles
@DevJungles Год назад
Ага В MediatR том же для этого есть Unit.Value
@sanphir
@sanphir Год назад
я таки вырезал кусок про войд😁
@DevJungles
@DevJungles Год назад
Для использования на закрытых лекциях по философии?)))
@sanphir
@sanphir Год назад
@@DevJungles ага, послал друзьям философам, выразили респект )
@user-gi4qu9do2v
@user-gi4qu9do2v Год назад
Для топ 1 возможно **args из питона подойдут, но лучше без них))
@vasiliylu8054
@vasiliylu8054 Год назад
А можно топ1 решить аннотациями, например добавить property в базовый класс с аннотацией [Inject]. Если что, я не настоящий волшебник....
@DevJungles
@DevJungles Год назад
Да, есть что-то вроде этого. В целом со свойствами get/init и модификатором required получается достаточно хорошо.
@vc36960
@vc36960 Год назад
Открой для себя Nemerle. В нем в 2006м недостатков было меньше чем в C# в 2023м.
@DevJungles
@DevJungles Год назад
Самое забавное, что я даже знаю это название и даже видел его сорсы и полтора проекта на нем где-то в 18м году) Но уже тогда, увы, и язык и проекты были заброшены
@vc36960
@vc36960 Год назад
@@DevJungles А я его до сих пор поддерживаю. 🤫
@daitedve1984
@daitedve1984 Год назад
"главная проблема №1" - пустой каприз и я бы даже сказал дилетантство. Если ты так смело хочешь залезать в базовый класс и чтобы потомки ничего не заметили, ты явно ошибся методологией - тут один пусть, в Бейсик. 😆 Базовый класс ОБЯЗАН ломать потомков, ибо так и задумано: если ты что-то изменил в предке, значит потомки уже не могут рассчитывать на прежнее поведение и должны сами измениться. Просто представь современный автопром: базовая конструкция моделей ОДНА, а сверху нахлобучивается купе, седан и т.п. И тут бравый анжанер удлинняет колёсную базу. Как думаешь, модели не заметят этих изменений? :)
@DevJungles
@DevJungles Год назад
Не согласен) У нас есть очень много способов изменить базовый класс так, что бы не сломать наследников. Проблема из жизни: есть абстрактный репозиторий с большим количеством методов. Есть около 40 наследников. Все создаётся лишь через DI. Что бы реализовать новый метод в базовом репозитории мне нужна ещё одна зависимость: что-нибудь инфраструктурное. Она уже лежит в DI. Мне нужно добавить ее в конструктор и все готово было бы... ...но нет, нужно ее ещё добавить в 40 наследников 😭
@ivanzrobok7148
@ivanzrobok7148 Год назад
25:48 думаю кто можно было отойти, создав ещё один пустой не дженерик интерфейс, и наследовать его от дженерикового, и уже в is проверять на не дженериковий интерфейс
@DevJungles
@DevJungles Год назад
Да да Я это и предлагаю в варианте обхода, но оно проблему полностью не решает, если нужно работать с объектом дальше
@anderwafe
@anderwafe Год назад
23:20 всмысле 6 модификаторов? а file?))
@DevJungles
@DevJungles Год назад
Да да!) Забыл его
@nztzn
@nztzn Год назад
Відносно першого місця, можна засетити дефолтом значення в null: (SomeType sometype, IMapper mapper = null)
@DevJungles
@DevJungles Год назад
Але ж він тоді для спадників так і залишиться null(
@vc36960
@vc36960 Год назад
Третья претензия вообще чистон непонимание. Что будем делать вот тут? class A : IX, IX Что тут даст is IX ?
@DevJungles
@DevJungles Год назад
Ну во-первых true)) А во вторых действительно не подумал, что в этом случае вывести тип не выйдет никак(
@vc36960
@vc36960 Год назад
@@DevJungles Для is вывод и не нужен. Но есть проблемы с тем, что дальше делать с этим знанием и с эффективностью реализации подобного оператора. А вообще универсальным решением были бы макры или пользовательские расширения языка. Тогда каждый мог бы написать библиотеку своих расширений и жить удовлетворённым.
@DevJungles
@DevJungles Год назад
Есть сорсген, но это не совсем то...
@vc36960
@vc36960 Год назад
@@DevJungles Совсем не то, точнее будет сказать.
@Fr0stick
@Fr0stick Год назад
Знаешь почему синтаксис switch такой? Потому его решили перенести один в один с Rust😂
@user-zj4jv5vv8r
@user-zj4jv5vv8r Год назад
Уже лет десять прогаю, даже половины из сказанного не использовал.
@daitedve1984
@daitedve1984 Год назад
"На каждом языке можно писать как на Бейсике!" (ц) кто-то-великий 😆 Оно и к лучшему - проще код - проще сопровождение или портирование.
@DaniilK-hq5go
@DaniilK-hq5go Год назад
Новый C# это Kotlin, расходимся
@denys-p
@denys-p Год назад
Синтаксис свича, кстати, реально противный и не очень понятно почему его сделали таким. Я его до сих пор толком не помню и приходится гуглить
@srvr4vr
@srvr4vr Год назад
его делали так по аналогии с F#, но там он добрый и ласковый друг, а здесь какой-то огузок, но выручал меня пару раз в связкой с ValueTupple может отлично заходить в некоторых ситуациях.
@joresso
@joresso Год назад
Занимался написанием компилятора для API одной системы... И пришла мысль что просто так проще компилятор реализовать, отличается порядок лексем. Отлично же, меньше возвратов назад делать, быстрее компиляция
@ak_nex
@ak_nex Год назад
Из относительно новинок ещё можно вспомнить проверку на null через is (pattern matching), а не == Способ через is рекомендуется самим майкрософтом, чтоб случайно не попасть на переопределение оператора == И всё было бы хорошо, если б этот is работал везде. На текущий момент его нельзя использовать в expression-ах (в отличие от лямбд, что дико путает). Т.е. во всех linq-выражениях на is будет ругаться... По итогу в коде получается сборная солянка, а ты постоянно натыкаешься на ошибку от IDE в linq... 🤬
@daitedve1984
@daitedve1984 Год назад
"чтоб случайно не попасть на переопределение оператора ==" - какой идиот придумал обходить переопределение операторов?!!? Их СПЕЦИАЛЬНО ПРИДУМАЛИ, чтобы глупый канпелятор знал, как ПРАВИЛЬНО сравнивать объекты.
@DevJungles
@DevJungles Год назад
Я уже в одном видео хорошенько прошёлся по паттерн матчингу как раз))
@wizzardTrololo
@wizzardTrololo Год назад
Ну что, опять НЛП в действии, позавчера ревьювил проект где ребята как раз Queryable передали в метод который принимает IEnumerable:)
@DevJungles
@DevJungles Год назад
Я очень плотно влез в реальность 🤪🤪🤪😜
@Sergio-jg4pr
@Sergio-jg4pr Год назад
я думав, що я один такий не можу запам'ятати switch expression)
@DevJungles
@DevJungles Год назад
Нііі) Нас таких купа
@user-qq9hw2cz6l
@user-qq9hw2cz6l Год назад
@@DevJungles да сих пор без подсказок среды не напишу. Но не согласен и с нападками, и представленными альтернативами. Дело в том что, switch как выражение, может, много больше по сопоставлению кейсов чем стандартный switch, и поэтому варианты из других языков не кажутся вдохновляющими. И естественно он должен вернуть что-то , когда ничего не совпало. Почему там _ , а не default -- загадка.
@user-dw1mv4vx5r
@user-dw1mv4vx5r Год назад
Сравниваю с котлин. 1. Проблема 10 - нету в таком виде, в перекрытых классах нельзя ставить дефолты 2. Проблема 9 - и есть и нет, да можно не то расширение вызвать, но нет идеи query able для внешних вызовов. Но проблема рантайма зато есть. Проблема есть и даже хуже но не из за языка, а jvm, jar с одинаковыми классами 3. Проблема 8 - нету, Unit (void) это тип 4. Проблема 7. - нету так как благо нет понятия событий 5. Проблема 6. - нету свитч (when) сразу был выражением, и не требуется break, как в golang, по умолчанию брек. 6. Проблема 5. - нету, вывод типов умеет из параметров выводить 7. Проблема 4. - другая, мне совсем не нравится, что в котлин по дефолту паблик, я бы предпочёл приват. Но дефолт тем не менее всюду один 8. Проблема 3. - другая, тоже сложности с апкаст можно сделать, зато рефлексия в куче контекстов не сработает ибо type erasure, генерики мне чуть больше в шарпе нравились, но правда хаки со звёздочкой там не работают 9. Проблема 2. Нету, явное ключевое слово constructor + init. Но в целом я предпочитаю приватные конструкторы и факторки в компаньонах 10. Проблема 1. Такая же. Специфика модели классов которая у джавы и Шарпа почти одна. Поэтому стараюсь меньше наследования, больше композиции, меньше конструкторов, больше фабричных методов
@DevJungles
@DevJungles Год назад
Потрясающий комментарий! Спасибо за подробный ответ: всего несколько раз смотрел Котлин. Но он доказывает, что мы не стоим на месте: были ошибки, мы(как индустрия разработки) их исправили.
@DevJungles
@DevJungles Год назад
На то чтобы составить такой же топ по котлину уйдет едва ли не десятилетие и, вероятно, список выйдет менее бесячис
@user-dw1mv4vx5r
@user-dw1mv4vx5r Год назад
Языки это ещё и рантайм под капотом. Например Kotlin основной и любимый собственно как язык уже 6 лет. Но JVM и джавовская экосистема которая у него под капотом такая мерзкая, что активно для новой разработки переходим на голанг, который как язык по примитивнее, зато всятэкосистема прямо очень хорошая. Не языком единым...
@IQ-120
@IQ-120 Год назад
погоди, а если базовый класс унаследовать от типа передаваемого аргумента и не передавать этот аргумент... как вариант... не утверждаю...
@DevJungles
@DevJungles Год назад
Базовый класс от типа передаваемого аргумента?.. Звучит как что-то очень странное))
@IQ-120
@IQ-120 Год назад
@@DevJungles да, туплю - это интерфейсы, их реализовывать придется. Хотя, можно, протыкать - может, там - просто... Найти реализацию IMapper и от нее унаследоваться... Хз, мысль, просто пришла...
@alexb.9806
@alexb.9806 Год назад
по поводу конструкторов -- наследование зло)) даже если ты и заюзаешь предложенный воркараунд, это не решает главную (и по факту единственную) проблему -- ты всё равно поменял поведение 50ти наследников, только теперь ты об этом скромно умалчиваешь в своём PR. не надо так делать. если зависимость какая-то опциональная, то можно поменять абстрактный класс на интерфейс с дефолтными реализациями и туда докинуть приватный геттер с дефолтной реализацией возвращать какой-нибудь стаб или нулл, а дальше уже по контексту. энивэй, сама по себе проблема больная, но она больная не просто так.
@DevJungles
@DevJungles Год назад
В целом согласен, но... Но у нас уже есть очень много способов более серьезно изменить поведение наследников и не сообщить об этом в PR: изменение тела базового виртуального метода, например. А вот опциональные зависимости меня обычно тоже довольно сильно пугают... В этих случаях мне скорее хочется решить это: - в идеале композицией - хотя бы наследованием.
@user-px7lr3wf3k
@user-px7lr3wf3k Год назад
тоже с топ 1 не согласен, предлооженное решение еще и приведет к созданию GodObject с кучей всякой нужной и не очень херней внутри, и там зависимости и использование вообще хер найдешь. у меня в одном рефаторинге пришлось поменять по этой схеме много конструкторов, но только благодаря их явному изменению Я смог заметить другую прблему, что в многие классы добавлялись вообще не нужные им зависимости просто потому что этого требовал базовый класс. в итоге было найдено кривое наследование.
@DevJungles
@DevJungles Год назад
Не понял как это приведет к созданию God Object. Кривые иерархии действительно бывают, но обычно их и видно из далека)
@user-px7lr3wf3k
@user-px7lr3wf3k Год назад
@@DevJungles может привести если начнут пихать в класс все подряд, типа "удобно же" и тогда есть шанс появления класа который будет в себе содержать резолв всех зависимостей и его будут пихать везде. тогда может быть уже сложно понять какие из зависимостей где используются. по сути получится внедрение репозитория зависимостей
@edwardfreedom
@edwardfreedom Год назад
зачем писать два минуса? --
@mideks
@mideks Год назад
Я нашёл для себя, что 3 "самых худших момента", мне были уже знакомы и я так или иначе с ними сталкивался 🤯 Ну и остальные по мелочи знакомы были, хы. Я шо профи?
@DevJungles
@DevJungles Год назад
Именно! Добро пожаловать в клуб)
@mideks
@mideks Год назад
@@DevJungles но я начал в c# первые шаги(до этого другие языки были) делать всего чуть больше года назад😅
@Timyrlanchik
@Timyrlanchik Год назад
Проблема №1 реально боль, но предложенное решение - это антипаттерн "God object". Нет, это не решение) Продолжаю страдать...
@DevJungles
@DevJungles Год назад
Почему God Object? Это же по объекту аргументов на каждый класс. Единственная задача: поддерживать аргументы.
@Timyrlanchik
@Timyrlanchik Год назад
@@DevJungles Наверное потому, что у меня был опыт работы на одном из проектов с таким объектом , который содержал в себе сотню полей, всегда частично заполненных, и ты никогда не знал, какие именно будут заполнены. Это был ад адский. Видимо, я получил психологическую травму, от которой так и не оправился))) Снизить поражающий эффект этого антипаттерна можно, если все поля будут обязательны, инициализироваться через конструктор, рид онли. Тогда, по крайней мере, ты будешь знать, глядя на этот, тасказать, ДТО, что от него ожидать. А что делать, если у тебя сложная иехархия базовых (абстрактных) классов (а у меня на текущем проекте именно так), делать еще один gob? и сколько их будет? В целом это системная проблема, которая говорит о том, что что-то сильно не так в королевстве Датском Для себя решил, что лучше терпеть эту боль, но следовать шаблону DI
@DevJungles
@DevJungles Год назад
Я может не слишком хорошо сформулировал идею... Идея для каждого класса с множеством аргументов в конструкторе делать отдельный класс аргументов. Если есть иерархия, то повторять ее в этих классах аргументах. Все отмечать required { get;init; } Здесь в самом конце видео еще раз к этому возвращаюсь как раз: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-euZvNDFwTQ8.html
@pfff-doh
@pfff-doh Год назад
Зачем слайды на английском? %) И вы похоже упорный девелопер - спеллчекер пытался направить на путь истинный, подсвечивая "Finilizer", но не смог победить :D Ну и "mension" тоже
@DevJungles
@DevJungles Год назад
С mension, если честно, прямо стыдно стало, когда допер(
@denys-p
@denys-p Год назад
Занудничаю: «упоминание»: Mention, не Mension
@DevJungles
@DevJungles Год назад
Вот это я опозорился( При том из-за того что есть слово mension(усадьба, поместье), то мне даже орфочеккер не ругнулся 😔😔😔 Спасибо за замечание!
@denys-p
@denys-p Год назад
@@DevJungles а поместье - Mansion 😁
@user-gi4qu9do2v
@user-gi4qu9do2v Год назад
Тема недоделаных дженериков раскрыта не до конца. Стандартные коллеккции не реализуют коваринтность, нет нормальной контрваринтности типа возвращаемого значения в реалилизциях методов базового класса. Нельзя сделать where T is SomeAbstractClass - нужно для SomeAbstractClass делать интерфейс ISomeAbstractClass. В джаве это реализовано гораздо лучше. Благо на бэкенде магия джеренриков нужна очень редко.
@DevJungles
@DevJungles Год назад
Не соглашусь... Давненько видел джаве, но тогда там дженерики меня прямо ужасали. Там не было generic constaints(может добавили?) и не было возможности сделать Generic от value-type: ArrayList, а только от Integer(который ref-type)
@IgorTkachev
@IgorTkachev Год назад
Объяснение 9 невнятное, запутанное и не объясняет происходящее. А так видос зачётный.
@DevJungles
@DevJungles Год назад
Может не слишком хорошо объяснил где-то местами...
@IgorTkachev
@IgorTkachev Год назад
@@DevJungles В данном примере переполнения памяти не будет. Данные не будут все ЗАкачаны в память, а будут ПРОкачены через локальный компьютер, но при этом фильтр хоть и локально, но работать будет. А вот если бы в примере был OrderBy или GroupBy, то все описанные страшилки случились бы.
@alexandrsharp920
@alexandrsharp920 Год назад
как создать обобщенный класс )) обобщенный метод можно
@DevJungles
@DevJungles Год назад
Создать то класс можно... А во создать экземпляр такого класса... Сиди и перечисляй все в конструкторе(
@alexandrsharp920
@alexandrsharp920 Год назад
@@DevJungles в моем случае у класса есть пустой конструктор
@godfather7695
@godfather7695 Год назад
"Современные" языки не проще, они еще просто не столкнулись с теми проблемами, с которыми уже десяток лет сталкиваются разрабы. Ваше утверждение как слова Бендера из футурамы про казино.
@DevJungles
@DevJungles Год назад
Да. Главная проблема в этом плане: просуществовать в мейнстриме лет 20-30
@valiantsinm
@valiantsinm Год назад
Ну, на самом деле многие ситнтаксические особенности C# унаследовал от C++, как это ни странно. Подозреваю, что бы облегчить переход первым девелоперам с С++ на C#. Да, как показывает практика, такой подход больше навредил чем помог. Но когда ты создаёшь новыя ЯП с нуля в условиях жесточайшей конкуренции с Java, который уже является отраслевым стандартом, то максимально простой переход девелоперов на этот язык является чуть ли не основным требованием.
@DevJungles
@DevJungles Год назад
На самом деле в первой версии видео даже была эта мысль. Но она осталась на "монтажном столе": там много других мыслей было сформулировано хуже. Но при перезаписе эту как раз потерял(
@daitedve1984
@daitedve1984 Год назад
Причём тут вообще сипипи? Ты историю C# вообще знаешь?
@valiantsinm
@valiantsinm Год назад
@@daitedve1984 А ты читать умеешь? Я же написал про синтаксис. С# относится к семейству языков с C подобным синтаксисом. И все этик конструкторы и деструкторы (которые на самом деле финализаторы т.к. сборщик мусора) они прямиком оттуда. Что бы при переходе между языками разработчики могли использовать привычные им паттерны при написании кода.
@nooftube2541
@nooftube2541 Год назад
Я конечно понимаю прикол 42, но возвращайти пожалуйста просто дефолт в таких случаях.
@DevJungles
@DevJungles Год назад
Это же демки, а не продакшн код)
@nooftube2541
@nooftube2541 Год назад
@@DevJungles знаю я как демки потом лежат по 10 лет в продакшене 😂 У нас в каких то тулзах в качестве успешного кода возвращается год рождения автора.
Далее
Flo Rida - Whistle НА РУССКОМ 😂🔥
00:29
Просмотров 904 тыс.
Middle/Strong Junior .NET Developer Job Interview
1:47:10