3 ms·
Redux or anything similar to it seems pretty close to this, assuming you always want to stick to its basic architecture (atomic immutable application state with
by baddox 11y ago
Redux or anything similar to it seems pretty close to this, assuming you always want to stick to its basic architecture (atomic immutable application state with "reducers" that take a state and an action and return the new resulting state).
Redux is so small that it's hard to see why you would need to switch away from it if you're keeping the same architecture, but even if you wanted to it ought to be fairly easy, since reducers are pure functions and actions are (or should be) simple JSON-able data.
The actual rendering of state to DOM is done completely separately by registering callbacks that listen for application state changes.
Of course, if you're using some other architecture to manage application state, results may vary.
- MatthewPhillips 11y agoHow can I write reusable components if my domain logic must be separate from my view logic?
- baddox 11y agoI was responding to a question about separating "the unique parts of your app" from other concerns like DOM and the network. I interpreted "the unique parts of your app" to be the way application state is represented and modified, which is a pretty reasonable definition for the common term "business logic." Library-agnostic reusable components is another question, and certainly a good one. There doesn't seem to be a good answer right now. Web Components appears to be intended to solve that problem, but it isn't looking so good in my opinion. I would probably go with a similar approach to reducers in Redux: a simple function that takes a state object and returns some library-agnostic representation of DOM. Of course there is no standard representation of DOM that I know of, but you could just output a plain JS object representing the DOM tree. There are probably many libraries out there offering a way to represent DOM that could easily to plugged into (with a simple wrapper) whatever new DOM rendering library is hot.
- zachrose 11y agoThe "separation" between your business logic and your view logic is really better thought of as a decoupling. Let's say for example that your application is a game of solitaire. Rendering the cards is a view concern. Interpreting UI events as game actions is a view concern. Accepting or rejecting those game actions is business concern. Animating that acceptance or rejection is a view concern. Persisting or restoring your moves or game state to an API is a business concern with some networking glued to the side of it. That's sort of a trivial example, but the event catalog for your application might look like this: name: GAME_STATE, payload: A JSON representation of the card stacks name: PLEASE_MOVE, payload: A representation of an attempted move name: MOVE_REJECTED, payload: The card that tried to make an illegal move A move event would result in a new state event or a rejection event. Your rendering components don't need to know how that happens or who controls the state. Your core components don't need to know if this game is being played on a server or a browser. Your move events might come from a swarm of multiple players. An analytics component can listen to the bus and fire off things that it's looking for.
- MatthewPhillips 11y agoThat's fine if my application is a game of solitaire. But what happens when I want to distribute it as a component, <Solitaire />? I can't, because it's not self-contained.
- zachrose 11y agoYou could package <SolitaireView/> and SolitaireGame together and distribute that? For somebody who just wants to drop a game of solitaire on their page that would work.
- zachrose 11y agoTotally. But if I'm being extreme I would say that keeping your application state "memoized" into a single value may or may not be necessary for your application. If it's not, you've just coupled all of the data models in your application to into the same entity, which makes it easier to turn those couplings into dependencies, which makes them harder to test and use separately later.