Per Brage's Blog

const String ABOUT = "Somehow related to code";

Category Archives: DDD

Misconceptions about domain events

There have been a lot of posts around the web, even for years now, trying to explain domain events. More often than not, I see people fail at understanding what domain events are. I guess it is often developers that blog about it, and when they hear domain events, they inherently thinks of system events.

Domain events has nothing to do with system events, event sourcing, any technical patterns or architectural pattern like CQRS. Domain events are something that actually happens in your customers business, not in your software. I think it is about time people understand that domain driven design is more about modeling complex behaviors in a business, and not so much about actual development (especially not building frameworks). The development in domain driven design is an iterative approach, where you continuously test the knowledge you gain from your domain experts through discussions and modeling. Repeating this, trying to reach an agreement with your domain experts is what will bring clarity to your model, which will also pave your way towards a supple design. This is part of something that Eric calls the Whirlpool, which I guess could be a blog post on its own.

The domain event pattern was not included in the blue bible, but it is definitely a major building block in domain driven design. Here is an excerpt from the domain event pattern, as defined by Eric Evans.

“Model information about activity in the domain as a series of discrete events. Represent each event as a domain object. These are distinct from system events that reflect activity within the software itself, although often a system event is associated with a domain event, either as part of a response to the domain event or as a way of carrying information about the domain event into the system.

A domain event is a full-fledged part of the domain model, a representation of something that happened in the domain. Ignore irrelevant domain activity while making explicit the events that the domain experts want to track or be notified of, or which are associated with state change in the other model objects.” – Eric Evans

Think of domain events as a log, or history table of things that have happened. A domain event is implemented more or less the same way as a value object, but typically without any behavior. An event is something that has already happened, and therefore cannot be changed, hence they are just like value objects, immutable! Do you often change things that happened in your past? If so, could you drop me a mail and enlighten me?

Is it an Entity or a Value object?

This is a question that seems to surface over and over again when I talk to fellow developers, and while it is somewhat clear to many what the difference between entities and value objects are, it seems it is not clear when to actually use an entity and when to use a value object. For some reason, people also seem to favor entities over value objects when modeling, when it really should be the other way around. If you are working with only entities, then my friend, it sadly seems you are not alone out there!

Why is this? And why are people so reluctant to implement and use value objects?

I figured I would try to clear up the misconceptions a bit, and provide two examples that I often use to exemplify the difference between entities and value objects. Both of them are insights taught by Eric Evans during his DDD Immersion class, which I attended in Stockholm about a year ago. They are slightly modified as I don’t remember the exact phrases used by Eric. I also extended, and twisted each of the examples.

Context

In domain driven design, context is everything, and it is also a key factor when choosing between modeling an object as either an entity or a value object. A context (or bounded context to be more specific) has explicit defined borders and is in itself an application of its own. Within this context we define a model, create our ubiquitous language and implement behavior among other things to fulfill our requirements.

The main thing here is to understand that a context’s model, is an abstracted view of either your, or your customer’s business, and will not solve all the problems of a domain. An object in one context might be something completely different in another context, even though both contexts are within the same domain, and the object has the same name. It all depends on which abstraction your requirements emphasize, and is also the reason why two customers operating in the same domain, may have two completely different models. In one of those models, an object might be a value object, whereas in the other model it is an entity.

The – $100 dollar bill! – example

You and your colleague are each holding one of your own $100 bills in your hands, and there isn’t anything wrong with them or anything like that. If I asked you to swap those two bills, none of you would really care, swap them, be none the wiser, and move along like nothing had happened. After all, neither of you earned nor lost money! A $100 bill is a $100 bill, and you would most likely only compare the number of zeros printed on the bill. After you compared that value you wouldn’t really care which one you hold in your hand, and since we do not care about instance, and we compare them by state, we are talking about typical value objects.

But, doesn’t a $100 bill have an identification number? Well, actually it does, and that means that in some context, the exact same bill you are holding in your hand is very important to somebody, in their context. And, in that context it might actually be an entity. However, even though the $100 bill has an identification number and we may think that it’s an entity, it is not necessarily so. As always, it depends on the context.

