Features
When it becomes difficult to find the boundaries of specific user scenarios in a project, which worsens the controllability and reuse of logic
Use it only if you are sure that additional separation by features will help your application, and will not cause too much misunderstanding and skepticism! (instead, you can locate such logic directly in widgets) โ ๏ธ
Descriptionโ
Each feature is a part of the business logic, while it necessarily has meaning and value for the end user
ProductList
,OfficeMap
- can hardly be called featuresWalletAddFunds
,AddToCart
- already makes more sense for the end user
At the same time:
- the underlying layers are used to build the logic
shared
,entities
- one feature cannot import another
- If there is such a need - the dependency needs to be transferred to the layer above / below, or solved through the composition through children-props
- features cannot be nested, but they can be combined by a common folder, i.e. structurally
- At the same time, you can not create intermediate files that are necessary for a specific group of features
- You can only use re-export files
Structureโ
โโโ features/{slice}
โโโ lib/
โโโ model/
โโโ ui/
โโโ index.ts
Thus, the feature stores information about:
- What data is needed for its operation
- By what rules do data changes occur
- What entities are needed for the complete construction of the feature
- How the data is presented to the user
Rulesโ
One feature = one functionalityโ
The feature contains code that implements one useful functionality for the user.
Structural grouping of featuresโ
Often there is a need to put together a number of somewhat related features (at the same time, they can and should not import each other directly)
The methodology recommends avoiding nested features, i.e. features that are strongly connected under a common wrapper with an additional one. by logic
Instead, the methodology suggests that, if necessary, group the necessary features by folders (at the same time, you can not link these features directly, folders are only needed for structural grouping by meaning)
features/order/ Feature group
โโโ add-to-cart Full-fledged feature
โโโ total-info Full-fledged feature
- โโโ model.ts General logic for the group
- โโโ hooks.ts General hooks for the group
โโโ index.ts Public API with re-export of features
Features should not depend on each otherโ
This rule is not always possible to comply with, but it is better to minimize the number of such violations.
Usually, it is precisely because of the neglect of this rule that there is a high coupling between the modules of the system and unpredictable side effects during development.
One of the ways to solve the problem is to use entity.
Examplesโ
From the point of view of the code: not all changes for the user are features
, but all features
are changes for the user.
Changing the application interface languageโ
Feature
for the user and the developer.
At the same time, the
i18n
logic itself can be used not only in this feature, but even in entities. Therefore, this should rather be placed inshared/lib
orshared/config
A separate guide will be added later
Transfer of funds between accountsโ
Feature
for the user and the developer.
Filter by tagsโ
- For the user:
feature
. - For the developer: entity
tags
allow you to implement a filter by tags insidefeature
.
Hints when filling in the form fieldsโ
- For the user:
feature
. - For the developer: part of
form
entity.
Authorization by phoneโ
import { viewerModel } from "entities/viewer";
export const AuthByPhone = () => {
return (
// for redux - dispatch is additionally needed
<Form onSuccess={(user) => viewerModel.setUser(user)}>
<Form.Input
type="phone"
...
/>
<Form.Button
...
/>
</Form>
)
}
See alsoโ
- "Guide to getting rid of cross-imports"
- Understanding user needs and business tasks
- To understand the
features
layer
- To understand the
- (Thread) About features and entities clearly