истории внедрения в готовый проект и создания с нуля / Хабр
Привет, Хабр! Этот пост подготовили два разработчика Росбанка — Максим из команды развития фронт-офисных систем и Никита из команды интернет-банка. Речь пойдет о том, как мы делаем микрофронтенды. Сначала расскажем про опыт интеграции в существующий проект, а потом про внедрение с нуля.
Микрофронтенды — это реализация микросервисного подхода для клиентских приложений; по факту, много маленьких независимых монолитов, которые взаимодействуют между собой. Их легко разрабатывать, развертывать, тестировать. При мерже возникает меньше конфликтов, так как релизы у всех независимые. Но при этом усложняется архитектура проектов. Также приходится дополнительно обдумывать взаимодействие микрофронтендов, их типизацию и документацию.
Внедрение микрофронтендов в готовый проект
Есть разные способы сделать это. Опишу те, которые рассматривали мы:
Iframe. Преимущества: изолированность и безопасность (для каждого микрофронтенда поднимается целая страница), простота внедрения.
Недостатки: сравнительно высокое потребление ресурсов и ограниченное пространство отрисовки.
Рендеринг в разные теги на странице. Преимущество: можно использовать разные фреймворки. Недостаток: конкуренция стилей. Важно также учесть, что здесь используется одно окно — этот момент к плюсам и минусам однозначно не отнести.
Module Federation. Преимущества: легкость взаимодействия фронтендов и shared модули. Недостаток: пока можно использовать совместно только React и Vue.
Теперь о проектах. Приложение кол-центра Росбанка предназначено для обслуживания физических лиц, и мы решили туда же добавить возможность обслуживания лиц юридических. Разработкой занималась другая команда в том же репозитории. При мерже появлялось очень много конфликтов, условий и проблем с релизами. Одна команда заканчивала, другая не успевала. В итоге получали очень много лишних условий в коде, прямо if if’ом погонял.
Мы учли ошибки и ко второму подобному проекту — обслуживанию физлиц в дополнительных офисах — решили подойти более обстоятельно. Начали думать, как предотвратить проблемы, и из трех перечисленных выше вариантов пошли через Module Federation, благо в обеих командах проекта пишут на React+Redux.
На иллюстрации выше я скомпоновал конфигурационные файлы. Как видите, всего несколько строчек кода, и в одном проекте мы легко можем использовать модуль, выделенный из другого проекта. В данном случае это компонент React, но на его месте может быть функция, другой объект и вообще что угодно.
Сначала мы подключали микрофронтенд постранично. Скопировали основной репозиторий и убрали из него всю функциональность именно для физических лиц. Остались компоненты UI, надстройки, роутинг и другая логика. Затем развернули там второе приложение, для юридических лиц, и сделали надстройку, которая при переключении вкладок меняет страницу. Такой вот микрофронтенд на минималках:
Первые проблемы начались, когда в приложение для физлиц начали добавляться новые вкладки:
Чтобы то же самое появлялось и для юрлиц, нужно было добавить это вручную в репозиторий. Мы изначально неправильно выделили микрофронтенды — нужно было брать всю «шапку» целиком, чтобы она стала общей для обоих кейсов.
Затем к нам пришли коллеги, работающие с юрлицами. Они хотели перетащить в то же окно вкладки сотрудников, как это сделано у тех, кто работает с физлицами. Всего это порядка 30 вкладок с кучей таблиц и разных модалок.
Переносить вручную было неразумно, и мы пошли через микрофронтенд: взяли компонент, выделили его в отдельный модуль и подключили в другом приложении с помощью Module Federation. И тут же столкнулись с ошибкой: при шаринге компонента таким способом теряется контекст, например, routing или store из Redux. У нас есть множество самописных контекстов, которые отвечают здесь за ролевые модели пользователей. Они тоже пропали.
Эта проблема решается разными способами. Мы можем выделить контекстные провайдеры в отдельные модули и в каждом приложении использовать такой выделенный модуль. Со ссылкой на один и тот же инстанс контекста все заработает само собой. Но мы решили поступить чуть иначе: обернули компонент с вкладками во все имевшиеся контексты и в другом приложении через пропсы прокинули контекст для замены.
Тогда возникла другая проблема. Все наши компоненты берут данные из одного хранилища. В компоненте у нас была информация о пользователе, но в тот момент, когда мы его со всеми вкладками выделили в модуль, при отрисовке на странице в его хранилище этих данных ещё не было. И мы решили передавать хранилище через window.
Какие здесь есть варианты обмена данными между микрофронтендами?
PostMessage — используем его для iframe’ов.
Выделение хранилища в отдельный модуль — это позволит подключать его в каждом микрофронтенде, а затем уже отправлять данные.
Redux-micro-frontend — мы наткнулись на эту библиотеку, когда пытались скрестить два первых способа.
Вот так выглядит схема подключения микрофронтенда к глобальному хранилищу с помощью этой библиотеки. По сути, она добавляет в window инстанс глобального хранилища, где создаются хранилища для других микрофронтендов. И при создании нового хранилища нам возвращается инстанс этого хранилища из глобального хранилища. Так мы в итоге ссылаемся на один объект и можем подписаться на его изменения.
Чтобы общаться с другими микрофронтендами, у нас также дополнительно предусмотрен dispatch global action — своего рода PostMessage между айфреймами, но уже на базе Redux. Если, например, в схеме выше хранилище 2 поддерживает эти экшены, то оно их примет, данные изменятся, соответствующий микрофронтенд получит их и перерендерится.
Вот как в итоге выглядит схема микрофронтендов в проекте дополнительных офисов:
Внутри приложения мы выделяем компоненты в микрофронтенды и подсовываем им хранилище для работы. Хранилище мы регистрируем в хост-приложении. Затем, когда один микрофронтенд будет отрисовываться в странице хост-приложения, он получит данные из своего хранилища, как и остальные микрофронтенды.
В дальнейшем мы планируем разработать UI-kit и оформить всё это в сторибуке. Сейчас UI-компоненты разнесены на два репозитория с разными используемыми приложениями, и это нужно унифицировать. Кроме того, у нас есть проблема с типизацией: для сторонних микрофронтендов типы приходится передавать вручную. Для решения этой проблемы мы подключим динамическую типизацию. Также мы планируем вывести в отдельное хранилище повторяющиеся данные — в частности, информацию о юзерах и ролевой модели.
Внедрение в проект с нуля
Теперь о другом проекте. Из-за возможных санкций нам потребовалось разработать новый интернет-банк. Бэкенд при этом у нас уже был.
Использовали следующий стек: TypeScript, React, Mobx, CSS-модули. Взяли именно Mobx, потому что Redux надоел и хотелось больше объектно-ориентированного подхода в разработке состояния приложения и бизнес-логики. CSS-модули вместо БЭМ использовали, потому что не хотели проблем со стилями в разных репозиториях. Также смотрели в сторону сборщика Vite — хотя во многом он быстрее Webpack, но официально Module Federation разрабатывался именно для Webpack, и версия для Vite имела много проблем (хотя сейчас, возможно, их уже меньше).
Подход через микрофронтенды позволяет разрабатывать приложения с использованием разных репозиториев. Микрофронтенды дают возможность при будущем увеличении числа команд четко разграничивать их зоны ответственности.
Мы используем разные репозитории, и все разработчики могут подтягивать разные их наборы. Нам был необходим шаринг типов — его мы сделали через самописный плагин Webpack. Он генерирует и складирует типы своего микрофронтенда, а также скачивает необходимые типы внешних микрофронтендов. При скачивании он получает d.ts файлы — их можно легко импортировать и типизировать таким образом внешние микрофронтенды. При этом они могут скачиваться локально или с сервера. В любом случае у разработчика будут в распоряжении все нужные типы.
Также нам бы хотелось управлять загрузкой и фоновой подгрузкой компонентов. Suspense и Lazy нам не подходят. Вроде бы в React планируют добавить создание асинхронных компонентов, там можно будет отслеживать загрузку динамических импортов. Надеюсь, это нам поможет.
Еще одна наша потребность — роутинг и шаринг путей по всем микрофронтендам. Маршруты у них всех разные, как внешние, так и внутренние. Мы пробовали делать это на хосте, но попадали на циклическую зависимость и проблемы с типами. Отбросили этот вариант и вынесли всё в отдельный микрофронтенд. Внутренние маршруты у нас изолированы внутри компонента, а внешние хранятся в микрофронтенде и шарятся по приложению.
Мы стараемся поддерживать независимую разработку микрофронтендов. Единственное место, где допускаем пересечение — это UI-kit; там бывают редкие проблемы, которые решаются быстро. При наличии ошибок в коде Husky не позволит сделать коммит и покажет, в чем проблема.
Что хотелось бы добавить в будущем
Было бы здорово конфигурировать приоритет подгрузки микрофронтендов. Или иметь внешние библиотеки для этого, заточенные именно под Module Federation и React.
Также нужен нативный шаринг типов между микрофронтендами при использовании Typescript. В интернете я наткнулся на вопрос разработчику Module Federation: а что делать с типизацией на Typescript? Он ответил, что не разрабатывает на TS и, соответственно, с этим не сталкивался. В обсуждении увидели плагин для скачивания типов с сервера и сделали аналогичный.
И, наконец, шаринг стилей. У нас есть наборы стилей и функций, которые хотелось бы шарить, чтобы вытаскивать код препроцессора SCSS для последующей компиляции. Увы, Module Federation не умеет создавать библиотеки стилей, поэтому мы реализовали это через CSS и CDN.
Итоги
Учитывая все проблемы на пути, мы довольны результатом. Архитектура микрофронтендов работает стабильно, пока кто-нибудь не ошибется со ссылками. Тогда, конечно, возникают ошибки и приложение падает. Но это также опасно и для монолитной архитектуры. Module Federation еще предстоит обкатывать, но все проблемы кажутся вполне решаемыми. Мы ждем больше крутых фичей и надеемся, что этот подход со временем станет стандартом.
МГ-10 • Лаборатория Микроприборов Инерциальный модуль
Skip links
- Skip to primary navigation
- Skip to content
- Описание
- Технические характеристики
- Документация
Инерциальный модуль МГ-10 предназначен для измерения инерциальных воздействий и вычисления ориентации. МГ-10 обеспечивает работу в расширенном диапазоне температур вследствие внутреннего подогрева.
Инерциальный модуль представляет собой блок трехосевых инерциальных датчиков: датчик угловой скорости, акселерометр и магнитометр. Модули МГ-10 индивидуально калибруются в диапазоне рабочих температур.
Инерциальный модуль применяется для широкого круга задач в промышленности, робототехнике и строительной технике.
Общие характеристики
Диапазон рабочих температур | от минус 60 °С до +85 °С |
Напряжение питания | от 4,5 В до 5,5 В |
Потребляемая мощность, не более | 1 Вт |
Неортогональность осей, не более | 0,05 ° |
Масса, не более | 40 г |
Канал угловой скорости
Канал ускорения
Канал магнитометра
Система ориентации
Характеристики подогрева
Характеристики инклинометра
Бриф на продукцию
Габаритный чертёж
STEP-модель
Руководство по эксплуатации
Протокол МГ-10
Помочь с выбором продукции?
Отправьте заявку на консультацию
Пожалуйста, включите JavaScript в вашем браузере для заполнения данной формы.
введите имя*
Телефон *
введите телефон*
E-mail *
укажите почту*
Рассылка
- Соглашаюсь получать рассылку и новости компании
Сколько будет *
=
Comment
Пожалуйста, включите JavaScript в вашем браузере для заполнения данной формы.Имя *
Название компании *
Введите название компании или сайт
Email *
Выберите документ: *Прошивка …Прошивка МГ-1
Captcha *
=
Рассылка
- Соглашаюсь получать рассылку и новости компании
Ваше имя *
Название вашей компании / сайт *
Ваш номер телефона
Ваш E-mail *
Какую задачу вы планируете решать с помощью демонстрационного ПО? *
Captcha *
=
Comment
Пожалуйста, включите JavaScript в вашем браузере для заполнения данной формы.
Имя *
Введите ваше имя
Компания *
Название компании
Введите ваш e-mail
Выберите документ: *Руководство по работе …Рук-во по работе с демо ПО
Рассылка
- Соглашаюсь получать рассылку и новости компании
Comment
Задать вопрос
Введите ваше сообщение ниже, и мы свяжемся с вами в рабочее время. Все поля обязательны для заполнения
Пожалуйста, включите JavaScript в вашем браузере для заполнения данной формы. Имявведите имя
введите название компании*
Телефон *
введите телефон*
Почта *
Ваш вопрос *
Сколько будет *
=
Согласие на рассылку
- Соглашаюсь получать рассылку и новости компании
Name
Скачать руководство по эксплуатации
Заполните форму и получите доступ к руководствам по эксплуатации.
Имя *
Введите ваше имя
Компания *
Название компании
Введите ваш e-mail
Выберите документ: *Руководство по эксплуатации …Рук-во по эксплуатации ГКВ-1 ОЕМРук-во по эксплуатации ГКВ-5/6/7 (общее)Рук-во по эксплуатации ГКВ-10/11/12 (общее)Рук-во по эксплуатации МГ-10Рук-во по эксплуатации МГ-1Рук-во по эксплуатации ТГ-18Рук-во по эксплуатации ТГ-18АРук-во по эксплуатации ТГ-19Рук-во по эксплуатации Комплекта отладочного ГКВ-1 ОЕМ
Рассылка
- Соглашаюсь получать рассылку и новости компании
Website
Скачать протокол
Заполните форму и получите доступ к протоколу
Пожалуйста, включите JavaScript в вашем браузере для заполнения данной формы.Имя *
Введите ваше имя
Компания *
Название компании
Введите ваш e-mail
Выберите документ: *Протокол. ..Протокол МГ-1Протокол МГ-10Протокол ГКВПротокол ТГ-18Протокол МА-10Протокол CAN-интерфейс
Рассылка
- Соглашаюсь получать рассылку и новости компании
Website
интуиция — Как объяснить ученикам, что $0 \bmod n$ равно $0$?
спросил
Изменено 3 года назад
Просмотрено 67 тысяч раз
$\begingroup$
Я преподаю начальный курс программирования на Visual Basic (для не-CS). Я сказал своим студентам, что оператор мода в основном дает остаток от деления. Итак, увидев $0 \bmod 10$, некоторые студенты (очевидно) решили, что » $10$ переходят в $0$ ноль раз, и остается $10$. »
Как лучше всего объяснить это студентам (не изучающим математику и не изучающим информатику)?
Я бы предпочел возразить » 10$ превращаются в 0$ ноль раз, а 10$ остаются »
- интуиция
- модульная арифметика
- образование
$\endgroup$
5
$\begingroup$
$10$ переходят в $0$ ноль раз, и остается $0$.
Вернитесь к тому, как вы учили его в третьем или четвертом классе: $$ \begin{массив}{ccccccc} & & 0 \\\\ 10 & ) & 0 \\ & & 0 \\ \hline & & 0 \конец{массив} $$ Остаток $0$.
$\endgroup$
11
$\begingroup$
Если вам нужно интуитивное объяснение, скажите им, что остаток не должен быть больше размера чашки (делителя), которым вы набираете воду из емкости (делителя), потому что, если бы в емкости было больше воды, чем размер чашки, вы всегда могли бы возьмите еще одну полную чашку.
Я также думаю, что было бы неплохо показать им уравнение алгоритма деления: $$a = bq + r$$ чем подставить переменные $$0 = 10 q + г$$ и покажите им, что допустима только замена $q$ и $r$ на $0$ и $0$, потому что $0$ и $10$ приведут к ложному равенству $0 = 10$.
$\endgroup$
1
$\begingroup$
На самом деле это проще объяснить, чем большинство пытается сделать. Пример:
4mod2 = 2 находится внутри 4 два раза, а остальное равно 0 Итак, если вы сделаете «if(4%2 == 0)», это будет правдой. в случае «if(i%2 == 0)» это также будет верно для i=0. Почему это так? Потому что остаток по модулю не зависит от знаменателя. если у вас есть 0 в качестве числителя, остальное никогда не будет больше, чем сам числитель. Неважно, насколько велик ваш знаменатель. например x%y =>

