Кросс-импорты
Статья находится в процессе написания
Чтобы ускорить ее появление, можно:
- 📢 Поделиться обратной связью в тикете (комментарии/эмодзи-реакция)
- 💬 Собрать в тикет накопленный по теме материал из чата
- ⚒️ Посодействовать любым другим способом
🍰 Stay tuned!
Кросс-импорты появляются тогда, когда слой/абстракция начинает брать слишком много ответственности, чем должна. Именно поэтому методология выделяет новые слои, которые позволяют расцепить эти кросс-импорты.
Введение
Кросс-импорт - ситуация, при которой в рамках какого-либо слоя появилась необходимость импорта данных одного слайса в другой.
Речь в статье идёт только о конфликтных ситуациях при импортах между слайсами. В рамках одного слайса, фрагменты могут импортировать друг друга, такая ситуация не запрещена.
Представим, что разрабатываем приложение TODO List для хранения заметок. Необходимо хранить несколько карточек с задачами и отображать их на доске. Досок с карточками может быть несколько. Рассмотрим упрощённый пример структуры такого приложения:
📂 entities📂 task📁 ui📄 TaskCard
📁 board📁 ui📄 BoardTasks
В данном примере компоненту BoardTasks для отображения карточек необходим импорт компонента TaskCard.
Импортировать компонент TaskCard напрямую нельзя, так как это нарушит принцип низкой связности и усложнит поддержку проекта в дальнейшем.
Варианты решения кросс-импортов
Объединение нескольких слайсов в один
Как видно из примера выше, доменная область компонентов TaskCard и BoardTasks довольно похожа, а значит существует возможность создания производного слайса из двух существующих, где оба метода находились бы в одной директории.
Результат объединения слайсов task и board:
📂 entities📂 board📁 ui📄 TaskCard📄 BoardTasks
Как видно из примера, мы избавились от ситуации, когда один слайс импортирует данные из другого и достигли высокой сцепленности и низкой связности в рамках сегмента одного слайса.
Перемещение кода на более высокий слой
Данный вариант скорее подходит для тех случаев, для которых объединение нескольких слайсов в один затруднено или невозможно.
Вполне вероятно, что слайс, в который Вы импортируете данные другого слайса сильно насыщен логически, и его можно переместить на слой выше, дабы устранить связность слайсов в рамках одного слоя.
Представим, что слайс board более насыщен бизнес-логикой, чем на примере выше, тогда объединение его со слайсом task создаст дополнительный беспорядок, поэтому хорошим решением будет реструктуризовать логику слайса board, в более высоком слое.
Результат перемещения логики слайсов task и board:
📂 entities📂 task📁 ui📄 TaskCard
📂 features📁 view-board📁 ui📄 BoardTasks
Реструктуризовав логику слайса board на слое features (не обязательно на него, подойдёт любой слой выше по иерархии), его доменная область более конкретно уточнилась появилась возможность построить правильный с точки зрения иерархии слоёв механизм импортов.
Дублирование кода
Если объем данных, который Вы собираетесь импортировать из другого слайса невелик, возможно стоит будет продублировать его в текущий слайс. Тем не менее, такой вариант не должен являться приоритетным, среди всех вышеописанных.
А если кросс-импорт неизбежен?
Подход, описанный в данном разделе является экспериментальным и ещё не стандартизирован. Тем не менее, в экзотических ситуациях, информация данного раздела может быть полезна.
Если в Вашем проекте необходим кросс-импорт и три вышеописанных способа не помогли, сообщество Feature Sliced Design предлагает следующий вариант решения проблемы.
📂 entities📂 task📁 ui📄 TaskCard
@x📁 board📁 ui📄 BoardTasks
@x
@x
@x - это эксперементальный подход, когда внутри слайса можно создать явный публичный экспорт только тех модулей, которые можно использовать в рамках нескольких слайсов одного слоя.
Рассмотрим пример (разметка TSX):
export { TaskCard } from './ui/TaskCard.tsx';
Компонент внутри слайса, которому необходим кросс-импорт:
import { TaskCard } from '/entities/task/@x/TaskCard';
export const BoardTasks = () => { return (
<div>
<TaskCard title="Task#1" description="Description..." />
<TaskCard title="Task#2" description="Description..." />
<TaskCard title="Task#3" description="Description..." />
</div>
)
}
Как видно по пути импорта в файле BoardTasks, благодаря экспорту из файла @x видно, что данный модуль не предназначен для публичного использования, а существует только для того, чтобы быть импортированным внутрь другого слайса.
Отмена запрета на кросс-импорты
Если Вы попробовали все способы в статье, но по каким-либо причинам всё равно не смогли избавиться от кросс-импортов, возможно, стоить задуматься о том, чтобы снять запрет на них в рамках конкретных слайсов, либо всего проекта в целом. Однако, важно понимать, что отмена запрета на кросс-импорты, потенциально может негативно сказываться на общей структуре проекта.
Полезные ссылки
- Команда Feature Sliced Design разработала инструмент, позволяющий автоматически проверить наличие кросс-импортов в проекте: Steiger
- Больше информации о правиле кросс-импортов: Steiger-Forbidden-Imports