В связи с быстрым появлением новых интерфейсных технологий и растущим спросом со стороны продукта на более сложный пользовательский интерфейс и пользовательский интерфейс, стало труднее поддерживать и управлять логикой во внешнем интерфейсе. В простом приложении с простым продуктом, не имеющим сложных запросов от внешнего интерфейса, легко управлять большим количеством кода в отдельных файлах или, в лучшем случае, разделять их на основе их основного домена.
Но недавно в Fiverr мы обнаружили ряд больших файлов, содержащих тысячи строк кода, которые не только очень сложно управлять, но и поддерживать.
В этой статье мы обсудим, что такое папка по типу / домену, почему ее так сложно поддерживать в крупномасштабном приложении, и представим лучший подход, а также его плюсы и минусы.
Папка по типу / домену
├── javascript │ ├── user.js ← — — feature #3 │ ├── order.js ← — — feature #2 | └── gig.js ← — — feature #1 ├── css │ ├── user.scss ← — — feature #3 │ ├── order.scss ← — — feature #2 │ └── gig.scss ← — — feature #1 ├── spec │ ├── user.js ← — — feature #3 │ ├── order.js ← — — feature #2 │ └── gig.js ← — — feature #1 ├── images │ └── user_default.jpg ← — — feature #3
Чтобы работать с этой структурой, вам придется работать с 3 разными большими папками. В крупномасштабном приложении это создает ряд проблем:
- Не масштабируемый - как только вы ограничите структуру папок одним типом, этот тип может легко превысить разумное количество файлов и станет трудным в обслуживании - в крупномасштабных приложениях вы можете легко закончить управление 100 различными css / js / файлы любого типа.
- Не модульный - с помощью таких сборщиков модулей, как webpack, browserify и т. д., мы можем создавать модули / файлы меньшего размера и использовать их в различных областях нашего кода.
- Сложно работать. Допустим, вы хотите удалить объект. Если функция связана и записана внутри большого файла, ее сложнее удалить или даже провести рефакторинг.
- Приводит к большим файлам - поскольку такая структура не поощряет модульный код, мы имеем тенденцию получать большие файлы в монолитном стиле, которые сложно реорганизовать и с которыми трудно работать.
- Склонность к конфликтам - в больших приложениях у вас есть большие группы, которые в рамках такой архитектуры могут работать с одними и теми же файлами, что приводит к путанице, конфликтам и гораздо большему общению, чем необходимо.
Для небольших приложений структура папок, подобная приведенной выше, может иметь смысл, но если вы планируете расширяться и масштабироваться, вам следует вместо этого рассмотреть следующую структуру.
Папка по функциям
Поскольку мы стремимся разработать крупномасштабное веб-приложение, используемое многими разными командами и разработчиками, нам нужно что-то модульное, простое в обслуживании и удобном для навигации.
├── gig ← — — feature #1 │ ├── gig.js │ ├── gig.scss │ ├── gig.spec.js │ └── index.js ├── order ← — — feature #2 │ ├── index.js │ ├── order.js │ ├── order.scss │ └── order.spec.js └── user ← — — feature #3 ├── index.js ├── user.js ├── user.scss ├── user.spec.js └── user_card ← — — feature #4 ├── index.js ├── user_card.js ├── user_card.scss ├── user_card.spec.js └── user_default.jpg └── user_default.jpg
Преимущества такой конструкции:
- Высокомодульный - модульный код - это код, который легко поддерживать.
- Архитектура по продукту. Если мы разделим код на основе функций, нам будет легко владеть / делиться / разделять код между разными командами. Таким образом, наш код не только отражает крупномасштабное клиентское веб-приложение, он также отражает большие команды, группы и т. Д.
- Легко реорганизовать - поскольку наш код написан небольшими фрагментами, в будущем его будет проще реорганизовать. Хороший код - это код, который в будущем можно будет реорганизовать. Плохой код - это код, который мы не можем рефакторировать, и его нужно будет переписать с нуля.
- Дружественность к команде - поскольку у нас много разработчиков из разных команд, нам нужно, чтобы они работали в относительно изолированных средах без каких-либо конфликтов кода.
- Сократите ненужное общение - очень маловероятно, что разные команды будут работать с одними и теми же файлами или изменять одни и те же функции или модули, поскольку структура папок побуждает разработчиков писать автономный модульный код.
Как и во всем, у этой структуры есть свои минусы:
- Сложнее научиться - легко сделать структурные ошибки, когда ваше приложение не ограничено типами - когда у вас есть 2, 3 или 4 основные папки для работы, легче понять, где разместить ваши недавно созданные файлы.
- Вложенный ад - вы можете легко найти свое приложение, содержащее 20 уровней папок, поэтому вам всегда нужно быть уверенным, что вы создаете свое приложение как можно более плоским, даже с папкой по структуре функций.
Как давать названия папкам / файлам
Если вы выберете папку по пути к функции, легко попасть в ловушку и назвать свои папки или файлы общими именами, такими как: ввод, кнопка, компоненты, действия, редукторы и т. Д. Но если вы используете эти имена, вам нужно знать об их ограничениях. Например, названия не являются описательными, и они противоположны концепции папки по функции: «компоненты» / «ввод» / «кнопка» не являются функциями, это общие модули или компоненты.
Прежде всего, нам нужно помнить, что наш пример, приведенный выше, живет в более крупном приложении, поэтому в вашем приложении у вас должен быть глобальный «ввод» или «кнопка», от которого должен унаследоваться любой другой соответствующий элемент («ввод» должен исходить от Сторонняя внутренняя / внешняя библиотека).
Пример из реальной жизни
Так что давайте попробуем учиться на собственном примере. Здесь у нас есть различные примеры, которые помогут нам понять, как мы принимаем во внимание различные проблемы с этой структурой папок:
- Поток данных (redux - где мы создаем модуль, подключаемся или реагируем)
- Компонент и подкомпоненты
- Написание тестов
- Укладка
- Многоразовые / общие компоненты
- Плоская конструкция, избегайте вложенного ада
Пример №1: приложение для проверки
Нашим первым примером является приложение обзора Fiverr - мы используем его на странице пользователя и на странице Gig.
Как видите, мы можем подключиться к redux store из любой точки нашего приложения. Наше приложение обращается к глобальным файлам, таким как index.js и reviews.scss.
- ReviewList - это место, где мы собираем наше приложение, где мы можем подключиться к redux и экспортировать большую часть нашего приложения.
- В будущем, когда сложность нашего продукта вырастет, мы сможем добавить новые функции - в данном случае папку с redux connect, module и т. Д.
Вот наш пример структуры:
├── LoadMoreButton.js ├── LoadMoreButton.scss ├── ReviewList.js ← Here we construct the app ├── ReviewList.scss ├── ReviewList.spec.js ├── index.js ← Here we simply import ReviewList component and export ├── module.js ← LoadMoreButton fetch side effect is here ├── module.spec.js ├── review_list_header │ ├── Filter.js │ ├── Filter.spec.js │ ├── ReviewListHeader.js │ ├── ReviewListHeader.scss │ └── index.js ├── single_review │ ├── NoReview.js ← NoReview can be its own folder sibling to SingleReview (#6) │ ├── NoReview.scss │ ├── NoReview.spec.js │ ├── PreviewImage.js │ ├── PreviewImage.scss │ ├── PreviewImage.spec.js │ ├── SingleReview.js │ ├── SingleReview.scss │ ├── SingleReview.spec.js │ └── index.js └── user_rating ← Big enough to be its own folder ├── UserRating.js ├── UserRating.scss ├── UserRating.spec.js └── index.js
У нас есть гибкость в отношении структуры нашего приложения, но у нас есть некоторые рекомендации. Например:
- Мы должны убедиться, что наша структура настолько плоская, насколько это имеет смысл - вот почему мы не всегда создаем новую папку.
- Мы должны создать папку для нашего компонента, когда это имеет смысл, например когда компонент имеет некоторую сложность, когда ожидается рост продукта или когда у нас есть более одного компонента под компонентом (например, у review_list_header есть Filter и ReviewListHeader, поэтому мы создали папку для review_list_header).
- Вы можете создать новую папку, если в противном случае у вас будет слишком много файлов, но снова создание папки для каждых 2–3 файлов может быть бессмысленным, поэтому это должно иметь смысл в структуре вашего приложения.
- Если у вашего компонента есть проблема, например, подключение к хранилищу redux, вы можете создать новую папку.
- Руководствуйтесь здравым смыслом - если в вашей корневой папке слишком много файлов, сгруппируйте их вместе на основе структуры DOM / продукта.
- NoReview может быть отдельным родственником по папке для SingleReview, но, с точки зрения продукта, noReview - это единый обзор, который позволяет нам сгруппировать эти два вместе и избегать создания другой папки.
Пример № 2: настройки платежного аккаунта
Настройки платежного аккаунта - еще одна функция, которую мы создали таким образом. Ниже вы найдете несколько снимков экрана пользовательского интерфейса, а в конце вы сможете увидеть подробную схему структуры приложения, которая включает побочные эффекты, компоненты, редукторы, действия, подключение и многое другое.
Резюме
Не все высечено на камне, нет строгих правил - это скорее ряд здравого смысла, что можно и чего нельзя. Нам не нужны папки со слишком большим количеством файлов, поскольку нет смысла управлять таким количеством файлов в одной папке. Нам не нужна слишком глубоко вложенная структура, поскольку ее сложно поддерживать и перемещать по ней. Мы хотите, чтобы код был легко доступен и потреблялся кодом и компонентами, которые его окружают.