Управляйте сложностью внешнего интерфейса проекта с помощью Feature First

внешний интерфейс

что такое сложность

Тремя причинами сложности программных систем являются размер, структура и изменения.

По трем причинам мы можем упростить систему следующими способами:

  • Разделяй и властвуй, Контрольная шкала
  • Держите структуру ясную и последовательную
  • Примите перемены

Как в соответствии с этими принципами организовать файловую структуру и управлять сложностью интерфейсных проектов?

Два распространенных способа организации файловой структуры во внешних проектах

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 «сосредоточена» на функциях и целях.

Разделение «язык» и разделение «компонент»

(Источник изображения:A feature based approach to React development)

Разделение «Функциональность»

(Источник изображения:Why React developers should modularize their applications?)

Какой путь вы должны пойти?

Характеристики File-Type First: лаконичность, прямота, соответствие интуиции разработчика. С другой стороны, Feature First имеет преимущество в управлении сложностью крупномасштабных проектов.

Глубокое погружение в организацию файлов Feature First.

Преимущества файловой организации Feature First:

  1. Код легко найти и найти Способ организации кода отражает структуру продукта и соответствует требованиям продукта.

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

  3. Включить механизм флагов функций

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/detailView
  • features/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/components
  • src/features/user/pages/listView/components
  • src/features/user/pages/components
  • src/features/user/components
  • src/features/components
  • src/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 目录.

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

использованная литература


Автор статьи: Конг Чанчжу

BDEEFE уже давно набирает выдающихся фронтенд-инженеров по всей стране.Потребности в подборе персоналапонимать?