Почему я использую паттерн "Шина событий" в проде

Поділитися
Вставка
  • Опубліковано 17 лис 2024

КОМЕНТАРІ • 117

  • @-X-Ray-
    @-X-Ray- 2 роки тому +17

    Клёвое видео
    Поздравляю с появлением спонсорской рекламы)

  • @spadar1602
    @spadar1602 2 роки тому +27

    было бы неплохо увидеть и пощупать реализации на гитхабе, тебе звёздочки, нам возможность потыкать код, ну пожалуйста...

  • @RimuruDev
    @RimuruDev Рік тому +5

    Охаё! На связи канал Rimuru Dev. Искал видео по "Шина событий" для Unity. Но в итоге понял как ее реализовать на вашем примере, да же при том, что я впервые вижу язык JS (судя по расширению файла). Объясняете очень лаконично и доступно, благодарствую за труд.

    • @it-sin9k
      @it-sin9k  Рік тому +2

      Спасибо! Да прибудет с Unity сила :)

  • @atlantatesla9348
    @atlantatesla9348 5 місяців тому

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

  • @ИванИванов-ц5ю6х
    @ИванИванов-ц5ю6х 2 роки тому +8

    Поздравляю вы изобрели сложный в дебаггинге велосипед с ивент басом, первый вариант правильнее, но надо в компонент записи не hasCall передавать(Вы правильно подметили компонент не должен знать про звонок) а к примеру isCancelled

    • @it-sin9k
      @it-sin9k  2 роки тому +2

      Почему он сложный в дебагинге? из-за того что через redux-devtools не виден?

    • @ИванИванов-ц5ю6х
      @ИванИванов-ц5ю6х 2 роки тому +1

      @@it-sin9k да, но не только редакс имеет тулзу для дебагинга, а любой нормальный стм, паб саб создает неразберимый флоу и циклич зависимости особенно заметно в сложных приложениях. Я не говорю паб саб это антипатиерн, но он тут не уместен, особенно если у вас есть стм или котекст

    • @ДмитрийКузьменко-о1ч
      @ДмитрийКузьменко-о1ч 2 роки тому +2

      @@it-sin9k Потому что события передаются неявно, по этому он сложен в дебагинге

    • @it-sin9k
      @it-sin9k  2 роки тому +4

      Мы чаще всего на проекте пишем свои логгеры. С ними можно дебажить любой кодой очень просто. Точно надо сделать про это видео))

    • @ИванИванов-ц5ю6х
      @ИванИванов-ц5ю6х 2 роки тому

      @@it-sin9k ты сталкивался с вложенными подписками в пабсабе?

  • @MAQULIYASO
    @MAQULIYASO 2 роки тому +3

    Спасибо большое, было интересно) Чтобы вы посоветовали прочесть для изучения паттернов?

    • @sergeys4732
      @sergeys4732 2 роки тому +1

      Patterns for humans чекан гитхаб репу

    • @it-sin9k
      @it-sin9k  2 роки тому +2

      Чистую архитектуру недавно читал, мне понравилось. Но немного сложно из-за того что там примеры не на JS

    • @MAQULIYASO
      @MAQULIYASO 2 роки тому

      Спасибо, но думаю эта книга для джуна как я будет сложновата, может ещё и опыта надо набраться

    • @sergeys4732
      @sergeys4732 2 роки тому

      @@MAQULIYASO не надо тебе никакие паттерны тогда, вникай в базу и качай ее

  • @modusvivaldi7701
    @modusvivaldi7701 2 роки тому +7

    Если утилиты внутри packages независимы (и, стало быть, не должны знать про конкретную бизнес-логику проекта, про Use Cases в терминологии DDD), почему в пакет с шиной складываются "бизнеслогические" события ‒ запись сообщения, звонок?

    • @it-sin9k
      @it-sin9k  2 роки тому

      Да, есть такой обсуждение с коллегами тоже. Я относился к пакетам не совсем как к независимым утилитарным инструментам. А скорее как к инструменту заточеному под бизнеслогику. Который часто использует инверсию зависимостей. Так как многих вводит это в заблуждение, думаю надо начинать разделять эти понятия пакет и адаптер

  • @profesor08
    @profesor08 2 роки тому +2

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

    • @it-sin9k
      @it-sin9k  2 роки тому +1

      Спасибо за комментарий. Не соглашусь лишь с несколькими моментами.
      "компонент отвечающий за запись, зависит от данных о звонке" (с) Нет не зависит от данных о звонке. Компонент зависит от события в шине, с названием "начало звонка".
      "был изобретен костыль, который корень проблемы, в принципе, не решает" (с) Смотря какую проблему вы для себя обозначили. Я в данном виде хотел уменьшить немного сцепление компонента звонков и компонента аудиозаписи. А так же уменьшить кол-во ненужных рендеров. Оставить только нужные. И с этим как раз справился
      "Достаточно было перенести логику переключения состояния на уровень выше." (с) Не всегда это так просто. Звонки могут присутствовать на любом экране. И на разных экранах могут быть голосовые сообщения или сообщения с музыкой. Со всем этим звонок может конфликтовать. Поэтому можно запилить верхнеуровневый менеджер потока аудио. Такое имплементировали, но это уже другой паттерн

    • @profesor08
      @profesor08 2 роки тому +1

      @@it-sin9k с этим прекрасно справляется компонент на высшем уровне, который занимается всей логикой разных состояний и передает только нужные пропсы в дочерние. А дочерние будут рендериться только тогда, когда их пропсы изменяются. Вот что если появится еще какая-то логика, при которой надо остановить запись? Снова лезть в компонент и дописывать его? Компоненты они для того и компоненты, сделал и больше внутрь не лезешь, а используешь его, передавая пропсы. В данном случае у компонента только один пропс состояния записи, ему нафиг не нужно знать о каких-то посторонних состояниях. Если же такое возникает, как в примере из видео, то это толстый намек на проблемы в архитектуре. И чтоб решить простейшую проблему, путем избавление от внутреннего useState передачей состояния через пропсы, был изобретен костыль, который подложит жирную свинью в дальнейшей разработке.

    • @it-sin9k
      @it-sin9k  2 роки тому

      @@profesor08 если просто выносить на компонент выше, появляется проблема props drilling, где нужно будет очень глубоко пробрасывать. В случае мессенджера и порядка 20 компонентов вниз возможно придется пробрасывать. А так же будет рендериться вся часть под дерева, начиная с того момента, где хранится state нужный

    • @profesor08
      @profesor08 2 роки тому

      @@it-sin9k для этого есть контекст

    • @it-sin9k
      @it-sin9k  2 роки тому

      @@profesor08 Как только начинаешь добавлять контекст, появляются другие проблемы. Информации может быть много. Все держать в одном контексте или в разных? Значение и функцию обновляющую значения нужно пробрасывать через один и тот же контекст или разные? И куча других мелких проблем. Я использую контекст сугубо для других целей. Вот мой доклад на эту тему:
      ua-cam.com/video/fWm-m1-_dVA/v-deo.html

  • @fexriimanzade4139
    @fexriimanzade4139 2 роки тому +1

    Ты Мега крут, спасибо за такой четкий контент

    • @it-sin9k
      @it-sin9k  2 роки тому +1

      Добро пожаловать на канал :)

  • @alexup7437
    @alexup7437 2 роки тому

    Не совсем уловил, в какой момент у нас включается voiceCall. Я вижу только сброс стора на false. Без примера кода очень сложно въехать в пример.

  • @АлексейСоснин-р4й
    @АлексейСоснин-р4й 2 роки тому +1

    а если событие называется toString ?)

    • @it-sin9k
      @it-sin9k  2 роки тому

      не уловил вопрос?

  • @whiteguards43
    @whiteguards43 Рік тому

    у ibs на сайте отправка резюме не работает, чем они прокачают?

    • @it-sin9k
      @it-sin9k  Рік тому

      известная проблема - сапожник без сапог))

  • @ДмитрийКузьменко-о1ч

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

    • @johnbrown3914
      @johnbrown3914 2 роки тому

      Привет, можно подробнее?

    • @it-sin9k
      @it-sin9k  2 роки тому +5

      Мысль очень даже здравая. Если вам нужна шина, лишь для 1 случая, то вероятно и пара рендеров лишних, точно не ухудшат сильно ваш перфоманс. Но если таких случаев гораздо больше, где хотелось бы использовать шину. То рано или поздно, кто-то добавит свое решение и команде придется научиться пользоваться этим инструментом. Это видео про то каким может быть этот инструмент :)

  • @shahimsafin9903
    @shahimsafin9903 Рік тому

    Автору огромное спасибо!
    Но у меня возник вопрос: почему isVoiseRecording не хранить в сторе и не диспатчить ему состояние false при начале звонка?

  • @efim.andrii
    @efim.andrii 2 роки тому +2

    Хороший контент. Спасибо.

  • @MrSmit-jg6ex
    @MrSmit-jg6ex 2 роки тому +2

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

  • @romannakoval3624
    @romannakoval3624 2 роки тому +5

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

    • @it-sin9k
      @it-sin9k  2 роки тому +1

      Я что то подобное видел, когда на одном проекте использовали mobX и злоупотребляли reaction на obervable переменные. Идея примерно такая же.
      Я же использую обычно шину для решения каких то узких задач. Например, вам нужно закрывать все попапы, если начался звонок. Т.е. для меня это мост для связи явно не связанного события одной сущности с UI компонентом другой сущности. И в таких случаях у меня даже наверное и не было не одного случая, когда несколько подряд событий вызываются друг за другом. Т.к. я минимально использую шину. Она словно дополняет стейт менеджмент, когда тебе нужно выполнить какую-то базовую операцию. Что то закрыть, что то переключить и т.д.

    • @romannakoval3624
      @romannakoval3624 2 роки тому +3

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

    • @it-sin9k
      @it-sin9k  2 роки тому

      @@romannakoval3624 Прикольный опыт. Я такого рода проекты не видел. Спасибо, что поделились своим опытом!)

    • @EgorMoscowNeverSleep
      @EgorMoscowNeverSleep 2 роки тому

      У нас на проекте, все построено поверх "шины данных" (это сложнее чем простая "шина событий"). Миллионы событий в секунду приходят на центральный сервис и перенаправляются подписчикам. Также реализованы RPC (при этом даже сессия запущенная в окне браузера также может зарегистрировать свой "удалённый метод").
      Конечно, понять логику обработки сотни разных типов событий, задача не тривиальная, однако документация и/или TypeScript спасают.
      А для сложных цепочек событий у нас реализован RequestLogger, который хранит подробности выполнения бизнес-логики (какие события были, в каких модулях/классах, сколько обрабатывались по времени и тд).

    • @grenadier4702
      @grenadier4702 2 роки тому +1

      @@EgorMoscowNeverSleep какой-то дикий оверенджиниринг

  • @meded90
    @meded90 2 роки тому

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

  • @bogdankarpus181
    @bogdankarpus181 2 роки тому +1

    Для полноты примера не хватает визуального присутсвия кода в котором это событие броадкастится

  • @gapnuk2434
    @gapnuk2434 Рік тому

    А зачем в данном примере вообще нужен useEffect? Можно сразу во время рендера компонента вызывать setVoiceRecording и react синхронно перерендерит компонент. Тогда не бедет лишних ререндеров дочених компонентов и изменений в DOM

  • @MrOzziris
    @MrOzziris 2 роки тому +2

    Как всегда топчег

    • @it-sin9k
      @it-sin9k  2 роки тому

      низкий поклон!

  • @maximlyakhov967
    @maximlyakhov967 2 роки тому

    7:00 в чём тут Dependency Inversion, если это классическое сокрытие?

    • @it-sin9k
      @it-sin9k  Рік тому

      в моих глазах инверсия зависимостей идет плечо к плечу с инкапсуляцией. Разница лишь в том, какая из сторон диктует как будет выглядеть интерфейс абстракции. Если интерфейс диктуется принимающей стороной, в таком случае мы должны внутри абстракции создать еще адаптеры, к этому интерфейсу. А что это уже как не Dependency Inversion

    • @maximlyakhov967
      @maximlyakhov967 Рік тому

      @@it-sin9k толсто

  • @ВасилийТеркин-б6з
    @ВасилийТеркин-б6з 2 роки тому +1

    А насколько большой может быть объект subscriptions? Стоит ли создавать один объект subscriptions для проекта и хранить внутри события для оповещения об изменениях компонентам?

    • @it-sin9k
      @it-sin9k  2 роки тому +1

      Учитывая что весь Redux тоже лежит в одном объекте, то пара подписок это вообще не страшно)

    • @pvpshoot
      @pvpshoot 2 роки тому

      @@it-sin9k мне кажется, что подобный подход не будет использоваться часто, это какие-то очень специфичные места, как например в видео, и скорее всего подписок много и не будет, так что хранение в 1 месте не будет вызыать никаких ишью, кмк

  • @Maxim9575
    @Maxim9575 2 роки тому

    И чем это отличается от паттерна Observer?

    • @it-sin9k
      @it-sin9k  2 роки тому

      По факту, шина (это pub / sub паттерн) является одной из вариаций паттерна Observer. Только в паттерне observer ты можешь подписываться на все что угодно на любое поле в любом модуле. А в случае с шиной. У нас есть прослойка в виде eventBus пакета и вся коммуникация идет через этот пакет, но никто не подписывается на данные напрямую

  • @AbraKadabra000
    @AbraKadabra000 2 роки тому

    Юзил паб саб ещё в жыквери. -- до того как это стало мейнстримом)

  • @fedordostoevskiy4209
    @fedordostoevskiy4209 2 роки тому

    Видел уже rxjs в хуки кастомные пробуют. Xstate, кстати тоже ОЧЕНЬ интересная штука. Такие инструменты крутые графические !

  • @_GyG_
    @_GyG_ 2 роки тому

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

  • @nozimjonjuraev2666
    @nozimjonjuraev2666 2 роки тому

    Всем привет, ролик топ спасибо автору, но есть не большой вопрос а можете объяснить простым языком что такое шина, или может у вас есть видео про это? Гугл не помог.

    • @it-sin9k
      @it-sin9k  2 роки тому +4

      Простым языком всегда сложнее всего объяснять))) Идея следующая. У вас есть несколько модулей (может быть как 2 так и 5, точное количество неизвестно). Сколько бы модулей не было, 1 модуль хочет например уведомить все остальное модули о каком то событии ( в нашем видео модуль по работе со звонками, хочет всем сообщить, что звонок начался). Суть шины, заключается в том, что уменьшает связанность между модулями. Модуль звонков уведомляет шину, что звонок начался. А кому надо, пусть подписывается на шину и ждет начало звонка (В нашем случае модуль записи голосового сообщения, слушает начало звонка).

    • @nozimjonjuraev2666
      @nozimjonjuraev2666 2 роки тому

      @@it-sin9k Понял, спасибо

  • @vladimirmaltsev1280
    @vladimirmaltsev1280 2 роки тому

    Спасибо за твои видео, на многое открыл глаза

    • @it-sin9k
      @it-sin9k  2 роки тому

      Рад быть полезным!

  • @VYuhim
    @VYuhim 2 роки тому

    Можно ещё напомнить, что есть возможность реализовать шину на том же редакс строе, у которого есть метод subscribe, который возвращает unsubscribe. Для этого совсем не обязательно пилить свой сервис :)

    • @sovaz1997
      @sovaz1997 2 роки тому +4

      Не надо во все проекты тянуть Redux

    • @Retruntobase
      @Retruntobase 2 роки тому +1

      @@sovaz1997 Звучит по сеньорски

    • @it-sin9k
      @it-sin9k  2 роки тому +1

      Так а зачем нужен redux в таком примере? Потом создавай экшен, думай как его задиспатчить (иногда диспатчить неудобно). А что если в redux еще другие данные, которые тоже тригерят колбек переданный в subscribe. Выглядит бесмысленно сложно

    • @igor_cojocaru
      @igor_cojocaru 2 роки тому +3

      У нас довольно большой проэкт. Три года в разработке и вообще не используем redux. Как говорит Дэн Абрамов, redax нужен в очень малом колличестве проэктов.

    • @it-sin9k
      @it-sin9k  2 роки тому

      А можете сбросить статью или твит или еще где Дэн так говорит)

  • @mercury_2379
    @mercury_2379 Рік тому

    спасибо!

  • @Asda990
    @Asda990 2 роки тому

    Не лучше ли положить event bus в какой-нибудь контекст, чтобы удостовериться, что он один. А то в этом случае надеяться, что при импорте нам вернётся один и тот же закешированный объект не очень хорошо на мой взгляд

    • @it-sin9k
      @it-sin9k  2 роки тому

      Не уловил идею, о каком именно закешированном объекте идет речь. Думаю, если есть переживания, что объект перезатирается кем-то, тогда лучше использовать Object.freeze
      По поводу контекста, я бы не использовал. Так как теперь ваша шина имеет зависимость ввиде реакта. При этом весь этот код будет прокручиваться реактом, не дай бог еще рендеры лишние вызовет, что крайне не желательно.

  • @igor_cojocaru
    @igor_cojocaru 2 роки тому

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

  • @sleepstream9433
    @sleepstream9433 2 роки тому

    Ну да, сэкономили пару рендеров, а дальше импортишь react-spring, который тебе добавляет пару сотен рендеров сверху

    • @it-sin9k
      @it-sin9k  2 роки тому

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

  • @Avenger49StO
    @Avenger49StO 2 роки тому

    На сколько мне известно, такая проблема с рендером относится к React до 17 версии. У Vue2 такого поведения не наблюдал.

    • @modusvivaldi7701
      @modusvivaldi7701 2 роки тому

      Имеете в виду проблему с перерендером при изменении результата селектора? Если речь об этом, то в видео вроде бы всё верно показано: изменения true -> false и false -> true приводят к перерендерам.

  • @danber1893
    @danber1893 2 роки тому

    Привет! Хотел бы узнать в вашу команду не нужен middle специалист, я думаю у тебя есть чему поучиться не только по видосам)

    • @it-sin9k
      @it-sin9k  2 роки тому

      Пока найм мы приостановили, но вероятно опять откроем в районе нового года. Пока критерий найма бы следующий Senior Fullstack JS + гибридное посещение офиса в Минске :)

  • @ВладиславГришин-ш7ш

    что за Язык?

  • @19n1ght
    @19n1ght 2 роки тому +5

    Чтобы не создавать свой велосипед, можно взять RxJS для реализации шины. Замечательный инструмент!

    • @sergeys4732
      @sergeys4732 2 роки тому +1

      XState Machine

    • @it-sin9k
      @it-sin9k  2 роки тому +7

      Не всегда разумно тянуть либу. Тянуть в проект 17.5кб, чтобы использовать RxJS как pub/sub механизм, выглядит как оверлоад. Потом либу надо еще обновлять поддерживать. Удердживать других разрабов использовать RxJS в других частях проекта. Проще кажется добавить 3-4 файла с кодом, добавить тесты к нему и забыть об этом коде на веки вечные

    • @AndriiKuftachov
      @AndriiKuftachov 2 роки тому +3

      @@it-sin9k можно изначально все делать поверх RxJS, тогда все ок.

    • @it-sin9k
      @it-sin9k  2 роки тому +2

      @@AndriiKuftachov если так, то и вопросов нет) Но если в вашем стеке нет (как у большинства React проектов). То добавлять RxJS для шины кажется избыточным

    • @roman3249
      @roman3249 2 роки тому +3

      @@it-sin9k У нас в проекте вообще Rx используют только для того, что бы события к кнопкам прикручивать 😅 И не запариваються 🤣

  • @ПавелБродкин
    @ПавелБродкин 2 роки тому +3

    первый) не смотрел знаю что топ - чуть позже гляну

    • @it-sin9k
      @it-sin9k  2 роки тому

      КрасавчЕГ))

  • @kulakofft4
    @kulakofft4 2 роки тому +4

    Дефолтные эскпорты, чтобы навигация по проекту была максимально "удобной"

    • @vitaliisliusar3089
      @vitaliisliusar3089 2 роки тому +2

      Не все так однозначно, к примеру, что бы использовать React.lazy компоненты которые будут рендериться должны экспортироваться через default export.
      Это конечно не аргумент, но смотрел как-то стрим Дэна Абрамова, он у себя в пэт проекте использовал default export и ему тоже сделали за это замечание, он ответил, что не видит в этом проблемы, так что, наверное, это дело вкуса и привычки

    • @kulakofft4
      @kulakofft4 2 роки тому +1

      @@vitaliisliusar3089 ну если не злоупотреблять, то конечно проблемы не будет. Если, к примеру, в проекте ТС. А если нет ТС, и дефолтные эскпорты через алиасы, то это зло.

  • @litvinenkow
    @litvinenkow 2 роки тому

    неочевидная херня, но да, такое постоянно всплывает

  • @shsh01212
    @shsh01212 2 роки тому +2

    ТЕХНОДРОМ - интересно, специалиста с 1 годом опыта взять на "обучение на реальный проект" и платить ему копейки, а не как мидлу. Прекрасная школа.

    • @Vladyslav_Sliusar
      @Vladyslav_Sliusar 2 роки тому +8

      1 год опыта это мидл?

    • @shsh01212
      @shsh01212 2 роки тому

      @@Vladyslav_Sliusar даже в епаме через год проходишь на миддла какие-то там экзамены. А в какой-нибудь небольшой компании где есть возможность брать большие блоки работы - ещё быстрее, если фигней не страдал а делал что-то

    • @it-sin9k
      @it-sin9k  2 роки тому +6

      вопрос что вы называете копейками и конечно же вопрос почему джуну с 1 годом опыта, должны платить как мидлу о_О

    • @shsh01212
      @shsh01212 2 роки тому

      @@it-sin9k повторяю - даже в такой бюрократий как епам для джунов из рсскул через год аттестация на мидла. Я понимаю что вам заплатили но не надо игнорировать что я написал выше

  • @dulyasdulyas4173
    @dulyasdulyas4173 Рік тому

    Есть способ намного проще - перейти на современный фреймворк, который не рендерит весь компонент от каждого чиха. Реакт диприкейтед

    • @it-sin9k
      @it-sin9k  Рік тому

      что за фреймворк такой?)

    • @dulyasdulyas4173
      @dulyasdulyas4173 Рік тому

      @@it-sin9k солид/свелт

    • @it-sin9k
      @it-sin9k  Рік тому

      @@dulyasdulyas4173 прикольно) надо бы изучить, как там все устроено)