I read Sam’s post on Contextl IoC, questioning its benefits. I’ve been skirting around this kind of thing for a while. I like the idea of being able to package all the things which a class needs in a box which ‘belongs’ to it.
Say my main class,
Gamey, knows how to start new Tetris games.
It needs a game factory which creates games.
The game factory needs to know about user preferences, the gui components to be used to draw the game, the score system, the rules, the timer which drops the shapes, the factory which makes the shapes, etc.
So I need to construct the GameFactory as:
new GameFactory(UserPreference preference, GuiComponentFactory factory, Scorer scorer, RulesEngine rulesEngine, Timer timer).
and ditto for the game it creates.
Except that what I really want is to be able to create different kinds of games, so I can choose to play either Tetris or PacMan, and use a different game factory for each one. They still each need the same stuff – a component factory, a preference, a scorer, a rules engine, a timer etc – so now I have to duplicate that factory constructor for both types of factory; the
TetrisGameFactory and the
Now I want to add multiplayer support, so that each monster killed appears in another person’s game, or each line deleted causes extra blocks to appear elsewhere. Now I need to add
- Two GameFactory constructors
- Two Game constructors
- The calls for Game construction
- probably some abstract stuff in some
AbstractGameFactory, and some
And I don’t even know, in the
GameFactory, which bits are related to the Game and which bits are being passed further down, to the Game’s pieces, like the Tetris shapes and the Pacman ghosts, which are also factory-driven but which need to be created by type. Oops, forgot the
PiecesFactory. That’s another change, then.
I really like the concept of a
Game.Context and a
Shape.Context and a
Tetris.Context and a
Gamey.Context. They can even extend each other or contain each other if required – for instance, the
Tetris.Context extends a
Game.Context, and contains a
ShapeFactory which needs a
Shape.Context. Then, when I want to change a dependency, all I need to do is change one context and its construction. I don’t need to pass it through all the layers, abstract and otherwise.
This solves a real problem I’ve been coming across when trying to do behaviour driven design. I don’t want to have to think about the behaviour of my shapes when I’m still thinking about the responsibilities of my games. If I can give the game an empty
Game.Context to start with and never worry about how the
GameFactory constructs the
Game again, then that’s one less piece of code to change every time I decide to add a bit of functionality.
Game.Context shouldn’t be responsible for using the Game’s tools for it, though. It’s just a little container; nothing else. It should probably just have
get methods (ugly, but suggestions welcome; will think on it) for each of the tools it requires.
I’m not even sure that the Game.Context needs to be an interface. It never needs to be mocked – you mock the tools underneath, not the container.
Stacy reckons there has to be another way to prevent the duplication which keeps cropping up in my normal dependency injected code. I also reckon ‘context’ is a poor name; ‘toolbox’ might be better.