update model best practise

mur4ik's Avatar

mur4ik

11 Mar, 2010 03:30 AM via web

Hi.

In my simple app (its my first try in RL :) ) I need to update my data from server xml every 20 min. The data contains list of object,
and every 30 sec I need update views by this data (from list of objects in given xml).
So I have command to update data by calling service, service class load data, after data loaded service fire event and update app model. In other word I need a two timers, one for update data from server, and second for update views by this data.
I dont understand when and where I shoold place/initiate this timers. I can do it, but I feel that I doing something wrong, and not in the best practice concepts of MVCS.

Wich is the best way of autoupdate data from service?
Can model update themself by dispatching update/refresh event for service?
Or I need to create a controller class (not a simple command) and initiate timer with in, that can fire update/refresh event in given interval?

Sorry for my Runglish ;)

  1. 2 Posted by Jonny Reeves on 11 Mar, 2010 09:55 AM

    Jonny Reeves's Avatar

    Hi!

    I'm no expert on Robotlegs, but personally I would be tempted to place a Timers into one of my Mediators which handle the calls to the Services.

    The Best Practices document states that Models should not be coupled to the application (in other words, they should not listen for Framework events or have other Actors injected into them, whenever possible!)

    Jonny.

  2. Support Staff 3 Posted by Shaun Smith on 11 Mar, 2010 12:17 PM

    Shaun Smith's Avatar

    Runglish! Heheee :)

    I don't think you need two timers for this. The service can hold a timer internally, and do it's remote call every 20 minutes.

    Now, depending on how re-usable you want this service to be, you could either have the model injected directly into the service (in which case the service will update the model directly) or you can fire off an event that triggers a command that updates the model.

    Either way, the model should dispatch an event when its data changes. That is the event the views should be listening for.

    I'm not sure why the views would need to check for new data every 30 seconds if the model is only changing every 20 minutes. Perhaps I am misunderstanding your needs.

  3. 4 Posted by mur4ik on 11 Mar, 2010 03:40 PM

    mur4ik's Avatar

    Shaun, thanks.

    I'm not sure why the views would need to check for new data every 30 seconds if the model is only changing every 20 minutes. Perhaps I am misunderstanding your needs.

    Views need to be updated every 30 seconds because XML that I requested from server contains list or coordinates, and some of views change his positions by its coordinates.

    Now I've do it in this way: I create TimerController class that extends Actor (for inject it where I need it) and inside it I have methods that start/stop/reset two timers. By timer tick TimerController fire events and commands mapped to this events do its jobs (one update model from sevise request and other update views).
    Is this a good solution that one of controller not a command?

  4. 5 Posted by Stray on 11 Mar, 2010 03:52 PM

    Stray's Avatar

    Just to help with the mvcs structure, I wonder if your TimerController is actually more like a TimerService?

    Controller implies that it makes decisions in some way, or contains logic, or initiates actions.

    I think it's a good solution - I would just call it a Service :)

  5. 6 Posted by mur4ik on 11 Mar, 2010 04:02 PM

    mur4ik's Avatar

    And other question is, in StartupCommand I map my TimerController class as singletone
    injector.mapSingleton(TimerController);
    but its instance dont create automaticaly, TimerController instantiate when first injection occurs. But I need instantiate and call some method from it in my StartupCommand. Now I inject TimerController in other command and start it, but its little complex that if I can instantiate it in command where I map it.

  6. 7 Posted by Stray on 11 Mar, 2010 04:15 PM

    Stray's Avatar

    In that case, I think the approach is:

    var timerController:TimerController = injector.instantiate(TimerController);

    injector.mapValue(TimerController, timerController); (this will cause it to use your timerController like a singleton).

    timerController.doStuff();

    You need to use the injector to instantiate your class because you want the Injections into it to happen (to give you the shared event dispatcher).

    That should work for you.

  7. 8 Posted by mur4ik on 11 Mar, 2010 04:34 PM

    mur4ik's Avatar

    Stray, thanks for help.

    Just to help with the mvcs structure, I wonder if your TimerController is actually more like a TimerService? TimerController just contains two timers instanses and some method to control timers

    Controller implies that it makes decisions in some way, or contains logic, or initiates actions. My TimerController not contain logic, but its is not just service (if I right understand role of services). One timer controll model update by calling other service class that request XML, other controls views update.
    If I place timer logic inside service class that load XML its be a not portable solution. My service just load xml and I can move it from one project to other.

    Its my first try in RL and in MVCS structure to ;)
    So some role of each part of system blow my mind, and I dont understand wher I should place parts of my code, its littele hard for me right now :)

    But I like RL. And I'll use it in my futher projects.

    var timerController:TimerController = injector.instantiate(TimerController); injector.mapValue(TimerController, timerController); (this will cause it to use your timerController like a singleton). timerController.doStuff();

    But I need unique instance of TimerController. For example for change interval of timer tick.

  8. 9 Posted by mur4ik on 11 Mar, 2010 04:38 PM

    mur4ik's Avatar

    Sorry, something wrong in my last post :)

    Just to help with the mvcs structure, I wonder if your TimerController is actually more like a TimerService?

    TimerController just contains two timers instanses and some method to control timers

    Controller implies that it makes decisions in some way, or contains logic, or initiates actions.

    My TimerController not contain logic, but its is not just service (if I right understand role of services). One timer controll model update by calling other service class that request XML, other controls views update.
    If I place timer logic inside service class that load XML its be a not portable solution. My service just load xml and I can move it from one project to other.

  9. 10 Posted by Stray on 11 Mar, 2010 04:45 PM

    Stray's Avatar

    Ah - it sounds like you're happy with your solution. I don't think there's anything wrong with it!

    I just wondered whether you could put the actual Timing itself into a TimerService (that has your start / stop functions and fires the events), and then do the model updating from Commands.

    I definitely agree that you shouldn't put your timer into the XML loading Service! I was thinking that perhaps it was a totally separate Service in its own right?

    What you're describing - the TimerController direct acting on the models / services is often achieved through the Command pattern in RL. The Commands would act upon the other services / models, and the TimerService would just have one job: keep time!

    I'm sure it works fine how you're doing it, it's just another level of decoupling that the RL CommandMap can help you with.

    Regarding this:

    >> var timerController:TimerController = injector.instantiate(TimerController);
    >> injector.mapValue(TimerController, timerController); (this will cause it to use your timerController like a singleton).
    >> timerController.doStuff();

    > But I need unique instance of TimerController. For example for change interval of timer tick.

    If you mean that you need just one single instance (like a singleton) then this will give you that. Using mapValue rather than mapSingleton essentially does the same but without the lazy instantiation - you have to instantiate the value before you map it, which sounds like what you wanted? If that's not what you wanted then maybe you could explain what you need in a bit more detail?

  10. 11 Posted by mur4ik on 11 Mar, 2010 05:10 PM

    mur4ik's Avatar

    Ah - it sounds like you're happy with your solution. I don't think there's anything wrong with it! Not exactly, I just dont understanf if I do it right :)

    If U think that TimerController its a service I'll do it (remove from controller package to service package and rename it to TimerService). ;)

    var timerController:TimerController = injector.instantiate(TimerController); injector.mapValue(TimerController, timerController); timerController.doStuff();

    Yeah, mapValue its exactly what I need!
    I misunderstand it, I thought that it inject new instance in each injection, but I was wrong.

    Thanks a lot to All. Question is solved.

Comments are currently closed for this discussion. You can start a new one.