From b5ea115a13f594be5759d979739a897113e32957 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 17 Aug 2024 16:18:46 +0300 Subject: [PATCH 1/8] chore: add post about cross-imports --- .../current/guides/issues/cross-imports.mdx | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index ee1d31475d..cfa3ad4452 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -12,6 +12,116 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' > Кросс-импорты появляются тогда, когда слой/абстракция начинает брать слишком много ответственности, чем должна. Именно поэтому методология выделяет новые слои, которые позволяют расцепить эти кросс-импорты +## Введение {#start} + +Перед тем, как разбираться, как необходимо работать с кросс-импортами для соответствия методологии FSD, необходимо понять, что такое "кросс-импорт" в принципе. + +**Кросс-импорт** - ситуация, при которой в рамках какого-либо слоя появилась необходимость импорта данных одного слайса в другой. + +:::warning Важно + +Речь в статье идёт только о конфликтных ситуациях при импортах между **слайсами**. В рамках одного слайса, фрагменты могут импортировать друг друга, такая ситуация не запрещена + +::: + +Рассмотрим абстрактный пример: + +- `📂 entities` + - `📂 countries` + - `📁 lib` + - `📄 getCountriesList ` + - `📁 cities` + - `📁 lib` + - `📄 getCitiesByCountryName` + +В данном примере для вызова метода `getCitiesByCountryName` необходимо получить результат вызова метода `getCountriesList`. +Получить результат работы метода `getCountriesList` напрямую нельзя, так как это нарушит принцип низкой связности и усложнит поддержку проекта в дальнейшем. + +Как разрешать ситуации, когда появилась необходимость сделать кросс-импорт? Рассмотрим в этой статье. + +## Варианты решения кросс-импортов {#solutions} + +### Объединение нескольких слайсов в один {#slices-merge} +Как видно из примера выше, доменная область методов `getCitiesByCountryName` и `getCountriesList` довольно похожа, а значит существует возможность создания производного слайса из двух существующих, где оба метода находились бы в одной директории + +Результат объединения слайсов `countries` и `cities`: +- `📂 entities` + - `📂 geography` + - `📁 lib` + - `📄 getCountriesList` + - `📄 getCitiesByCountryName` + +Как видно из примера, мы избавились от ситуации, когда один слайс импортирует данные из другого и достигли высокой сцепленности и низкой связности в рамках сегмента одного слайса + +### Разбиение слайсов на разные слои {#slices-moving} +Данный вариант скорее подходит для тех случаев, для которых объединение нескольких слайсов в один затруднено или невозможно. + +Вполне вероятно, что слайс, в который вы импортируете данные другого слайса достаточно сильно насыщен логически, и его можно переместить на слой выше, дабы устранить их связность в рамках одного слоя. + +Результат разбиения слайсов `countries` и `cities` на разные слои: +- `📂 entities` + - `📂 countries` + - `📁 lib` + - `📄 getCountriesList ` +- `📂 features` + - `📁 cities` + - `📁 lib` + - `📄 getCitiesByCountryName` + +Переместив слайс `cities` на слой `features` (не обязательно на него, подойдёт любой слой выше по иерархии), мы более конкретно уточнили его доменную область и дали возможность правильного с точки зрения иерархии слоёв механизма импортов. + +### Дублирование кода {#duplication-code} +Если объем данных, который вы собираетесь импортировать из другого слайса невелик, не самой плохой идеей будет продублировать его в текущий слайс. Тем не менее, такой вариант не должен быть приоритетным, среди всех вышеописанных. + +## А если кросс-импорт неизбежен? {#cross-import-is-inevitable} + +:::caution Внимание + +Информация в данном разделе **не является руководством к действию**. Она не отражает официальную позицию авторов методологии Feature Sliced Design. +Тем не менее, в экзотических ситуациях, информация данного раздела может быть полезна + +::: + +Если в Вашем проекте необходим кросс-импорт и два вышеописанных способа не помогли, сообщество Feature Sliced Design предлагает следующий вариант решения проблемы + +- `📂 entities` + - `📂 countries` + - `📁 lib` + - `📄 getCountriesList ` + - `@x` + - `📁 cities` + - `📁 lib` + - `📄 getCitiesByCountryName` + - `@x` + +### @x {#export-private-api} +**@x** - это подход, когда внутри слайса можно создать явный публичный экспорт только тех модулей, которые можно использовать в рамках нескольких слайсов одного слоя + +Рассмотрим пример: +```ts title="entities/countries/@x.ts" +export { getCountriesList } from './lib/getCountriesList.ts'; +``` +Метод внутри слайса, которому необходим кросс-импорт: +```ts title="entities/cities/lib/getCitiesByCountryName" +import { getCountriesList } from '/entities/countries/@x/getCountriesList'; + +const countries = getCountriesList(); + +const getCitiesByCountryName = (countryName: string) => {} // logic + +return getCitiesByCountryName(countries[0]); +``` +Как видно по пути импорта в файле `getCitiesByCountryName`, благодаря экспорту из файла @x, явно видно, что данный модуль не предназначен для публичного использования, а существует только для того, чтобы быть импортированным внутрь другого слайса + +### Отмена запрета на кросс-импорты {#disable-cross-imports-rule} +Если Вы попробовали все способы в статье, но по каким-либо причинам всё равно не смогли избавиться от кросс-импортов, возможно, стоить задуматься о том, чтобы снять запрет на них в рамках конкретных слайсов, либо всего проекта в целом. +Однако, важно понимать, что отмена запрета на кросс-импорты, потенциально может негативно сказываться на общей структуре проекта. + +## Полезные ссылки {#useful-links} + +1. Команда Feature Sliced Design разработала инструмент, позволяющий автоматически проверить наличие кросс-импортов в проекте: [Steiger](https://github.com/feature-sliced/steiger) +2. Больше информации о правиле кросс-импортов: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md) + ## См. также {#see-also} - [(Тред) Про предполагаемую неизбежность кросс-импортов](https://t.me/feature_sliced/4515) From 888409f1b1a420f9d71cf3330d0369b406b99147 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 19 Aug 2024 08:45:54 +0300 Subject: [PATCH 2/8] chore: add translate in english --- .../current/guides/issues/cross-imports.mdx | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index 033b68930d..c2cc7d88ef 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -12,6 +12,117 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' > Cross-imports appear when the layer or abstraction begins to take too much responsibility than it should. That is why the methodology identifies new layers that allow you to uncouple these cross-imports +## Introduction {#start} + +Before we look at how to work with cross-imports to comply with the FSD methodology, we need to understand what "cross-import" is in principle. + +**Cross-import** is a situation in which, within a layer, there is a need to import data from one slice to another. + +:::warning Important + +The article only deals with conflict situations when importing between **slices**. Within one slice, fragments can import each other, such a situation is not prohibited + +::: + +Let's look at an abstract example: + +- `📂 entities` + - `📂 countries` + - `📁 lib` + - `📄 getCountriesList ` + - `📁 cities` + - `📁 lib` + - `📄 getCitiesByCountryName` + +In this example, to call the `getCitiesByCountryName` method, you need to get the result of calling the `getCountriesList` method. +It is not possible to obtain the result of the `getCountriesList` method directly, as this would violate the principle of low coupling and complicate the project's maintenance in the future. + +How to resolve situations when there is a need to make a cross-import? Let's consider in this article. + +## Cross-import solutions options {#solutions} + +### Merging multiple slices into one {#slices-merge} +As you can see from the example above, the domain scope of the `getCitiesByCountryName` and `getCountriesList` methods is quite similar, which means it is possible to create a derived slice from the two existing ones, where both methods would be in the same directory. + +Result of merging slices `countries` and `cities`: +- `📂 entities` + - `📂 geography` + - `📁 lib` + - `📄 getCountriesList` + - `📄 getCitiesByCountryName` + +As you can see from the example, we got rid of the situation where one slice imports data from another and achieved high cohesion and low cohesion within a segment of one slice. + +### Splitting slices into different layers {#slices-moving} +This option is more suitable for those cases where combining several slices into one is difficult or impossible. + +It is likely that the slice into which you are importing data from another slice is quite logically rich and can be moved to a higher layer in order to eliminate their connectivity within a single layer. + +The result of splitting the `countries` and `cities` slices into different layers: +- `📂 entities` + - `📂 countries` + - `📁 lib` + - `📄 getCountriesList ` +- `📂 features` + - `📁 cities` + - `📁 lib` + - `📄 getCitiesByCountryName` + +By moving the `cities` slice to the `features` layer (not necessarily to it, any layer higher in the hierarchy will do), we have more specifically specified its domain area and made it possible to have a correct import mechanism from the point of view of the layer hierarchy. + +### Code duplication {#duplication-code} +If the amount of data you are going to import from another slice is small, it is not a bad idea to duplicate it into the current slice. However, this option should not be a priority among all the above. + +## But what if cross-import is inevitable? {#cross-import-is-inevitable} + +:::caution Attention + +The information in this section **is not a guide to action**. It does not reflect the official position of the authors of the Feature Sliced ​​Design methodology. +However, in exotic situations, the information in this section may be useful + +::: + +If your project requires cross-import and the two methods described above did not help, the Feature Sliced ​​Design community offers the following solution to the problem + +- `📂 entities` + - `📂 countries` + - `📁 lib` + - `📄 getCountriesList ` + - `@x` + - `📁 cities` + - `📁 lib` + - `📄 getCitiesByCountryName` + - `@x` + +### @x {#export-private-api} +**@x** - this is an approach where within a slice you can create an explicit public export of only those modules that can be used within several slices of the same layer + +Let's look at an example: +```ts title="entities/countries/@x.ts" +export { getCountriesList } from './lib/getCountriesList.ts'; +``` +The method inside the slice that requires cross import: +```ts title="entities/cities/lib/getCitiesByCountryName" +import { getCountriesList } from '/entities/countries/@x/getCountriesList'; + +const countries = getCountriesList(); + +const getCitiesByCountryName = (countryName: string) => {} // logic + +return getCitiesByCountryName(countries[0]); +``` +As you can see from the import path in the `getCitiesByCountryName` file, thanks to the export from the @x file, it is clear that this module is not intended for public use, but exists only to be imported inside another slice. + +### Lifting the ban on cross-imports {#disable-cross-imports-rule} +If you have tried all the methods in the article, but for some reason still could not get rid of cross-imports, it may be worth considering lifting the ban on them within specific slices, or the entire project as a whole. +However, it is important to understand that lifting the ban on cross-imports can potentially negatively affect the overall structure of the project. + +## Useful links {#useful-links} + +1. The Feature Sliced ​​Design team has developed a tool that allows you to automatically check for cross-imports in a project: [Steiger](https://github.com/feature-sliced/steiger) +2. More information about the cross-import rule: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md) + + ## See also - [(Thread) About the supposed inevitability of cross-ports](https://t.me/feature_sliced/4515) From bafd497d7c79252e3c46f98bf6063052f77c2a25 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 19 Sep 2024 19:47:20 +0300 Subject: [PATCH 3/8] fix comments --- .../current/guides/issues/cross-imports.mdx | 61 +++++++++---------- .../current/guides/issues/cross-imports.mdx | 38 ++++++------ 2 files changed, 46 insertions(+), 53 deletions(-) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index c2cc7d88ef..9040d11494 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -6,22 +6,18 @@ pagination_next: reference/index import WIP from '@site/src/shared/ui/wip/tmpl.mdx' -# Cross-imports +# Кросс-импорты -> Cross-imports appear when the layer or abstraction begins to take too much responsibility than it should. That is why the methodology identifies new layers that allow you to uncouple these cross-imports - -## Introduction {#start} - -Before we look at how to work with cross-imports to comply with the FSD methodology, we need to understand what "cross-import" is in principle. +> Cross-imports appear when a layer/abstraction starts to take on too much responsibility than it should. That is why the methodology allocates new layers that allow these cross-imports to be decoupled. +## Введение {#start} **Cross-import** is a situation in which, within a layer, there is a need to import data from one slice to another. -:::warning Important - -The article only deals with conflict situations when importing between **slices**. Within one slice, fragments can import each other, such a situation is not prohibited +:::warning Warning +The article only deals with conflict situations when importing between **slices**. Within one slice, fragments can import each other, such a situation is not prohibited. ::: Let's look at an abstract example: @@ -37,28 +33,28 @@ Let's look at an abstract example: In this example, to call the `getCitiesByCountryName` method, you need to get the result of calling the `getCountriesList` method. It is not possible to obtain the result of the `getCountriesList` method directly, as this would violate the principle of low coupling and complicate the project's maintenance in the future. -How to resolve situations when there is a need to make a cross-import? Let's consider in this article. - ## Cross-import solutions options {#solutions} ### Merging multiple slices into one {#slices-merge} -As you can see from the example above, the domain scope of the `getCitiesByCountryName` and `getCountriesList` methods is quite similar, which means it is possible to create a derived slice from the two existing ones, where both methods would be in the same directory. +As you can see from the example above, the domain scope of the `getCitiesByCountryName` and `getCountriesList` methods is quite similar, meaning it is possible to create a derived slice from the two existing ones, where both methods would be in the same directory. Result of merging slices `countries` and `cities`: - `📂 entities` - - `📂 geography` + - `📂 location` - `📁 lib` - `📄 getCountriesList` - `📄 getCitiesByCountryName` -As you can see from the example, we got rid of the situation where one slice imports data from another and achieved high cohesion and low cohesion within a segment of one slice. +As you can see from the example, we have eliminated the situation where one slice imports data from another and achieved high cohesion and low connectivity within a segment of a single slice. -### Splitting slices into different layers {#slices-moving} +### Moving code to a higher layer {#slices-moving} This option is more suitable for those cases where combining several slices into one is difficult or impossible. -It is likely that the slice into which you are importing data from another slice is quite logically rich and can be moved to a higher layer in order to eliminate their connectivity within a single layer. +It is likely that the slice into which you are importing data from another slice is highly logically rich and can be moved to a higher layer to eliminate the connectivity of slices within a single layer. + +Let's imagine that the `countries` slice is more dense with business logic than in the example above, then merging it with the `cities` slice will create additional clutter, so a good solution would be to move the `cities` slice to a higher layer in order to maintain the correct slice structure. -The result of splitting the `countries` and `cities` slices into different layers: +The result of moving the `countries` and `cities` slices to different layers: - `📂 entities` - `📂 countries` - `📁 lib` @@ -68,21 +64,21 @@ The result of splitting the `countries` and `cities` slices into different layer - `📁 lib` - `📄 getCitiesByCountryName` -By moving the `cities` slice to the `features` layer (not necessarily to it, any layer higher in the hierarchy will do), we have more specifically specified its domain area and made it possible to have a correct import mechanism from the point of view of the layer hierarchy. +By moving the `cities` slice to the `features` layer (not necessarily to it, any layer higher in the hierarchy will do), its domain area became more specific and it became possible to build an import mechanism that is correct from the point of view of the layer hierarchy. -### Code duplication {#duplication-code} -If the amount of data you are going to import from another slice is small, it is not a bad idea to duplicate it into the current slice. However, this option should not be a priority among all the above. +### Duplication code {#duplication-code} +If the amount of data you are going to import from another slice is small, it may be worth duplicating it into the current slice. However, this option should not be a priority among all the above. -## But what if cross-import is inevitable? {#cross-import-is-inevitable} +## What if cross-import is inevitable? {#cross-import-is-inevitable} -:::caution Attention +:::caution Warning -The information in this section **is not a guide to action**. It does not reflect the official position of the authors of the Feature Sliced ​​Design methodology. -However, in exotic situations, the information in this section may be useful +The approach described in this section is experimental and has not yet been standardized. +However, in exotic situations, the information in this section may be useful. ::: -If your project requires cross-import and the two methods described above did not help, the Feature Sliced ​​Design community offers the following solution to the problem +If your project requires cross-import and the three methods described above did not help, the Feature Sliced ​​Design community offers the following solution to the problem. - `📂 entities` - `📂 countries` @@ -95,7 +91,7 @@ If your project requires cross-import and the two methods described above did no - `@x` ### @x {#export-private-api} -**@x** - this is an approach where within a slice you can create an explicit public export of only those modules that can be used within several slices of the same layer +**@x** - this is an experimental approach where within a slice you can create an explicit public export of only those modules that can be used within multiple slices of the same layer. Let's look at an example: ```ts title="entities/countries/@x.ts" @@ -114,19 +110,18 @@ return getCitiesByCountryName(countries[0]); As you can see from the import path in the `getCitiesByCountryName` file, thanks to the export from the @x file, it is clear that this module is not intended for public use, but exists only to be imported inside another slice. ### Lifting the ban on cross-imports {#disable-cross-imports-rule} -If you have tried all the methods in the article, but for some reason still could not get rid of cross-imports, it may be worth considering lifting the ban on them within specific slices, or the entire project as a whole. -However, it is important to understand that lifting the ban on cross-imports can potentially negatively affect the overall structure of the project. +If you have tried all the methods in the article, but for some reason still could not get rid of cross-imports, perhaps it is worth considering lifting the ban on them within specific slices, or the entire project as a whole. +However, it is important to understand that lifting the ban on cross-imports could potentially have a negative impact on the overall structure of the project. ## Useful links {#useful-links} 1. The Feature Sliced ​​Design team has developed a tool that allows you to automatically check for cross-imports in a project: [Steiger](https://github.com/feature-sliced/steiger) 2. More information about the cross-import rule: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md) +## См. также {#see-also} -## See also - -- [(Thread) About the supposed inevitability of cross-ports](https://t.me/feature_sliced/4515) -- [(Thread) About resolving cross-ports in entities](https://t.me/feature_sliced/3678) +- [(Thread) On the supposed inevitability of cross-imports](https://t.me/feature_sliced/4515) +- [(Thread) About resolving cross-imports in entities](https://t.me/feature_sliced/3678) - [(Thread) About cross-imports and responsibility](https://t.me/feature_sliced/3287) - [(Thread) About imports between segments](https://t.me/feature_sliced/4021) -- [(Thread) About cross-imports inside shared](https://t.me/feature_sliced/3618) +- [(Thread) About cross-imports inside shared](https://t.me/feature_sliced/3618) \ No newline at end of file diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index cfa3ad4452..3dfced02b3 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -10,17 +10,15 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' -> Кросс-импорты появляются тогда, когда слой/абстракция начинает брать слишком много ответственности, чем должна. Именно поэтому методология выделяет новые слои, которые позволяют расцепить эти кросс-импорты +> Кросс-импорты появляются тогда, когда слой/абстракция начинает брать слишком много ответственности, чем должна. Именно поэтому методология выделяет новые слои, которые позволяют расцепить эти кросс-импорты. ## Введение {#start} -Перед тем, как разбираться, как необходимо работать с кросс-импортами для соответствия методологии FSD, необходимо понять, что такое "кросс-импорт" в принципе. - **Кросс-импорт** - ситуация, при которой в рамках какого-либо слоя появилась необходимость импорта данных одного слайса в другой. :::warning Важно -Речь в статье идёт только о конфликтных ситуациях при импортах между **слайсами**. В рамках одного слайса, фрагменты могут импортировать друг друга, такая ситуация не запрещена +Речь в статье идёт только о конфликтных ситуациях при импортах между **слайсами**. В рамках одного слайса, фрагменты могут импортировать друг друга, такая ситуация не запрещена. ::: @@ -37,28 +35,28 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' В данном примере для вызова метода `getCitiesByCountryName` необходимо получить результат вызова метода `getCountriesList`. Получить результат работы метода `getCountriesList` напрямую нельзя, так как это нарушит принцип низкой связности и усложнит поддержку проекта в дальнейшем. -Как разрешать ситуации, когда появилась необходимость сделать кросс-импорт? Рассмотрим в этой статье. - ## Варианты решения кросс-импортов {#solutions} ### Объединение нескольких слайсов в один {#slices-merge} -Как видно из примера выше, доменная область методов `getCitiesByCountryName` и `getCountriesList` довольно похожа, а значит существует возможность создания производного слайса из двух существующих, где оба метода находились бы в одной директории +Как видно из примера выше, доменная область методов `getCitiesByCountryName` и `getCountriesList` довольно похожа, а значит существует возможность создания производного слайса из двух существующих, где оба метода находились бы в одной директории. Результат объединения слайсов `countries` и `cities`: - `📂 entities` - - `📂 geography` + - `📂 location` - `📁 lib` - `📄 getCountriesList` - `📄 getCitiesByCountryName` -Как видно из примера, мы избавились от ситуации, когда один слайс импортирует данные из другого и достигли высокой сцепленности и низкой связности в рамках сегмента одного слайса +Как видно из примера, мы избавились от ситуации, когда один слайс импортирует данные из другого и достигли высокой сцепленности и низкой связности в рамках сегмента одного слайса. -### Разбиение слайсов на разные слои {#slices-moving} +### Перемещение кода на более высокий слой {#slices-moving} Данный вариант скорее подходит для тех случаев, для которых объединение нескольких слайсов в один затруднено или невозможно. -Вполне вероятно, что слайс, в который вы импортируете данные другого слайса достаточно сильно насыщен логически, и его можно переместить на слой выше, дабы устранить их связность в рамках одного слоя. +Вполне вероятно, что слайс, в который Вы импортируете данные другого слайса сильно насыщен логически, и его можно переместить на слой выше, дабы устранить связность слайсов в рамках одного слоя. + +Представим, что слайс `countries` более насыщен бизнес-логикой, чем на примере выше, тогда объединение его со слайсом `cities` создаст дополнительный беспорядок, поэтому хорошим решением будет переместить слайс `cities` на слой выше, дабы сохранить корректную структуру слайсов. -Результат разбиения слайсов `countries` и `cities` на разные слои: +Результат перемещения слайсов `countries` и `cities` на разные слои: - `📂 entities` - `📂 countries` - `📁 lib` @@ -68,21 +66,21 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' - `📁 lib` - `📄 getCitiesByCountryName` -Переместив слайс `cities` на слой `features` (не обязательно на него, подойдёт любой слой выше по иерархии), мы более конкретно уточнили его доменную область и дали возможность правильного с точки зрения иерархии слоёв механизма импортов. +Переместив слайс `cities` на слой `features` (не обязательно на него, подойдёт любой слой выше по иерархии), его доменная область более конкретно уточнилась появилась возможность построить правильный с точки зрения иерархии слоёв механизм импортов. ### Дублирование кода {#duplication-code} -Если объем данных, который вы собираетесь импортировать из другого слайса невелик, не самой плохой идеей будет продублировать его в текущий слайс. Тем не менее, такой вариант не должен быть приоритетным, среди всех вышеописанных. +Если объем данных, который Вы собираетесь импортировать из другого слайса невелик, возможно стоит будет продублировать его в текущий слайс. Тем не менее, такой вариант не должен являться приоритетным, среди всех вышеописанных. ## А если кросс-импорт неизбежен? {#cross-import-is-inevitable} :::caution Внимание -Информация в данном разделе **не является руководством к действию**. Она не отражает официальную позицию авторов методологии Feature Sliced Design. -Тем не менее, в экзотических ситуациях, информация данного раздела может быть полезна +Подход, описанный в данном разделе является экспериментальным и ещё не стандартизирован. +Тем не менее, в экзотических ситуациях, информация данного раздела может быть полезна. ::: -Если в Вашем проекте необходим кросс-импорт и два вышеописанных способа не помогли, сообщество Feature Sliced Design предлагает следующий вариант решения проблемы +Если в Вашем проекте необходим кросс-импорт и три вышеописанных способа не помогли, сообщество Feature Sliced Design предлагает следующий вариант решения проблемы. - `📂 entities` - `📂 countries` @@ -95,7 +93,7 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' - `@x` ### @x {#export-private-api} -**@x** - это подход, когда внутри слайса можно создать явный публичный экспорт только тех модулей, которые можно использовать в рамках нескольких слайсов одного слоя +**@x** - это эксперементальный подход, когда внутри слайса можно создать явный публичный экспорт только тех модулей, которые можно использовать в рамках нескольких слайсов одного слоя. Рассмотрим пример: ```ts title="entities/countries/@x.ts" @@ -111,7 +109,7 @@ const getCitiesByCountryName = (countryName: string) => {} // logic return getCitiesByCountryName(countries[0]); ``` -Как видно по пути импорта в файле `getCitiesByCountryName`, благодаря экспорту из файла @x, явно видно, что данный модуль не предназначен для публичного использования, а существует только для того, чтобы быть импортированным внутрь другого слайса +Как видно по пути импорта в файле `getCitiesByCountryName`, благодаря экспорту из файла @x видно, что данный модуль не предназначен для публичного использования, а существует только для того, чтобы быть импортированным внутрь другого слайса. ### Отмена запрета на кросс-импорты {#disable-cross-imports-rule} Если Вы попробовали все способы в статье, но по каким-либо причинам всё равно не смогли избавиться от кросс-импортов, возможно, стоить задуматься о том, чтобы снять запрет на них в рамках конкретных слайсов, либо всего проекта в целом. @@ -128,4 +126,4 @@ return getCitiesByCountryName(countries[0]); - [(Тред) Про резолвинг кросс-импортов в сущностях](https://t.me/feature_sliced/3678) - [(Тред) Про кросс-импорты и ответственность](https://t.me/feature_sliced/3287) - [(Тред) Про импорты между сегментами](https://t.me/feature_sliced/4021) -- [(Тред) Про кросс-импорты внутри shared](https://t.me/feature_sliced/3618) +- [(Тред) Про кросс-импорты внутри shared](https://t.me/feature_sliced/3618) \ No newline at end of file From 4f71890708b3b05f3deab4a87089e40ae0ba5f32 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 19 Sep 2024 19:48:36 +0300 Subject: [PATCH 4/8] fix comments --- .../current/guides/issues/cross-imports.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index 9040d11494..56f6502b3b 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -6,12 +6,12 @@ pagination_next: reference/index import WIP from '@site/src/shared/ui/wip/tmpl.mdx' -# Кросс-импорты +# Cross-imports > Cross-imports appear when a layer/abstraction starts to take on too much responsibility than it should. That is why the methodology allocates new layers that allow these cross-imports to be decoupled. -## Введение {#start} +## See also {#start} **Cross-import** is a situation in which, within a layer, there is a need to import data from one slice to another. From d990451f9d9ad1b569c620d7c5ba6223bff5be3a Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 19 Sep 2024 19:49:16 +0300 Subject: [PATCH 5/8] fix comments --- .../current/guides/issues/cross-imports.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index 56f6502b3b..3f3628ff3c 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -11,6 +11,7 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' > Cross-imports appear when a layer/abstraction starts to take on too much responsibility than it should. That is why the methodology allocates new layers that allow these cross-imports to be decoupled. + ## See also {#start} **Cross-import** is a situation in which, within a layer, there is a need to import data from one slice to another. From d6ae62a0c7b3569b763637c083bb3f452ea240d0 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 19 Sep 2024 19:50:36 +0300 Subject: [PATCH 6/8] fix comments --- .../current/guides/issues/cross-imports.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index 3f3628ff3c..7117368e0c 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -12,7 +12,7 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' > Cross-imports appear when a layer/abstraction starts to take on too much responsibility than it should. That is why the methodology allocates new layers that allow these cross-imports to be decoupled. -## See also {#start} +## Introduction {#start} **Cross-import** is a situation in which, within a layer, there is a need to import data from one slice to another. @@ -119,7 +119,7 @@ However, it is important to understand that lifting the ban on cross-imports cou 1. The Feature Sliced ​​Design team has developed a tool that allows you to automatically check for cross-imports in a project: [Steiger](https://github.com/feature-sliced/steiger) 2. More information about the cross-import rule: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md) -## См. также {#see-also} +## See also {#see-also} - [(Thread) On the supposed inevitability of cross-imports](https://t.me/feature_sliced/4515) - [(Thread) About resolving cross-imports in entities](https://t.me/feature_sliced/3678) From 62eedf519416d39234be67003afa812f36fe9237 Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 20 Sep 2024 17:29:35 +0300 Subject: [PATCH 7/8] fix comments --- .../current/guides/issues/cross-imports.mdx | 8 ++++---- .../current/guides/issues/cross-imports.mdx | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index 7117368e0c..c6209182cd 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -53,19 +53,19 @@ This option is more suitable for those cases where combining several slices into It is likely that the slice into which you are importing data from another slice is highly logically rich and can be moved to a higher layer to eliminate the connectivity of slices within a single layer. -Let's imagine that the `countries` slice is more dense with business logic than in the example above, then merging it with the `cities` slice will create additional clutter, so a good solution would be to move the `cities` slice to a higher layer in order to maintain the correct slice structure. +Let's imagine that the `countries` slice is more dense with business logic than in the example above, then merging it with the `cities` slice will create additional clutter, so a good solution would be to restructure the logic of the `cities` slice in a higher layer. -The result of moving the `countries` and `cities` slices to different layers: +The result of moving the logic of the `countries` and `cities` slices: - `📂 entities` - `📂 countries` - `📁 lib` - `📄 getCountriesList ` - `📂 features` - - `📁 cities` + - `📁 get-locations` - `📁 lib` - `📄 getCitiesByCountryName` -By moving the `cities` slice to the `features` layer (not necessarily to it, any layer higher in the hierarchy will do), its domain area became more specific and it became possible to build an import mechanism that is correct from the point of view of the layer hierarchy. +By restructuring the logic of the `cities` slice on the `features` layer (not necessarily on it, any layer higher in the hierarchy will do), its domain area was more specifically clarified, and it became possible to build a correct import mechanism from the point of view of the layer hierarchy. ### Duplication code {#duplication-code} If the amount of data you are going to import from another slice is small, it may be worth duplicating it into the current slice. However, this option should not be a priority among all the above. diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index 3dfced02b3..6bd488c895 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -54,19 +54,19 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' Вполне вероятно, что слайс, в который Вы импортируете данные другого слайса сильно насыщен логически, и его можно переместить на слой выше, дабы устранить связность слайсов в рамках одного слоя. -Представим, что слайс `countries` более насыщен бизнес-логикой, чем на примере выше, тогда объединение его со слайсом `cities` создаст дополнительный беспорядок, поэтому хорошим решением будет переместить слайс `cities` на слой выше, дабы сохранить корректную структуру слайсов. +Представим, что слайс `countries` более насыщен бизнес-логикой, чем на примере выше, тогда объединение его со слайсом `cities` создаст дополнительный беспорядок, поэтому хорошим решением будет реструктуризовать логику слайса `cities`, в более высоком слое. -Результат перемещения слайсов `countries` и `cities` на разные слои: +Результат перемещения логики слайсов `countries` и `cities`: - `📂 entities` - `📂 countries` - `📁 lib` - `📄 getCountriesList ` - `📂 features` - - `📁 cities` + - `📁 get-locaitons` - `📁 lib` - `📄 getCitiesByCountryName` -Переместив слайс `cities` на слой `features` (не обязательно на него, подойдёт любой слой выше по иерархии), его доменная область более конкретно уточнилась появилась возможность построить правильный с точки зрения иерархии слоёв механизм импортов. +Реструктуризовав логику слайса `cities` на слое `features` (не обязательно на него, подойдёт любой слой выше по иерархии), его доменная область более конкретно уточнилась появилась возможность построить правильный с точки зрения иерархии слоёв механизм импортов. ### Дублирование кода {#duplication-code} Если объем данных, который Вы собираетесь импортировать из другого слайса невелик, возможно стоит будет продублировать его в текущий слайс. Тем не менее, такой вариант не должен являться приоритетным, среди всех вышеописанных. From d533dd6405cc00f2657b09aabd442b6ced3f0403 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 24 Sep 2024 18:03:08 +0300 Subject: [PATCH 8/8] add new example --- .../current/guides/issues/cross-imports.mdx | 107 +++++++++--------- .../current/guides/issues/cross-imports.mdx | 102 +++++++++-------- 2 files changed, 110 insertions(+), 99 deletions(-) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index c6209182cd..588b54ba2d 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/en/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -10,41 +10,43 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' -> Cross-imports appear when a layer/abstraction starts to take on too much responsibility than it should. That is why the methodology allocates new layers that allow these cross-imports to be decoupled. +> Cross-imports appear when a layer/abstraction starts taking on too much responsibility than it should. That is why the methodology allocates new layers that allow these cross-imports to be decoupled. ## Introduction {#start} **Cross-import** is a situation in which, within a layer, there is a need to import data from one slice to another. -:::warning Warning +:::warning Important The article only deals with conflict situations when importing between **slices**. Within one slice, fragments can import each other, such a situation is not prohibited. + ::: -Let's look at an abstract example: +Let's imagine that we are developing a TODO List application for storing notes. We need to store several task cards and display them on a board. There can be several boards with cards. +Let's look at a simplified example of the structure of such an application: - `📂 entities` - - `📂 countries` - - `📁 lib` - - `📄 getCountriesList ` - - `📁 cities` - - `📁 lib` - - `📄 getCitiesByCountryName` + - `📂 task` + - `📁 ui` + - `📄 TaskCard` + - `📁 board` + - `📁 ui` + - `📄 BoardTasks` -In this example, to call the `getCitiesByCountryName` method, you need to get the result of calling the `getCountriesList` method. -It is not possible to obtain the result of the `getCountriesList` method directly, as this would violate the principle of low coupling and complicate the project's maintenance in the future. +In this example, the `BoardTasks` component needs to import the `TaskCard` component to display cards. +You cannot import the `TaskCard` component directly, as this would violate the principle of low coupling and make it more difficult to maintain the project in the future. ## Cross-import solutions options {#solutions} ### Merging multiple slices into one {#slices-merge} -As you can see from the example above, the domain scope of the `getCitiesByCountryName` and `getCountriesList` methods is quite similar, meaning it is possible to create a derived slice from the two existing ones, where both methods would be in the same directory. +As you can see from the example above, the domain of the `TaskCard` and `BoardTasks` components are quite similar, which means it is possible to create a derived slice from the two existing ones, where both methods would be in the same directory. -Result of merging slices `countries` and `cities`: +The result of merging the `task` and `board` slices: - `📂 entities` - - `📂 location` - - `📁 lib` - - `📄 getCountriesList` - - `📄 getCitiesByCountryName` + - `📂 board` + - `📁 ui` + - `📄 TaskCard` + - `📄 BoardTasks` As you can see from the example, we have eliminated the situation where one slice imports data from another and achieved high cohesion and low connectivity within a segment of a single slice. @@ -53,19 +55,20 @@ This option is more suitable for those cases where combining several slices into It is likely that the slice into which you are importing data from another slice is highly logically rich and can be moved to a higher layer to eliminate the connectivity of slices within a single layer. -Let's imagine that the `countries` slice is more dense with business logic than in the example above, then merging it with the `cities` slice will create additional clutter, so a good solution would be to restructure the logic of the `cities` slice in a higher layer. +Let's imagine that the `board` slice is more dense with business logic than in the example above, then merging it with the `task` slice will create additional clutter, so a good solution would be to restructure the logic of the `board` slice in a higher layer. + +The result of moving the logic of the `task` and `board` slices: -The result of moving the logic of the `countries` and `cities` slices: - `📂 entities` - - `📂 countries` - - `📁 lib` - - `📄 getCountriesList ` + - `📂 task` + - `📁 ui` + - `📄 TaskCard` - `📂 features` - - `📁 get-locations` - - `📁 lib` - - `📄 getCitiesByCountryName` + - `📁 view-board` + - `📁 ui` + - `📄 BoardTasks` -By restructuring the logic of the `cities` slice on the `features` layer (not necessarily on it, any layer higher in the hierarchy will do), its domain area was more specifically clarified, and it became possible to build a correct import mechanism from the point of view of the layer hierarchy. +By restructuring the logic of the `board` slice on the `features` layer (not necessarily on it, any layer higher in the hierarchy will do), its domain area was more specifically clarified, and it became possible to build a correct import mechanism from the point of view of the layer hierarchy. ### Duplication code {#duplication-code} If the amount of data you are going to import from another slice is small, it may be worth duplicating it into the current slice. However, this option should not be a priority among all the above. @@ -74,41 +77,43 @@ If the amount of data you are going to import from another slice is small, it ma :::caution Warning -The approach described in this section is experimental and has not yet been standardized. -However, in exotic situations, the information in this section may be useful. +The approach described in this section is experimental and has not yet been standardized. However, in exotic situations, the information in this section may be useful. ::: If your project requires cross-import and the three methods described above did not help, the Feature Sliced ​​Design community offers the following solution to the problem. - `📂 entities` - - `📂 countries` - - `📁 lib` - - `📄 getCountriesList ` - - `@x` - - `📁 cities` - - `📁 lib` - - `📄 getCitiesByCountryName` - - `@x` + - `📂 task` + - `📁 ui` + - `📄 TaskCard` + - `@x` + - `📁 board` + - `📁 ui` + - `📄 BoardTasks` + - `@x` ### @x {#export-private-api} **@x** - this is an experimental approach where within a slice you can create an explicit public export of only those modules that can be used within multiple slices of the same layer. -Let's look at an example: -```ts title="entities/countries/@x.ts" -export { getCountriesList } from './lib/getCountriesList.ts'; +Let's look at an example (TSX markup): +```ts title="entities/task/@x.ts" +export { TaskCard } from './ui/TaskCard.tsx'; ``` -The method inside the slice that requires cross import: -```ts title="entities/cities/lib/getCitiesByCountryName" -import { getCountriesList } from '/entities/countries/@x/getCountriesList'; - -const countries = getCountriesList(); - -const getCitiesByCountryName = (countryName: string) => {} // logic - -return getCitiesByCountryName(countries[0]); +Component inside slice that needs cross import: +```tsx title="entities/board/ui/BoardTasks.tsx" +import { TaskCard } from '/entities/task/@x/TaskCard'; + +export const BoardTasks = () => {  return ( +   
+      +      +      +   
+  ) +} ``` -As you can see from the import path in the `getCitiesByCountryName` file, thanks to the export from the @x file, it is clear that this module is not intended for public use, but exists only to be imported inside another slice. +As you can see from the import path in the `BoardTasks` file, thanks to the export from the @x file, it is clear that this module is not intended for public use, but exists only to be imported into another slice. ### Lifting the ban on cross-imports {#disable-cross-imports-rule} If you have tried all the methods in the article, but for some reason still could not get rid of cross-imports, perhaps it is worth considering lifting the ban on them within specific slices, or the entire project as a whole. @@ -116,8 +121,8 @@ However, it is important to understand that lifting the ban on cross-imports cou ## Useful links {#useful-links} -1. The Feature Sliced ​​Design team has developed a tool that allows you to automatically check for cross-imports in a project: [Steiger](https://github.com/feature-sliced/steiger) -2. More information about the cross-import rule: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md) +1. The Feature Sliced ​​Design team has developed a tool that allows you to automatically check for cross-imports in a project: [Steiger](https://github.com/feature-sliced/steiger)  +2. More information about the cross-import rule: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md)  ## See also {#see-also} diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx index 6bd488c895..926387c16b 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/guides/issues/cross-imports.mdx @@ -22,30 +22,32 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' ::: -Рассмотрим абстрактный пример: +Представим, что разрабатываем приложение TODO List для хранения заметок. Необходимо хранить несколько карточек с задачами и отображать их на доске. Досок с карточками может быть несколько. +Рассмотрим упрощённый пример структуры такого приложения: - `📂 entities` - - `📂 countries` - - `📁 lib` - - `📄 getCountriesList ` - - `📁 cities` - - `📁 lib` - - `📄 getCitiesByCountryName` + - `📂 task` + - `📁 ui` + - `📄 TaskCard` + - `📁 board` + - `📁 ui` + - `📄 BoardTasks` -В данном примере для вызова метода `getCitiesByCountryName` необходимо получить результат вызова метода `getCountriesList`. -Получить результат работы метода `getCountriesList` напрямую нельзя, так как это нарушит принцип низкой связности и усложнит поддержку проекта в дальнейшем. +В данном примере компоненту `BoardTasks` для отображения карточек необходим импорт компонента `TaskCard`. +Импортировать компонент `TaskCard` напрямую нельзя, так как это нарушит принцип низкой связности и усложнит поддержку проекта в дальнейшем. ## Варианты решения кросс-импортов {#solutions} ### Объединение нескольких слайсов в один {#slices-merge} -Как видно из примера выше, доменная область методов `getCitiesByCountryName` и `getCountriesList` довольно похожа, а значит существует возможность создания производного слайса из двух существующих, где оба метода находились бы в одной директории. +Как видно из примера выше, доменная область компонентов `TaskCard` и `BoardTasks` довольно похожа, а значит существует возможность создания производного слайса из двух существующих, где оба метода находились бы в одной директории. + +Результат объединения слайсов `task` и `board`: -Результат объединения слайсов `countries` и `cities`: - `📂 entities` - - `📂 location` - - `📁 lib` - - `📄 getCountriesList` - - `📄 getCitiesByCountryName` + - `📂 board` + - `📁 ui` + - `📄 TaskCard` + - `📄 BoardTasks` Как видно из примера, мы избавились от ситуации, когда один слайс импортирует данные из другого и достигли высокой сцепленности и низкой связности в рамках сегмента одного слайса. @@ -54,19 +56,20 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' Вполне вероятно, что слайс, в который Вы импортируете данные другого слайса сильно насыщен логически, и его можно переместить на слой выше, дабы устранить связность слайсов в рамках одного слоя. -Представим, что слайс `countries` более насыщен бизнес-логикой, чем на примере выше, тогда объединение его со слайсом `cities` создаст дополнительный беспорядок, поэтому хорошим решением будет реструктуризовать логику слайса `cities`, в более высоком слое. +Представим, что слайс `board` более насыщен бизнес-логикой, чем на примере выше, тогда объединение его со слайсом `task` создаст дополнительный беспорядок, поэтому хорошим решением будет реструктуризовать логику слайса `board`, в более высоком слое. + +Результат перемещения логики слайсов `task` и `board`: -Результат перемещения логики слайсов `countries` и `cities`: - `📂 entities` - - `📂 countries` - - `📁 lib` - - `📄 getCountriesList ` + - `📂 task` + - `📁 ui` + - `📄 TaskCard` - `📂 features` - - `📁 get-locaitons` - - `📁 lib` - - `📄 getCitiesByCountryName` + - `📁 view-board` + - `📁 ui` + - `📄 BoardTasks` -Реструктуризовав логику слайса `cities` на слое `features` (не обязательно на него, подойдёт любой слой выше по иерархии), его доменная область более конкретно уточнилась появилась возможность построить правильный с точки зрения иерархии слоёв механизм импортов. +Реструктуризовав логику слайса `board` на слое `features` (не обязательно на него, подойдёт любой слой выше по иерархии), его доменная область более конкретно уточнилась появилась возможность построить правильный с точки зрения иерархии слоёв механизм импортов. ### Дублирование кода {#duplication-code} Если объем данных, который Вы собираетесь импортировать из другого слайса невелик, возможно стоит будет продублировать его в текущий слайс. Тем не менее, такой вариант не должен являться приоритетным, среди всех вышеописанных. @@ -83,42 +86,45 @@ import WIP from '@site/src/shared/ui/wip/tmpl.mdx' Если в Вашем проекте необходим кросс-импорт и три вышеописанных способа не помогли, сообщество Feature Sliced Design предлагает следующий вариант решения проблемы. - `📂 entities` - - `📂 countries` - - `📁 lib` - - `📄 getCountriesList ` - - `@x` - - `📁 cities` - - `📁 lib` - - `📄 getCitiesByCountryName` - - `@x` + - `📂 task` + - `📁 ui` + - `📄 TaskCard` + - `@x` + - `📁 board` + - `📁 ui` + - `📄 BoardTasks` + - `@x` ### @x {#export-private-api} **@x** - это эксперементальный подход, когда внутри слайса можно создать явный публичный экспорт только тех модулей, которые можно использовать в рамках нескольких слайсов одного слоя. -Рассмотрим пример: -```ts title="entities/countries/@x.ts" -export { getCountriesList } from './lib/getCountriesList.ts'; +Рассмотрим пример (разметка TSX): +```ts title="entities/task/@x.ts" +export { TaskCard } from './ui/TaskCard.tsx'; ``` -Метод внутри слайса, которому необходим кросс-импорт: -```ts title="entities/cities/lib/getCitiesByCountryName" -import { getCountriesList } from '/entities/countries/@x/getCountriesList'; - -const countries = getCountriesList(); - -const getCitiesByCountryName = (countryName: string) => {} // logic - -return getCitiesByCountryName(countries[0]); +Компонент внутри слайса, которому необходим кросс-импорт: +```tsx title="entities/board/ui/BoardTasks.tsx" +import { TaskCard } from '/entities/task/@x/TaskCard'; + +export const BoardTasks = () => {  return ( +   
+      +      +      +   
+  ) +} ``` -Как видно по пути импорта в файле `getCitiesByCountryName`, благодаря экспорту из файла @x видно, что данный модуль не предназначен для публичного использования, а существует только для того, чтобы быть импортированным внутрь другого слайса. +Как видно по пути импорта в файле `BoardTasks`, благодаря экспорту из файла @x видно, что данный модуль не предназначен для публичного использования, а существует только для того, чтобы быть импортированным внутрь другого слайса. ### Отмена запрета на кросс-импорты {#disable-cross-imports-rule} Если Вы попробовали все способы в статье, но по каким-либо причинам всё равно не смогли избавиться от кросс-импортов, возможно, стоить задуматься о том, чтобы снять запрет на них в рамках конкретных слайсов, либо всего проекта в целом. -Однако, важно понимать, что отмена запрета на кросс-импорты, потенциально может негативно сказываться на общей структуре проекта. +Однако, важно понимать, что отмена запрета на кросс-импорты, потенциально может негативно сказываться на общей структуре проекта.  ## Полезные ссылки {#useful-links} -1. Команда Feature Sliced Design разработала инструмент, позволяющий автоматически проверить наличие кросс-импортов в проекте: [Steiger](https://github.com/feature-sliced/steiger) -2. Больше информации о правиле кросс-импортов: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md) +1. Команда Feature Sliced Design разработала инструмент, позволяющий автоматически проверить наличие кросс-импортов в проекте: [Steiger](https://github.com/feature-sliced/steiger)  +2. Больше информации о правиле кросс-импортов: [Steiger-Forbidden-Imports](https://github.com/feature-sliced/steiger/blob/master/packages/steiger-plugin-fsd/src/forbidden-imports/README.md)  ## См. также {#see-also}