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

Поделиться
HTML-код
  • Опубликовано: 24 авг 2024

Комментарии • 256

  • @rogiawos8737
    @rogiawos8737 Год назад +66

    Чел, хорош , контент вообще в кайф!! Можно вот этого вот всего почаще❤❤❤

    • @K1llRay64
      @K1llRay64 Год назад +6

      с языка)) всем маслятам маслят )))

    • @tyomios
      @tyomios Год назад +5

      Вы перепутали канал)

  • @MrNachosVIDEOS
    @MrNachosVIDEOS Год назад +19

    Замечательное видео)
    Внесу свою лепту (как человек что много лет пишет на чистом С/Ассемблере, а сейчас пишу этот комеет как С# фулстек)
    1) модификаторы доступа - это годнота. Если не нужно, то не используешь "лишнее". У С\C++ вместо internal вообще static (это при том, что там есть external)
    Я выступаю за то, чтобы был максимально гибкий контроль за областью видимости, потому как много раз видел, как сужение области видимости просто "схлопывает" тонны кода на выхлопе компилятора. И таких инструментов, которые несут смысл как для программиста, так и для компилятора очень мало, если так подумать
    2) Мне очень нравится, что вложенные типы видят приватные поля тех, что выше по иерархии. Благодаря этому можно очень красиво делать реализации Строителей.
    Если делать как по науке, то нужно подводить желаемый тип под интерфейс, в котором можно менять значения полей. И сам интерфейс хорошо бы спрятать, чтобы уши не торчали... а так, вложил один тип в другой и всё готово. Потому как руки всё равно потянтся проверить, а не будет ли у типа фабричного метода, если конструктор приватный
    Про путаницу с модификаторами доступа по умолчанию -- полностью солидарен
    3) Дженерики - это прям беда. Столько раз себя ловил на мысли, что это какой-то кастрат плюсовых шаблонов, что аж неловко становилось
    Они ну слишком базовые. Есть попытки в метапрограммирование (те же where и всякие контр/ко/ин-вариантности), но пользоваться ими очень неудобно, когда нужно работать с иерархией этих типов
    Спасаемся базовыми типами, как и было упомянуто в видео)
    Но лично моя боль №1 -- поведение структуры с интерфейсами
    Это прямо дичь. Моментально рушится вся идея строго значимого типа. Плюс к тому очень много странных ограничений (нельзя давать полям значения по умолчанию, вне конструктора без аргументов, но как только ты этот самый конструктор определяешь, то ты рушишь целую вереницу оптимизаций, что заботливо для тебя выстроили авторы языка)
    А те же readonly ref struct я смог применть только в паттерне итератор. И работает это только из-за костылей с утиной типизацией... вне этого как только у тебя появляется хоть маломальски выстроенная иерархия типов и ты хочешь внести "перформанса" , то ты быстро обнаруживаешь, насколько же у тебя связаны руки. Либо рефлексия, либо переписывать всё в совсем другой парадигме
    Я бы добавил интерфейсу гарантию, что он представляет только значимый тип (с синтаксисом для такого поведения).
    По сути легальный и чистый способ для утиной типизации
    С# получился очень удобным прикладным языком
    И он может решать целый спектр задач
    Потому его сейчас как лебедь/рак/щука тянут в сторону обратной совместимости, рядом новые и модные практики с функциональщиной, а особняком системные программисты, которым нужон High Performance
    Ещё раз выражаю благодарность за видео и труд!
    Смотрю тебя с большим удовольствием)

    • @DevJungles
      @DevJungles  Год назад +3

      1.2. согласен)
      3. Я вот и рад, что не стали брать шаблоны из плюсов целиком: уж очень они сложны, но то, что затянули явно недостаточно, это тоже факт

  • @ppc2012
    @ppc2012 Год назад +16

    Хаха, я смог заполнить switch expression. Буквально всего то пара лет прошло) Теперь осталось запомнить синтаксис его паттерн матчингов.

    • @DevJungles
      @DevJungles  Год назад

      О дааааааа....
      На канале, кстати, есть ролик про pattern matching... Я там тоже немного горю от синтаксиса)

  • @user-jd2kx9nb1t
    @user-jd2kx9nb1t Год назад +56

    Мне пришлось перейти с C# на Java, ребят. Как же вы счастливы, ребят, вы не понимаете, насколько C# кажется прекрасным после перехода на джаву!

    • @DevJungles
      @DevJungles  Год назад +3

      О дааа! Помню на первой работе иногда нужно было лазить в сорсы ANTLR, а он на старехонькой Java. И я прямо страдал без var и LINQ... Но это и была совсем старая Java..

    • @valiantsinm
      @valiantsinm Год назад +3

      В Java самая попоболь это отсутствие единого стандарта. Всякие там спринги, груви и прочий заопарк. 90% процентов Java чатика на проекте забито вопросами типо "вот я обновил версию библиотеки с х на y и вот тут у меня всё сломалось" или "взял последнюю версиюю исходников из репозитория и уменя всё сломалось". И вот когда видишь советы типа "надо взять вот эту весию либы X и вот эту версию либы Y. а вот этот код откатить/закоментить/переписать" волосы на голове шевелятся.

    • @pfff-doh
      @pfff-doh Год назад

      зачем вообще жаба, если есть котлин

    • @daitedve1984
      @daitedve1984 Год назад

      Жаба - лютое говнищще из прошлого века, зачем на него переходить?? Котлина мало что ли?

    • @user-jd2kx9nb1t
      @user-jd2kx9nb1t Год назад

      @@ruslooob лямбды, не умеющие менять значения переменных, недогенерики, отсутствие await, операторы перегружать нельзя, поэтому упаси вас бог создавать через new и сравнивать стринги через ==, прекрасное совершенно поведение типа long с недооптимизацией, странные моменты с уборкой мусора, и т.д., всего не упомнишь. Больше всего конечно трогают лямбды, await и недогенерики, 2023 год на дворе, остальное реже.

  • @gnchrtd
    @gnchrtd Год назад +8

    Ух, про switch прямо в точку. Помню сходил на неделю в отпуск и напрочь забыл его синтаксис. Дело было года два назад, когда он только входил в обиход.
    По части модификаторов доступа - там еще file завезли) а где internal, там и InternalsVisibleTo, так сказать)
    P.S. На фразе «С деструктором все еще хуже. Во-первых, он у нас… есть» заржал и подавился своим смузи

    • @DevJungles
      @DevJungles  Год назад

      😁😅😅😅

    • @endemic3401
      @endemic3401 Год назад

      Читаешь такой книжочку/статейку по сишарп, встречаешь слово "деструктор", реакция: "А, че? точно.."))

  • @daitedve1984
    @daitedve1984 Год назад +3

    "главная проблема №1" - пустой каприз и я бы даже сказал дилетантство. Если ты так смело хочешь залезать в базовый класс и чтобы потомки ничего не заметили, ты явно ошибся методологией - тут один пусть, в Бейсик. 😆 Базовый класс ОБЯЗАН ломать потомков, ибо так и задумано: если ты что-то изменил в предке, значит потомки уже не могут рассчитывать на прежнее поведение и должны сами измениться.
    Просто представь современный автопром: базовая конструкция моделей ОДНА, а сверху нахлобучивается купе, седан и т.п. И тут бравый анжанер удлинняет колёсную базу. Как думаешь, модели не заметят этих изменений? :)

    • @DevJungles
      @DevJungles  Год назад

      Не согласен)
      У нас есть очень много способов изменить базовый класс так, что бы не сломать наследников.
      Проблема из жизни: есть абстрактный репозиторий с большим количеством методов. Есть около 40 наследников.
      Все создаётся лишь через DI.
      Что бы реализовать новый метод в базовом репозитории мне нужна ещё одна зависимость: что-нибудь инфраструктурное. Она уже лежит в DI. Мне нужно добавить ее в конструктор и все готово было бы... ...но нет, нужно ее ещё добавить в 40 наследников 😭

  • @user-fy3dv8em6o
    @user-fy3dv8em6o 3 месяца назад +1

    1.
    В С++ если констуктор наследника будет по аргументам повторять базовый + без тела (только вызов конструктора базового класса), то можно написать внутри класса наследника
    class Derived : public BaseClass {
    using BaseClass::BaseClass;
    }

    • @DevJungles
      @DevJungles  3 месяца назад

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

    • @user-fy3dv8em6o
      @user-fy3dv8em6o 3 месяца назад

      @@DevJungles да, это уже не сработает, но в видео было так, что набор аргументов одинаковый)

  • @user-zd6di5mq9z
    @user-zd6di5mq9z Год назад +1

    Не знал о некоторых проблемах даже, повезло-повезло.
    Спасибо, интересный формат!

  • @hel2x
    @hel2x Год назад +4

    Невероятно интересный видос. Большое тебе спасибо ❤

  • @EugeneS88-RU
    @EugeneS88-RU Год назад +2

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

  • @WisdomHacks
    @WisdomHacks Год назад +1

    Очень интересно! Спасибо)

  • @Speed-Run-Facts
    @Speed-Run-Facts Год назад +1

    Крутое видео)

  • @user-qp8bt7gq4b
    @user-qp8bt7gq4b Год назад +1

    Крутое видео. Спасибо за воркэраунды для некоторых проблем!

  • @denys-p
    @denys-p Год назад +3

    У меня как-то было веселье с перегрузкой методов. Уже не помню деталей, но идея была в том что было 2 версии метода и одна принимала энум, а вторая инт. В итоге я передаю энум, а вызывается версия с интом.

  • @redice8928
    @redice8928 Год назад +1

    очень хорошее видео, благодарю за труд

  • @independentexpert8349
    @independentexpert8349 Год назад +1

    я десь рік тому стикнувся з 10-ю проблемою, тоді теж мало не здурів і майже постарів на 50 років поки дебажив, в кінці в мені щось перегоріло і я просто змирився що це так не працює, розбиратись в причинах вже не було ні часу ні моральних сил, просто переробив і забув.
    Ти зараз прям витяг на "світ божий" коварне зло приховане в пітьмі, яке паскудить життя багатьом.
    Вважай - ти рятуєш людям нерви і час для чогось більш прекрасного, так тримати👍

    • @DevJungles
      @DevJungles  Год назад

      Крутий комент)
      Радий, що відео сподобалося)

  • @nanvlad
    @nanvlad Год назад +1

    Добротний відос. Тепер по пунктах
    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  Год назад

      Дяка за крутий і розгорнутий комент)

  • @user-oi9vo7xk4x
    @user-oi9vo7xk4x 4 месяца назад

    По поводу 8. Про void это не конкретно шарпа беда, а вообще всех языков, генеалогическм восходящих к Си. Поэтому в си возвращают 0, что значит, что процедура выполнена успешно.

  • @user-qq9hw2cz6l
    @user-qq9hw2cz6l Год назад

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

    • @DevJungles
      @DevJungles  Год назад

      Проблемы начинаются если есть взвешенные значения)
      Не понятно: как получить все, какое именно ты получил итд.

  • @alvkn
    @alvkn Год назад +2

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

  • @native-nature-video
    @native-nature-video Год назад +1

    Имхо косяк #1 - это неудобство отписки от ивентов. Особенно с анонимными методами

    • @DevJungles
      @DevJungles  Год назад +1

      Мне кажется мы их слишком редко используем последнее время, чтобы это было проблем.
      Все меньше и меньше АПИ работают с ивентами.

  • @native-nature-video
    @native-nature-video Год назад +1

    Спасибо за видос!!!

  • @ever-modern
    @ever-modern Год назад +1

    про 9: Правильным решением будет использование асинхронных методов у IQueryable. У IEnumerable таких нет.

    • @DevJungles
      @DevJungles  Год назад

      Не совсем так.
      WhereAsync, SelectAsync нету и там. Там есть лишь "финализирующие" методы... SingleAsync, ToListAsync итд

  • @ka4ep
    @ka4ep Год назад +2

    Кому как, у меня каждый раз болят дженерики из 3-го места, ну и с ними всё время паровозиком идут массивы из 1-го места. Это массив, список, словарь, как их понимать? И каждый раз либо изобретаешь с нуля, либо тащишь свою библиотеку с решением. Создаёшь в каждой библиотеке модуль Autofac, автоматчески регистрируешь вот это всё... а под капотом боль от "а класс реализует дженерик интерфейс", а "интерфейс наследует этот дженерик интерфейс"? А атрибут? А как из этого безобразия создать инстанцию?... 🤯

    • @DevJungles
      @DevJungles  Год назад

      Массивы были всего лишь в упоменаниях)

  • @HOSTRASOKYRA
    @HOSTRASOKYRA Год назад

    Дуже дякую. Корисне відео. Реквест на налаштування статичних аналізаторів. Тільки в студії, а не в цих ваших джетбрейнах!

    • @DevJungles
      @DevJungles  Год назад +1

      А там нащастя як MS став розвивати команд лайн і compiler as a service, воно стало більш-менш універсально, бо працює рівнем нижче за IDE

  • @user-ll2fo1vf2n
    @user-ll2fo1vf2n 10 месяцев назад

    Проблему с 1 места мне доводилось решать похожим способом, но со временем я понял, что лучше будет сделать отдельный класс RepoMappedEntittiesBase, который собственно и добавляет новый функционал и будет требовать уже для новых наследников передачу нужных данных. Тем самым мы и не нарушаем Open-Closed принцип.
    Как по мне оба подхода имеют смысл, т.к. все зависит от контекста того, какие изменения вы планируете внести.

    • @user-ll2fo1vf2n
      @user-ll2fo1vf2n 10 месяцев назад

      Из всех перечисленных моментов, считаю худшими только с 10 места.
      Довольно часто сталкивался с проблемой из 7 места, из-за которой приходилось писать кучу костылей, однако спасибо тебе за её решение, ведь действительно запомнить disposables при подписке упрощает решение этой проблемы.

    • @DevJungles
      @DevJungles  10 месяцев назад

      Немного запутался в обоих Ваших комментариях, если честно.

  • @joresso
    @joresso Год назад +1

    Обычно с коллегами обсуждаем новые фичи... и часть просто не используем))) чтоб не бесили. Как в шутке - "если вам не нравятся гейпарады, прекратите в них участвовать"

    • @DevJungles
      @DevJungles  Год назад

      Обычно, если команда большая, то провернуть такое довольно сложно)

  • @GamDevRus
    @GamDevRus Год назад +1

    Крут!!!

  • @user-pn9rm2xr7x
    @user-pn9rm2xr7x Год назад +1

    На счёт конструкторов: можно сгенерировать пачку паршл классов в которых определяется конструктор. Либо иньектить зависимости в свойства. Ну а 50 тестов всё ровно придётся изменить.

  • @xjdn-34-gdndnk-45-aa
    @xjdn-34-gdndnk-45-aa Год назад +2

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

  • @64narayan
    @64narayan Год назад +1

    По девятому пункту (IQueryable и IEnumerable): если такая проблема появляется на продакшене, то у вас большие проблемы с тестированием своей работы и язык тут не при чем. Подобные проблемы у вас будет при использовании любого языка

    • @DevJungles
      @DevJungles  Год назад

      И с одной стороны я согласен, но с другой это лишнее место, где частые ошибки случаются. Язык или API могли быть задизайнены чуть иначе.

  • @pispis3617
    @pispis3617 Год назад +1

    Чет так заслушался на вступлении, что показалось, что начала какого-нибудь фильма от Гая Ричи)))

  • @endemic3401
    @endemic3401 Год назад +1

    1ое место. Был такой случай на первой самой работе. Был самым зеленым джуном среди сеньоров. И потел каждый раз, когда в процессе багфикса приходилось трогать "то что работает" и было написано опытными программистами. Но в один прекрасный день попался баг, в качестве решения которого, было необходимо добавить в конструктор базового класса некий объект. Как сейчас помню, звоню наставнику и несколько раз уточняю, что "пук среньк надо вот в базу добавить вот это, но там наследование 5> потомков и типа мне надо каждому из них в ктор пробросить этот тип..???" "- Да"....

    • @DevJungles
      @DevJungles  Год назад

      Дада)
      Первое место прямо в самое сердечко.
      Где-то пол года выписывал проблемы для этого видео. За это время сам в работе столкнулся с проблемой раза 4

  • @denys-p
    @denys-p Год назад +4

    А первая проблема у меня чаще решается практически полным отсутствием наследования, если честно. Если там какая-то общая логика, то её можно вывести в какой-нибудь класс-хелпер.
    С наследованием в принципе очень легко отстрелить себе ногу не в одном месте, так в другом.
    Была весёлая история, когда переопределили то ли Equals то ли GetHashCode в базовом классе сущности и у нас то ли работа с базой, то ли какие-то вычисления взорвались от этого в совсем другом месте

    • @alexlightweight
      @alexlightweight Год назад +6

      " у меня чаще решается практически полным отсутствием наследования, если честно." сейчас тебе мамкины архитекторы и мамкины тимлиды накидают г...внеца на вентилятор в комментах )))
      А если серьезно, то я согласен, лепить где попало наследование что бы казаться умным бред, его надо применять там где действительно есть общая логика которую копипастить не стоит в классах, но любителей что то поменять в базовом классе всегда можно ткнуть носом в SOLID, а точнее в Open/Closed, но на практике лучше конечно применять наследование там где это РЕАЛЬНО нужно, а не потому что "мы же умные программисты".
      Последнее время вообще наблюдаю тенденцию что сейчас код пишется не для решения бизнес задач, а для применения паттернов, архитектур, "умных идей из книжек" и т.д., то есть сейчас не принято думать при написании кода, главное написать код "поумнее" и главное чем сложнее тем лучше, что бы не выглядеть идиотом, потому что забыли про главный принцип программирования KISS, который я считаю поважнее будет чем SOLID и ООП вместе взятые. )))

    • @user-kk7ib8hu3v
      @user-kk7ib8hu3v Год назад

      ну да, ну да, особенно на 10 летних проектах вообще нету наследования, и статиков и классов на 10000 строк)

    • @denys-p
      @denys-p Год назад

      Ну, там где классы по 10000 строк, там поможет только мучительный рефакторинг или переписывание начисто

    • @DevJungles
      @DevJungles  Год назад +1

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

    • @alexlightweight
      @alexlightweight Год назад +2

      ​@@DevJungles да, согласен, 1 уровень, максимум 2 это норм. У нас в проекте TL является "архитектурным астронавтом" (загуглите термин кому интересно что это за тип программистов), так вот у нас иерархия в 20-30 бессмысленных классов, черт ногу сломит, а главное что необходимости в этом вообще нет, но у нас в конторе главное написать "код позамудренее" и чем больше он непонятный и сложный тем ты круче.
      Так что согласен с @Dev Jungles - Andrii Podkolzin на все сто процентов, 1 уровень вообще идеально, 2 допустимо но нужно точно иметь на это обоснование. 🙂

  • @mudrecsalimkhanov329
    @mudrecsalimkhanov329 Год назад +1

    Хорошее видео, Новый switch case конечно же это ужас. + в последних версиях шарпа очень много сахара, это не очень радует.!

  • @DjonNIK777
    @DjonNIK777 Год назад +1

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

    • @DevJungles
      @DevJungles  Год назад +1

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

    • @DjonNIK777
      @DjonNIK777 Год назад

      Диалог да, а когда фактически изменил конструктор (или любой другой метод), то прям из контекстного меню можно добавить новый параметр во все наследники (или реализации)

    • @DjonNIK777
      @DjonNIK777 Год назад +1

      Кстати, я про IEnumerable/IQuerible всегда факаплю сам, но в приведенном примере еще большее зло - ToList().
      Я даже долгое время думал, что для листа ToList вернет тот же самы инстанц, но в реализации увидел, что всегда создается новый экземпляр

    • @Kitulous
      @Kitulous Год назад

      @@DjonNIK777 уточню:
      когда прописываешь новый аргумент, он выделяется такой белой рамочкой, и если в этот момент нажать Альт+Энтер или какая у вас комбинация для квик фиксов, то там первым пунктом будет применение рефакторинга

  • @vdrmkr
    @vdrmkr Год назад +1

    Новый C# это Kotlin, расходимся

  • @Robit666
    @Robit666 Год назад +1

    На счёт 6го места... default там не впихуемый т.к. в этом случае будет сравнение на значение по умолчанию

  • @Hafune
    @Hafune Год назад +1

    С дженериками конечно боль, особенно после котлина где можно сказать "тут у меня интерфейс с неважно каким дженериком IMyInterface".

    • @DevJungles
      @DevJungles  Год назад

      Да да да!
      Я вот примерно это и хотел бы иметь

  • @vc36960
    @vc36960 Год назад

    Третья претензия вообще чистон непонимание. Что будем делать вот тут?
    class A : IX, IX
    Что тут даст is IX ?

    • @DevJungles
      @DevJungles  Год назад

      Ну во-первых true))
      А во вторых действительно не подумал, что в этом случае вывести тип не выйдет никак(

    • @vc36960
      @vc36960 Год назад +1

      @@DevJungles Для is вывод и не нужен. Но есть проблемы с тем, что дальше делать с этим знанием и с эффективностью реализации подобного оператора.
      А вообще универсальным решением были бы макры или пользовательские расширения языка. Тогда каждый мог бы написать библиотеку своих расширений и жить удовлетворённым.

    • @DevJungles
      @DevJungles  Год назад

      Есть сорсген, но это не совсем то...

    • @vc36960
      @vc36960 Год назад

      @@DevJungles Совсем не то, точнее будет сказать.

  • @alfany6252
    @alfany6252 Год назад +1

    Есть ещё реализация интерфейсов по умолчанию. Когда на это первый раз смотришь вообще мозг ломается

    • @DevJungles
      @DevJungles  Год назад

      О да!)
      Но потом привыкаешь и далее подсаживаешься 😂😂😂

  • @denys-p
    @denys-p Год назад +2

    А в целом - да, вроде косяков хватает, но с многими или вообще не сталкиваешься или они лишь чуточку портят жизнь. А потом садишься за Питон или того хуже Джаваскрипт и стреляешь себе в ногу на пустом месте. Например в Питоне свойства объекта в конструкторе надо писать через self., иначе это будут статические свойства. Я разок так выстрелил себе в ногу.
    Вон стильно-модно-молодёжный Rust из коробки не имеет yield, пользуйтесь библиотеками :( Подозреваю что если пописать на нём подольше, то тоже можно всякого найти

  • @user-zf7ue6uv9d
    @user-zf7ue6uv9d Год назад +2

    Немалую часть проблем фиксят линтеры и копайлот.
    Лично мне не нравится, что когда у меня есть интерфейс с синхронным методом, я подключаю асинхронную реализацию (хз, например перехожу на новую бд, к которой драйвер предоставляет возможность делать асинхронные вызовы), так вот теперь эти таски пронизывают код полностью. Придётся переписать все вфункции, чтобы они работали с тасками. И это прям вымораживает. Какого чёрта вообще моя бизнес логика должна знать синхронный или асинхронный вызов порта она должна вызывать (например в гексагональной архитектуре)? Бл не должна зависеть от инфра уровня. А тут язык подсовывает явную зависимость.

    • @DevJungles
      @DevJungles  Год назад

      1. Мне кажется, эти проблемы копайлот не фиксит вообще никак.
      2. Вполне реально выстроить слой бизнес логики без тасок и асинхронности. В том примере, что приводите судя по всему бизнес логика вызывает слой данных. Это ок в трехслойке, но не ок в гексагональной. Там бизнес модель в центре и не зависит ни от чего.

  • @PsiHamster
    @PsiHamster Год назад +1

    Насчет конструкторов вариантов не особо много, средствами языка сейчас, как вариант, только добавлять вторым конструктором, и вызывать из первого с созданием нужного класса. Но если нужно какую-то зависимость протаскивать, то тут без изменений никак не обойтись.
    Жаль райдер не умеет сигнатуры всех зависимых конструкторов обновлять.
    С языковой конструкцией не хватает какого-то наследования конструкторов, возможно. Так, чтобы если есть класс A с недефолтным конструкторов, то в классе B : A, он сразу был бы доступен, с возможностью переопределения через override.
    Так, если бы в наследниках не было бы специализированных конструкторов, тогда кода пришлось бы меньше лопатить.
    (Но если в наследниках есть дополнительные параметры, то всё равно фигачить придется)
    По-моему тут особо вариантов нет, если появляется необходимость какую-то чувствительную часть кода подергать, то к этому надо быть готовым. Вариант с моделькой с сервисами в приведенном примере считаю перебором. Если у базового класса много зависимостей, которые ещё и часто меняются, и не нужны наследникам, то это скорее всего признаки плохой архитектуры.

    • @DevJungles
      @DevJungles  Год назад

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

  • @antonkaster
    @antonkaster Год назад +1

    11:47 Плачу на этом моменте. Сколько часов было убито в борьбе с этим!

  • @mierce
    @mierce Год назад +1

    Не понятно,но очень интересно)

  • @grant1118
    @grant1118 Год назад +1

    Спасибо за очередное полезное!) Никак не пойму как до такого уровня подняться. Ты не рассказывал про свой путь, что надо сделать? Не поступать в вуз, сразу стартапы, куча пет проектов и потом куча ком. проектов, не жениться (чтобы не отвлекали), с друзьями никуда не ходит и пр. Поделись лайф хаком, очень интересно!)

    • @DevJungles
      @DevJungles  Год назад +1

      Ахахаха))
      Да фиг его: ничего такого вроде не было.
      Мне кажется тут сыграло просто время движения: если 10 лет заниматься разработкой постоянно стараясь узнать что-то новое и сделать что-то новое, без экстрима в плане темпа, но и без длинных пропусков, то все сработает)

    • @grant1118
      @grant1118 Год назад

      Отлично, выглядит как план!) Надо будет такой roadmap и транслировать подрастающим разработчикам.👍

  • @vc36960
    @vc36960 Год назад +1

    Открой для себя Nemerle. В нем в 2006м недостатков было меньше чем в C# в 2023м.

    • @DevJungles
      @DevJungles  Год назад

      Самое забавное, что я даже знаю это название и даже видел его сорсы и полтора проекта на нем где-то в 18м году)
      Но уже тогда, увы, и язык и проекты были заброшены

    • @vc36960
      @vc36960 Год назад +1

      @@DevJungles А я его до сих пор поддерживаю. 🤫

  • @user-wj7er2go9d
    @user-wj7er2go9d Год назад +1

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

    • @DevJungles
      @DevJungles  Год назад +1

      Дада! Есть такое: особенно с модификатором required и get/init свойствами это становится прямо вменяемо.

  • @kkk-tk6gq
    @kkk-tk6gq Год назад +1

    Классный видос, лайк

  • @user-me6ey7gq4j
    @user-me6ey7gq4j Год назад +1

    У меня проблема, которая на первом месте, была в ts'e, только там в конструкторе было 17 сервисов, в родитель я передавал 10, у того был еще один родитель с 4 параметрами. И к этим четырём параметрам надо было добавить пятый... Энивей у свитч экспрешена первое место у меня

    • @radiosh66
      @radiosh66 Год назад

      Слушайте, а в райдере (или любой другой IDE от JB) это проблема не решается простым рефакторингом сигнатуры конструктора?

  • @maximkonoplyanik9155
    @maximkonoplyanik9155 Год назад +1

    Отличный ролик 👍

  • @Ivolution091
    @Ivolution091 Год назад +1

    К обходу 7-й проблемы в пример можно ещё библиотеку System.Reactive привести. Там тоже логика помещения подписки в IDisposable используется. Также есть механизмы адаптации классических событий. Но, с другой стороны, это уже не Subscriber/Puslisher, а Observable/Observer получается.

    • @DevJungles
      @DevJungles  Год назад

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

    • @Ivolution091
      @Ivolution091 Год назад

      @@DevJungles Да, сложная вещь, объемная. Я с WPF в основном работаю, там неплохо весьма приживается эта технология. А вот WEB, например, сложно представить, как её использовать.

  • @6trica1a3
    @6trica1a3 Год назад +1

    Разложил сисярп по фактам, так ему 😅👍

  • @jarogor
    @jarogor Год назад +1

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

    • @DevJungles
      @DevJungles  Год назад +1

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

  • @stanislavsh6582
    @stanislavsh6582 Год назад +1

    Ну. Большая часть это не проблемы языка.
    Но с чем согласен, это с войдом. Войд - это реально боль, если тебе нужно библиотеку для команды делать.
    Приходится либо одинаковую логику мутить, либо вводить какое-то извращение в духе Unit, Empty, Nothing и всем говорить, что оно есть.
    И проблема со вторым подходом, в том что шарп начинает ворнинги сыпать, дескать ты результат не используешь, а ну как сделай Nothing _ = Lib.Execute();

  • @user-gi4qu9do2v
    @user-gi4qu9do2v Год назад

    Тема недоделаных дженериков раскрыта не до конца. Стандартные коллеккции не реализуют коваринтность, нет нормальной контрваринтности типа возвращаемого значения в реалилизциях методов базового класса. Нельзя сделать where T is SomeAbstractClass - нужно для SomeAbstractClass делать интерфейс ISomeAbstractClass.
    В джаве это реализовано гораздо лучше. Благо на бэкенде магия джеренриков нужна очень редко.

    • @DevJungles
      @DevJungles  Год назад

      Не соглашусь... Давненько видел джаве, но тогда там дженерики меня прямо ужасали. Там не было generic constaints(может добавили?) и не было возможности сделать Generic от value-type: ArrayList, а только от Integer(который ref-type)

  • @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 и джавовская экосистема которая у него под капотом такая мерзкая, что активно для новой разработки переходим на голанг, который как язык по примитивнее, зато всятэкосистема прямо очень хорошая. Не языком единым...

  • @evg12345
    @evg12345 Год назад +1

    Спасибо

  • @MrCommanderKid
    @MrCommanderKid Год назад +1

    Чем опытней разработчик тем грандиозней ляпы он совершает.

  • @shkippitor1895
    @shkippitor1895 Год назад +1

    про гит в точку

  • @bulsond
    @bulsond Год назад +1

    По поводу массивов (их необобщенности) и конструктора - это же следствие истории создания шарпа, как сводного брата Java.

    • @DevJungles
      @DevJungles  Год назад

      Ага... Но разве оно от этого меньше болит?)

    • @joresso
      @joresso Год назад

      При просмотре подумал что прсто дженерики появились в netFramework 2. И не свящано с историей создания... создатели специально отказались от дженериков?

  • @ivanvoyager
    @ivanvoyager Год назад

    Половина проблем просто надуманы. А насчёт массивов и генериков и общего кода что мешает использовать интерфейсы? У массива спокойно есть генериковый интерфейс IReadOnlyList`T, например.

    • @DevJungles
      @DevJungles  Год назад +1

      Да, есть способы выкрутится.
      Но, если работаешь в уровня рефлексии и пишешь какой-то обощенный код, то GetType().IsGenericType нужно помнить, что массивы туда не попадают.

  • @user-tx8lw5ti9m
    @user-tx8lw5ti9m Год назад +1

    На счёт 8го места. Видел затычку с классом Void с приватном конструктором, а методы с таким типом просто возвращают null

    • @DevJungles
      @DevJungles  Год назад

      Ага
      В MediatR том же для этого есть Unit.Value

  • @Kitulous
    @Kitulous Год назад

    30:00 а ещё я в райдере когда копирую файл с классом, вставляю, меняю ему имя, и оно не меняет имя класса внутри! и его приходится менять в двух местах!

  • @user-qg6fn3qx9m
    @user-qg6fn3qx9m Год назад

    Речь конечно про с# но добавлю по поводу косяков, в entity framework 7 завезли column json, только нельзя чтобы классы в этих колонках имели поле с названием id, будет вылетать ошибка при запросах , так как конфликтует как я понял с ихним десерелизатооом .

    • @DevJungles
      @DevJungles  Год назад

      Ух.. Не знал этой штуки.

  • @anderwafe
    @anderwafe Год назад +1

    23:20 всмысле 6 модификаторов? а file?))

    • @DevJungles
      @DevJungles  Год назад

      Да да!)
      Забыл его

  • @dimaaannn1
    @dimaaannn1 Год назад

    Вот женерики да, прям иногда хочется хитрых проверок навернуть, и так чтобы "оно само" потом работало при использовании.
    А в итоге получаются костыли с кучей наследований.
    А на счёт конструкторов - у меня была идея, что если бы на вход можно было передавать какой то класс (или анонимный тип) который может деконструктиться в нужный список аргументов прямо при передаче в конструктор.
    var arguments = new SomeClassArgsRecord(a, b, c);
    var someClass = new SomeClass(arguments.Deconstruct()); // new SomeClass(a, b, c)

    • @DevJungles
      @DevJungles  Год назад

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

  • @rechw769
    @rechw769 Год назад +2

    там ещё модификатор доступа file завезли в 11 шарпе)))

    • @DevJungles
      @DevJungles  Год назад +1

      Ох.. Точно.
      Забыл про него. И он еще и со своим особым контекстом применения)

    • @rechw769
      @rechw769 Год назад +1

      @@DevJungles спасибо за контент, делаешь крутейшие ролики)

  • @kOPOBkAAA
    @kOPOBkAAA Год назад +1

    решение на топ1 крутое!

  • @user-gi4qu9do2v
    @user-gi4qu9do2v Год назад +1

    Для топ 1 возможно **args из питона подойдут, но лучше без них))

  • @vasiliylu8054
    @vasiliylu8054 Год назад

    Я не очень понял про 9 пункт, вроде это же можно запомнить, почти как "жи-ши", не тащи тонны данных через enumerable, юзай силу, Люк.

    • @DevJungles
      @DevJungles  Год назад +1

      Ну да, но это нужно постоянно помнить
      А ещё легко сделать классный метод для работы с IEnumrrable, а потом "случайно" его заюзать для какого-то Queryable

  • @Fr0stick
    @Fr0stick Год назад +1

    Знаешь почему синтаксис switch такой? Потому его решили перенести один в один с Rust😂

  • @KLNHOMEALONE
    @KLNHOMEALONE Год назад +1

    Андрей, а тебе еще не говорили, что ты реально крут? :)

  • @user-zj4jv5vv8r
    @user-zj4jv5vv8r Год назад +1

    Уже лет десять прогаю, даже половины из сказанного не использовал.

    • @daitedve1984
      @daitedve1984 Год назад

      "На каждом языке можно писать как на Бейсике!" (ц) кто-то-великий 😆 Оно и к лучшему - проще код - проще сопровождение или портирование.

  • @Dread2607
    @Dread2607 Год назад

    А можна лінк на оригінальну статтю ? Чи на презентацію, якою ти користуєшся ?

    • @DevJungles
      @DevJungles  Год назад

      Оригінальної статті не існує, все для цього відео створював ексклюзивно.
      Лінку на презентацію та сценарій виклав для спонсорів та патронів каналу.

  • @vladrega6862
    @vladrega6862 Год назад

    Хорошее видео, насчёт конструкторов с абстрактными классами полностью согласен, а так же с асинхронными и не асинхронными перегрузками. Как по мне уже давненько пора отказаться от явного применения Task с асинхронными методами и отдать это на вотчину компилятора, т.к. нам, как правило, нужен дженерик объект таска, а не сам таск,🤘

    • @edwardfreedom
      @edwardfreedom Год назад

      сделай свой обьект или касти внутри как нибудь

    • @DevJungles
      @DevJungles  Год назад

      С одной стороны согласен, с другой асинхронность тоже важная часть сигнатуры и ее хотелось бы видеть... Не знаю. Не простой вопрос.

    • @vladrega6862
      @vladrega6862 Год назад

      @@DevJungles ну, такое, я бы предпочел асинхронные методы суффиксом отмечать, и, возможно, чтобы явный тип был указан при наведении на метод. С var же так работает, почему бы не сделать что-то подобное. А возвращаемый тип, на самом деле не всегда говорит о том, что метод асинхронный, не знаю, доводилось ли ковыряться в либах к sql различным, там можно часто встретить методы, которые возвращают таск, но при этом прям параметром принимаю булевый флаг async и если ты выбрал false, то у тебя будет синхронный метод беспантово завернут в таск, такое..

  • @Mnogoznaal_
    @Mnogoznaal_ Год назад

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

    • @stanislavpetrov6124
      @stanislavpetrov6124 Год назад

      Гугл: YourDiContainerName property injection

    • @joresso
      @joresso Год назад

      Смотря каким DI пользуетесь. В MicrosoftDI Add(Singleton/Scoped/Transient)(provider=>/*тут выбираете из провайдера что надо и конструируете экземпляр класса*/)... посмотрите повнимательнее методы регистрации типов в вашем DI должно быть что-то похожее

    • @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; }
      ...
      }
      Він генерується як звичайний клас, взагалі без нічого. Тож незрозуміло, який в ньому сенс.
      }

  • @pfff-doh
    @pfff-doh Год назад

    Зачем слайды на английском? %)
    И вы похоже упорный девелопер - спеллчекер пытался направить на путь истинный, подсвечивая "Finilizer", но не смог победить :D Ну и "mension" тоже

    • @DevJungles
      @DevJungles  Год назад

      С mension, если честно, прямо стыдно стало, когда допер(

  • @Diyozen
    @Diyozen Год назад

    Тоже отмечу жуткую боль от дженериков. Они вроде бы неплохие, но не хватает кучи инструментов (по типу усилений ограничений по иерархии интерфейсов, например, и других).
    Тему самой главной проблемы (№1), честно говоря, не очень понял. Как изначальную проблему (наследование реализаций в программировании бьёт по рукам ещё со времён множественного наследования), так и решение-костыль (оно же усложняет чтение класса и параметров конструктора). Не совсем понимаю контекста, но разве использование Type Object паттерна не излечит от этой проблемы? Или декоратор, опять же.

    • @DevJungles
      @DevJungles  Год назад

      Если честно не вижу как декоратор или тайп объект может решить эту проблему...

    • @Diyozen
      @Diyozen Год назад +1

      @@DevJungles нет наследования - нет проблем протягивания зависимостей через всю иерархию. Что-то в этом роде))
      Но это, наверное, я просто изначальную проблему не так понял.

  • @denys-p
    @denys-p Год назад +2

    Синтаксис свича, кстати, реально противный и не очень понятно почему его сделали таким. Я его до сих пор толком не помню и приходится гуглить

    • @srvr4vr
      @srvr4vr Год назад

      его делали так по аналогии с F#, но там он добрый и ласковый друг, а здесь какой-то огузок, но выручал меня пару раз в связкой с ValueTupple может отлично заходить в некоторых ситуациях.

    • @joresso
      @joresso Год назад

      Занимался написанием компилятора для API одной системы... И пришла мысль что просто так проще компилятор реализовать, отличается порядок лексем. Отлично же, меньше возвратов назад делать, быстрее компиляция

  • @Timyrlanchik
    @Timyrlanchik Год назад

    Проблема №1 реально боль, но предложенное решение - это антипаттерн "God object". Нет, это не решение) Продолжаю страдать...

    • @DevJungles
      @DevJungles  Год назад

      Почему God Object? Это же по объекту аргументов на каждый класс.
      Единственная задача: поддерживать аргументы.

    • @Timyrlanchik
      @Timyrlanchik Год назад +1

      @@DevJungles Наверное потому, что у меня был опыт работы на одном из проектов с таким объектом , который содержал в себе сотню полей, всегда частично заполненных, и ты никогда не знал, какие именно будут заполнены. Это был ад адский. Видимо, я получил психологическую травму, от которой так и не оправился)))
      Снизить поражающий эффект этого антипаттерна можно, если все поля будут обязательны, инициализироваться через конструктор, рид онли. Тогда, по крайней мере, ты будешь знать, глядя на этот, тасказать, ДТО, что от него ожидать.
      А что делать, если у тебя сложная иехархия базовых (абстрактных) классов (а у меня на текущем проекте именно так), делать еще один gob? и сколько их будет?
      В целом это системная проблема, которая говорит о том, что что-то сильно не так в королевстве Датском
      Для себя решил, что лучше терпеть эту боль, но следовать шаблону DI

    • @DevJungles
      @DevJungles  Год назад

      Я может не слишком хорошо сформулировал идею...
      Идея для каждого класса с множеством аргументов в конструкторе делать отдельный класс аргументов.
      Если есть иерархия, то повторять ее в этих классах аргументах.
      Все отмечать required { get;init; }
      Здесь в самом конце видео еще раз к этому возвращаюсь как раз: ruclips.net/video/euZvNDFwTQ8/видео.html

  • @Alex-qt9oo
    @Alex-qt9oo Год назад

    спасибі за роботу. А можна приклад як навчити DI створювати об'єкти як в топовій проблемі 🙃🙃🤗🤗

    • @DevJungles
      @DevJungles  Год назад

      Буде відео.
      У травні, сподіваюсь)

  • @sanphir
    @sanphir Год назад +1

    я таки вырезал кусок про войд😁

    • @DevJungles
      @DevJungles  Год назад

      Для использования на закрытых лекциях по философии?)))

    • @sanphir
      @sanphir Год назад

      @@DevJungles ага, послал друзьям философам, выразили респект )

  • @alexb.9806
    @alexb.9806 Год назад +1

    по поводу конструкторов -- наследование зло))
    даже если ты и заюзаешь предложенный воркараунд, это не решает главную (и по факту единственную) проблему -- ты всё равно поменял поведение 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# первые шаги(до этого другие языки были) делать всего чуть больше года назад😅

  • @nztzn
    @nztzn Год назад

    Відносно першого місця, можна засетити дефолтом значення в null:
    (SomeType sometype, IMapper mapper = null)

    • @DevJungles
      @DevJungles  Год назад

      Але ж він тоді для спадників так і залишиться null(

  • @vasiliylu8054
    @vasiliylu8054 Год назад

    А можно топ1 решить аннотациями, например добавить property в базовый класс с аннотацией [Inject]. Если что, я не настоящий волшебник....

    • @DevJungles
      @DevJungles  Год назад

      Да, есть что-то вроде этого.
      В целом со свойствами get/init и модификатором required получается достаточно хорошо.

  • @IgorTkachev
    @IgorTkachev Год назад

    Объяснение 9 невнятное, запутанное и не объясняет происходящее. А так видос зачётный.

    • @DevJungles
      @DevJungles  Год назад

      Может не слишком хорошо объяснил где-то местами...

    • @IgorTkachev
      @IgorTkachev Год назад

      @@DevJungles В данном примере переполнения памяти не будет. Данные не будут все ЗАкачаны в память, а будут ПРОкачены через локальный компьютер, но при этом фильтр хоть и локально, но работать будет. А вот если бы в примере был OrderBy или GroupBy, то все описанные страшилки случились бы.

  • @Sergio-jg4pr
    @Sergio-jg4pr Год назад +2

    я думав, що я один такий не можу запам'ятати switch expression)

    • @DevJungles
      @DevJungles  Год назад +1

      Нііі) Нас таких купа

    • @user-qq9hw2cz6l
      @user-qq9hw2cz6l Год назад

      @@DevJungles да сих пор без подсказок среды не напишу. Но не согласен и с нападками, и представленными альтернативами. Дело в том что, switch как выражение, может, много больше по сопоставлению кейсов чем стандартный switch, и поэтому варианты из других языков не кажутся вдохновляющими. И естественно он должен вернуть что-то , когда ничего не совпало. Почему там _ , а не default -- загадка.

  • @ivanzrobok7148
    @ivanzrobok7148 Год назад

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

    • @DevJungles
      @DevJungles  Год назад +1

      Да да
      Я это и предлагаю в варианте обхода, но оно проблему полностью не решает, если нужно работать с объектом дальше

  • @daitedve1984
    @daitedve1984 Год назад

    40 минут видео только для того, чтобы словесно описать 2-страничный документ? Куда же катится человечество....

    • @DevJungles
      @DevJungles  Год назад

      Если ограничение не время, а пропускная способность головы, то это может быть небольшой проблемой)
      Теперь вопрос: так ли мы уверены, что нас ограничивает время?
      Что бывает чаще: в конце рабочего дня вы хорошо поработали, есть ещё много дел, вы бороды и веселы, но уже 19:00 и пора домой.
      Или
      17:00 и лузится стекающая изо рта от тупняка начала капать на стол))

  • @batyabatya6817
    @batyabatya6817 Год назад

    Еще после котлина раздражает то что все по-умолчанию мутабельно.
    И I в названиях интерфейсов, которое по началу кажется здравой идеей на деле полная ерунда, ну больше выбешивает конечно IReadOnly, это просто супербойлерплеейт, ведь для хорошего тона все должно быть ридонли, в итоге у тебя весь код с полями засран этими IReadOnly... .
    Как по-мне это самая серьезная ошибка, которая говнит весь clr, и никакой новый язык (аля котлин для clr) это уже не исправит в отличии от других ошибок из видео
    Ну еще отсутсвие var в полях, который тоже очень сильно бойлерплейтит в некоторый случаях.
    А еще async/await после котлина это просто ужас, просто не хочется возвращаться в c# когда вспоминаешь о них и о cancellationToken, крайне недальновидное решение которое язык подпортило, конечно их можно оживить и адаптировать если сделать новый clr язык правда с костылями.

    • @DevJungles
      @DevJungles  Год назад

      По мутабельности соглашусь, даже хотел поставить в видео, но потом решил не делать: много про это сказано и, пожалуй, это дань тому как тогда видели парадигму.
      А можешь подробнее сказать про cancellationToken и async/await? Что с ними не так?

    • @batyabatya6817
      @batyabatya6817 Год назад

      @@DevJungles 1) Синтастический бойлерплейт постоянно надо писать Task и await хотя на деле для компилятора в этом нет необходимости все и так понятно. 2) Сложно провести аналог, ведь корутины это немного другое, но вообщем в котлине с канселяцией все проще ибо этот токен уже вшит в корутину и есть дочернии опреации которые канселятся вместе с родителем и следовательно не нужно постоянно прокидывать и комбинировать эти кансел токены и следить за этим.

    • @user-qq9hw2cz6l
      @user-qq9hw2cz6l Год назад

      можете показать 1 и 2? очень интересно, но пока не понятно.

  • @ak_nex
    @ak_nex Год назад

    Из относительно новинок ещё можно вспомнить проверку на null через is (pattern matching), а не ==
    Способ через is рекомендуется самим майкрософтом, чтоб случайно не попасть на переопределение оператора ==
    И всё было бы хорошо, если б этот is работал везде. На текущий момент его нельзя использовать в expression-ах (в отличие от лямбд, что дико путает). Т.е. во всех linq-выражениях на is будет ругаться...
    По итогу в коде получается сборная солянка, а ты постоянно натыкаешься на ошибку от IDE в linq... 🤬

    • @daitedve1984
      @daitedve1984 Год назад +1

      "чтоб случайно не попасть на переопределение оператора ==" - какой идиот придумал обходить переопределение операторов?!!? Их СПЕЦИАЛЬНО ПРИДУМАЛИ, чтобы глупый канпелятор знал, как ПРАВИЛЬНО сравнивать объекты.

    • @DevJungles
      @DevJungles  Год назад +1

      Я уже в одном видео хорошенько прошёлся по паттерн матчингу как раз))

  • @godfather7695
    @godfather7695 Год назад

    "Современные" языки не проще, они еще просто не столкнулись с теми проблемами, с которыми уже десяток лет сталкиваются разрабы. Ваше утверждение как слова Бендера из футурамы про казино.

    • @DevJungles
      @DevJungles  Год назад +1

      Да.
      Главная проблема в этом плане: просуществовать в мейнстриме лет 20-30

  • @IQ-120
    @IQ-120 Год назад

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

    • @DevJungles
      @DevJungles  Год назад

      Базовый класс от типа передаваемого аргумента?..
      Звучит как что-то очень странное))

    • @IQ-120
      @IQ-120 Год назад

      @@DevJungles да, туплю - это интерфейсы, их реализовывать придется. Хотя, можно, протыкать - может, там - просто... Найти реализацию IMapper и от нее унаследоваться... Хз, мысль, просто пришла...

  • @nooftube2541
    @nooftube2541 Год назад

    Я конечно понимаю прикол 42, но возвращайти пожалуйста просто дефолт в таких случаях.

    • @DevJungles
      @DevJungles  Год назад

      Это же демки, а не продакшн код)

    • @nooftube2541
      @nooftube2541 Год назад

      @@DevJungles знаю я как демки потом лежат по 10 лет в продакшене 😂
      У нас в каких то тулзах в качестве успешного кода возвращается год рождения автора.

  • @wizzardTrololo
    @wizzardTrololo Год назад

    Ну что, опять НЛП в действии, позавчера ревьювил проект где ребята как раз Queryable передали в метод который принимает IEnumerable:)

    • @DevJungles
      @DevJungles  Год назад

      Я очень плотно влез в реальность 🤪🤪🤪😜

  • @denys-p
    @denys-p Год назад

    Занудничаю: «упоминание»: Mention, не Mension

    • @DevJungles
      @DevJungles  Год назад +1

      Вот это я опозорился(
      При том из-за того что есть слово mension(усадьба, поместье), то мне даже орфочеккер не ругнулся 😔😔😔
      Спасибо за замечание!

    • @denys-p
      @denys-p Год назад

      @@DevJungles а поместье - Mansion 😁