Автор оригинала: Dmitry Zherebko.
Идея этой структуры зависит от статьи https://martinfowler.com/bliki/presentationdomaindatalayering.html Чистая архитектура книга
Эта структура не принудительно использует точно такую же структуру папки, но она показывает базовую линию для хорошей структуры проекта. Этот подход улучшается
- Особенности инфекции,
- Привлечение новых членов в команду – вам не нужно сосредоточиться на целом приложении, вы можете просто сосредоточиться на отдельных компонентах и не думать о остальных,
- Это уменьшает объем внимания разработчика – когда вы разрабатываете единую функцию, существует редкий шанс нарушать что-то еще.
- Поддерживайте устойчивый путь сложности для огромных приложений – вам не нужно думать или даже знать о других частях вашего приложения, если вы сосредоточены на одном наборе функций.
Каждая функция/использование/модуль – это самостоятельно, имеет несколько слоев абстракций: модели, вид, селекторы, страницы и т. Д. Это также зависит от случая использования, но у вас может быть доступ к данным (API) в качестве отдельного объекта сверху вашего приложения или вы можете иметь его на функцию. Тематическое исследование показывает, что легче координировать доступ к данным с одного места, а не в децентрализации, но это зависит от вашего приложения.
Тот факт, что у нас есть все файлы компонентов, связанные с конкретными функциями в пределах одной папки, это не о том, что мы не должны иметь разделение опасений. Каждая особенность должна иметь слои абстракций в зависимости от его сложности, но вы не должны белый сопряженный код только потому, что это единственная функция.
Структура проекта
Структура проекта высокого уровня.
api types modules \ |- auth \ |- atoms |- molecules |- organisms |- pages |- services |- state |- selectors |- users |- todos |- dashboard libs \ |- charts |- table |- validation |- file-upload |- calendar |- pagination ui \ |- atoms |- molecules |- organisms |- pages |- templates |- theme // rest of the files for some setup App index setup
либей
Эта папка должна хранить файлы без каких-либо отношений к правилам проекта libs.
- Они не должны включать в себя код, специфичный для проекта
- Они не должны полагаться на конкретный код проекта, константы, маршрутизатора и т. Д. Кодовой код в lib должен полагаться на внешнюю конфигурацию
- Код в Libs должен быть хорошо документирован и иметь код покрытия 80+
- Другие модули не должны использовать дополнительные сети без критической необходимости.
- Libs должны иметь как можно меньше внешних зависимостей Например, все в порядке, чтобы иметь эмоции/логаш/момент/d3 в качестве зависимости, но лучше пропустить некоторые конкретные библиотеки, такие как Recharts или React-Router, лучше найти такой код в модулях. В целом, если вы можете сделать некоторые функциональные возможности работать без зависимости или принять его как реквизиты, просто сделайте это. Если вы чувствуете, что решают иметь что-то в качестве зависимости, затем используйте его.
- Libs может иметь какую-либо структуру папки, но для больших функций лучше следовать структуре атомной папки или разделы. Не помещайте код в Libs, если он очень мало или очень специфичен для некоторой функциональности.
В целом libs – это вторая папка Node_Modules, но с вашим кодом или разветвленным кодом из других проектов. Папка Libs – это хорошее место для использования, таких как пользовательские визуализации, пользовательские пользователи, такие как слайдер, флажок, таблица. Имейте в виду, что такие компоненты должны иметь настраиваемые свойства стиля. Руководства для проектирования ваших компонентов API https://material-ui.com/guides/api/
Таким образом, вы можете поставить код, если Libs, если
- Этот код не имеет отношения к другим модулям и другому коду проекта, кроме папки LIBS
- Этот код может быть повторно использован во всех проектах без отношения к любой функции
- Этот код реализует атомную функциональность, и эта функциональность может быть настроена с помощью аргументов, реквизитов и т. Д.
- Этот код readme и покрывается тестами
Рекомендации:
- Не пытайтесь построить самую маленькую атомную библиотеку, которая может быть повторно использована везде. Этот код до сих пор до сих пор достаточно конкретно для вашего проекта, и он отвечает за некоторые функциональные возможности, поэтому этот компонент должен быть использован с минимальной конфигурацией, но он не должен быть конкретным для любого из наших доменов.
- Попробуйте сгруппировать вашу функциональность. Например, вы построили кучу модных элементов управления, такие как флажки, ползунки, номера входных данных и т. Д. Это будет лучше сгруппировать их вместе как «форм-элементы управления» вместо того, чтобы лечить их как отдельные экземпляры. Другим примером являются графики, у вас много аккуратных диаграмм, таких как гистограммы, пироги, ARS, участки, вероятно, все они разделяют D3 в качестве зависимости и построены по теми же принципам, поэтому лучше их объединить.
Модули (функции aka)
Модули являются доменными частями кода. Модуль может содержать все и иметь какую-либо структуру кода, но для них есть несколько простых правил и рекомендаций.
Модули должны быть самосодержательными и описаны достаточно большой части функциональности приложения. Например, у вас есть новая функция с оповещениями разных типов. Эта функция включает в себя: компонент для других страниц с некоторой индикацией состояния и всплывающего окна с коротким списком запускаемых предупреждений, таблица спускового оповещения, страницы для управления оповещениями. Это хороший кандидат на новый модуль. В результате у нас будут компоненты, реализованные при оповещении модуля и другие модули полагаются на этот модуль.
Модули не должны полагаться на внутренние внутренние модули. Модуль должен предоставить простое API для использования в других модулях, например, Наши оповещения модуль выставит страницу с списком оповещений, компонентами для короткого списка и индикации, и это.
Вы можете иметь какую-либо структуру папки в модуле, но предпочитаю плоскую структуру, и если этот модуль довольно большой, используйте структуру атомной папки (см. Позже)
Форма зависимости модулей Dag Использование может использовать это тоже для обеспечения применения этой политики https://github.com/sverweij/dependency-cruiser Атомная структура в модулях: Каждый модуль может иметь следующую структуру
atoms molecules organisms pages templates
атомы
– это минимальный элемент здания в вашем модуле, его следует повторно использовать и настраиваться только с реквизитами молекулы
– написанные атомами, которые они могут быть достаточно большими, как заслуги или небольшие кнопки с нагрузкой. Поскольку эта атомная структура специфична для вашего домена, молекулы могут определить некоторые специфические стили и имеют некоторое твердое поведение, но все же, которые предназначены для воспроизведения Организмы
– Воспроизведение компонентов с некоторыми функциональными возможностями, они могут иметь предварительно определенное поведение, но они должны быть вставлены в любую часть страницы. Страницы
– Страницы компонентов, которые не предназначены для воспроизведения, они просто составляют организмы, молекулы, атомы и шаблоны. Шаблоны
– В случае, если у вас есть много отдельных страниц, вы можете переместить функциональность макета для шаблона, иначе этому объекту не очень полезно в домене
Также есть некоторые дополнительные объекты, это сильно зависит от того, что вы делаете
state - description of your domain model state effects - async operations within your modules selectors - derived data from your state services - usually you can put here some utilities or some data transformation api - method for backend api calls, I prefer to have them at top lvl but feel free to keep them at module lvl types - type definitions if you have a lot of the across the module
Ui
Компоненты пользовательского интерфейса. Это проектный внутренний комплект пользовательского интерфейса.
- Все компоненты предназначены для многоразового использования.
- Все компоненты не полагаются на состояние и не имеют зависимости от любых модулей
- Компоненты могут иметь код, специфичный для проекта в случае, если это код, связанный с стилями
Разница между компонентами в папке LIB и в папке UI, которые компоненты в папке UI могут определять стили брендинга и используют глобальные константы темы, в отличие от компонентов в Lib.
Руководства о атомной структуре для UI Kit:
Atomic Design
https://codeburst.io/atomic-design-with-react-e7aea8152957
Тестирование
Для тестирования у меня есть строгие требования. Но у меня мало рекомендаций.
Общая рекомендация для тестирования: всегда думайте, как будет использоваться ваш компонент, и тестируйте краевые чехлы без погружения в интернет-компонент.
Это имеет смысл для модулей. Поскольку каждый модуль сам, содержащий его, описывает ограниченный набор признаков, которые лучше для проверки функции с использованием его API и его вывода. Но это не всегда возможно, поэтому иногда мы должны разделить функцию в несколько подмножеств по функциональности и тестировать их. Обычно лучше тестировать функциональность функций с использованием организмов и страниц и не полагаться на более мелкие компоненты.
Постарайтесь не полагаться на определенные компоненты и контролирует в ваших тестах и использовать «данные-TAXID». Вы можете установить Data-testid на некоторую кнопку, а затем во время рефакторинга вы будете свободны перемещать эту кнопку без разбитых испытаний.
Попробуйте переместить столько же логики, поскольку вы можете выйти из UI для крючков. И тестовые крючки сиперально. Таким образом, вы можете сделать ваши тесты более надежными и устойчивыми для изменения. Также это позволяет вам обращаться с гораздо большим количеством краевых чехлов и получить лучший опыт разработки для разработки испытаний. Тестирование пользовательского интерфейса по умолчанию является хрупким, но это не значит, что вы не должны делать это или делать это неправильно. Нет, это означает, что вы проводите дополнительное время для реализации хороших тестов пользовательского интерфейса. Из-за этого разделения зрения и лигика для просмотра (крючков) – это хорошая идея, чтобы улучшить опыт тестирования.
Вы тесты должны потерпеть неудачу только в том случае, если функциональность изменилась, но не при изменении имени ОБЗЕ или замените один компонент для кнопки с другим. Функциональность тестового компонента, но не реализация компонентов.
Для ливок намного сложнее следовать этому правилу. Прежде всего, потому что вам нужно проверить больше кромки и во-вторых, потому что вам нужно более высокое покрытие кода. Для Libs имеет смысл разделить функциональность на более мелких кусках и тестировать его в изоляцию. Конечно, это в дополнение к полному компонентному тестированию API.
Заметки
Вложенные особенности
Обычно вы начинаете новые функции с некотором именем, специфическими для функции или домена, над которой вы работаете, но по мере роста вашего приложения вы получите все больше и больше, который вы хотите структурировать надлежащим образом с лучшим разложением. Есть много способов сделать это, вы можете сделать вложенные функции, вы можете гнездить вам оргинанизмы и т. Д. Но все эти вещи приводят вас к плохую структуру кода и плохое обнаружение кода. Мои рекомендации к этому:
- Всегда ищите код, который можно перемещать в Libs или компоненты, например, он может быть графиками, некоторые сложные виртуализированные списки, некоторые математические, утилиты для передачи данных, алгоритмы. Вы просто можете сделать лучшее разложение и переместить какой-то код, который не связан с каким-либо доменом в Libs/Components, и освободиться от накладного расхода кода в вашем проекте. Но будьте осторожны и не двигайте код, который вздрогнул в вашу функцию в общий код. Больше примеров: этот материал может быть что-то вроде сложных элементов управления форм (передача, выбор, предложений) или общие диаграммы (участки, бары и т. Д.).
- Другой подход состоит в том, чтобы сделать некоторую параллельную функцию на том же LVL в качестве основной функции, например У вас есть сообщения и записи галереи, которые довольно большой и довольно специфичны для вашего приложения, что вы можете сделать, это создает такую структуру
features/ - posts - posts-gallery
В результате у вас есть отдельная функция, но в то же время вы можете видеть, что он затянут к главной особенности. Такой подход приводит к лучшему обнаружению кода и легче рефакторинга. Если вы рефакторируете сообщения, вы, вероятно, поймете, как по сообщениям-галереи работают прямо сейчас и наоборот. Одно примечание для этого подхода, что лучше делать ленивый импорт вложенной функции.