Domain Driven Design (DDD) Pattern of paterns

Domain Driven Design (DDD) Pattern of paterns

Today’s enterprise applications are undoubtedly sophisticated and rely on some specialized technologies (persistence, AJAX, Service layers and so on) to do what they do. And as developers it’s understandable that we tend to focus on these technical details. But the truth is that a system that doesn’t solve the business needs is of no use to anyone, no matter how pretty it looks or how well architected its infrastructure.

The philosophy of domain-driven design (DDD) – first described by Eric Evans in his book [1] of the same name – is about placing our attention at the heart of the application, focusing on the complexity that is intrinsic to the business domain itself. We also distinguish the core domain (unique to the business) from the supporting sub-domains (typically generic in nature, such as money or time), and place appropriately more of our design efforts on the core.

Domain-driven design consists of a set of patterns for building enterprise applications from the domain model out. In your software career you may well have encountered many of these ideas already, especially if you are a seasoned developer in an OO language. But applying them together will allow you to build systems that genuinely meet the needs of the business.

In this article I’m going to run through some of the main patterns of DDD, pick up on some areas where newbies seem to struggle, and highlight some tools and resources (one in particular) to help you apply DDD in the domain oe works.

Of Code and Models…

With DDD we’re looking to create models of a problem domain. The persistence, user interfaces and messaging stuff can come later, it’s the domain that needs to be understood, because that’s the bit in the system being built that distinguishes your company’s business from your competitors. (And if that isn’t true, then consider buying a packaged product instead).

By model we don’t mean a diagram or set of diagrams; sure, diagrams are useful but they aren’t the model, just different views of the model (see Figure). No, the model is the set of concepts that we select to be implemented in software, represented in code and any other software artifact used to construct the delivered system. In other words, the code is the model. Text editors provide one way to work with this model, though modern tools provide plenty of other visualizations too .

Model vs Views of the Model

 

 

 

 

 

 

 

This then is the first of the DDD patterns: a model-driven design. It means being able to map – ideally quite literally – the concepts in the model to those of the design/code. A change in the model implies a change to the code; changing the code means the model has changed. DDD doesn’t mandate that you model the domain using object-orientation – we could build models using a rules engine, for example – but given that the dominant enterprise programming languages are OO based, most models will be OO in nature. After all, OO is based on a modelling paradigm. The concepts of the model will be represented as classes and interfaces, the responsibilities as class members.

Speaking the Language

Let’s now look at another bedrock principle of domain-driven design. To recap: The goal is to build a domain model that captures the problem domain of the system being built, and we’re going to express that understanding in code / software artifacts. To help us do that, DDD advocates that the domain experts and developers consciously communicate using the concepts within the model. So the domain experts don’t describe a new user story in terms of a field on a screen or a menu item, they talk about the underlying property or behavior that’s required on a domain object. Similarly the developers don’t talk about new instance variables of a class or columns in a database table.

Doing this rigorously one get to develop a ubiquitous language. If an idea can’t easily be expressed then it indicates a concept that’s missing from the domain model and the team work together to figure out what that missing concept is. Once this has been established then the new field on the screen or column in the database table follows on from that.

Like much of DDD, this idea of developing a ubiquitous language isn’t really a new idea: the XPers call it a "system of names", and DBAs for years have put together data dictionaries. But ubiquitous language is an evocative term, and something that can be sold to business and technical people alike. It also makes a lot of sense now that "whole team" agile practices are becoming mainstream.

Models and Contexts …

Whenever a discussion is made over a model it’s always within some context. This context can usually be inferred from the set of end-users that use the system. So have a front-office trading system deployed to traders, or a point-of-sale system used by cashiers in a supermarket. These users relate to the concepts of the model in a particular way, and the terminology of the model makes sense to these users but not necessarily to anyone else outside that context. DDD calls this the bounded context (BC). Every domain model lives in precisely one BC, and a BC contains precisely one domain model.

I must admit when I first read about BCs I couldn’t see the point: if BCs are isomorphic to domain models, why introduce a new term? If it were only end-users that interacted with BCs, then perhaps there wouldn’t be any need for this term. However, different systems (BCs) also interact with each other, sending files, passing messages, invoking APIs, etc. If we know there are two BCs interacting with each other, then we know we must take care to translate between the concepts in one domain and those of the other.

Putting an explicit boundary around a model also means we can start discussing relationships between these BCs. In fact, DDD identifies a whole set of relationships between BCs, so that we can rationalize as to what we should do when we need to link our different BCs  together:

  • published language: the interacting BCs agree on a common a language (for example a bunch of XML schemas over an enterprise service bus) by which they can interact with each other;
  • open host service: a BC specifies a protocol (for example a Restful web service) by which any other BC can use its services;
  • shared kernel: two BCs use a common kernel of code (for example a library) as a common Doreman and Nobitha, but otherwise do their other stuff in their own specific way;
  • customer/supplier: one BC uses the services of another and is a stakeholder (customer) of that other BC. As such it can influence the services provided by that BC;
  • conformist: one BC uses the services of another but is not a stakeholder to that other BC. As such it uses "as-is" (conforms to) the protocols or APIs provided by that BC;
  • anti-corruption layer: one BC uses the services of another and is not a stakeholder, but aims to minimize impact from changes in the BC it depends on by introducing a set of adapters – an anti-corruption layer.

