Ok...so I've gotten way behind. The 4-day immersion class finished today and I'm just getting to day two. Also, the days have blurred together a bit, so I'll try to get it all straight. If you haven't read my earlier blogs, DDD Immersion is a training class on Eric Evan's book Domain Driven Design.
Before I get started on the topics covered in the training, I'd like to mention a couple of interesting things that I've noticed. First of all, although DDD is not really a methodology, and therefore not an Agile methodology, I believe that almost all of its core principles are founded on the same principles. Not only is evidence of that found in its teachings, but also in the make-up of its students. It was quite interesting to see the mix of people that attended this class. Every one of us thought alike...well, perhaps not thought alike, but we all shared the same principles and that made our thoughts compatible. It seemed that most everyone in the class (if not everyone) was either already working in an agile environment or were striving to make their environment agile.
Anyhow, back to the class. The three main topics that we discussed on day two (or at least the three that are still paramount in my mind and notes) were: Aggregates, Entities, and Value Objects. At first I was having a really hard time understanding Aggregates, however, after a little more study I think I am starting to understand them...and their value. I'll come back to aggregates in a minute. First, lets talk about entities and value objects.
Just about any class in a project that is not a UI specific class or a service (meaning a class that exists only to perform some sort of operation and has no identity or data of its own) is either an entity or a value object. The difference between an entity and a value object is that an entity is individually identifiable (meaning it has something like and ID or a set of fields that, when combined, create a unique identifier). Entities also track state. Value objects, on the contrary, do not have an identity of their own nor do they track state. In addition, there is a cost that comes with tracking identity and state, so wherever possible we want to avoid creating more entity classes and instead create value objects.
Value objects can be freely and promiscuously shared across objects. This is because value objects are also, by definition immutable. Imagine a string which is also a value object an immutable. You don't hesitate to pass around a string from one object to another. If you say person2.FirstName = person1.FirstName and then you change person1.FirstName, you know that won't affect person2 because FirstName is a string, and is therefore immutable so each object has its own copy. But, immutability for our own objects, doesn't just happen, we have to actually put thought and effort into making our value objects immutable. For example, instead of instantiating a value object and then setting its properties, you would set create it all at once with a constructor (otherwise, every time you change a property you'd have to actually be creating a whole new object in memory. Also, once created, if you want to modify the object, you will actually need to create a whole new copy. This sounds like extra work, but it's actually quite liberating when you understand the benefits.
So, lets look at an example. An example (which is in the DDD book) of these two types of objects is Cargo, Itinerary, and Legs (not human legs, legs of an itinerary). These objects (I should stop using the term classes, since we want to be able to speak about these things in a way the business user also understands) are used within a shipping company model. Consider this scenario...a piece of cargo needs to be shipped from Hong Kong (HKG) to Dallas, Texas (DAL). In order for that to happen it will also have to make a stop at a port city such as Long Beach (LGB).
So you can imagine, a piece of cargo has an itinerary and that itinerary is made up of two legs: HKG to LGB and LGB to DAL. So, I've just described three objects (Cargo, Itinerary and Leg). Which of these has to be an entity and which ones can we make into value objects? Clearly cargo will need to be an entity because it has identity. One piece of cargo is different from another piece of cargo, even if everything about it (other than the ID) is the same. That's because we need to track the delivery of each piece of cargo separately and make sure they arrive at their respective destinations.
So, can we make Itinerary and Leg both value objects? That really should be our goal. We want as many of our objects as possible to be value objects. If a leg is just a starting point and an ending point, such as "HKG" and "LGB", then it can definitely be a value object. This is because the leg containing "HKG" and "LGB", can be used anywhere without consequence. We can feel free to share a leg with other objects because no matter where it is used it means the same thing and it has no identity or state. So we'll make Leg a value object.
Now, how about Itinerary? If itinerary is just going to contain a list of legs then it can certainly also be a value object. We could have a further discussion here about other things that could go into itinerary or legs such as tracking which legs have been completed, but it actually makes sense to move these tracking items up to the cargo object so that we can continue to leave itinerary and leg as value objects. And it actually makes sense for them to be on cargo anyhow.
Ok, phew! One more topic. Aggregates. An aggregate is essentially a grouping of objects. The definition Eric gave was "a clump of data that is completely internally consistent." In this case, Cargo, Itinerary, and Leg all belong within the same aggregate because they are so closely related and it is important that the data always remains consistent across these three elements. There is a rule regarding aggregates which is what gives aggregates all their power and benefits. This rule states that anything outside of the aggregate must access anything inside the aggregate via the "Aggregate Root". What is the aggregate root? It is the primary entity class at the top of the aggregate that is responsible for tracking the state of the whole aggregate (or something like that :) ). Like I said, this was an area that I struggled with for a bit in the training so I think I may have a few things a little unclear, but I believe, nonetheless that I have it clear enough that I could implement it. In our example, he Cargo object is the aggregate root. If I want to know anything about the cargo's itinerary, I have to ask the cargo object, I can't ask the itinerary object itself.
So here is where the power of aggregates comes in. Think about any project of significant size and complexity that you have worked on. Now consider all the inter-dependencies of all the objects in that project. Now think of that one really bad project you worked on where everything was just a big tangled mess (most of us have had that...um...opportunity). Aggregates help prevent this mess. By forcing everything outside of an aggregate to access anything inside the aggregate via the aggregate root, you significantly limit the number of inter-dependencies between classes. This is very helpful in keeping the state maintainable and bug free.
So there is a recap of Entities, Value Objects, and Aggregates. There is much more that could be learned than could be laid out in one blog post (or even ten blog posts). If you are intrigued and would like to learn more about it, read the book Domain Driven Design, by Eric Evans, or go to the DDD immersion training which you can find at http://www.domainlanguage.com/.
Sorry for the long posts. These are not concepts that can be explained briefly, nor completely in a blog post. But I have found them very valuable and I am excited to start teaching them to our team and our business users.
In my next post DDD Immersion - Day Three we'll learn about Context Mapping.
UbiquitousGecko
Friday, March 25, 2011
Tuesday, March 22, 2011
DDD Immersion - Day One
Yesterday was the first day of Domain Driven Design immersion training. Domain Driven Design is a book written by Eric Evans and this training is all about what is taught in that book. Before class began, I noticed that the name on the instructor's name tag said, "Eric Evans"! I seriously thought to myself, "No, that's not really Eric Evans. Either this is another guy by the same name, or it is the instructor goofing around." But, alas, it really was Eric Evans. I was thrilled that I would be learning directly from Eric. There are a number of authors that I really admire including: Martin Fowler, Alistair Cockburn, Uncle Bob Martin, Dave Thomas and, of course, Eric Evans among others. All but Eric Evans are signatories of the Agile Manifesto, but Eric has earned his place among the ranks in my mind for his work on Domain Driven Design. And for the record, I'm not fans of these individuals because they signed the manifesto (or at least not JUST because they did), but because I've read some their books and what they say makes a lot of sense. These are all people who, I believe, are pioneers in bringing the software industry (an industry that is still in it's infancy as professions go) out of obscurity and defining methodologies and practices that help the masses to write the type of great software that they've been writing for a long time. So ya, learning that the class was actually going to be taught by Eric Evans was a thrill for me.
Before I get started, I have to apologize to Eric Evans (as if he'll ever hear about or read this post, but still, I feel better making the disclaimer) for misrepresenting him or any of what he taught in this training. Domain Driven Design is a deep and complex topic and I'm sure I have misunderstood some of what he taught. Having said that, I do feel like I got a good feel for some important concepts that I'd like to share. Also, it seems weird for the rest of this blog to continue to use the full name "Eric Evans" and it also seems too formal for a blog to say "Mr. Evans". I'm going to take the liberty of using "Eric" although I don't intend to infer a personal friendship with "Mr. Evans" and hope he doesn't mind.
During day one, we mostly talked about modeling. Not the get dressed up in freaky clothes and walk down a runway type of modeling, but creating models of domains. Before I go further, let me provide the following definitions that Evans supplied:
It is important to understand what is meant by a model. It should not be confused with (or at least not limited to) the type of models used in patterns such as Model View Controller and Model View Presenter, in which models are classes that represent real (or abstract) objects. Indeed these are models, but to say that is what DDD refers to as a model is over-specific and over-simplified. The description Eric gave is that a model is "a system of abstractions representing selected aspects of the domain." The domain is "a sphere of knowledge". For someone in the shipping business (an industry Eric pulls from extensively for samples in his book and in the training) the domain is a business person's knowledge of the shipping business. A model then is just a system of abstractions representing parts of that domain. A model can exist in someone's head, on a white-board or in a UML diagram. It really is just a model in any form. Also, a model does not have to be a complete model of the entire domain. It can be just a model of one small part of the domain.
One of the more valuable things I've gotten from the class so far is how to work with a business user (or users) to define a model. This process is displayed in the image below which I've borrowed from here (http://domainlanguage.com/ddd/whirlpool/):

When brainstorming to create a model, start out with a scenario, such as "we have to be able to ship cargo from an origin location to a destination location". Already from that one statement there are a few key words that we can start using to create a model, namely, "cargo", "origin", and "destination". So you could infer from this a model that includes just a cargo entity and that entity would have an origin and destination. So you could start with that on a whiteboard. You have now followed the first two arrows in the diagram above "scenario" and "model".
This all seems pretty straightforward so far and is not unfamiliar to anyone that has been doing any level of analysis in the past. However, the thing I found helpful is the continuation of this whirlpool. You can now through more scenarios at the model to see if the model holds up. So, you may ask, "is it really that simple, you just have a piece of cargo and it just has to go from point A to point B?" and the business user replies, "Well, no. It is rarely just a sing stop. Typically it has to go through several stops on the way to its destination so that it can be transfered from ship, to train, to truck, etc." So now we've re-entered the "scenario" part of the whirlpool. Now lets take that scenario and try to apply it to the model and see if the model holds up? Does our Cargo entity, with just a single origin and destination support this new scenario?" No, it doesn't, so we start re-working the model. This may send us into an "eddie" in the whirlpool where we start having a mini-whirlpool discussion about the how to support multiple stops. In the end you may decide that the cargo entity needs to have a series of "Stops" (essentially a listing of destinations), or perhaps you decide that a series of "legs" would work better (a listing of legs that contains both origin and destination, where the origin of each leg is the same as the destination of the prior leg). Either way, you then modify your model (erase a few things on the white board and write in the new objects). So now you've made another pass around the whirlpool. Occasionally, the developers will decide that they need to do a "code probe" in order to find out how well a certain concept will play out in code. This is the other arrow in the diagram and doesn't always happen (probably only occasionally). During this probe, they are exploring the capabilities of the technology to meet the needs of the model. The developers should at this point be trying to write code that looks and sounds just like the model. If the developers write code that is not recognizable by the business user, the code will eventually grow apart from and no longer be representative of the model, something that is critical in domain driven design.
Eric mentioned that when he is modeling like this, he often has one scenario in front of him and several other scenarios forming in the back of his mind (that he will need to use to challenge the model when he gets to them). I actually think it would be useful to maybe have a little area off to one side of the white board where we could jot down those scenarios as people think of them without them becoming a distraction to the current scenario we are exploring together. Whether this could be done without becoming a distraction or not, I'm not sure, but it would be a shame if those scenarios got lost.
Notice that I've avoided using words like "class" or "property" when creating the model. This is because the model should be a common ground between development and business that both parties can understand and speak about without confusion. The word "class" means nothing to a business user. This is part of what Eric calls the Ubiquitous language and it is a core part of DDD. The business and developers need to all speak the same language. This even means that developers speak the ubiquitous language amongst themselves. If the developers speak one language when they're talking with the business or talking about the model and then speak another language when they're coding, something isn't right with the model that is making it so that there is a disconnect between the way it has to be coded and the way its represented in the model.
Also, during the whirlpool process, Eric mentioned that we are trying to create an explosion of scenarios and models. This is how we get the information transfered out of the minds of the domain experts and into the minds of the developers. During this discussion the much used (and sometimes abused) agile phrase YAGNI (you ain't gonna need it) was brought up. YAGNI spawned from the agile concept of attempting to avoid wasting time creating functionality that we are never going to need (or as Eric said, "functionality you won't need before your project is cancelled" :). YAGNI was meant to counter the waterfall approach of having to design everything you could possibly ever need up front because once development begins we can't change any of the specifications or design. Some self-proclaimed agilists use the YAGNI term, in Eric's words "as a weapon". When it is abused, it is used to prevent ANY sort of design at all. Certainly this is not what was meant by authors who have cautioned about the old waterfall approach and how that more often than not leads to wasted time creating features that really are never used. However, it is important to note how inexpensive it is to do modeling and how expensive it can be to refactor code later, especially if refactoring is done on objects that are core to the design and used everywhere. A class discussion spawned on this topic as we tried to explore, "how much design/modeling is too much". Eventually, Eric suggested that we focus heavily on the part of the system we are about to work on and do a little exploration into the other parts of the system. Jump into the waterfall in a few key places that you know will eventually exist. Jump in just long enough to gain a very high-level understanding of those areas. Doing so may help you create a better design for what you are about to start coding and may help you avoid costly re-work down the road.
That was the bulk of what we discussed on day one. Here are a few other brief points that were brought up:
That's all for now. I'm a day behind. Tomorrow I'll try to blog what we learned today including some interesting stuff about Anemic domains.
Good night!.
Before I get started, I have to apologize to Eric Evans (as if he'll ever hear about or read this post, but still, I feel better making the disclaimer) for misrepresenting him or any of what he taught in this training. Domain Driven Design is a deep and complex topic and I'm sure I have misunderstood some of what he taught. Having said that, I do feel like I got a good feel for some important concepts that I'd like to share. Also, it seems weird for the rest of this blog to continue to use the full name "Eric Evans" and it also seems too formal for a blog to say "Mr. Evans". I'm going to take the liberty of using "Eric" although I don't intend to infer a personal friendship with "Mr. Evans" and hope he doesn't mind.
During day one, we mostly talked about modeling. Not the get dressed up in freaky clothes and walk down a runway type of modeling, but creating models of domains. Before I go further, let me provide the following definitions that Evans supplied:
- Domain
- A sphere of knowledge, influence of activity
- Model
- A system of abstractions representing selected aspects of the domain
- Context
- The setting in which a word or statement appears that determines its meaning (i.e. move to the front two “tables”)
- Bounded Context
- The conditions under which a particular model is defined and applicable
- Ubiquitous Language
- A language structured around the domain model and used by all team members to connect all the activities of te team with the software (Within a bounded context – not enterprise wide)
- Domain Driven Design
- A set of driving principles:
- Focus on the core domain
- Explore models in a creative collaboration of domain practitioners and software practitioners
- Speak a ubiquitous language within an explicitly bounded context
It is important to understand what is meant by a model. It should not be confused with (or at least not limited to) the type of models used in patterns such as Model View Controller and Model View Presenter, in which models are classes that represent real (or abstract) objects. Indeed these are models, but to say that is what DDD refers to as a model is over-specific and over-simplified. The description Eric gave is that a model is "a system of abstractions representing selected aspects of the domain." The domain is "a sphere of knowledge". For someone in the shipping business (an industry Eric pulls from extensively for samples in his book and in the training) the domain is a business person's knowledge of the shipping business. A model then is just a system of abstractions representing parts of that domain. A model can exist in someone's head, on a white-board or in a UML diagram. It really is just a model in any form. Also, a model does not have to be a complete model of the entire domain. It can be just a model of one small part of the domain.
One of the more valuable things I've gotten from the class so far is how to work with a business user (or users) to define a model. This process is displayed in the image below which I've borrowed from here (http://domainlanguage.com/ddd/whirlpool/):

When brainstorming to create a model, start out with a scenario, such as "we have to be able to ship cargo from an origin location to a destination location". Already from that one statement there are a few key words that we can start using to create a model, namely, "cargo", "origin", and "destination". So you could infer from this a model that includes just a cargo entity and that entity would have an origin and destination. So you could start with that on a whiteboard. You have now followed the first two arrows in the diagram above "scenario" and "model".
This all seems pretty straightforward so far and is not unfamiliar to anyone that has been doing any level of analysis in the past. However, the thing I found helpful is the continuation of this whirlpool. You can now through more scenarios at the model to see if the model holds up. So, you may ask, "is it really that simple, you just have a piece of cargo and it just has to go from point A to point B?" and the business user replies, "Well, no. It is rarely just a sing stop. Typically it has to go through several stops on the way to its destination so that it can be transfered from ship, to train, to truck, etc." So now we've re-entered the "scenario" part of the whirlpool. Now lets take that scenario and try to apply it to the model and see if the model holds up? Does our Cargo entity, with just a single origin and destination support this new scenario?" No, it doesn't, so we start re-working the model. This may send us into an "eddie" in the whirlpool where we start having a mini-whirlpool discussion about the how to support multiple stops. In the end you may decide that the cargo entity needs to have a series of "Stops" (essentially a listing of destinations), or perhaps you decide that a series of "legs" would work better (a listing of legs that contains both origin and destination, where the origin of each leg is the same as the destination of the prior leg). Either way, you then modify your model (erase a few things on the white board and write in the new objects). So now you've made another pass around the whirlpool. Occasionally, the developers will decide that they need to do a "code probe" in order to find out how well a certain concept will play out in code. This is the other arrow in the diagram and doesn't always happen (probably only occasionally). During this probe, they are exploring the capabilities of the technology to meet the needs of the model. The developers should at this point be trying to write code that looks and sounds just like the model. If the developers write code that is not recognizable by the business user, the code will eventually grow apart from and no longer be representative of the model, something that is critical in domain driven design.
Eric mentioned that when he is modeling like this, he often has one scenario in front of him and several other scenarios forming in the back of his mind (that he will need to use to challenge the model when he gets to them). I actually think it would be useful to maybe have a little area off to one side of the white board where we could jot down those scenarios as people think of them without them becoming a distraction to the current scenario we are exploring together. Whether this could be done without becoming a distraction or not, I'm not sure, but it would be a shame if those scenarios got lost.
Notice that I've avoided using words like "class" or "property" when creating the model. This is because the model should be a common ground between development and business that both parties can understand and speak about without confusion. The word "class" means nothing to a business user. This is part of what Eric calls the Ubiquitous language and it is a core part of DDD. The business and developers need to all speak the same language. This even means that developers speak the ubiquitous language amongst themselves. If the developers speak one language when they're talking with the business or talking about the model and then speak another language when they're coding, something isn't right with the model that is making it so that there is a disconnect between the way it has to be coded and the way its represented in the model.
Also, during the whirlpool process, Eric mentioned that we are trying to create an explosion of scenarios and models. This is how we get the information transfered out of the minds of the domain experts and into the minds of the developers. During this discussion the much used (and sometimes abused) agile phrase YAGNI (you ain't gonna need it) was brought up. YAGNI spawned from the agile concept of attempting to avoid wasting time creating functionality that we are never going to need (or as Eric said, "functionality you won't need before your project is cancelled" :). YAGNI was meant to counter the waterfall approach of having to design everything you could possibly ever need up front because once development begins we can't change any of the specifications or design. Some self-proclaimed agilists use the YAGNI term, in Eric's words "as a weapon". When it is abused, it is used to prevent ANY sort of design at all. Certainly this is not what was meant by authors who have cautioned about the old waterfall approach and how that more often than not leads to wasted time creating features that really are never used. However, it is important to note how inexpensive it is to do modeling and how expensive it can be to refactor code later, especially if refactoring is done on objects that are core to the design and used everywhere. A class discussion spawned on this topic as we tried to explore, "how much design/modeling is too much". Eventually, Eric suggested that we focus heavily on the part of the system we are about to work on and do a little exploration into the other parts of the system. Jump into the waterfall in a few key places that you know will eventually exist. Jump in just long enough to gain a very high-level understanding of those areas. Doing so may help you create a better design for what you are about to start coding and may help you avoid costly re-work down the road.
That was the bulk of what we discussed on day one. Here are a few other brief points that were brought up:
- We need to bring the business into discussions that we are having as developers when we start discussing the subtleties and complexities of the domain (or even the software)
- We need to listen carefully to the way the business users talk about the domain. Often small words can give us very useful clues into something they're thinking but haven't really expressed.
- We often look for validation from the business user and when we get that validation (even the smallest hint of validation) we move on. We latch on to the first model we come up with when we should instead press further and make sure that we aren't all missing something important. Just because the business user says they agree to something doesn't mean they aren't forgetting about something or failing to recognize something that is not right in our model
- We need to make the business user's value evident. That starts with us recognizing how important they are to even very simple discussions about the domain and the model. We can't make assumptions and we need the business users to know how important we feel they are to helping us understand the domain
- Models are not about "realism" they are about usefulness. A good example of this was Mercator's map from 1569. This map, when you look at it is not accurate at all as to the size of the continents (Greenland looks huge), but it is a very affective navigational map. It is a projection that makes the map look odd, but makes calculating navigation from one location to another much easier. This model is not realistic, but it is very useful. The same can apply to our models
- Usefulness is specific to particular scenarios. A chair is useful, but it's not useful for swimming. Models are useful for specific purposes.
- Scenarios should not branch. If, while discussing one scenario you come up with two possible paths, finish one and then come back with the other one as a separate scenario.
- Using and adhering to a ubiquitous language can help prevent anemic objects (Anemic is a symptom, not the problem).
That's all for now. I'm a day behind. Tomorrow I'll try to blog what we learned today including some interesting stuff about Anemic domains.
Good night!.
Subscribe to:
Posts (Atom)