что такое сложность
Тремя причинами сложности программных систем являются размер, структура и изменения.
По трем причинам мы можем упростить систему следующими способами:
- Разделяй и властвуй, Контрольная шкала
- Держите структуру ясную и последовательную
- Примите перемены
Как в соответствии с этими принципами организовать файловую структуру и управлять сложностью интерфейсных проектов?
Два распространенных способа организации файловой структуры во внешних проектах
File-Type First (FTF)
«Упорядочить по типу файла», который также является наиболее распространенным методом организации во внешних проектах. Например:
src
├── index.js
├── components
│ ├── index.js
│ ├── footer
│ ├── header
│ ├── posts
│ └── users
│ ├── UserDetail.js
│ └── UserList.js
├── containers
│ ├── home
│ ├── posts
│ │ └── index.js
│ └── users
│ └── index.js
├── actions
│ ├── posts.js
│ └── users.js
├── reducers
│ ├── posts.js
│ └── users.js
└── sagas
├── posts.js
└── users.js
Feature First
«Организовано по функциональным характеристикам». Например:
src
├── components
│ ├── footer
│ ├── header
│ └── index.js
├── features
│ ├── posts
│ │ ├── action.js
│ │ ├── components
│ │ │ └── index.js
│ │ ├── containers
│ │ │ └── index.js
│ │ ├── reducers.js
│ │ └── sagas.js
│ └── users
│ ├── action.js
│ ├── components
│ │ └── index.js
│ ├── containers
│ │ └── index.js
│ ├── reducers.js
│ └── sagas.js
└── index.js
Различия в «разделении интересов»
Две файловые организации делают «разделение проблем» разным пониманием «проблем».
- «Точка следования» File-Type First — это технология и средства.
- Feature First «сосредоточена» на функциях и целях.
Разделение «язык» и разделение «компонент»
Разделение «Функциональность»
Какой путь вы должны пойти?
Характеристики File-Type First: лаконичность, прямота, соответствие интуиции разработчика. С другой стороны, Feature First имеет преимущество в управлении сложностью крупномасштабных проектов.
Глубокое погружение в организацию файлов Feature First.
Преимущества файловой организации Feature First:
-
Код легко найти и найти Способ организации кода отражает структуру продукта и соответствует требованиям продукта.
-
Код легче поддерживать Каждая функция изолирована. При изменении кода одной функции это не повлияет на другие функции. Когда несколько функций разрабатываются параллельно, конфликтов, возникающих во время слияния, можно избежать в большей степени.
-
Включить механизм флагов функций
Feature FlagЭто технология, которая открывает функции через конфигурацию без передислуги кода.
Такие требования, как A/B-тестирование, также могут быть реализованы с помощью флагов функций.
Пример кода:
// features.json
{
...,
portal: true,
users: true,
posts: false
}
// index.js
export function isFeatureEnabled(feature) {
return features[feature] || false;
}
Перенести Feature First в конец
Если функция является сложной, ее можно разделить, чтобы сформировать вложенную структуру функции. Например: разделить функции/пользователей на
features/users/features/detailViewfeatures/users/features/listView
src
├── features
│ └── users
│ ├── components
│ │ ├── Table.js
│ │ └── index.js
│ └── features
│ ├── index.js
│ ├── detailView
│ │ └── components
│ │ └── Detail.js
│ └── listView
│ └── components
│ └── List.js
└── index.js
Как организовать общие компоненты в приложении
Некоторые компоненты повторно используются в функциях, а некоторые компоненты повторно используются на страницах в рамках одной и той же функции. Чтобы обеспечить хорошую ремонтопригодность, организация общих компонентов должна следовать четким правилам.
Ниже приведена схема для справки. (index.js в каталоге компонентов отвечает только за экспорт компонентов и не реализует конкретных функций)
src
├── components
│ ├── Notification.js
│ └── index.js
├── features
│ ├── posts
│ │ └── components
│ │ └── index.js
│ └── users
│ ├── components
│ │ ├── Table.js
│ │ └── index.js
│ └── features
│ ├── index.js
│ ├── detailView
│ │ └── components
│ │ └── Detail.js
│ └── listView
│ └── components
│ ├── List.js
│ ├── Title.js
│ └── components
│ ├── index.js
│ ├── Pagination.js
│ └── components
│ └── index.js
└── index.js
Подумайте об этом, в приведенной выше структуре проекта,src/features/users/pages/listView/components/List.jsКакие компоненты можно использовать совместно?
Далее, давайте рассмотрим их один за другим:
-
src/componentsВнутри размещены общие компоненты для всего приложения, поэтому List может использовать их все. -
src/features/posts/componentsЭто функция, отличная от List, поэтому ее компоненты использовать нельзя. -
src/features/users/pages/detailView/components, хотя он принадлежит к той же функции, что и список, если это разрешено изlistViewприбытьdetailView«Ссылка на том же уровне» также усложнит ссылку на файл в Feature. Поэтому такие ссылки также запрещены. -
src/features/users/pages/listView/components/components(каталог компонентов на том же уровне, что и список), подкомпоненты списка помещаются в каталог компонентов того же уровня, поэтому доступ разрешен. -
src/features/users/pages/listView/components/components/component(Компоненты подуровня каталога компонентов на том же уровне, что и список), «межуровневые ссылки» также увеличат сложность, поэтому такие ссылки также не допускаются.
Описанную выше ситуацию можно описать одним предложением:
За исключением файлов в том же каталоге, компоненты могут ссылаться только на каталог компонентов по пути каждого уровня файла, в котором они расположены.
Будуsrc/features/user/pages/listView/components/List.jsРазвернуться по вышеуказанным правилам:
src/features/user/pages/listView/components/componentssrc/features/user/pages/listView/componentssrc/features/user/pages/componentssrc/features/user/componentssrc/features/componentssrc/components
Увидев это, вы, возможно, нашли знакомую фигуру. Да, это очень похоже на правила поиска модулей в CommonJS.
что положить в каталог компонентов? Строгое значение каталога компонентов состоит в том, чтобы размещать подкомпоненты, которые повторно используются только родственными компонентами. Например, указанный выше каталог компонентов на том же уровне, что и список, должен хранить подкомпоненты, которые повторно используются только списком и заголовком.
Сложность проекта выходит за рамки возможностей
новый логический уровень
В приложениях уровня предприятия, таких как управление талантами и управление финансами, только приложение и функция больше не могут соответствовать структуре продукта, как ожидалось.
На этот раз нам нужен новый логический уровень, такой как: Решение. Решение содержит несколько приложений, и каждое приложение имеет несколько функций.
Благодаря новому логическому уровню решения исходная функция может быть разделена на разные приложения в соответствии со связностью. По сравнению с Feature связь между приложениями меньше, и его можно даже использовать как независимую единицу развертывания.
От мультимодуля к мультипакету
Масштабы проекта выросли, и возникли проблемы управления зависимостями. Чтобы уменьшить зависимости между функциями и еще больше изолировать приложения, Модули, которые повторно используются в приложениях, нельзя просто импортировать.
Чтобы уменьшить связь между приложениями, блок мультиплексирования необходимо инкапсулировать в пакет. Затем каждое приложение объявляет зависимости в package.json. Точно так же в глазах Solution каждое приложение также является пакетом.
При переходе от многомодульного к многокомпонентному сопряжение уменьшается, Но это также приносит новые затраты на разработку, и эти проблемы можно решить с помощью таких инструментов, как Lerna.
Использование Lerna может решить проблему управления зависимостями и версиями, кроме того, необходимо хорошо поработать над многоуровневым дизайном пакета.
Иерархический дизайн в управлении несколькими пакетами
Приложение — это пакет, и модуль, от которого зависит приложение, также является пакетом. Тем не менее, два типа пакетов отличаются по качеству.
Чтобы сделать структуру проекта более понятной и понятной, нам необходимо выделить эти пакеты и выполнить иерархическое проектирование. Например:
packages
├── solutions
│ ├── login.sln
│ ├── finance.sln
│ └── people.sln
├── apps
│ ├── portal.app
│ ├── financial-management.app
│ ├── recruting.app
│ └── global-search.app
├── biz-libs
│ ├── workflow-engine
│ ├── rendering-engine
│ └── network
├── base-libs
│ ├── ui-components
│ └── animations
└── vendor-libs
├── router
└── state-manager
Суммировать
По сравнению с файловой организацией File-Type First, Feature First имеет очевидные преимущества в улучшении ремонтопригодности крупномасштабных проектов.
- Легче найти и найти файлы кода;
- При рефакторинге и модификации кода лучше контролируйте сферу влияния;
- Удобнее использовать Feature Flags;
При организации общих компонентов в приложении вы можете следовать аналогичному подходу к поиску модулей в CommonJS:组件只引用其所在文件各级路径下的 components 目录.
В крупномасштабных проектах, таких как приложения корпоративного уровня, сложность проекта можно дополнительно контролировать, вводя новые логические уровни и управление несколькими пакетами.
использованная литература
- Углубленный анализ сложности программного обеспечения
- feature-u: Feature Based Project Organization for React
- A feature based approach to React development
- How to better organize your React applications?
- How to use Redux on highly scalable javascript applications?
- 100% правильный способ структурирования приложения React (или почему нет такой вещи)
Автор статьи: Конг Чанчжу
BDEEFE уже давно набирает выдающихся фронтенд-инженеров по всей стране.Потребности в подборе персоналапонимать?