Очень понравился формат! Нарезки со стримов ощущаются вырванными из контекста, а полностью стримы не всегда есть возможность смотреть. Такой стиль видео вместе с подготовленным кодом, сценарием и монтажом гораздо лучше заходят)
@DevJungles Жыл бұрын
Спасибо!)) На самом деле он уже давно существует на канале: в разделе видео все что со скобкой не синего цвета это как раз отснятые заранее ролики по заготовленному сценарию)
@anatoliytkachenko7081 Жыл бұрын
Лайк за гідний контент! Дуже корисно, як завжди!
@PetroChernykh Жыл бұрын
Спасибо за видео!
@native-nature-video Жыл бұрын
Спасибо за видос!
@kl45gp Жыл бұрын
твой канал просто открытие, спасибо. казалось вроде асе знаешь, а вот нихера)
@extense1337 Жыл бұрын
крутое видео, спасибо за контент!
@Diyozen Жыл бұрын
Согласен. Мне кажется, оператор new() в том числе нарушает SRP, поскольку объект начинает порождать другие объекты, не являясь фабрикой. Происходит совмещение нескольких обязанностей в одном месте. Само использование оператора new() - это как жесткая ссылка внутри кода на другой класс, тем самым делая порождающий класс зависимым от этого конкретного типа. Со всеми вытекающими последствиями. Причём зависимость эта не явная, поскольку попадает в объект не через конструктор, а создаётся на месте - оно может быть зарыто глубоко-глубоко в коде.
@DevJungles Жыл бұрын
Все так)
@IgorTkachev Жыл бұрын
30:31 на T можно навесить конетрейнт, который реализует интерфейс, в котором можно прописать минимально необходимый API в том числе и для, например, property injection, который автор ролика хвалил ранее
@DevJungles Жыл бұрын
Да Но тут же сразу ряд ограничений: Т обязательно должен быть твоим, а на другой класс не навесишь никак твой интерфейс. Но в целом, да: так и крутимся)
@pavelromashuk237 Жыл бұрын
Никогда не рассматривал оператор new в таком ракурсе, интересно! Спасибо за видос! В одном из видео ты упоминал вопрос сравнения скорости работы автомаппера и DI, что DI работает гораздо быстрее, ты не мог бы этот вопрос более широко ответить?
@DevJungles Жыл бұрын
Если честно не помню именно такой формулировки.. если и была, то может оговорился. Сравнивал перформанс разных подходов мапперов между собой. Сравнивал разные DI между собой. Говорил, что в целом, заняты они похожими штуками)
@HOSTRASOKYRA Жыл бұрын
Дякую!
@agnia.starovoitova Жыл бұрын
Здравствуйте. А почему logger инжэктится через transient, а mapper через singleton?
@DevJungles Жыл бұрын
Mapper обычно содержит конфигурацию и компилированные Execution Plans. Сильно быстрее сделать это один раз. Логгер обычно привязывается к конкретному объекту, что бы дописывать что-то доп в логе. В инфре логгера тоже есть синглтоны: провайдер или фабрика.
@user-oi7js1fs72 Жыл бұрын
Классный канал, много полезной информации. Только может делай видео чуть короче, если конечно возможно, просто 30 мин немного длинно, не всегда захочется смотреть. 15 мин было бы идеально. :)
@DevJungles Жыл бұрын
Делаю всё что могу!))) Если посмотришь, то большинство видео были больше 2х часов и только со временем появились короткие вроде этого)
@nbukov Жыл бұрын
Формат афигенный так как не всегда получается смотреть стримы, со скримера олдскулы свело... Видос - база и польза, буду баловаться в пете...
@native-nature-video Жыл бұрын
А что на счёт использования "new" с небольшими классами такими как StringBuilder, Random и т.п. Насколько целесообразно делать абстракции на все классы типа StringBuilder только чтобы избежать использования "new"? Есть какие-то best practices для принятия решения когда нужно абстрагировать, а когда - нет?
@DevJungles Жыл бұрын
СтрингБилдер, обычно не изолируют... А вот рандом изолируют почти всегда, чтобы иметь возможность помучать тестами. Скорее всего грань как раз где-то между ними)
@HOSTRASOKYRA Жыл бұрын
Було б непогано побачити випуск про класичне застосування якогось DI контейнеру, бажано не з коробки, хоча можна і так і так. З налаштуванням об'єктів від простого до складних залежностей та їх використанням.
@DevJungles Жыл бұрын
Думаю щось зроблю таке, але не обіцяю поки, що дуже скоро. Взагалі гарний стрім є плагіни: kzbin.info9qsOLGjgKOc?feature=share Там багато з того, що було названо роблю.
@ИванОсинин-с7и Жыл бұрын
Дисклеймер: Здравствуйте, я последователь секты свидетелей Егора Бугаенко и элегантных объектов. DI похож на свалку долго живущик объектов и например не решает задачи из начала ролика: не позволяет порождать объекты (одного класса) с разными данными (по крайней мере я не увидел решения, можете показать?). Так же весь DI можно заменит банальной композиций объектов (в одном каком-то центральном месте) и это будет максимально прозрачно. В случае ошибки настройки контейнера дебажить его будет очень больно, а при ошибке в композиции компилятор лиьо поругается, либо можно будет не далеко от места использования объекта увидеть что ему дается в пользование. На последок спрошу: знаете про язык EOLANG? (можно считать за рекламу)
@DevJungles Жыл бұрын
> DI похож на свалку долго живущик объектов Не обязательно долго живущих. Хорошо организованная свалка, где DI умеет эффективно искать, что нужно. > порождать объекты (одного класса) с разными данными Autofac: container.Resolve(someArg1, someArg2); - и еще много похожих вариантов на любой вкус. > Так же весь DI можно заменит банальной композиций объектов Эта задача очень быстро становится очень сложной. Разные жизненные циклы итд.: код по управлению ими приходится дублировать. Данные необходимые для композиции постоянно меняются и эти изменения могут быть болезненными. > В случае ошибки настройки контейнера дебажить его будет очень больно Часто забываю насетапить контейнер: ошибки очень простые и сразу тыкают меня носом и говорят, что нужно сделать. > при ошибке в композиции компилятор лиьо поругается Мне бы хотелось, получить и Compile-Time и DI. Есть DI на основе source generators. Думаю в одном из ЯПов следующего поколения мы получим DI как часть языка. > знаете про язык EOLANG? Даже не слышал, если честно. UPD. Гугольнул, глянул примеры в гитхаб: на первый взгляд пугающе)
@ИванОсинин-с7и Жыл бұрын
@@DevJungles а какие ошибки вы получите, если вы попросили объект через интерфейс, а в контейнере на этот интерфейс настроен "неправильный" или сломанный (но мы пока об этом не знаем) объект? Про остальное я понял. Да, DI - это выход. Как я писал в дисклеймере, я похож на религиозного фанатика по отношению к EO (Elegant Objects) описанным Егором Бугаенко. Поэтому добавлю, что если объекты, с которыми мы работаем, будут представителями неких сущностей, не будут изменять сущность, которую они представляют (в EO это назвали иммутабельностью), не будут называться отглагольными существительными (-er, -or) и ещё с десяток правил, то в DI просто не будет необходимости, при этом код не будет переусложнен. Правила описаны в книге Elegant Objects и так же реализованы в EOLANG (с настолько кратким синтаксисом, что черт ногу сломит). Есть применение этого подхода и на Java, например библиотеки takes и cactoos.
@DevJungles Жыл бұрын
> а какие ошибки вы получите, если вы попросили объект через интерфейс, а в контейнере на этот интерфейс настроен "неправильный" или сломанный (но мы пока об этом не знаем) объект? Если объект удовлетворяет интерфейсу, то никаких. Если не удовлетворяет, то его просто не выйдет зарегистрировать в DI используя рекомендованные методы. > я похож на религиозного фанатика по отношению к EO (Elegant Objects) Это окей, если это результат длинного пути разработки во многие годы и его осмысления. Может быть те проблемы и проекты, что вы встречали могли быть сделаны лучше с использованием EO. > иммутабельность. Термин распространненный. Особенно в ФП, но и в ООП его все больше. Сейчас почти любой анализатор и любая IDE подталкивает писать код построенный на Immutable объектов. Но не вижу как это связано с DI и его необходимостью. По мне это оставляет необходимость в DI ровно на прежнем уровне)
@ИванОсинин-с7и Жыл бұрын
@@DevJungles В идеале я получу цепочку эксепшенов, которая закончится внутри поломанного объекта Не знаю как заведено в C#, но например в Java Spring очень много магии и в частности можно 3мя способами определить бины, что привращается в ад если кто-то зарегистрировал 2 бина для одного и того же интерфейса, но разными способами. Про immutable: если каждый immutable по отношению к сущности, которую он представляет, то не возникает проблемы с контролем их жизненного цикла. IDisposable на мой взгляд выглядит как ошибка. Вызов dispose() похож на ручной вызов функции-деструктора в Си, C++ использует RAII и деструкторы которые вызываются сразу, а не как финализаторы.
@ram0973 Жыл бұрын
Effective Java by Joshua Bloch, chapter 2: 5 плюсов статических фабрик и два минуса
@olezhonnv3215 Жыл бұрын
Ничего не понял, но было интересно))) У вас в шарпах свои мутки, насколько я вижу.
@DevJungles Жыл бұрын
Ага) А сам ты из какой технологии?
@IgorTkachev Жыл бұрын
30:00 DI без рантайм генерации кода не работает? 🤣
@DevJungles Жыл бұрын
Без рефлексии точно не работает) Без кологенерации по идеи в теории может ... Ну там в теории есть уже DI на sourcegen
@AlexBychenkov Жыл бұрын
Не понял почему статика нарушает опенклозед ктонить пояснит?
@bulsond Жыл бұрын
Тоже не очень уловил этот момент. Подозреваю, что речь о том, что расширить функциональность статического метода невозможно без его изменения. Его невозможно подменить другим статическим методом для этого расширения.
@const8241 Жыл бұрын
потому что статические поля хранят значение не конкретного объекта, а значения всего класса... То есть объявив в нестатическом классе статическое поле вы нарушите саму суть существования объекта данного класса.. или если не вы, а коллега допишет статику..короче, статика - это генератор багов на мой взгляд... Хотите передавать настройки из файла конфигурации ? - Ипользуйте интерфейс настроек в качестве параметра конструктора класса
@antibioticknone3057 Жыл бұрын
Сама статика плохо ложится под всю парадигму обектно ориентированного программирование, у статики нет состояния, нет поведения. У статики есть просто набор функций, которые кто-то обектно ориентированный где-то когда-то может вызвать
@DevJungles Жыл бұрын
Потому что в какой-то момент где-то будет находится вызов этой статики и он там будет прибит намертво: этот вызов невозможно поменять или расширить не изменив этот код. Ты не можешь, например, протестировать вызывающий код в отрыве от статики замокав ее(ну не считая совсем уж черной рефлексии)
@stefano_schmidt Жыл бұрын
@@bulsond приведи пожалуйста пример, как бы мы "расширили функциональность метода без его изменения" будь у нас не-статический метод?
@ДенисЕгоров-ь3в Жыл бұрын
Насчет того, что ты создавал конструктор из объекта со свойствами могу сказать, что его использует гугл в своей библиотеке и называется он у них Initializer. Сам точно также перешел на такую систему передачи аргументов и экономлю кучу времени
@DevJungles Жыл бұрын
Хм. Интересно: а подскажи, плиз еще раз что за либа? Не гуглится что-то
@Gamil-le4fi Жыл бұрын
@@DevJungles Самому интересно стало, нагуглил только BaseClientService.Initializer. За видео спасибо!
@ДенисЕгоров-ь3в Жыл бұрын
@@DevJungles google-api-dotnet-client
@const8241 Жыл бұрын
Концовка классная! Но самая отталкивающая тема в DI в том, что нам предлагается использовать контейнеры DI , то есть "черный ящик", это как выгуливать свою собаку в картонной коробке... не узнаешь куда она помочилась в коробку или куда следует...
@DevJungles Жыл бұрын
А почему черный ящик-то не очень понял... Исходники все есть: можно глянуть. Наполнять его тоже сами будете: где-то будут прописаны все маппинги зависимостей. Где же тут черный ящик?
@const8241 Жыл бұрын
@@DevJungles я привык писать весь функционал руками, потому что я знаю как у меня это будет работать или у коллег по команде...а любое обновление чужих библиотек может принести баги (в 13-м году кажется исходники ещё не были выложены у MS), которых не было в предыдущих версиях... Ну то есть это заново погружаться в исходники. Плюс эта магия настройки DI контейнеров выглядит вообще очень странно, если не заглядывать под капот... Так что я пока пытаюсь разобраться с этим..
@const8241 Жыл бұрын
@@DevJungles если я верно понимаю, там много рефлексии в момент настройки...
@DevJungles Жыл бұрын
Сейчас там по большей части рефлексия. Есть эксперименты с source generators. > я привык писать весь функционал руками Очень крутой подход, позволяющий делать потрясающе качественные маленькие программы. Для средних и больших, к сожалению, может уводить дату релиза в бесконечность
@ПавелФамильевич Жыл бұрын
В юнит тестах часто видно мощь и пользу ДИ. Когда вручную создают интсансы и все зависимости пробрасывают - начинается треш. Хотя это решается через тестовые либы вполне себе просто, но по опыту в половине случаев просто вручную в тестах коллеги создают инстансы
@bulsond Жыл бұрын
Тесты - это не только тесты, а еще и документация о функциональности приложения. Когда в тестах явно создаются инстансы, то хорошо видно, что от чего зависит и как. Если же этот этап создания зависимостей спрятать за кулисы контейнера, то читая тест можно много что-то пропустить и не понять сразу, особенно если вы, допустим, вливаетесь в новый для себя проект.
@ПавелФамильевич Жыл бұрын
@@bulsond Auto-mocking Container позволяет делать то же самое, но без лишнего шума. "Фризишь" интересующие зависимости и потом проверяешь на них все, что надо. Единственное, бывает, что оно все работает-работает, но потом добавляешь какую-то хитрую зависимость и дефолтная конфигурация ломается, приходится подшатывать
@DevJungles Жыл бұрын
Кстати, если честно никогда не видел либ для тест-контейнеров или даже не знаю как это назвать. Если есть название какого-то нагета, то с радостью ознакомился бы)
@ПавелФамильевич Жыл бұрын
@@DevJungles AutoFixture.AutoMoq
@DevJungles Жыл бұрын
Спасибо!
@nooftube2541 Жыл бұрын
Еще убогость констрейнта new() в том, что new T() работает через рефлексию.
@ookhands3843 Жыл бұрын
А после занавеса, будут неудачные трюки, как у Джеки Чана?
@DevJungles Жыл бұрын
Ахахах)
@АндрійГуцалюк-м5д Жыл бұрын
Первый раз читаю комментарии : без быдло-комиков и всякой токсичной херни... чисто... разбор видео ... Которые не менее интересны чем видос ... Господа снимаю шляпу 😎🎩
@edwardfreedom Жыл бұрын
зачем столько точек? Писать нормально не научили в школе?
@RelentlessDebique Жыл бұрын
С ума сойти, если честно) Через сколько лет опыта я должен задуматься об этом? Нормально ли то что для джуниора это достаточно сложно для понимания или это со мной что то не так? 😢
@DevJungles Жыл бұрын
Не переживай)) Это брюзжание начнется лет через 10 работы)
@loam Жыл бұрын
Времена, когда чел говорил ещё на русском языке)
@zool3056 ай бұрын
Как много лишних слов, выключаю. Я не сериал индийский посмотреть зашёл
@DevJungles6 ай бұрын
Хех
@Timyrlanchik Жыл бұрын
Или я чекнутый, или я ненормальный. Зачем так сложно заполнять поля этого ДТО? Почему не переложить опять-таки их заполнение на DI через конструктор? Может я туплю под вечер? public class MyBaseClass { protected MyBaseClass(MyBaseClassParams prms) { Prms = prms; } protected MyBaseClassParams Prms { get; } public void Work() { Prms.MyOtherClass.Do(); } } public class MyChildClass : MyBaseClass { public MyChildClass(MyBaseClassParams prms) : base(prms) { } } public class MyBaseClassParams { public MyBaseClassParams(IMyOtherClass myOtherClass) { MyOtherClass = myOtherClass; } public IMyOtherClass MyOtherClass { get; } } public interface IMyOtherClass { public void Do() { Console.WriteLine("do"); } } public class MyOtherClass : IMyOtherClass { } public static class MyDiExtension { public static void AddMyId(this IServiceCollection services) { services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); } }
@DevJungles Жыл бұрын
1. Child class может иметь дополнительные параметры по отношению к базовому. Это добавляет MyChildParams:MyBaseParams А отсюда и необходимость использовать именно property injection ведь иначе проблема обновлён просто переляжет на иерархию классов параметров. 2. Параметры точно ни в коем случае нельзя регистрировать синглтоном: ведь это значит, что свойства этих параметров могут быть пошарены между разными потоками на что могут и не быть рассчитаны.