In the State Machine Framework page on the QState machine, it talks about how QHistoryState works. A QHistoryState is instantiated as the child of another state, like in the example on the doc page:
However, while this QHistoryState in the example will remember which s1x state you were at before interruption, I wanted to know how far down it can remember transitions. For example, say state s13 had it's own subsidiary state machine like so:
In this expanded example, QHistoryState is not the child of s13, only s1. However, let's say we were at state s132 and then the interruptButton is clicked, thus temporarily transitioning to s3. When we go back to s13....which child state of s13 will we be in? s131, s132, or s133?
Therefore, my question is:
Question
Can the QHistoryState in the example I set up remember which s13x state was active upon transitioning back to the parent s1 state from s3?
Look at the historyType member. As an aside, you might want to re-examine your design. State machines aren't intended to rely on prior states for execution.
Related
I made this post on the Qt Forum as well but I haven't gotten any follow up so I'm hoping to continue the discussion some here. Here is the relevant parts of my post and the response.
My Post:
I have the following design: A main window which has a widget, and
inside that widget different widgets of type "Page" can be loaded. The
first page, let's call it the startup page, allows the user to type in
the serial number of the product. The database is then queried to get
some info about the product itself, and then a concrete child class
representing the type of "Product" is created. All child product
classes inherit from an abstract class, Product.
Basically, when the user selects the product by entering a serial
number, a product factory is called to create the concrete object and
then check if it's physically connected to the system via a bus. This
created product will then be passed to and used by other pages in
somewhat of a wizard like fashion.
Response:
The biggest problem I see [...] is that the ui
is kinda driving your logic. Typically that's a bad idea and down the
line leads to problems that are hard to foresee in the planning stage.
The way I would approach it is that your app is a state machine.
There's user input stage, product lookup stage (which may fail from
what you describe), product view/editing stage etc. Transitions
between those stages would dictate a ui change, for example switching
from product id input to product lookup would switch ui page from
input form to a wait indicator and finishing the query would move
either to success or fail state, which would show an error page or the
product page accordingly. The product object would then be governed by
the state machine state that handles it. Lookup would produce an
object and pass it to the view/edit state and that state would free it
when transitioning to another state. Your logic would be better
encapsulated this way and independent of the ui, which you may want to
change someday or make optional e.g. drive the state machine in a
silent mode, app params or something else. The ui would just send a
signal that would change the machine state e.g. entering a number
would transition the machine from input to lookup, which in turn could
be connected to page change.
The issue I'm having here is I'm not seeing how this actually decouples my application logic from my UI? The QStateMachine would be configured to transition between states based on button clicks which is inherently coupling it to my UI. If I wanted some type of "headless" mode, I'd basically have to reconfigure my entire state machine to attach to signals from different objects. I suppose I could try to abstract this by having a builder type class that configures all the state transitions based on what mode I'm in.
Maybe this indicates I would need some sort of intermediate object which is used whether or not I have a UI, and the state machine connects to signals from that object instead. My different widgets would then contain a reference to this same object and utilize it.
Basically, I am asking how I can decouple my state machine from the UI when it seems it's coupled by design, since what's driving the state machine is the UI itself.
The QStateMachine class and its related classes are not coupled “by design” to the UI. They could be used to implement state machines in any layer of the app.
The response you received just advocates for a better separation of concerns.
Like you already said (about the “headless” mode), you can pack your business logic in a component that drives such a state machine to handle the flow of your process. You can of course have also other state machines, in the UI, to handle model updates, user interaction and page navigation.
I'm a bit new to GMS2 and am having a bit of a problem.
In the current state of my game, you start in a useless room that only exists to initialize global variables and a persistent object. This room then switches to an actual level. All of this occurs in the creation code of the first room:
globalVars();
instance_create_depth(-2*global.tile_size, -2*global.tile_size, 0, OBJ_UTIL_manager);
room_goto(2);
Upon switching rooms, only some of the instances appear. In particular, only objects without a parent or with one certain parent appear. Objects with another type of parent do not appear. They are present in the room builder. They DO exist, but are invisible.
The same room, if moved to the top of the room queue and therefore being the first room created, works just fine as long as I add the above global variable initialization and manager object creation. Is there anything special that must be done when switching rooms to make things visible?
This is how the room appears in the editor: http://prntscr.com/lg2x3w
Compared to how it appears upon being switched to: http://prntscr.com/lg2wdg
I do not know the full detail of the problem, but I did have a similar issue, so I can tell you a solution without actually knowing what went wrong, but anyways hope it helps.
Firstly, use the instance_create_layer instead of instance_create_depth and make sure that these layers where you create your objects exist in both the first "fake" room and the actual room.
secondly, make sure you do not have any code that change the depth/layer in the create event. [again I do not know why this could cause an issue, but it did cause an issue to me, so maybe you have the same issue/solution]
I struggle finding the right way to mutate my state in an ngrx application as the state is rather complex and depending on many factors. This Question is not about doing one piece of code correct but more about how to design such a software in general, what are doe's and don'ts when finding some hacky solutions and workarounds.
The app 'evolved' by time and i wan't to share this process in an abstracted way to make my point clear:
Stage 1
State contains Entities. Those represent nodes in a tree and are linked by ids. Modifying or adding an entity requires a check about the type of nodes the new/modified ones should be connected with. Also it might be that upon modifying a node, other nodes had to be updated.
The solution was: create functions that do the job. Call them right in the reducer so everything is always up to date and synchronus when used (there are services that might modify state).
Stage 2
A configuration is added to the state having an impact on the way the automatically modifyed nodes are modifyed/created. This configuration is saved in it's own state right under the root state.
The solution:
1) Modify the actions to also take the required data from the configuration.
2) Modify the places where the actions are created/dispatched (add some ugly
this.state.select(fromRoot.getX)
.first()
.(subscribe(element => {this.state.dispatch(new Action({...old_payload, newPayload: element}))})
wrapper around the dispatch-calls)
3) modify the functions doing the node-modification and
4) adding the argument-passing to the function calls inside the reducer
Stage 3
Now i'am asked to again add another configuration to the process, also retrived by the backend and also saved in another state right under the root state
State now looks like:
root
|__nodes
|__config_1
|__config_2
i was just about to repeat the steps as in stage 2 but the actions get really ig with all the data passed in and functions have to carry around a lot of data. This seems to be wrong, when i actually dispatch the action on the state containing all the needed info.
How can i handle this correct?
Some ideasi already had:
use Effects: they are able to get everything from state they need and can create everything - so i only need to dispatch an action with only the actions payload, the effect then can grab everything from the state it needs. I don't like this idea because it triggers asynchronus tasks to modify the state and add not-state-changing actions.
use a service: with a service holding state it would be much like with effects but without using actions to just create asynchronus calls which then dispatch the actions that relly change state.
do all the stuffi n the component: at the moment the components are kept pretty simple when it comes to changing state as i prefer the idea that actions carry as little data as possible, since reducers can access the state to get theyr data - but this is where the problem occus, this time i can't get hands on the data i need.
I was wondering if it is better to put long execution logic in triggers or in states.
My concern is that if I put a complex, long logic within the triggers, then my state machine would stay too much time in a transitioning phase, and the information about the current state is no more meaningful.
Would the entry of each state the correct place to put long running logic?
Thanks
You don't put logic in a state directly but in a state entry or exit event. So no matter where you place it is runs as part of a state transition. Now as to what is the correct place, that completely depends on the logic. Simply stated, put it where it is appropriate :-)
suppose I have a domain classes:
public class Country
{
string name;
IList<Region> regions;
}
public class Region
{
string name;
IList<City> cities;
}
etc.
And I want to model this in a GUI in form of a tree.
public class Node<T>
{
T domainObject;
ObservableCollection<Node<T>> childNodes;
}
public class CountryNode : Node<Country>
{}
etc.
How can I automatically retrieve Region list changes for Country, City list changes for Region etc.?
One solution is to implement INotifyPropertyChanged on domain classes and change IList<> to ObservableCollection<>, but that feels kinda wrong because why should my domain model have resposibility to notify changes?
Another solution is to have that responsibility put upon the GUI/presentation layer, if some action led to adding a Region to a Country the presentation layer should add the new country to both the CountryNode.ChildNodes and the domain Country.Regions.
Any thoughts about this?
Rolling INotifyPropertyChanged into a solution is part of implementing eventing into your model. By nature, eventing itself is not out of line with the DDD mantra. In fact, it is one of the things that Evans has implied that has been missing from his earlier material. I don't remember exactly where, but he does mention it in this video; What I've learned about DDD since the book
In and of itself, impelemnting an eventing model is actually legitimate in the domain, because of the fact it introduces a decoupling between the domain and the other code in your system. All you are doing is saying that your domain has the capability of notifying interested parties in the fact that something has changed. It is the responsibility of the subscriber, then, to act upon it. I think that where the confusion lies is that you are only using an INotifyPropertyChanged implementation to relay back to an event sink. That event sink will then notify any subscribers, via a registered callback, that "something" has happened.
However, with that being said, your situation is one of the "fringe" scenarios that eventing does not apply all that well to. You are looking to see if you need to repopulate a UI when the list itself changes. At work, the current solution that we have uses an ObservableCollection. While it does work, I am not a fan of it. On the flip side, publishing a fact that one or more items in the list have changed is also problematic. For example, how would you determine the entropy of the list to best determine that it has changed?
Because of this, I would actually consider this to not be a concern of the domain. I do not think that what you are describing would be a requirement of the domain owner(s), but rather an artifact of the application architecture. If you were to query the services in the domain after the point that the change is made, they would return correctly and the application would still be what is out of step. There is nothing actually wrong inside the world of the domain at this momeent in time.
So, there are a few ways that I could see this being done. The most inefficient way would be to continually poll for changes directly against the model. You could also consider having some sort of marker that indicates that the list is dirty, although not using the domain model to do so. Once again, not that clean of a solution. You can apply those principles outside of the domain, however, to come up with a working solution.
If you have some sort of a shared caching mechanism, i.e. a distributed cache, you could implement a JIT-caching/eviction approach where inserts and updates would invalidate the cache (i.e. evict the cached items) and a subsequent request would load them back in. Then, you could actually put a marker into the cache itself that would indicate something identifiable as to when that item(s) was/were rebuilt. For example, if you have a cache item that contains a list of IDs for region, you could store the DateTime that it was JIT-ed along with it. The application could then keep track of what JIT-ed version it has, and only reload when it sees that the version has changed. You still have to poll, but it eliminates putting that responsibility into the domain itself, and if you are just polling for a smaller bit of data, it is better than rebuilding the entire thing every time.
Also, before overarchitecting a full-blown solution. Address the concern with the domain owner. It may be perfectly acceptable to him/her/them that you simply have a "Refresh" button or menu item somewhere. It is about compromise, as well, and I am fairly sure that most domain owners would have a preference of core functionality over certain types of issues.
About eventing - most valuable material I've seen comes from Udi Dahan and Greg Young.
One nice implementation of eventing which I'm eager to try out can be found here.
But start with understanding if that's really necessary as Joseph suggests.