Скажите, если у вас нет пиццы и вы хотите раздать пиццы 10 ученикам, сколько пицц останется? Точно, ноль. Ваши ученики рассуждали, что 10 учеников хотят съесть 0 пицц, но осталось 10 пицц. Так что на самом деле вы должны показать им, что осталось 10 студентов с пустыми желудками, но до сих пор нет пиццы на столе. (студенты всегда голодны, это сработает)
$\endgroup$
$\begingroup$
Если вы обучаете будущих программистов, в какой-то момент вам нужно будет упомянуть теорему о делении. Хотя ответ Харди, безусловно, лучше всего подходит для конкретного вопроса, который вы задали, вашим ученикам также потребуется некоторое руководство, когда речь идет об отрицательных числах.
Например, что вы ожидаете от -22 Mod 3
или 7 Mod -2
? Поначалу результаты могут показаться загадочными, но они явные следствия отношения к целочисленному делению, которое, как мне кажется, всегда округляется до 0 в Visual Basic.
Другие языки могут обрабатывать округление иначе, но уравнение a = b * (a div b) + (a mod b)
кажется универсальным.
$\endgroup$
$\begingroup$
Нет никакой проблемы $0$ равно $0\times10+0$, что означает, что остаток евклидова деления равен нулю. Вы можете сделать это для каждого положительного целого числа.
$\endgroup$
$\begingroup$
Мне тоже сложно составить формулировку вопроса. Но если бы кто-то попросил меня объяснить им $0 \mod 10 \equiv 0$, я мог бы сказать одну из следующих трех вещей.
Все конгруэнтно само себе. То есть, если бы я сказал $x \mod 10 \equiv x$, это верно для всех $x$. Но, возможно, это не вдохновлено.
$10$ делится на $0-0$. Это стандартное (по крайней мере, то, которое я считаю стандартным) определение мода, поэтому $0 \equiv 0$.
По алгоритму деления мы видим, что $0 = 0 \cdot 10 + 0$, так что (читая два внешних числа) $0 \equiv 0$.
$\endgroup$
$\begingroup$
Мне помогло, я изучаю программирование.
- 0%2 = 0 (0/2 = 0, остаток 0)
- 1%2 = 1 (1/2 = 0, остаток 1)
- 2%2 = 0 (2/2 = 1 остаток 0)
- 4%2 = 0 (4/2 = 2, остаток 0)
- 5%2 = 1 (5/2 = 2 остаток 1)
$\endgroup$
$\begingroup$
Остаток от деления при $k>0$ должен быть равен некоторому числу от $0$ до $k-1$. Теорема об остатке от деления должна обрабатывать все остальное.
$\endgroup$
$\begingroup$
Подумай об этом так.
x mod n, где n > 0 и x > 0.
Например, x = 49 и n = 10. Поскольку нас нет, осталось 9.
Однако откуда у x может что-то остаться, если не с чего было начинать.
I.E x = 0.
0 mod n == 0, так как сначала не на что было делить, поэтому не может быть остатка.
$\endgroup$
$\begingroup$
Вы сказали интуиция?
Операция по модулю находит остаток после деления одного числа на другое.
A mod B
Но когда дело доходит до интуиции и понимания логики за кулисами, операция по модулю — это расстояние от НУЛЯ при движении в направлении A в диапазоне B.
Расстояние, выделенное оранжевым цветом:
$\endgroup$
python — как подсчитать модуль 0 в списке
спросил
Изменено 3 года, 8 месяцев назад
Просмотрено 643 раза
Я создал список и итерационный цикл для этого списка. Я пытаюсь подсчитать все четные числа, используя оператор модуля. Я инициализировал переменную count и использовал приращение счетчика и оператор if, чтобы поймать все четные числа во вложенном цикле. Однако все, что я получаю, это номер один. count равен 1, это из-за неправильного использования модуля, а item = 10, это из-за того, что итерационный цикл достигает конца списка?
Я не знаю, что изменить, со структурой кода мне все в порядке. Я попытался сделать отступ для функции печати. Это показало мне, что модуль улавливает четные числа, но подсчет не суммирует их.
список = [1,2,3,4,5,6,7,8,9,10] для элемента в списке: количество = 0 если (элемент % 2 == 0): количество = количество + 1 распечатать (количество) печать (элемент) распечатать (список)
Я ожидаю число 5 в результате работы программы, так как в списке 5 четных чисел
- python
- количество
- модуль
2
Поместите count=0
вне цикла for.