This is a response to Bill Fisher regarding experience with Flux:
@abdullin Also, can you clarify what you mean by "solution structure"? I am thinking about revising the examples soon.
Currently all flux samples (that I've seen) group files into folders based on technical similarity. For example, stores go with stores, action creators reside in the same folder shared with the other action creators.
This pattern works quite well for smaller projects. It feels especially good for the sample projects of various MVC frameworks, when you have just a bunch of controllers, models and views.
However, as we discovered on some production projects, such approach doesn't scale well. At some point you end up with dozens of technically similar files per folder and logically messy solution.
- Doesn't scale well.
- While you work on a component, you have to suffer from extra context switching overhead (jumping between various folders).
- Solutions become more "entangled" than needed.
- More complex IDE features are needed to support the workflow (e.g. context-aware navigation and completion).
- More merge conflicts, since it is harder to bound work by a feature (and communicate that).
We discovered that aligning solution with the domain model leads to a better design in the long run. E.g. we try to group files by their functionality or feature. This would mean, that different technical elements of a single feature could be squashed into one folder or onto one file. For example, for Flux we are considering to have a single folder for "News feed", which would contain all related action creators, fetchers and stores. Of course, there could be some other components that the this chat page would use (e.g. avatars, like buttons or user stores), such components would reside in their own folders. On the overall, such component decomposition is requires more effort than simply grouping files by class type. However, we value both the process (it leads to a deeper insight) and the outcome (solution that is more simple to think and reason about).
Of course, this is just something that seems to work only in a subset of cases I've been exposed to. There can easily be a deeper pattern which I fail to recognize.
Hi Thomas,
Yes, this is essentially how I would do validation, but only if my validation was somewhat simple, like a regex to validate that the text looks like an email address.
However, if the validation requires me to examine the state of the stores, then I would want to move all of this to the store. If I was concerned about race conditions with the resolution of the API call vs. the current dispatch, I would manage that with a check to Dispatcher.isDispatching() in the action creator called from the response handler.
Keeping the validation and the API call in the action creator has the advantage of keeping action creators out of the store. The advantage of having the validation and API call in the store, however, is that application logic resides in the store along with state management.
See also: http://stackoverflow.com/questions/27363225/tracking-ajax-request-status-in-a-flux-application/27459732#27459732
Semantic tangent:
In our action types, we often don't have an agent or other details. They primarily have the form of OBJECT_VERB. There is no agent. In this case, the user has actually submitted the message to the application. They pressed the enter key on their keyboard. And this is what the action is saying about something that happened in the real world. The application has not submitted the message to the store or the API, but this is an internal detail. The results of an XHR may not seem like something happening in the real world, but I would argue that they are -- we become painfully aware of this while developing for the mobile web.