When in Rome…August 12, 2008
use dependency injection.
Recently, when working on a Flex project, and being the numpty that I am, I was trying to work out how to design the app for the usual stuff (extensibility, maintainability, etc). It’s a GUI app with several components, and it needs to interact with various web services, so I went for an engine / GUI split as a starting point. All the code that directly deals with user actions, UI controls, and UI layout lives in a “ui” package, and all of the code that modifies application state, controls reading / writing data, and does the “business logic” (such a hateful term – is there a better one?) lives in an “engine” package. Application actions are executed following the Command pattern, and there are some data objects that live in a “data” package that talk to the web services and store data on disk, providing methods for reading and writing data that the engine code can use.
All seems well and good so far (unless I’ve already made some horrible mistake – <fear/>), but I now need a way of linking the engine components (called things like UserPreferencesManager) and the UI components (called things like UserPreferencesDialog) together. Typically, there will be one UserPreferencesManager (or whatever) for the application, and the preferences will need to be accessed all over the shop. Several options spring to mind:
- Instantiate a UserPreferencesManager object as a member of the Application object, then access it from everywhere else using the handy ActionScript object “Application.application“
- Make the UserPreferencesManager a singleton (there’s only going to be one of them, right?)
- Make the UserPreferencesManager a global static object
- Instantiate a UserPreferencesManager object as a member of the Application object, then expose a property on all components requiring access to a UserPreferencesManager, and follow the Dependency Injection pattern to set each property to our application’s UserPreferencesManager (directly in the Application definition for children of Application, then from those objects to their children that require access to the UserPreferencesManager, and so on)
- Use the Model Locator pattern
To be honest, these options didn’t spring to mind the first time I wrote a Flex app. I found out about Application.application and thought “great, that makes all this design pattern rubbish totally irrelevant – I can bind straight to the object wherever I am! Woohoo!”. Naturally, when I wanted to change one of these objects in my Application that was coupled to everything else, things started to look less rosy, so I asked my old friend Google for help.
Google sent me to the Adobe Developer Centre page linked to above, which made me very happy indeed. Some advice on the very problem I was struggling with, straight from the horse’s mouth! I read about their Model Locator pattern and it all made sense. I already knew what a Singleton was, and while I’d avoided that because I had some vague notion that it might behave very much like the Application.application method, Model Locator was a rubber-stamped, ready-made solution. Right?
Fortunately I found the Architectural Atrocities blog series, which has quite a lot to say about Flex, and Cairngorm in particular (which is what the Model Locator pattern comes from – I’ve never used the framework myself). The relevant part:
We though all the patterns in the J2EE catalog looked too complicated so we came up with this idea of using global variables instead, it’s much easier.
Indeed the Model Locator is just another, more complicated way of writing a singleton (or global variable, if you like your bad programming to be more obvious). Strangely, the Adobe authors do mention the correct solution in their article:
This brings up an important best practice. When you create components that rely upon client-side data, it is all too easy to create a direct reference to a Singleton model, such as
ShopModelLocator. Indeed this is true throughout the application. We discourage this approach. Instead, consider passing the model and/or its properties down through a hierarchy of your view components, for a cleaner and more thoughtful solution.
That’s dependency injection! Why bother with the singleton at all? If you just want one ShoppingCart object, just create one instance. There’s no reason to make the shopping cart object a Singleton – that just makes your life more difficult if you decide in the future that actually, you do want more than one shopping cart.
So I’ve been using dependency injection, and it’s great. It makes it obvious which classes depend on which objects, even if they’re nested several levels deep (because their parents, and their parents’ parents, etc, all need to have the dependencies injected into them). If you change your object instance, you’ll get compile errors (if you’re using type annotations in Flex, or otherwise statically typing your variables in other languages). You can even have more than one object of a given type if you like!
To summarise the methods listed above, then:
- Global variable
- Global variable
- Global variable
- Single instance that is passed around where it is needed
- Global variable
It’s impressive how many different names there are for the same thing (and that’s not even mentioning Monostate). Yes, I know there are subtle differences and they’re designed to do slightly different things… but really.
My Command invoker is still a singleton though.