Object-Oriented Theater
Update 30/10/14: I first read about the “Object Theatre” in a message by Anthony Green on the GOOS mailing list; I didn’t remember it consciously when I wrote this post, but it certainly has been working in my brain ever since. The “Object Theatre” metaphor is his invention, not mine. Thanks Kevin and Anthony for pointing it out.
Yesterday evening I attended a good introduction on functional programming by Mario Fusco. One of his slides illustrated a well-known principle of functional programming. There are pure functions, and “functions” with side effects. Good FP style suggests to keep non-pure functions at the edges of the program, so that the inner core of your program only contains pure, mathematical functions.
He showed this picture
In fact, a very similar picture can be drawn for good object-oriented style. In good OO style, you want to separate your domain objects from infrastructure objects. The domain objects contain just domain logic, they execute in memory and have no references to file system, databases or network services. They can be mutable, of course! But they are “pure logic” in the sense that they live in a platonic world where we are only concerned with the functional behaviour of our programs.
Infrastructure objects, on the other hand, deal with everything else: user interface, databases, file systems, web services… All the things that are needed to connect our platonic world of objects to the outside world.
So what’s good OO style in this context? In my opinion, it’s good to keep the infrastructure objects in an outside shell, while the inner core of the program contains only pure domain objects. Let me give you an example.
Suppose you have a Counter object that needs (for non-functional reasons!) to be made persistent. The functional logic is about incrementing and decrementing the value of the counter. The infrastructure logic is about making sure that the counter retains its value across reboots (which is definitely a non-functional requirement.)
The wrong way to do this is
// bad style! don't do this
class Counter {
public Counter(int id, CounterDao dao) {
this.id = id;
this.dao = dao;
}
public void increment() {
value++;
dao.incrementCounter(id);
}
private int value = 0;
private int id;
private CounterDao dao;
}
The usage of this counter would be
CounterDao dao = ...;
Counter counter = new Counter(123, dao);
// here we perform logic and also persist the state
counter.increment();
The above example is bad style, because it mixes persistency logic with functional logic. Bah! A better way to do it is:
class Counter {
public void increment() {
value++;
}
private int value = 0;
}
See? Only pure logic. We don’t care about persistency there. We could use the counter this way:
// we start this use case in the world of infrastructure
CounterDao dao = ...;
Counter counter = dao.findCounter(id);
// here we enter the world of pure logic
counter.increment();
// here we return to the world of infrastructure
dao.save(counter);
I like to call this structure “object theatre”. Imagine your domain objects as actors in a play. You want to setup a scene where your actors are set up in a certain way: Arlecchino talks to Colombina, Colombina has a fan in her hand, etc. When the scene starts, the actors perform each according to their character. When the scene ends, we lower the curtain.
I imagine that an object-oriented system works the same way. When a request arrives, we set up the scene by retrieving all the proper objects from various repositories and we connect them appropriately. This is setting the scene. Then we send a message to one object that sets some logic in motion. The objects send messages to each other, carrying out a computation. This is playing out the scene. When the domain objects are done, we conclude by returning the objects to their respective repositories. This is lowering the curtain.
October 30th, 2014 at 16:58
I entirely agree! Infrastructure changes tend to be driven by different forces than functional ones, even though there is obviously a degree of cross-influence.
To put it in one sentence: a car is-not-a car factory.
October 31st, 2014 at 18:47
I agree, “core” should be totally decoupled from details.
It should only define the abstraction needed applying DIP.
November 1st, 2014 at 07:11
I think this is a beautiful metaphor… may it also help in finding better names for methods, objects, tests… just like a canovaccio?
November 1st, 2014 at 19:25
Yes! There are other words in programming that imply a theatrical metaphor: test double (controfigura), script (copione)… any others?
December 7th, 2015 at 17:44
I have been using exactly the same “stage” metaphor for a while, for explaining how domain objects with a specific task (role) should be created (called to stage), assigned a context (inject collaboating objects) and later when executed, perform a specific part of a scenario.
Very glad to see someone has documented it already :-)