Define communication between features
Opened this issue · 11 comments
A feature could expose actions for other features to use and affect its internal state.
Could the feature also expose its state for other features to use,
or it should implement its own UI peaces connected with the data that other features need to use in ?
for example if the a header need to show the username then we could :
- expose the username from the user feature (which breaks the dispose-ability role)
- implement that peace of the header in user feature and expose it (which couples that feature to every peace that needs to use it differently)
I consider features state to be private. This is very important, because otherwise you can't know when and how its going to change within a feature.
Another constraint is that a feature can't depend on another feature, otherwise they become coupled and the entire architecture rendered to zero.
Knowing this we need to find ways to implement a communication in a way without violating those constraints.
One way could be to implement the communication inside of the page that renders both features. Page passes callbacks to both features, so we can make it work.
If this approach becomes too verbose or you want to reuse those 2 features on more than one pages, you will want to extract this logic into something reusable.
I was thinking about a "cluster" concept. It could be something generiс in terms of implementation that allows to connect any features. Or it could be a specific cluster that connects them in a specific way. I don't have an answer there, it needs to be tried.
It's a very interesting concept. I have some questions for discussion, but better with examples.
- We have feature Login, for authorization. After we authorize, we save some information about use to state (name, maybe role, etc.), and we need this information in other features. I guess it's a common case. We should create 'login selectors' in the shared folder?
- The same situation about actions, but it's break encapsulation of the feature. Or, we should duplicate actions like 'featureName/send_document' and 'global/send_document'?
@pgrekovich what do you mean by "we save"? Where? If a feature doesn't render any more then page is supposed to hold the login state and pass it down to any other feature. Alternatively context api could be used if you are in React.
A feature can expose actions and a page can dispatch those to avoid duplicating them.
Important is that a feature doesn't depend on a feature. Also, nothing can access feature-controlled state subtree except of the corresponding feature itself.
@kof I wrote it wrong, sorry. I meant, redux state, and after login we have information in the redux state, but it's the feature state (in the redux store), and other features will depend on this state, it's ok?
They will depend on it, but they can't access it directly. Login feature will have to pass public values to a callback to the page/cluster and page/cluster will pass it to any other feature. This roundtrip is what allows features to stay decoupled.
@kof Thanks, now it is clear to me! I think we should start writing spec, for discussing and refining. I want help, if you do not mind, but I do not know where to start. Any ideas?)
I think writing and discussing proposals in every issue would be a first step before composing a document.
I think bullet points with problems and solutions would be a good structure, in each issue.
Why we can't describe public API for each feature? What if selectors are an abstraction for feature's state and some facade-like methods that control actions?
And we can use annotations for more clearance:
import { someDataSelector } from '@features/featureA/selectors'
@meetromb I think it's because we can't predict everything that can be exported from a feature. Someone wants to use redux-saga, and export sagas, someone else - redux-thunk, someone wants export translations files, etc. I guess principles of creating public interfaces for features is more useful.
@pgrekovich Yep, you are right about principles of creating public interfaces.
Each project/team must have strict rules about exporting and creating feature's public interface, otherwise it gonna be a mess.