The journeylism of @yreynhout

On CQRS, DDD(D), ES, …

Object Inheritance

When mentioning “object inheritance” most people immediately think of “class inheritance“. Alas, that’s not what it is. Quoting from Streamlined Object Modeling*:

Object inheritance allows two objects representing a single entity to be treated as one object by the rest of the system.

Put a different way, where class inheritance allows for code reuse, object inheritance allows for data reuse.

Application

Where could this be useful? Depending on the domain you are in, I’d say quite a few places. Whenever you replicate data from one object to another object, you should stop and consider if “object inheritance” could be applicable. While object inheritance does impose some constraints, it also saves you from writing reconciliation code to synchronize two or more objects (especially in systems that heavily rely on messaging).
A common example I like to use is the one of a video title and a video tape (**). From a real world point of view, a video tape has both the attributes of the tape itself and the title. Yet, if I modeled this as two separate objects, I run into trouble (a.k.a. synchronization woes). If I copy the title information to the tape upon creation of the tape, and I made an error in say the release date of the title, I now have to replicate that information to the “affected” tapes. Don’t get me wrong, sometimes this kind of behavior is desirable, i.e. it makes sense from a business perspective. But what if it doesn’t? That’s where “object inheritance” comes in. To a large extent, it can cover the scenarios that a synchronization based solution can, IF constraints are met.

Constraints

  • Localized data: “Object inheritance” assumes that the data of both objects lives close together. That might be a deal breaker for larger systems, or at least an indication that you’d have to consider co-locating the data of “both” objects.
  • Immutable data: One of the objects, the “parent”, its data is immutable during object inheritance. From an OOP perspective that means you can only invoke side-effect free functions on a “parent”.
  • “Parent” object responsibilities: the parent object contains information and behaviors that are valid across multiple contexts, multiple interactions, and multiple variations of an object.
  • “Child” object responsibilities: the child object represents the parent in a specialized context, in a particular interaction, or as a distinct variation.

The aforementioned book also states other constraints such as the child object exhibiting the parent object’s “profile” (think interface), but I find those less desirable in an environment that uses CQRS. For more in-depth information, I strongly suggest you read it. It has a wealth of information on this very topic.

Code

In its simplest form “object inheritance” looks and feels like object composition.

The composition can be hidden from child object consuming code behind a repository’s facade as shown below.

The gist of “object inheritance” is that the child object (the video tape) asks the parent (the video) for data or invokes side-effect free functions on the parent to accomplish its task.

Lunch -> Not Free

Whether you go down the route of “object inheritance” or (message based) “synchronization”, you will have to think about object life-cycles (both parent and child). Sometimes it’s desirable for the child to have a still view of the parent, a snapshot if you will. Other times you may want the child to always see the parent in its most current form. Children can even change parent during their life-cycle. Other children may want a more “controlled” view of the parent, rolling forward or backward based on their needs or context. You can get pretty sophisticated with this technique, especially in an event sourced domain model since it’s very well suited to roll up to a certain point in time or a certain revision of a parent. In the same breath, I should also say that you can very well shoot yourself in the foot with this technique, especially if the composition is to be taking place in the user interface, in which case there’s no point in using this. It’s also very easy to bury yourself in the pit of abstraction when talking about “child” and “parent”, so do replace those words with nouns from your domain, and get your archetypes right.

All in all, I’ve found this a good tool in the box, that plays nicely with aggregates, event-sourcing, even state-based models that track the concept of time. It’s not something I use everyday, but whenever I did, I ended up with less code. YMMV.

(*) Streamlined object modeling is a successor to Peter Coad’s “Modeling In Color“. A Kindle version of the former is available.
(**) I’m from the “cassette & video” ages.

Advertisements

4 responses to “Object Inheritance

  1. Javier Ruiz Aranguren October 15, 2012 at 09:29

    Hi, Yves.
    I have struggling with SOM and ES quite a lot. SOM is a great book and it would be fantastic to have some kind of formalized framework of patterns that help with business modeling (nice project to promote :-).

    I find object collaboration in ES e bit different than in SOM. In SOM state is distributed among the participants in a collaboration, but in ES state is just THE stream. You don’t have several streams for a given aggregate (I have made some questions related to this in DDD/CQRS group without much success), and that changes things a lot.

    Relating to your proposal, I see more natural to ES logic to hydrate the collaboration from the event stream itself. LoadFromHistory(IEnumerable events), and let’s say we have VideoTapeCreated(VideoTapeId id, VideoTitle title).
    Then you build Video from state persisted in the event.

    Despite of this, if there is some business logic related to the use of Video value object within VideoTape, it also is included in following events.

    Many more posts like this are needed.
    Best regards.

  2. yreynhout October 15, 2012 at 17:02

    RE: “Relating to your proposal, I see more natural to ES logic to hydrate the collaboration from the event stream itself.”

    This is where we differ. I have no problem allowing multiple aggregates to collaborate in order to accomplish a task. This allows, as you mention, to have each aggregate govern its own state. I do not make assumptions about the consistency of the collaborating aggregates involved. I know that all but the aggregate whose state will get affected, could be in a different state by the time I commit. I accept this staleness explicitly. If you don’t, then having collaborating aggregates will never work for you. If you require consistency at that level either redraw the boundaries of the aggregates or have a deeper discussion with the domain expert to get to the bottom of true invariants.
    Since I embrace multiple collaborating aggregates in the commandhandler/application services/domain services, I see no problem in using “object inheritance” behind the repository seam. It’s just moving around the loading of aggregates and, yes, it’s a bit less explicit. But it offers value, since I don’t have to spend time synchronizing aggregate state. As I said, the applicability is pretty niche, and there’s the risk of using this in inappropriate places.

    You are right that the video could have been modeled as a single aggregate, containing video tapes as entities or value objects. In such case, there would be no use for object inheritance.

    • Javier Ruiz Aranguren October 15, 2012 at 21:02

      Perhaps we don’t have such different viewpoints.
      I have also no problem with having collaboration between aggregates. It depends on the case.

      I don’t understand the last paragraph. Object inheritance is posible within a single aggregate (and bidireccional business rules could be checked before creating the collaboration, i.e. applying the new event). Or you just mean that it is no needed in such a simple case?

      Nevertheless, do you think would it be posible to engage a few people from ES-DDD-CQRS world in order to post/discuss this kind of business models questions?

      • yreynhout October 15, 2012 at 21:48

        Oh, sure, OI could happen within the boundaries of an aggregate. I’ve just found more use for it across aggregate boundaries (within the same BC). Although I’m flirting with the idea of doing this cross BC, to be honest, it seems like a really bad idea.

        I think you might have more luck on the yahoo DDD list (http://tech.groups.yahoo.com/group/domaindrivendesign/) with regard to modeling questions.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: