The StateManager in Ember.js isn't that well documented yet, so I've got some questions regarding its usage.
Should one strive to call .goToState only from within the state manager?
I sometimes find myself mirroring methods in the state manager on the view, e.g. save: -> StateManager.send("save"). Does that make sense or am I missing something?
Should all modification of models (generally) go through the state manager?
If one view has different states, should that be modeled using a ViewState with child states, or should I use computed properties and view properties to hold that information only in the view (without the state manager knowing of the views internal state)?*
*One example could be a three-step form, where the same template is used for all states but different areas are shown/hidden in the three steps.
Github reference: https://github.com/emberjs/ember.js/tree/master/packages/ember-states/lib
Should one strive to call .goToState only from within the state
manager?
Probably. I don't know this for certain, but it seems to me that because the state manager knows what state you're in, it's the place to enforce legal state transitions. If you called .goToState from outside the state manager, you're doing it without really knowing what state you're in, and while that's sometimes OK (maybe it's a state you really can reach from any other state) it's not a great habit to be in.
I sometimes find myself mirroring methods in the state
manager on the view, e.g. save: -> StateManager.send("save"). Does
that make sense or am I missing something?
I like what pangratz has to say about this.
Should all modification of
models (generally) go through the state manager?
The way I use statecharts, no. I've seen some people using statecharts as pretty much a complete replacement for the controller layer, however, and if that's how you're working, then yes, it should go through the state manager. The pattern is to avoid direct manipulation of models from views; whether it's a controller layer or a state manager in between seems like a moot point to me.
The way I use state charts, however, the state manager is made to manage the state of the application. It can play traffic manager for the modification of models if that modification will change the state of the application (e.g. if there's a progress indicator while an update completes), but it seems to me that model updates aren't part of its mandate; they belong to controllers.
If one view has
different states, should that be modeled using a ViewState with child
states, or should I use computed properties and view properties to
hold that information only in the view (without the state manager
knowing of the views internal state)?
I think the state manager needs to know (or ought to know) the view's internal state.
Out of curiosity, are you coming from a web development background, or a desktop/mobile app development background? I came from web development, and state charts were a new concept for me. I found it very useful to read the canonical State Chart paper by David Harel ('ware PDF!). It's surprisingly readable for an academic paper and lays out the basic state chart concept most of the SproutCore/Ember world has been using since late 2010 (i.e. it's what Michael Cohen had in mind when he wrote Ki.)
Regarding your point 2:
I sometimes find myself mirroring methods in the state manager on the view, e.g. save: -> StateManager.send("save"). Does that make sense or am I missing something?
You could use the action helper in your Handlebars template and set your StateManager as target
{{action "send" target="App.stateManager"}}
And the the send event is send to your App.stateManager.
Related
I'm facing a stupid problem.
In a web app (my stack is vue + vuex + vue-router) I'm totally unable to synchronize my store state with the page the user is viewing.
When a user triggers the back or forward button, it triggers the same onpopstate event that gives absolutely no information about "direction" or the number of page. Only the array key in the state object seem to be barely workable (saving it when going to new places and then guessing where the user went onpopstate) but I don't even know where the "door" corresponding for "the key".
So from there I thought about manually tracking the history state key and guessing where the user has been but I guess it wouldn't be cross-compatible, and also it's heavy code to lift.
Here is my question: Am I missing some key element in the html5 API, how could I do (and keep code/logic minimalist)?
Thank you in advance!
EDIT: renamed the title and added info
EDIT2: vuex-router-sync is inappropriate since it only provides route info on vuex side and does not really sync router state and store state...to bad
P.S.: please don't c/p definitions, read carefully, think
onpopstate provides the state object in event.state correlating to the respective place in history of your application.
Write your application so that providing this state object encompasses the entire state of your application, regardless of time. I recommend you read about State pattern, and understand what "state" means, e.g.
the particular condition that someone or something is in at a specific time.
The implication I'm making is that you should not need to know the relative location in history your application is in, because event.state should be all your application needs in order to determine what to render.
I'm reading on design patterns and while authors agree that observer pattern is cool, when it comes to design, everybody talks MVC.
I'm a bit confused, MVC diagram is not circular, isn't it natural for code flow to have closed topology ? Why nobody talking this pattern:
model -> observer -> view -> listener -> model -> ..
If view needs controller, then model needs observer, no ? With Object.observe() coming with next JavaScript version, what is wrong with such a pattern ?
The View and and the Controller are both, also, observers.
The view /is/ an observer, of events on the model. The controller /is/ an observer of events in the view. The controller fires commands at the model, which results in it changing which propagates events which are observed by the view which changes its state appropriately.
The problem this is trying to solve is having a UI respond to changes in a model, and having the model respond to input from a user via a UI. There is no great reason to have a third component involved in this, other than the frailty of human vision -- it is far easier to envision a command and control system than an event driven system, though surprisingly the latter is often easier to implement.
One problem with your proposed design is separation of concerns. With MVC (when done properly, with messages/events) each component only knows about itself and its own concerns. With the model you're proposing the Observer component must know how to orchestrate the view, something which the view is better placed to do itself.
Of course, you're thinking that the controller orchestrates changes to the model, so why wouldn't we have an equivalent component on the far side of the relationship?
In fact, although we do typically implement something in the 'controller' space, it's often just 'infrastructure' to pass messages/events/commands from the view to the model, which responds accordingly -- that is, often the controller devolves into a simple router. The need for an orchestration component has been reduced in modern designs due to our better understanding of DDD and the aggregate-root pattern, and of course the possibilities of event-sourcing.
Finally, the pattern you're referring to was originally documented by the Gang of Four as existing in practice and relatively common. At the time there were no mobile or webapps, and one of the largest systems they considered was gimp. As our technologies have matured and our apps are delivered via multiple channels so have the patterns of development in this space. A few years back we were discussing MVC2, then we moved on to oddities like MVVC and MMVC. Now, with CQRS, event-sourcing, and DDD, we have started talking about MV as the orchestration approach has started showing its limitations and event driven systems come to the fore.
I am thinking about how to organize Model in my webapp. I have two options, as I see it:
Create a single globally available Model object, then on instantiating new components they must register themselves in the Model object via methods, then update it when their state changes. Others would listen to changes from the Model by some key.
Create a model object for each component and let others know via some Event dispatcher about their state change.
In 1st case I feel like it will be easier to manage all the state change in one place, have more standardized way of doing it, while with the latter scenario I think it will be harder to maintain consistence over the system.
What are the factors I should base the decision on?
I would go with the first but adding the idea of the second: Instead of the components checking constantly the keys for changes you can make the only model signal the components when needed after they register. You can pass the signal/callback with the register itself.
That way you don't need to create an army of models that update themselves (that might also mean you have to avoid cyclic propagation). In addition to this, if I understand correctly it would violate the single source of truth. Also it looks worse both memory and performance wise.
I'm new to ReactJS and I'm trying to figure out how to store and manipulate global state. For example, I'm writing an editor app that has some global state: selected color/background, active tool, current selection, etc.
I'm thinking about having a root interface component to store this information, and I'm ok with explicitly passing the state around using properties. I guess the idiomatic way for a children component to change global state is calling a callback received from the parent - personally I find this a bit annoying.
Instead, I'm firing custom events at the children and setting listeners on the parent. So far it is working really well, but I looked at a lot of sample code and never saw people using this pattern.
Is there any practical consequences I should consider?
Flux is great for manipulating global state because the Stores are globally accessible. Globals are known to be bad, but the way you interact with the Stores is through Actions. Actions make the state predictable and localized. So even though the state storage itself is global, Actions make the state interactions very local. At work we tend to do both reading & writing through Actions, so every state change is an "event" that leads to easily programmable behavior.
I really wouldn't compare Flux to Angular as their principles and flows are entirely different. Suggest you try Reflux.
I'm pretty new to this world so I need some clarifications on it. Maybe I could be wrong on the subject. So, feel free to correct me.
I'm studying how Marionette and Backbone work together. Oh yeah. Marionette gives us extension to Backbone. Really nice stuff.
The thing that is not obvious to me is when to use the routing mechanism provided by Backbone and when to use publisher/subscriber pattern by Marionette.
Is there any rule of thumb?
Here, Where to use event aggregator in backbone marionette?, a similar discussion but there is no advice on how using that or the other.
My take on the route management is explained in the free preview to my book on Marionette (http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf)
Basically, my opinion (others don't necessarily share it) is that Backbone's routing should be used to configure the application state when the user "enters" the application via a URL. In other words, it will parse parameters, and call proper controller actions.
But once that initial state is setup, routing code should no longer be triggered, even as the user navigates through the application.
Here's an example:
The user enters arrives on the "contacts/2/edit". Backbone routing code will extract the 2 argument and call the edit controller action with that id parameter (which fetches that contact, displays the proper views, etc.). In other words, the initial application state is being configured.
The user clicks on the "show all contacts" link leading to the "contacts" URL. Here, I believe this modification should be handled through Marionette events (i.e. indicating the user wants to see all contacts). After all, we know what the user wants to do, and which URL fragment should be displayed. In other words, there is no reason for the routing code to get involved.
Note that this is my opinion, and other developers simply pass trigger: true when the user clicks a link. But as I explain in the book extract linked above, this tends to lead developers to create "stateless applications in javascript" (e.g. passing lots of parameters in the URL, even though they should be stored in the application's state). Ater all there is a reason that by default, Backbone's navigate method has trigger: false.
Derick Bailey (Marionette's creator) also discussed the issue here: http://lostechies.com/derickbailey/2011/08/03/stop-using-backbone-as-if-it-were-a-stateless-web-server/
Event aggregator is more useful for notifying things. (think small bits of feedback)
Message from server (updated record)
Let other models know things have changed
Lock everything down while saving until saved
Single Moment in time things
Router is for things where you want the state to be save-able (think separate page in a MPA)
Model Edit Page
Model View Page
Something that will stay until another event or activity changes it
If you are not sure if something is an event or a page, then think about it and ask that separate question.