Skip to content

Commit 5aeea00

Browse files
authored
docs: excessive-entities page (#865)
1 parent 96ae579 commit 5aeea00

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Excessive Entities
2+
3+
The `entities` layer in Feature-Sliced Design is one of the lower layers that's primarily for business logic. That makes it widely accessible β€” all layers except for `shared` can access it. However, its global nature means that changes to `entities` can have a widespread impact, requiring careful design to avoid costly refactors.
4+
5+
Excessive entities can lead to ambiguity (what code belongs to this layer), coupling, and constant import dilemmas (code scattered across sibling entities).
6+
7+
## How to keep `entities` layer clean
8+
9+
### 0. Consider having no `entities` layer
10+
11+
You might think that your application won't be Feature-Sliced if you don't include this layer, but it is completely fine for the application to have no `entities` layer. It doesn't break FSD in any way, on the contrary, it simplifies the architecture and keeps the `entities` layer available for future scaling. For example, if your application acts as a thin client, most likely it doesn't need `entities` layer.
12+
13+
:::info[What are thick and thin clients?]
14+
15+
_Thick_ vs. _thin client_ distinction refers to how the application processes data:
16+
17+
- _Thin_ clients rely on the backend for most data processing. Client-side business logic is minimal and involves only exchanging data with the backend.
18+
- _Thick_ clients handle significant client-side business logic, making them suitable candidates for the `entities` layer.
19+
20+
Keep in mind that this classification is not strictly binary, and different parts of the same application may act as a "thick" or a "thin" client.
21+
22+
:::
23+
24+
### 1. Avoid preemptive slicing
25+
26+
In contrast to previous versions, FSD 2.1 encourages deferred decomposition of slices instead of preemptive, and this approach also extends to `entities` layer. At first, you can place all your code in the `model` segment of your page (widget, feature), and then consider refactoring it later, when business requirements are stable.
27+
28+
Remember: the later you move code to the `entities` layer, the less dangerous your potential refactors will be β€” code in Entities may affect functionality of any slice on higher layers.
29+
30+
### 2. Avoid Unnecessary Entities
31+
32+
Do not create an entity for every piece of business logic. Instead, leverage types from `shared/api` and place logic in the `model` segment of a current slice. For reusable business logic, use the `model` segment within an entity slice while keeping data definitions in `shared/api`:
33+
34+
```plaintext
35+
πŸ“‚ entities
36+
πŸ“‚ order
37+
πŸ“„ index.ts
38+
πŸ“‚ model
39+
πŸ“„ apply-discount.ts // Business logic using OrderDto from shared/api
40+
πŸ“‚ shared
41+
πŸ“‚ api
42+
πŸ“„ index.ts
43+
πŸ“‚ endpoints
44+
πŸ“„ order.ts
45+
```
46+
47+
### 3. Exclude CRUD Operations from Entities
48+
49+
CRUD operations, while essential, often involve boilerplate code without significant business logic. Including them in the `entities` layer can clutter it and obscure meaningful code. Instead, place CRUD operations in `shared/api`:
50+
51+
```plaintext
52+
πŸ“‚ shared
53+
πŸ“‚ api
54+
πŸ“„ client.ts
55+
πŸ“„ index.ts
56+
πŸ“‚ endpoints
57+
πŸ“„ order.ts // Contains all order-related CRUD operations
58+
πŸ“„ products.ts
59+
πŸ“„ cart.ts
60+
```
61+
62+
For complex CRUD operations (e.g., atomic updates, rollbacks, or transactions), evaluate whether the `entities` layer is appropriate, but use it with caution.
63+
64+
### 4. Store Authentication Data in `shared`
65+
66+
Prefer `shared` layer to creating a `user` entity for authentication data, such as tokens or user DTOs returned from the backend. These are context-specific and unlikely to be reused outside authentication scope:
67+
68+
- Authentication responses (e.g., tokens or DTOs) often lack fields needed for broader reuse or vary by context (e.g., private vs. public user profiles).
69+
- Using entities for auth data can lead to cross-layer imports (e.g., `entities` into `shared`) or usage of `@x` notation, complicating the architecture.
70+
71+
Instead, store authentication-related data in `shared/auth` or `shared/api`:
72+
73+
```plaintext
74+
πŸ“‚ shared
75+
πŸ“‚ auth
76+
πŸ“„ use-auth.ts // authenticated user info or token
77+
πŸ“„ index.ts
78+
πŸ“‚ api
79+
πŸ“„ client.ts
80+
πŸ“„ index.ts
81+
πŸ“‚ endpoints
82+
πŸ“„ order.ts
83+
```
84+
85+
For more details on implementing authentication, see [the Authentication guide](/docs/guides/examples/auth).
86+
87+
### 5. Minimize Cross-Imports
88+
89+
FSD permits cross-imports via `@x` notation, but they can introduce technical issues like circular dependencies. To avoid this, design entities within isolated business contexts to eliminate the need for cross-imports:
90+
91+
Non-Isolated Business Context (Avoid):
92+
93+
```plaintext
94+
πŸ“‚ entities
95+
πŸ“‚ order
96+
πŸ“‚ @x
97+
πŸ“‚ model
98+
πŸ“‚ order-item
99+
πŸ“‚ @x
100+
πŸ“‚ model
101+
πŸ“‚ order-customer-info
102+
πŸ“‚ @x
103+
πŸ“‚ model
104+
```
105+
106+
Isolated Business Context (Preferred):
107+
108+
```plaintext
109+
πŸ“‚ entities
110+
πŸ“‚ order-info
111+
πŸ“„ index.ts
112+
πŸ“‚ model
113+
πŸ“„ order-info.ts
114+
```
115+
116+
An isolated context encapsulates all related logic (e.g., order items and customer info) within a single module, reducing complexity and preventing external modifications to tightly coupled logic.

0 commit comments

Comments
Β (0)