Carrying on with previous blog posts about RobotLegs I thought it might be useful to someone to have a simple process flow diagram along with an explanation on how it hangs together.
Initially Robotlegs (or any framework that I can see) can appear a little over the top and there seems to be a lot of bits of code hanging together but this granularity is important as it allows reuse and testability and tries to eliminate close coupling between bits of code this in turn makes it easier to manage change.
The described process is for the initial part of an Adobe Flex application which needs to load some external configuration data. This data needs to be loaded first and then it needs to be made available to the rest of the application in a controlled manner. In Lotus Notes terms these would typically be your keyword documents.
This is a common requirement so I want this to be a reusable technique / codebase.
I have decided to follow convention and use the suggested design pattern of MVC(S). In the process below I haven’t actually reached the point where I need a view yet so we are only going to cover Commands, Events, Models and Services (No View or Mediator).
NB This is not an explanation of Robotlegs but more about how the various bits hang together. Even with that in mind its worth quickly explaining what each of the bits are again.
Commands are small short lived bits of logic, they are typically mapped to an event such that when that event is fired the command reacts to it. The event is normally injected into the Command so if it has any payload it can be accessed.
Events are used to communicate between your application tiers, there are Framework events – as in Robotleg ones, System events – as in Flash Player / Flex ones and there are custom events which you create yourself. These custom events can be used just for passing a Flag e.g. Something has loaded and / or they can carry payloads e.g. Data Objects which are then worked on by whatever is listening for the event.
Models are used to control access to your data – this is the place you would hold your arraycollections and any business logic to do with that data. You would also typically have Value Objects (VO) defined here. Value Objects are used to convert data you have received from a service into a strongly typed object which means you gain type ahead and compilation checking which helps to reduce bugs.
Services are used to communicate with outside services i.e. to get the data.
It is good practice to define your Service methods in an interface and then create a concrete class from that interface. Where ever you need to use that service you refer to the Interface as the object type and then at runtime Robotlegs will inject the concrete version (you map this relationship in the Context which is described below).
By using an interface you can then change 1 line in the Context to map the interface to a different concrete class and nothing else will need to be changed .
The process diagram has numbered steps and these are the details for each step:
1. The context of which there has to be at least 1, though you can have more, is used to bootstrap the application. Its here you map your commands to events, setup your various injections and finally dispatch a Robotlegs Event – ContentEvent.Startup(2).
*2. *The Robotlegs Event – ContentEvent.Startup is being listened for by the StartupCommand (3).
*3. *The StartupCommand in this case only does 1 thing and that is to dispatch a custom event ApplicationEvent.LOAD_CONFIG (4).
4. The custom event has several flags – in this case It has been dispatched with the LOAD_CONFIG flag. The LoadConfig (5) Command is listening for this event with this flag.
*5. *The LoadConfig Command has been Injected with the ConfigService(6) Interface.
Now the Command has access to the ConfigService it can call a method directly on it – in this case loadConfig().
The ConfigService will load the configuration data from an external location and then convert the returned data into a value object. Therefore the service in this case will loop through the data and create an ApplicationConfig Value Object, it will then dispatch a custom event (7) but this time it will carry the ApplicationConfig Value Object with it.
The custom event ApplicationEvent.CONFIG_LOADED is the same custom event as 4 but this time with a different flag and a ApplicationConfig Value Object payload. The UpdateConfigCommand(8) is listening for this event.
The UpdateConfigCommand has been injected with the ApplicationConfigModel(9) and this command will take the ApplicationConfig Value Object from the event it was listening for and update the ApplicationConfigModel.
9. When the command (8) updates the ApplicationConfigModel it dispatches a custom event(10) to let any listeners know the the config model has been updated.
10. The custom event ApplicationEvent again is the same event as 4 & 7 but with a different flag and there is no payload this time. This means any part of the application that needs to know the config has been updated can react.
- Setup Context, map commands to events and inject dependencies.
- Dispatch a startup event to indicate Context is setup and we are good to go.
- Have a command listen for when the Context is setup so the initial application logic can start.
- Dispatch a custom event to indicate Startup Command has finished.
- Have the LoadConfig command listen for the custom event, it then runs the loadConfig() method on the injected Service.
- The loadConfig() method in the Service will got out over HTTP and load some XML data, the result handler in the Service will then parse this data into a Value Object and dispatch a config data loaded custom event and include this Value Object with it.
- The UpdateConfigCommand is listening for the data config loaded event, it has the model injected into it so it can take the config data object and update the model with it.
- The model then dispatches an event to let all listeners know that it has been updated.
- At this point I can then proceed with the Application flow as I have my config data.
I know it looks like a lot – but imagine the following scenarios:
You need to reload the config at another time within the application, all I need to do is dispatch the custom event – ApplicationEvent.LOAD_CONFIG and then listen for when the model dispatches its event to say its been updated.
You need to change your service so that rather than use XML it now needs to be a SOAP based webservice. Create a new concrete service class than implements the Service Interface and change one line in your context.
If anyone wants the Flex source just let me know.