01-04-2016 07:17 AM
Thoric wrote:
Firstly, you specifically declared App actor as being responsible for configuring View actor, ergo it must understand the configuration data required by View in order to provide it. This is reasonably a typedf cluster owned by View, or a class, or a list of named pairs or whatever.
All you need to represent config information is a Variant, or something similar (such as a JSON Value object from the LAVA-CR JSON Library).
Secondly, messages that need to go up the tree to come down a different branch to reach their destination have to pass through the root actor, which will therefore 'see' messages that pass between branches (such as View retrieving the list of last opened projects from ConfigData actor - as per my original post). Having to deal with all messages in this way makes the root actor 'aware' of everything that's happening in all other actors. I appreciate the message content isn't parsed/verified, only repackaged and passed on down the link, but it is overhead that bloats root actor (assuming my understanding of message forwarding through several AF actors is properly understood).
You need an actual AF person here. I use a different actor-model framework. I generally don't forward things, and if I do I'm not repackaging anything (I don't use Command Pattern generally).
For Actor C to learn of the most up to date list of recently opened projects, information known only to D, we need to do the following:
1. C sends a message to B's enqueuer asking for the list of recently opened projects...
If I were to adopt the AF, particularly if I was managing junior developers, the first thing I would need to do would be to find a way to stop actors from being able to explicitly send messages to there Caller. See Suggestion: Get rid of the "Actor-to-Caller" Queue. Expecting something from your Caller completely breaks the "Service hierarchy" I discussed above.
A good option for your example problem is this. C needs a tool to get its job done so give it that tool. Have A package up D's enqueuer in an API wrapper that provides what C needs. A provides this to B, who provides it to C. The API is just a wrapper that allows command-response communication with D. D, the ConfigData actor, is now a service provided to the other actors. No problem with this if you don't try and make the services go both ways. D doesn't depend on C; C depends on the API (which could be a parent class with D-specific child class injected by A).
Technically the API is not necessary, but would be good practice, as you can limit what abilities it grants C. This is the kind if thing I referred to above when I said you, as a worker, are "sent something that allows you to request resources you need". In that earlier example that would be something connecting to the "ResourcePool" that has the pencil sharpener.
For shutdown, Root Actor (A) tells B to shutdown, and when B is shutdown it tells D to save config and shutdown, then it exits.
When told to shutdown, B tells C to shutdown, waits for it to shutdown, then tells A it has shutdown and exits.
When told to shutdown, C sends config info to the D (via API), tells B it has shutdown, then exits.
This is a clean synchronous shutdown procedure that doesn't require D, ConfigData actor, to make any requests of other actors, so a service hierarchy is maintained and no potential deadlock.
01-04-2016 07:54 AM
Noticed something on rereading an earlier post:
Thoric wrote:
"Enforced Dependency Heirarchy" - by ensuring there is a defined dependency heirarchy to the actor tree we can prevent deadlocks by creating an associated mono-directional syncronicity. If an actor has information that is required by another, a heirarchy must be defined that elevates the requesting actor above the data source actor.
It's not about information, it's about exerting control or using something as a service. If A has info that B needs, it's fine for a common Caller to register B to receive published info from A. And at the same time to register A to receive info from B. Neither A nor B is "above" the over in this case. The Caller is exerting control on both. It's not a "Data" dependancy; it's a control or service dependancy. Can also by thought of as a "Compositional" dependancy: if A uses B, then B can be considered a part of A. B can be part of A, or A can be part of B, but they cannot both be parts of each other.
To me this is a "Natural Dependancy Heirarchy" that greatly simplifies things and seldom needs to be "enforced".
01-05-2016 06:26 AM
No AF Users back from their holidays yet? Someone must have addressed these issues with the AF.
01-05-2016 06:49 AM
I haven't read through all the material above as carefully as I should have, it looks like there is quite a bit of good dialog to digest. I like to solve this problem like this by using an event aggregator to implement pub/sub between actors. This can be handled in a way that allows Actor Framework actors to register/subscribe using "zero coupled" AF message classes so it doesn't totally violate the AF messaging scheme. It does however step outside the actor tree for message routing.
The event aggregator is very much based on a presentation given by Dmitry Sagatelyan at the 2015 CLA summit. Check out his presentation for more details.
01-05-2016 06:55 AM
drjdpowell schrieb:
No AF Users back from their holidays yet? Someone must have addressed these issues with the AF.
Hmmm... as for me.. I have forgotten re-enable the email notification so I'm also a bit late for this specific party.
So I've just had a brief look at the discussion and I'm hoping I haven't missed many important parts. IMHO there are two areas of discussion:
1.) Hierarchy: how should the Actors communicate? Use a strict heirarchy or every Actor talking to one another. I have to admit, that I am in general in favour of a strictly hierarchical approach (yes, the Boss organising the pencil! Those highly paid managers need to be occupied so they don't get bored and take strange decisions ). It involves quite a bit of message handling, but it also makes debugging easier. Imagine a room full of people talking to each other and you have to find out, what's going wrong...
2.) Coupling: you can decrease coupling by using low or zero coupling messages. But it comes at the price of having to set up an architecture that supports this kind of communication. Which can also be cumbersome to develop.
Having written the general part... (and just seen that there has already been another reply):
I have written an TestStand User Interface which is fully AF based. Strictly hierachical and using zero and low coupling. It works pretty good also using Actors for state machines (State Actor). Although it has been a pain to develop from time to time.
I don't know your timeline for this project, but once the documentation is in a state that can be shown without falling ashame, I'll be happy to share the architectural bits
01-05-2016 02:44 PM
I was following along and trying to project the questions onto the way I have solved things.
1. Some things are coupled. A UI for a device is coupled to the device. Getting concrete (implementation specific) information from a low level thing to a UI is often needed. I do this with #2.
2. You can wrap things so that intermediate layers don't "see" what is passing through. Make a parent class. Create a message that sends the class. Create children classes with the implementation specific data. Send it on the parent class message. You might need to aggreagate the data somewhere, but that isn't too hard.
3. My specific example is a UI where I bound the entry on setpoints based on the config of a component stored in a file on the cRIO. Component reads the config. Component sends config class to subsystem. Subsystem aggregates all component configs. Subsystem sends the aggregated config classes to the UI wrapped in a "subsystem config class". The UI knows the concrete version that it is linked to and can deconstruct the data (static cast to specific child type, but I am looking at the JSON solution).
4. When I use a typedef for the data I don't put it in the actor class. I keep it separate. Then the things that know about the data type depend on the data type not on the actor that can place data into the data type. This is just a statement on dependencies.
5. I made a decision early on to follow the hierarchy. Encapsulating the message payload in a parent class (#2) made for excellent reuse and helped minimise the number of messages for going between the levels.
6. I have a couple exceptions to the hierarchy. A) Error Logger; everyone gets direct access to send error codes for logging. B) A Run Controller that is system specific and lives at the same level as my system controller. Subsystems send data to the run controller and send state to the system controller. The system controller launches the Run Controller (and gives it the enqueuers for the subsystems) and then the run controller gives the subsystems a "zero coupled" reply message class.
Phoenix, LLC
CLA, LabVIEW Champion
Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!
01-07-2016 03:42 AM
Thoric,
has this discussion been of help for you or has it rather driven you away from using the AF?
01-07-2016 07:43 AM
Oli_Wachno wrote:
Thoric,
has this discussion been of help for you or has it rather driven you away from using the AF?
Some of the discussion makes my head spin. I followed Jon McBee's link and got lost about three quarters of the way down the blog. "Creating abstract children of AF message class to ensure zero-coupling between actors" sounds like a complex approach that I don't fully get, mainly because I think I'm still about one chapter behind my Computer Science textbook than some of the brainboxes on here.
I don't like having to pass messages up and down a tree. My original example has moved on a bit (the whole thread got a bit derailed to be fair) but I've been exploring another framework for the last two days and I'm much more comfortable with the inter-actor communication strategies offered there. It seems that here I would need to build on the AF architecture to devise (and fully comprehend) a more sophisticated solution that ensure zero- or loose-coupling. The AF is complex enough without me needing to personally advance it.
I'm interested in being able to establish communications between actors without the continuous involvement of other actors. My View and ConfigData actors, not coupled and therefore not using the same data format, must be able to share data through a channel of some form. It's ok for a common parent actor to establish this line of communication, but once set up it should have no further involvement. If I honour the task tree principle of AF (up and down the tree without distant enqueuer sharing) I'll need to involve every parent of each branch to the point where they join in order to pass a message back and forth. I still wonder if there's something I'm just not understanding here?
So currently I'm still a bit overwhelmed by the AF. It's clearly very clever in its design and abilities, but my attempts to implement it result in my spending much more time trying to understand how I should be correctly implementing my solution, leaving no time to actually create working code. I feel like it actually gets in the way, rather than help me. Perhaps I just need more education on recommended ways to use it.
01-07-2016 07:55 AM
Hi Thoric,
wich other framework did you try?
I did build my 1st afw application. It did grow to a complex thing and now its time to deside:
- continue to use afw, redesign/refactor code to try to make it simplier to use or
- change the framework and redesign/refactor code
Best regards
Thomas
01-07-2016 08:10 AM
T.L. wrote:
Hi Thoric,
wich other framework did you try?
I'll try at least one more, probably DQMH, before I settle on one. I dont think it will be an easy decision.