, and StrategyPattern
This is a structure which recurs in my code. I've seen 7 or 8 instances of it in the past 6 months.
There are two fundamental objects and a set of strategies:
The Processing Flow:
- An object which started out modeling some aspect of the user's world (ala the classic starting points of OO modeling). The facade.
- A memento (in my code it usually gets called something like "ProcessingContext" or "Signposts")
- A set of strategies (method objects).
The facade implements a bunch of public methods. Each of which mangles arguments (fills in defaults etcetera) and calls a private method. The private method calls a method object, passing it the Namespace (which is sort of a memento), to do the actual processing.
How it Gets into my Code:
The above is nothing new: it's simply taking MethodObject
to some sort of logical limit. The interesting thing to me is:
Things I like:
- I used to get there by refactoring.
- I now start there when it seems likely that I'm going to get there anyway.
. Explicitly breaking out everything into method objects
allows lots of play and enables easier what-if games.
It lets me keep all the code within an object at the same level of abstraction
Things I dislike:
It's hard for other people to understand the code without talking to me. I've had the experience several times where people using a library of mine, come to me and say "what are all these things doing." Once I explain things, they get it and quickly become comfortable with using / modifying things. But there is a conceptual leap involved and hence this style of coding violates TheSourceCodeIsTheDesign
To actually follow a thread of execution requires hopping between many different objects.
It means that, at the heart of it, I'm no longer doing what the industry calls OO. I've separated out the state from the methods. And the classic "find the objects" strategies wouldn't even come close to finding mine.
This seems bizarre to me. I've made objects like this, but very rarely,
and it seems to me like it would be much more complex than necessary.
I'm trying to imagine a context in which this is a good pattern. Maybe
your methods are usually fairly complicated. What makes them complicated?
I would like to see some examples. Maybe that would help me to figure out
when this is a good idea and how your context differs from mine.
I fixed the above a little (to qualify the phrase "recurs a lot").
Alas, I am at home right now (I am, by and large, a WeekendWikier?
). I don't
have the actual code in front of me but I can summarize a recent example. The validation code (see also TypeInferenceStory
) from a constraint engine I am building. Protege is a knowledge base development tool for frame-based knowledge representation. It's being reimplemented in Java so that it can be easily extended (using Java's dynamic linking and the whole notion of JavaBeans
One of the ways Protege can be extended is that new engines to evaluate
constraints (written in PAL: the Protege Axiom Language. I'm very proud of
that name) can be plugged in. So the framework uses strategies to evaluate constraints (and passes the strategy objects an instance of Knowledge
Base). And I'm writing the first constraint engine.
There are two methods on the Constraint
Engine interface that are important here.
public Collection checkTheory(KnowledgeBase kb)
public Collection checkInstance(Instance instance, KnowledgeBase kb)
These do exactly what the above says: they call a private method which creates an instance of Evaluation
Context (the memento) and passes it to a whole slew
of strategies (this code also uses exception handling to avoid actually checking return values for the strategies. But that's another issue).
Something very much like this also occurred when I refactored the Gamelication library into a general 2-d layout library (for use in several projects in the lab). I added a lot of functionality to their "Actor" class and then gutted it completely. It became a facade which rerouted all calls to one of 8 or 9 much simpler objects (off the top of my head I can only remember 4: Movement
Policy, Location, Connection
Handler and Glyph).
And a graduate student who uses the 2-d layout stuff had a lot of trouble at first seeing how things fit together. After I walked him through it, he understood it, was able to use the objects to create pretty complex things quickly, and thought the whole thing made sense. But he wasn't really able to make that first pass through the abstractions by himself.
A brief historical comment: I noticed that this was recurring in my code about a month and a half ago when I wrote something and then thought "Hey. I've been doing this a lot lately." Since then, before posting, I asked 4 or 5 other people. All of whom said "Yeah. That sort of thing is in my code too." But it's a very weird sample-- we're all Java programmers, we're all early adopters (all of us have been on JDK1.2 for quite some time now) and we're pretty much in the R & D part of the universe (though not all at universities).
I'm not sure i'll understand without seeing some more complete examples, but it sounds to me like using the MethodObject
in this way is an instance of CommandPattern
(which is a more specific application of StrategyPattern