You can see as we go down this list that the level of co-operation between the two BCs  gradually reduces (see Figure 2). With a published language we start off with the BCs establishing a common standard by which they can interact; neither owns this language, rather it is owned by the enterprise in which they reside (it might even be an industry standard). With open host  still doing pretty well; the BC provides its functionality as a runtime service for any other BC to invoke but will (presumably) maintain backwards compatibility as the service evolves.

Spectrum of Bounded Context Relationships

However, by the time we get down to conformist we are just living with our lot; one BC is clearly subservient to the other. If we had to integrate with the general ledger system, purchased for megabucks, that might well be the situation we’d live in. And if we use an anti-corruption layer then we’re generally integrating with a legacy system, but introduce an extra layer to isolate ourselves as best we can from it. That costs money to implement, of course, but it reduces the dependency risk. An anti-corruption layer is also lot cheaper than re-implementing that legacy system, something that at best would distract our attention from the core domain, and at worst would end in failure.

DDD suggests that we draw up a context map to identify our BCs and those on which we depend or are depended, identifying the nature of these dependencies. shows such a context map for a system.

Context Mapping

One question comes to the Mind is that how do the functionality as services, will they have leverage over me? Misunderstand this and your application could easily be a failure.

Layers and Hexagons

Let’s now turn inwards and consider the architecture of our own BC (system). Fundamentally DDD is only really concerned about the domain layer and it doesn’t, actually, have a whole lot to say about the other layers: presentation, application or infrastructure (or persistence layer). But it does expect that they exist. This is the layered architecture pattern.

building multi-layer systems for years, of course, but that doesn’t mean we’re necessarily that good at it. Indeed, some of the dominant technologies of the past – yes, EJB 2, I’m looking at you! – have been positively harmful to the idea that a domain model can exist as a meaningful layer. All the business logic seems to seep into the application layer or (even worse) presentation layer, leaving a set of anaemic domain classes  as an empty husk of data holders. This is not what DDD is about.

So, to be absolutely clear, there shouldn’t be any domain logic in the application layer. Instead, the application layer takes responsibility for such things as transaction management and security. In some architectures it may also take on the responsibility of ensuring that domain objects retrieved from the infrastructure/persistence layer are properly initialized before being interacted with.

Where the presentation layer runs in a separate memory space then the application layer also acts as a mediator between the presentation layer and domain layer. The presentation layer generally deals with serializable representations of a domain object or domain objects (data transfer objects, or DTOs), typically one per "view". If these are modified then the presentation layer sends back any changes to the application layer, which in turn determines the domain objects that have been modified, loads them from the persistence layer, and then forwards on the changes to those domain objects.

One downside of the layered architecture is that it suggests a linear stacking of dependencies, from the presentation layer all the way down to the infrastructure layer. However, we may want to support different implementations within both the presentation and infrastructure layer. That’s certainly the case if (as I presume we are!) we want to test our application:

  • similarly, one may well have more than one persistence implementation. the production implementation probably uses RDBMS or similar technology, but for testing and prototyping one may have a lightweight implementation (perhaps even in-memory) so the easy way is to  mock out persistence.

We might also want to distinguish between interactions between the layers that are "internal" and "external", where by internal  mean's an interaction where both layers are wholly within the application boundary (under on BC (Binding context)) , while an external interaction goes across BCs across different applications

So rather than consider your application as a set of layers, an alternative is to view it as a hexagon . The viewers used by the end-users,  while calls coming in from other BCs (eg Restful for an open host interaction, or an invocation from an ESB adapter for a published language interaction) hit an external client port. For the back-end infrastructure layer we can see a persistence port for alternative object store implementations, and in addition the objects in our domain layer can call out to other BCs through an external services port.

From the descriptive perspective DDD seams to be an high end pattern that has been derived but in actual this is combination of the existing patterns that has been used and the correct junctures to separate the domain specific implementation.

The Hexagonal Representation is shown at the top that has various plugin points that like View , Model , RDBMS, Restful, In memory ...etc.

The one understands this DDD pattern the terminology is different like in traditional applications we have APP context here it is Binding context and published language a standard is defined that is XML for communication.Open Host is nothing but specifies the protocol on which the communication has to happen. The constraint is nothing but the service under on BC can access another BC but has limitations like the admin still under the control of the BC under which the Restful Service is defined.

Pras Biswas

RETIRED - DO NOT CONTACT

7 年

Naked plagiarism in a corrupt country.

Vegard Steinsholt

Omr?deleder i Produktomr?de Helse

8 年

Is this really your text? I found the exact same here; https://www.methodsandtools.com/archive/archive.php?id=97

要查看或添加评论,请登录

社区洞察

其他会员也浏览了