in·dom·i·ta·ble
adj.
Incapable of being overcome, subdued, or vanquished; unconquerable.
12th
NOV
Eric Evans on Domain Driven Design (again)
Posted by indomitablehef | Filed under DDD
A full-length video presentation from Eric Evans on DDD: putting the model to work
I attended the DDD BOF (Birds-of-a-Feather) group at the QCon conference, hosted by Eric. Some of the things that resonated with me from that session:
1. Look for Pain Points
It should be a given that not all parts of a large, complex system will be well designed (he gave a presentation on that earlier in the week, too). So, don’t waste time doing a complete overhaul of an existing system in an attempt to take advantage of Domain Modeling and Domain Modeling. Instead, look for pain points, problems, things that are difficult, and things that annoy. There’s a good place to start refactoring towards a domain driven design.
2. Well placed Value objects
For clues on how to refactor towards DDD, look for places where you are passing strings around. A few well-placed value objects, instead of strings, can encapsulate domain concepts, and get you started in the right direction.
3. Bounded Contexts
Eric said several times that he wished that Chapter 14 of his domain driven design book had been chapter 2, because a lot of people never got to chapter 14, and it turns out that Bounded Contexts (the subject of chapter 14) are critical. Building anti-corruption layers between systems you have control over and systems you don’t have control over is a good way to maintain the purity of your domain model. These anti-corruption layers are a type of Bounded Context.
Update:
Another thought on those Bounded Contexts. A domain model is “a” model of a system, of a domain. It is rarely “the” model. And that’s ok. Multiple models may be useful for different purposes. In supply chain, the contract management model is different from the purchasing model. Much of the underlying system overlaps, but these different models are perfect for their different purposes. A bounded context (or bounded contexts), then, can be used to translate between the models, and preserve the usefulness of each.
24th
SEP
Domain Driven Design
Posted by indomitablehef | Filed under DDD
An interview with Eric Evans on Domain Driven Design. [infoQ]
14th
MAR
How should we then live?
Posted by indomitablehef | Filed under Agile, DDD
If we are convinced of the value of domain driven design, what do we do next?
1. Don’t try to model everything
Let me ’splain.
[pause]
No, there is too much. Let me sum up. - Inigo Montoya
You could create a complete set of UML structural diagrams for your entire application (package diagrams, class diagrams) and some detailed interaction diagrams (sequence diagrams, state machine diagrams) and use them to generate source code.
You could.
I did it once.
But as Inigo Montoya says, “there is too much”. Instead, carve out that distinct domain layer. This is the core of your application. This is what you should spend time thinking deep thoughts about. This is what you should refactor over and over again. This is what you should model.
That is not to say that the only diagrams you do are the ones that are specific to the domain model. It does mean, however, that you shouldn’t bother trying to maintain the most of the other diagrams you do while designing and building an application. When you are done, the artifacts that will remain are probably only the high-level use case diagrams, the deployment diagram, and the diagrams that are part of the domain model. You may decide to keep some of your activity diagrams, etc., but pretty soon the application will be updated, and those diagrams will be out of sync, and it won’t be worth it to keep up with them. If you want to keep it, keep it. But don’t get caught up in maintaining diagrams that aren’t valuable anymore. We have better things to do.
2. Do maintain the domain model
If you have really carved out the domain model into its own distinct layer, this should turn out to be easier than it sounds. The day-to-day requests of users for little tweaks to application functionality should not change the way the business operates, should it? Neither should those requests require changes to the domain layer. If you’ve really captured deep knowledge about the domain, it will be obvious both to you and to the business users when they have a request that affects this core. They will recognize it as a change to their business practices or structure. You will recognize it as a change to the domain model. Keep the code, the diagrams, and the language/glossary up-to-date and in sync.
3. Your software experts must become domain experts
The tendency among very talented software developers is sometimes to take the position that “I am a software expert, not a(fill in the blank)expert”. (Not a healthcare expert, not a manufacturing expert, etc. ) If we want to do better than we have done in the past, we have to take a different attitude. The best developers/architects (I’m starting not to like the term ‘architect’, but I don’t have a good replacement for it) will have to begin to become domain experts. They will need to have a close relationship with the business domain experts. Their domain expertise becomes an asset of significant value to the company. Of course, they still have to be software experts, too. It’s becoming clearer and clearer that developers are architects/designers/modelers. These roles cannot be so distinct that a designer writes the spec and a developer goes off and writes the code according to the spec. (except in narrowly defined situations)
(a topic I intend to address further in the future is how a company can ramp up development, making use of competent mid-level developers, without having to search for developers that already have domain expertise, who often come at a premium)
4. Do it first, and put your best man on it
Domain-driven design flows from the premise that the heart of software development is knowledge of the subject matter and finding useful ways of understanding that subject matter. The complexity that we should be tackling is the complexity of the domain itself — not the technical architecture, not the user interface, not even specific features. This means designing everything around our understanding and conception of the most essential concepts of the business and justifying any other development by how it supports that core. - Eric Evans
Do it first. Let the evolution of the domain model dictate your other decisions whenever possible. Your best developers should be tasked with developing the most important parts of your software, right? Put them on the domain model first.
14th
What is a domain model?
Posted by indomitablehef | Filed under DDD
Maybe I’ve convinced you that a domain model is useful. Maybe I haven’t. Either way, let’s talk more about what a domain model is.
It is not a UML diagram. It is not a bunch of Objects in an object oriented programming language. (go ahead, cry “heresy!” if it will make you feel better)
A domain model is a conceptual model of key business concepts, entities, processes, and their relationships.
It has three important components:
- a visual representation of the business concepts and their relationships
- a shared language between developers/modelers and the business experts (domain experts)
- a software representation of the domain model
Some or all of the domain model will eventually be turned into software. When it is, that portion of the software that represents the domain model becomes part of the domain model. A change to the software becomes a change to the model.
The domain model may be supplemented by specification of a set of business rules. It may be expounded upon by detailed representations of the interactions between key business entities. The domain model often expresses the state of the business - the state of the business entities and relationships - at a point in time. In such cases, the model may be expounded upon by detailed representations of the possible states of the business entities and relationships.
Ubiquitous Language
Throughout the creation of a rich domain model, developers/modelers must communicate effectively with domain experts. These developers and business experts must learn to speak the same language. Since we are writing software to support the business, instead of the other way around, this means that the developers must learn to speak the language of the business (for the most part). As the model begins to develop, a ubiquitous language begins to develop, and is shared by the developers and domain experts. This shared language is an essential part of the domain model itself. It may even take the form of a glossary document that becomes a model artifact. Even if their is no glossary document, however, the ubiquitous language is an essential part of the model.
It is the language that tells you when the model is probably wrong. If developers and domain experts have trouble expressing themselves to each other, trouble understanding the meaning of language that is important to the business, then something is wrong with the model. If the language is clumsy and unwieldy, and you have to continually translate back and forth from developer understanding of the domain to business people’s understanding of the domain, then something is wrong with (or missing from) the model.
Further reading about Domain Models and Domain Driven Design:
12th
MAR
So, what are our design goals?
Posted by indomitablehef | Filed under Agile, DDD
So, assuming we’ve established the need for an “on purpose” design approach, and the need for a process to support our design goals, the question remains: what are those design goals?
(I’m going to skip over all the thought progressions about creating “quality software within time and budget constraints”, and just get on with the point, assuming you understand the background.)
Let’s talk about layers. There are physical layers and then there are conceptual layers.
Think about the evolution of physical layers:
- Mainframe = 1 layer
- Client-Server = 2 layers
- Distributed = n layers
Then there are conceptual layers:
- UI layer
- Business/Service Layer
- Data Layer
(Remember Windows DNA?)
As I mentioned previously, when I stared learning .Net development, the world of object-oriented development was opened before me. While I was learning the nuts and bolts of being a developer, some other people had already been doing a lot of deep thinking about object-oriented development, and software development in general. Part of that deep thinking involved the evolution of conceptual layers. I’m not going to try to present a complete history of this evolution here - instead, we’ll just pick a starting point near the present, and jump in.
To pick a starting point for our discussion of these layers, we’ll begin with the layers described in Patterns of Enterprise Application Architecture, by Martin Fowler. Fowler divides the conceptual layers of an application into Presentation, Domain, and Data layers.
A “domain layer” implies for us the use of a Domain Model. (not technically necessary in this context, but I’m choosing to gloss over the exceptions). A Domain Model is a very interesting design pattern, and one that I believe contains a huge amount of value in application design.
A Domain Model is ” An object model of the domain that incorporates both behavior and data.” ( FOWLER)
At its worst business logic can be very complex. Rules and logic describe many different cases and slants of behavior, and it’s this complexity that objects were designed to work with. A Domain Model creates a web of interconnected objects, where each object represents some meaningful individual, whether as large as a corporation or as small as a single line on an order form.( FOWLER)
This “web of interconnected objects”, which represent real business entities and relationships, is an extremely expressive, powerful construct. (especially for business applications). More on that, and why it is so important, just a little later…
Fowler goes on to carve his Domain Layer in two, splitting it into a Service Layer and a layer of Domain Objects. This puts us into the ever-fashionable realm of a Service Oriented Architecture. In (or “around”) the Domain Layer, Services act on Domain Objects to provide Application functions. (which are then exposed to the user through the Presentation layer, and saved for later in the Data layer)
This is indeed a powerful, expressive architecture. The presentation logic is separate from the application/domain logic. The persistence/data layer is separate from the Domain Layer (ideally). The application functions and the business entities represented in the application (Domain Objects) exist in an interconnected web of objects, independent of the nuts and bolts of displaying and persisting data. Services perform application functions on Domain Objects, so that even the application functions are separate from the business entities modeled by the application.
But let’s take it one step further. Ever have one of those moments where you read or hear something, and you want to stand up and shout “amen!” ? I had one of those moments when I read Domain-Driven Design: Tackling Complexity in the Heart of Software
, by Eric Evans. Evans takes the Domain Model one step further, if only in nuance and focus, when describing the principle of Domain Driven Design.
Evans divides the conceptual layers into Presentation, Application, Domain, and Infrastructure.
The Presentation Layer is obvious: show information and interpret commands.
The Application Layer is a new layer between the Presentation and Domain layers.
The Application Layer:
- defines the jobs the software is supposed to do
- performs tasks meaningful to the business and handles interaction with other layers
- coordinates tasks and delegates work to collaborations of domain objects in the domain layer
- is kept thin - no business rules or domain knowledge
Notice that the Application Layer, as we have described it, takes on most of the responsibilities of the Service Layer described in (FOWLER). As we shall see, however, it is not just a re-naming and separating of Service Layer.
The Domain layer, then is reduced to Domain Objects, as well as Domain Services.
The Domain Layer:
- represents concepts of the business, business rules, and information about the state of the business
- contains Services that represent what the business does, but not what the application does.
Of course, since we are building a business application, “what the business does” and “what the application does” will often be very similar, on it’s face. Conceptually, though, there is an important distinction. What the business does will not cease if the application ceases to function (hopefully). If the business negotiates contracts, processes shipments, or analyzes pharmaceutical events, the business will find a way to do those things, even if the software doesn’t work.
Thus, if the application assists in the execution of these business processes, we will construction our Application and Domain layers such that:
- Presentation Layer commands will be processed by the Application Layer services.
- When those commands initate a process that is a core function of the business, the Application Layer services will pass on data and commands to the Domain Layer services.
- The Domain Layer services will act on the Domain Objects to execute the core functions of the business
The Infrastructure Layer, then:
- provides generic technical capabilities to support higher layers (messaging, persistence, UI widgets, etc.)
- may involve architectural frameworks
- includes its own Services
Do you see the distinctions? We no longer have a single Service Layer that interacts with Domain Objects and the Presentation/Data Layer. Instead, our layers separate the application even further, such that Application services, though they often interact with business services, are conceptually separate. Even the nuts-and-bolts Infrastructure layer provides services that can be used by the Application Layer Services.
UPDATE: Reading over this again, it occurs to me to interject a warning about focusing too much on “Services”, such that you end up creating an Anemic Domain Model
In this way, the core application Application functions are isolated not only from the Infrastructure, but also from the Domain. An application may twist and turn Domain data in any way desired by the users, without affecting the “real” meaning and implication of the Domain Objects and the Domain Services.
Why am I so excited about this? These layers, remember, are presented in Evans discussion of Domain Driven Design:
Domain-driven design flows from the premise that the heart of software development is knowledge of the subject matter and finding useful ways of understanding that subject matter. The complexity that we should be tackling is the complexity of the domain itself — not the technical architecture, not the user interface, not even specific features. This means designing everything around our understanding and conception of the most essential concepts of the business and justifying any other development by how it supports that core.(EVANS)
The Domain is the heart of business software. The Domain Model represents, in software, the accumulated knowledge that you have about the business. It can express deep, powerful understanding of the business, and you can build better software to support the business around it. The real intellectual property part of our software is the software representation of the domain…separate even from the “specific features” of the applications we build around the domain. Applications can come and go. A real Domain Model changes with and grows with the business itself.
I can never hope to do as good a job explaining it in a simple blog post as Evans does, so I encourage you to read the book.
Next, we’ll talk about some of the implications of this approach, and some guidance on creating knowledge-rich domain models.
9th
MAR
Process and Design
Posted by indomitablehef | Filed under Agile, DDD
Why begin with design?
As we begin our discussion about software architecture, there are a lot of places we could choose to start. We could start by talking about phases of the software development life cycle, UML, Use Case diagrams, or the Microsoft Solutions Framework. But I think that there is actually a “right place” to start…and I’ll endeavor to make the case for that here.
Let me start by stating a couple of thoughts that are purely my opinion:
- Process without design leads to well managed projects that produce clumsy software.
- Design without a process that supports that design leads to good intentions, but may not lead to good software.
Stop me when this sounds familiar…
At the beginning of a project, you take a fairly simple list of requirements, and quickly turn it into an application. Imagine that it’s a web page that does x, a report that shows y, and an email whenever z happens. The results are quick and easy to see, and the users are thrilled. Then come the “ah-ha requirements”…as in “ah-ha! Now I remember - it also needs a page that shows x wherever y is also true, and the report needs to exclude some of the z events, and lets be sure that only users with role a can edit y records, and then only when the date on z hasn’t already passed.” You make the changes, wishing you had known about these things when you started, but still not too concerned. Once you are done, the users are happy, and they start to show the application around to other users. At this point, it becomes apparent that the users you were talking to didn’t know everything there was to know about the business that the application was designed to support. These new users include experts in z, and they promptly pronounce the application unusable, and demand sweeping changes to the nature of z. See the pattern? At some point, you will have cobbled together a solution that mostly meets most of the users needs, with some quirks that the y users will just have to get used to, because now the deadline has already passed and we don’t have time to re-do the whole thing. Your small project to build a storage shed in the backyard has become a seven acre shanty-town.
That is the “without design” scenario. If you want the “process without design” scenario, insert a business analyst, a project manager, a set of requirements documents, a project charter, and a whole lot of meetings, and there you have it. It may end up looking slightly better from the outside, but on the inside it will still be a jumbled mess. Imagine the scenario on a grand scale, where it involves an application of greater importance and a large team of analysts/developers, etc., and you can add an ulcer, a bald spot, a prescription, or a lawsuit in at the end.
And now for my next trick…
So, we read a few design books, get excited about design patterns and domain models, learn some UML, pronounce ourselves “software architects” and on our next project…
The users come to us with an idea for an application, or ideas for a re-write of an old application. Business analysts set to work defining requirements, and the software architect (that’s us now) sets to work developing Use Case diagrams and detailed exception based textual use cases. Once the software architect is satisfied that enough detail has been specified in the requirements and hashed out during the development of the use case diagrams, he and the business analyst call a halt to the requirements gathering, and pronounce the analysis phase of the project complete. Only two months have gone by, and though the users think that the whole process took too long and was way too painful, they breathe a sigh of relief and look forward to the fine software that is sure to result from such painstaking analysis. Now the software architect studies the requirements and use cases, and develops a set of UML diagrams to represent the detailed design of the system. It is an elegant design, and makes use of several very distinguished design patterns. It is, in fact, a good design (probably) at this point. The software architect is no slouch, and he’s done his research and taken great care to come up with the best possible design for this application. It took another two months, but now the entire design is specified in UML diagrams, and he can easily hand off most of the development to more junior members of the team, and we should have the application developed in no time. With explicit instructions to each developer to “write your unit tests first”, the architect hands off the major sections of the design to several junior developers. Each is supplied with a use case diagram, a list of relevant requirements, a class diagram that includes all the public members of each class in the design, and sequence diagrams for all the significant interactions. The software architect breathes a sigh of relief, believing that the hard part (for him) is over. All that is left to do now is to simply write the code according to the design. And though the developers on his team are not “architects” like him, they should all be capable of transferring his elegant design into C# code, with perhaps a little hand-holding from time to time.
This is when it starts to get ugly. Developers (once they figure out all the documents they’ve been given) start writing code. While doing so, they notice things, and begin raising concerns about little details in the design. Of course, the architect couldn’t have thought of everything, and there might even be a few mistakes in the diagrams, but those can be corrected quickly enough. The architect is called in, and based on the previously created analysis and design documents, decides on the best way fix the issues that the developers found with the design. These incidents occur fairly frequently, but they are still no major hassle. The architect begins to complain that he is spending all his time “hand-holding” for the developers, and doesn’t get to write much code himself, but such is the burden of being The Architect. These issues that the developers raise are mostly minor, and though some parts of the design are not as elegant now as they were when construction started, overall it is still pretty good.
We are now a couple of months into construction, and the application is beginning to take shape. There have been a few surprises along the way, but we’ve adapted well. Every now and again the architect has to ask the business analyst to ask the users for clarification on a particular issue. During construction, the business analyst and project manager are still holding bi-weekly status meetings with the users. One day, the business analyst visits the software architect and asks, “how big a deal is it to make it do this…?”. The business owner proceeds to describe a feature that, given the current design, should not be possible! It violates everything we know about x and y! We’ve been working on this project now for six months, and we still haven’t shown the users anything, other than some screen design mock-ups the business analyst put together. Now they are asking for something that affects the very core of our elegant design. We frantically try to reconcile their needs and our new understanding of the business domain with the existing design, but in the end we compromise. We “fall back and punt”, and cobble together the new feature in a way that no one who understands how it was done is really comfortable with.
When the application is finally deployed, it is a success, but the users demand some quick follow-up releases to add features or behavior that we discovered too late to get it into the initial release. More design compromises are made at this point, since some of the requests that seem so minor to our users have major repercussions when it comes to the integrity of the original design. By this time, the architect is already re-designing the system from the ground up in his head. “If I had known then what I know now, I would have done it this way…”. Our good intentions have been compromised again and again, by the realities discovered by developers during construction and by new information coming in from the users (through the business analyst, of course). At that moment when we completed our last diagram, before we handed it out to developers for implementation, we looked upon our design, and it was good. A lot has happened since then. If we look back at those original design documents, the don’t look all that much like the code we actually wrote. You can still see the basic shape of things, but you know that there are a whole lot of things going on in the actual code that don’t fit anywhere in the original model.
That example describes what happens when the process does not support the design. Notice that it is not an example of a lack of process. There’s plenty of process there, but it’s too much and the wrong kind. The process described calls for all the design to be done up front, then design ends and construction begins.
We can do better.
Recent Posts
Recent Comments
- Open Floor Plan vs. Private Offices « Step Into Design on It's Caves AND Commons...
- indomitablehef on Forms Authentication in Asp.Net MVC, Part II
- Dugald Wilson on Forms Authentication in Asp.Net MVC, Part II
- MyWeeklyLinks – Week 5 « Ole Morten Amundsen on Implementing Done, In Process, and Ready Queues in LeanKit Kanban
- indomitablehef on Schema Generation using FluentNHibernate and S#arp Architecture
Categories
- .Net (5)
- Agile (17)
- Alt.Net (3)
- Anti Patterns (3)
- Asp.Net MVC (9)
- Continuous Integration (4)
- Craftsmanship (1)
- CruiseControl.Net (1)
- DDD (6)
- DevLink (2)
- jQuery (2)
- Kanban (4)
- Lean (2)
- LeanKit (3)
- NAnt (2)
- NHibernate (2)
- ORM (1)
- Personal (4)
- Productivity (6)
- qUnit (2)
- Refactoring (1)
- S#arp Architecture (2)
- SOLID (1)
- SqlTdd (5)
- TDD (17)
- Tools (12)
- Uncategorized (11)
- Visual Studio (4)