With the same context as above, how many of you would swap your credit cards, if each card had a $100 balance on it?

The – A glass of water! – example

Imagine you and I just sat down to have a meeting. I poor two glasses of water, and then give you the opportunity to pick one of the glasses. You would not really care which one of the glasses you would pick, since it is just two glasses on a desk. So far, in this context, both glasses are the same, and its equality would be determined by the type of glass, amount of water, and perhaps the quality of the water. Since we do not care about instance, and we compare by state, we are talking about typical value objects once again.

Now, let’s redo the same scenario, but as I poor the two glasses of water, I take a sip from one of the glasses. Most people (I don’t know about you though) would by default pick the glass I have not taken a sip from, as the other glass would have immediately become my glass of water. At this point, the type of glass, amount of water and quality is no longer of any concern, because in this new context I have, by the sip I took, polluted one glass as mine, thus imposed it with an identity. So as this context has evolved, both glasses of water are now entities, even though I only sipped from one of them.

You could argue that the glass of water is still a value object, but now attached to a person object. But, I didn’t swallow a glass, I drank from the contents of a glass. That content might in itself be a value object, which was temporarily attached to the glass, but is now attached to the person object. So now we separated the glass of water into two objects, and now we have to reevaluate the whole scenario as our context evolved.

For fun, let’s back up and twist this -sip to impose identity- example further, and I will generalize a bit here (sorry all smokers). Smokers often ask for the butt of a cigarette if they are temporarily out of smokes. They don’t mind putting a cigarette to their mouth that someone else already smoked on, but at the same time they wouldn’t share a glass of water with the same person. So by taking a sip from a cigarette, we may still be using value objects.
What we changed here is the object we interact with, and by changing from a glass of water to a cigarette we also changed an attribute of the context. It might be that we are in two completely different contexts, but if we are in the same context, both a cigarette and a glass of water would most likely not inherit from a shared abstraction like, Product, as they would be modeled and implemented quite differently. Watch out for those generalized abstractions, as they will most likely impede you reaching a supple design.

Consider the context above and these method signatures, which would you prefer? These,


    void Drink(IDrink drink);
    void Smoke(ICigarette cigarette);

or


    void Sip(IProduct product);

Again, it comes down to our context and how we want to implement our behavior. And while we are on the subject of behavior, we actually changed a few behaviors in the model, without really mentioning it, but the most important change to the scenario above is that we can no longer assume that, taking a sip from something, will automatically be okay by a person object.

Those examples didn’t help me at all

Here are some information and a few tips about value objects that you might want to use as guidance.

  • Context

    Always understand the context you are in, listen to the language and the concepts that your domain experts talk about. Without a clear perception of your context, you are much more likely to fail before you even get started.

  • Identity through state

    A value objects identity is based on its state. Two value objects with the same property values would be considered the same object.

  • Immutability

    Value objects are immutable objects, which means you cannot change a value object’s state without replacing the whole object. Immutable objects are always easier to handle and understand, and since immutable objects are inherently thread-safe, they are a better choice for today’s multi-threading applications.

  • Interchangeable

    Value objects are throwaway objects. During a transaction you may fetch one, and then by using the Side-Effect Free pattern, which is especially useful when dealing with value objects, create n-objects before reaching your final instance, which is the one that will be persisted.

  • Explicit identity

    Even though the object you are trying to model has an explicit identity, do not get fooled into making it an entity just because it has this identity. Does the identity mean anything in your context?

  • Temporary name

    At times when you are unsure of what an object is and what it should do, it can help to give your object some random name that doesn’t mean anything. This will allow you, and people around you, to not get stuck on a particular concept, and hopefully you will be able to continue refining your model. This will also help you to stick with a value object implementation as long as possible.

  • Refactoring

    When you need to refactor your model, it will always be easier to make an entity out of a value object, than the other way around.

Still in doubt?

When in doubt, and you wonder what an object is, and how it should be modeled, always favor value objects. I will let Bart repeat it a few times on his chalkboard, and perhaps you will remember this chant, and think twice the next time you are about to add another entity to your model.

I will always favor value objects