Sunday, December 03, 2017

DDD Observers

Observers automatically run code when some condition occurs, without the causing code having to care.

Even in an imperative, object oriented environment, we'd like to support "birds sing when the sun comes up" without having to change the code for the sun coming up.

Theoretically, we could do this with simple polling. We could just explicitly check the condition every interval. E.g. is the sun up yet? Five seconds later: is the sun up now? Five second after that: what about now? This is not elegant, and could be costly, and completely falls down when we need to poll many objects.

We can implement observers cleanly by wrapping our entities!

Instead of triggering on changes to the internal state of an entity, using  "properties" as Kotlin does for example, we can wrap our entities in decorators that intercept calls from client code. Instead of introducing a new event abstraction, we can allow triggered code to compare the visible state of the entity before and after the triggering method.

Even a seemingly innocuous "event observer" class ruins the entity’s nice obliviousness. We step onto the slippery slope of adding notification features because some client might be interested. We shouldn't let our observing clients couple to our commanding clients, nor should we introduce a completely new abstraction in between. Observing clients are really interested in the change of an existing observable field, though not all clients are interested in the same changes.

The decorator solution does require calling code to know about the observer, usually at creation time. For all of the practical use cases for which I've needed observers, it's been sufficient to set them up at creation time. The calling code could be a factory, or even better a repository that wraps the entity at persist time.

This use of observers creates a nice parallel to "Collection Oriented Repositories" as discussed by Vernon in Implementing Domain Driven Design. That is, we explicitly wire our entities once, and then we don't need to subsequently worry about persistence and publishing every time the entity changes. We might even be able to leverage observers to support a Collection Oriented API on top of a Persistence Oriented Repository, and still avoid the morass of the full object relational mapping.

One last important point: be careful not to overuse the observer pattern. By definition, it hides the implementation. This can make it hard to figure out what the system is doing. In particular, never let your observing code make changes to your observed objects. Even if you're not worried about infinite loops, this is wrong because the observed code can't actually be oblivious.

Without further ado, here's the java implementation of this properly decoupled observer. It uses annotation processing to generate code to support observers of this interface:
public interface Observer<T, V> {
 default V beforeChange(T t) {
  return null;
 };
 void afterChange(T t, V v);
}
Which may be wired simply by:
 YourEntity entity = new YourEntityImpl();
 entity = new YourEntityObservable(entity, yourObserver);


You could implement this observable decorator manually. It’s kind of boring, so you could instead generate it using something like the linked project above.