Об авторе Директор Ant Financial Data Experience Техническая группа
Группа внешнего интерфейса платформы данных Ant Financial в основном отвечает за несколько одностраничных веб-приложений для ПК, связанных с данными. Бизнес-сложность аналогична сложности настольных приложений, таких как Excel. Объем внешнего бизнес-кода варьируется от десятков от тысяч до сотен тысяч строк.С постоянным улучшением продуктов, разбить миллион не за горами. Управление интерфейсными приложениями со 100 000 или даже миллионами строк кода — одна из основных задач нашей команды.
В следующей серии статей я попытаюсь представить подход нашей команды к проблеме со следующих точек зрения:
- Интерфейсная архитектура
- Гарантия качества
- оптимизация производительности
- Процесс фронтенд-разработки в команде
- Качество персонала
Интерфейсная архитектура
Архитектурное решение группы представляет собой набор архитектурных решений, которые подходят для бизнес-сценариев группы продуктов данных посредством непрерывной итерации нескольких продуктов в течение одного года.В архитектурном решении все еще есть нерешенные болевые точки и спорные части, которые необходимо постоянно оптимизировать. Нет гарантии, что эта архитектура подойдет для вашего продукта.
Функции
Во-первых, давайте представим особенности продукта нашей команды:
- Продукты ToB имеют высокую сложность бизнеса и высокий порог понимания бизнеса;
- Объем внешнего кода огромен (продукт анализа данных прошел 8 месяцев итерации с нуля с 80 000 строк бизнес-кода, и только 20% требований долгосрочного планирования продукта были реализованы)
Схема архитектуры
Цель архитектуры состоит в том, чтобы управлять сложностью, разделять и властвовать над сложными проблемами, а также эффективно управлять ими.Наши конкретные методы заключаются в следующем:
1. Сначала вырезайте функциональные модули с детализацией «на уровне страниц» посредством маршрутизации.
Детализация «на уровне страницы» здесь относится к компоненту с отображением маршрута.
2. Разделение модулей на одной «странице»
Принцип деления:
- портрет: Разделено по бизнес-функциям (о которых можно судить по модулю просмотра)
- горизонтальный: разделен на три разные функции Model-View-Controller
3. Объединяйте похожие элементы
Продолжайте разделять детализацию, а затем извлекайте повторно используемые модули или компоненты в общую область.
3.1 Модель данных
Модели данных делятся на две категории в зависимости от обязанностей:
- Модель предметной области Модель предметной области
- Модальная модель состояния приложения
3.1.1 Модель предметной области
Модель предметной области — это бизнес-данные, которые часто сохраняются в базе данных или локальном хранилище и относятся к общедоступным данным, которые можно повторно использовать в модулях, например:
- Информация о пользователях
- Наборы данных Информация о наборе данных
- Отчеты сообщают информацию
В качестве общедоступных данных модель предметной области рекомендуется хранить в единомDomain Model LayerАрхитектура является независимой многоуровневой (отрасль фронтенда обычно называет этот уровень уровнем ORM).
Погружение в уровень модели предметной области имеет много преимуществ:
- Проблема межмодульной синхронизации данных больше не существует, например: Ранее объект «Пользователи» хранился отдельно в двух бизнес-модулях A и B. После изменения объекта «Пользователь» в модуле A изменение «Пользователи» необходимо синхронизировать с модулем B. Если оно не синхронизировано, информация о пользователе, представленная модулями A и B на интерфейсе, несовместима, после перехода на уровень модели предметной области для унифицированного управления проблема больше не существует;
- Помимо повторного использования модели предметной области, также можно повторно использовать редукторы CRUD, связанные с моделями предметной области., например: предыдущий метод Create Read Update Delete, соответствующий объекту Users, может поддерживать по одному набору в каждом из двух бизнес-модулей A и B, а после перехода на уровень модели предметной области для унифицированного управления проблема дублирования кода уменьшается ;
- Естественно, взял на себя некоторые обязанности по обмену данными между модулями.код межмодульной связи, ранее связанный с синхронизацией данных, больше не нужен;
3.1.2 Модель состояния приложения
Модель состояния приложения — это данные состояния, связанные с представлением, такие как:
- Текущая страница выбирает n-ю строку списка currentSelectedRow: someId
- Открыто ли окно isModalShow: false
- Перетаскивается ли определенный элемент представления isDragging: true
Эти данные тесно связаны с конкретными модулями представления или бизнес-функциями, и их рекомендуется хранить в модели бизнес-модуля.
3.2 Просмотр компонентов слоя
Компоненты делятся на две категории в соответствии с их обязанностями:
- Компонент контейнера
- Презентационный компонент
3.2.1 Компоненты контейнера
Компоненты-контейнеры — это компоненты, которые напрямую подключены к хранилищу, предоставляя данные и поведение для компонентов представления или других компонентов-контейнеров, и стараются избегать выполнения в них некоторых действий, связанных с отрисовкой интерфейса.
3.2.2 Компоненты дисплея
Презентационный компонент не зависит от других частей приложения, не заботится о загрузке и изменении данных, несет единственную ответственность и выполняет только представление представления и самые основные интерактивные действия.props
Получите данные и выходные результаты функции обратного вызова, убедитесь, что полученные данные являются минимальным набором зависимостей данных компонента.
В сложной системе с сотнями компонентов дисплея, если гранулярная сегментация компонентов дисплея может хорошо следовать принципам высокой связности, низкой связанности и единой ответственности, можно выделить много повторно используемых компонентов.Общие бизнес-компоненты.
3.3 Государственные услуги
- Все HTTP-запросы объединяются для унифицированного управления;
- Служба журнала, служба локального хранилища, мониторинг ошибок, фиктивная служба и т. д. единообразно хранятся на уровне общедоступных служб;
После объединения схожих элементов в соответствии с тремя вышеуказанными пунктами диаграмма бизнес-архитектуры изменяется на
4. Межмодульное взаимодействие
Гранулярность модулей постепенно уточняется, что будет предъявлять больше требований к межмодульному взаимодействию.Чтобы избежать взаимной связи между модулями и гарантировать, что архитектура будет чистой и ремонтопригодной в течение длительного времени, мы оговариваем:
- Не допускается прямой вызов метода Dispatch других модулей внутри модуля (операции записи, изменение состояния других модулей)
- Не допускается прямое чтение метода состояния других модулей внутри модуля (операция чтения).
Мы рекомендуем размещать логический код для межмодульной связи в родительском модуле или вMediatorОтдельно хранится слоями.
Наконец, мы получаем полную диаграмму архитектуры бизнес-логики нашей команды:
управление потоком данных
Я только что говорил о схеме управления архитектурой из пространственного измерения, а теперь я говорю о потоке данных приложения из временного измерения — одностороннем потоке данных Redux.
Ядром архитектуры Redux является односторонний поток данных.Все данные в приложении должны следовать одному и тому же жизненному циклу, чтобы обеспечить предсказуемость состояния приложения.
1. Action
- Поведение пользователя: нажмите и перетащите ввод...
- Сервер возвращает последующее поведение данных
2. Reducer
Каждое действие соответствует функции обработки данных, а именно редьюсеру. Особо подчеркивается, что Reducer должен быть чистой функцией.Это регулирование приносит очень большую пользу.Код слоя обработки данных становится очень простым для написания юнит-тестов.
Характеристика чистых функций заключается в том, что при одинаковых входных параметрах возвращаемое значение одинаково, например:
Чистая функция:
function add(a, b) {
return a + b;
}
Нечистая функция:
function now() {
let now = new Date();
return now;
}
Если функция содержитMath.random
,new Date()
, асинхронные запросы и т.п., и влияют на возврат конечного результата, то есть нечистой функции.
3. Store
Хранилище — это место, где хранятся данные. В хранилище хранится состояние данных (состояние), созданное всеми операциями Action с момента входа на страницу. Каждое изменение данных, вызванное действием, должно генерировать новый объект состояния и гарантировать, что старый объект состояния не модифицированный. Это гарантирует Предсказуемое и отслеживаемое состояние приложения также облегчает разработку функций Redo/Undo.
Наша команда использует легкое неизменное решениеimmutability-helper
, который имеет лучшую производительность и более высокий уровень использования дискового пространства, чем полная копия (глубокое клонирование).
immutability-helper
API недостаточно дружелюбный, мы написали библиотекуimmutability-helper-xповысить удобство его использования.
Стиль API-помощника неизменности:
import update from 'immutability-helper';
const newData = update(myData, {
x: {
y: {
z: { $set: 7 }
}
},
});
Стиль API immutability-helper-x:
import update from 'immutability-helper-x';
const newData = update.$set(myData, 'x.y.z', 7);
4. Единый вид рендеринга
React/Redux — это типичная среда разработки, управляемая данными (Data-Driven-Development).В процессе разработки мы можем больше сосредоточиться на работе и потоке данных (модель предметной области + модель состояния) и больше не беспокоиться о различные громоздкие коды манипулирования DOM, когда хранилище изменится, платформа React/Redux поможет нам автоматически и единообразно отобразить представление.
Функция прослушивания изменений Store для обновления представления выполняется react-redux:
- компонент
через context
Атрибут предоставляет объект хранилища потомкам компонентов; — это высокоуровневый компонент, который используется для подключения компонентов хранилища и уровня представления (это повторяется здесь, redux официально определяет компонент, напрямую подключенный через , как компонент-контейнер), а — открыто для разработчиков.Хук функции обратного вызова (mapStateToProps, mapDispatchToProps...) используется для настройки положения реквизита, введенного в компонент-контейнер; - react-redux прослушивает изменения в хранилище избыточности. После изменения хранилища он уведомляет каждый компонент подключения о необходимости обновить себя и его дочерние компоненты. Чтобы уменьшить количество ненужных обновлений и повысить производительность, подключение реализует метод shouldComponentUpdate. Если реквизиты остаются неизменными , контейнер пакета подключения не будет обновляться.
Суммировать
Строгое следование спецификации архитектуры и спецификации одностороннего потока данных может обеспечить ремонтопригодность и масштабируемость наших клиентских приложений с относительно грубой детализацией.Для более мелкозернистого кода мы организуем детскую обувь, чтобы учиться и делиться ею."Шаблоны проектирования"а также«Рефакторинг — улучшение дизайна существующего кода», продолжать полировать и оптимизировать собственный код, и в будущем команда продолжит выпуск серии статей по этому поводу.
В этой статье сначала рассказывается об общей архитектуре интерфейса, а бизнес-архитектура конкретных модулей, принципы, которым следует архитектура, а также процесс обзора архитектуры группой по архитектуре команды будут описаны в следующей серии статей. Заинтересованные студенты могут следить за колонкой или отправлять свои резюме на tao.qit####alibaba-inc.com'.replace('####', '@'). Приглашаются люди с высокими идеалами~
Оригинальный адрес:GitHub.com/proto team/no…