Integrating a set of independent software systems is difficult and usually a very big effort. Every large company has this painful experience in their IT landscapes. SAP’s is now investing significantly into integrating the applications of the Intelligent Suite. A big part of that integration is of course the data that is exchanged between the applications and the effort for transformation between the different data models of the applications. A general overview of our approach was already given by Rui Nogueira in his blog post “SAP One Domain Model – the lingua franca of the integrated intelligent suite“.
In this blog post I want to describe how Domain Driven Design (DDD) has influenced our approach to the alignment process and the modeling guidelines for SAP’s One Domain Model.
A canonical data model – doomed to fail?
Many have attempted to define a canonical data model as ‘the one consistent common data model for the whole enterprise’. These projects are doomed to fail as other prominent voices have rightfully stated (e.g. here). This is because models are only consistent within what DDD calls a ‘Bounded Context’, e.g. a domain like shipping, marketing, CRM etc. All of these domains may have a concept of a ‘Customer’ but all of them will look very different according to what the particular application domain needs, i.e. what a proper model of ‘reality’ is in that domain. Trying to unify them is not only futile but fundamentally wrong because it merges together models that are inherently different. This realization is what led Eric Evans to invent Domain Driven Design 15 years ago.
But what then is a meaningful approach to integration of multiple applications that share master data and business processes going across the applications? On one hand we want to avoid n**2 point-to-point integrations between applications, on the other hand we want to avoid the pitfalls of a global canonical data model.
In early 2019 we thought about what the design goals and modeling guidelines should be for SAP’s One Domain Model that was positioned to become the data model for integration of the Intelligent Suite. Some key design goals were:
- Restrict alignment efforts to those parts that must be aligned, i.e. where a producer and consumer agree on an exchange format.
- Do not let current system / application boundaries define model boundaries. Instead domains should define the top level of models and these should remain stable in the face of system evolution, carve-outs of monoliths etc.
- Allow domains to evolve independently and easily without any global synchronization need.
- Our model ‘objects’ are DDD aggregates. They are the unit of modeling and distribution and consist of one root entity, sub-entities and value types. As it is standard in DDD, associations are only allowed to aggregate roots. Strong consistency exists only within and eventual consistency between aggregates.
Applying Domain Driven Design principles
For the discussion of modeling guidelines and patterns, it makes sense to consider master data (e.g. Product, Customer) and transactional data (e.g. Quote, Order) separately. In this blog post we will discuss the master data, in a later blog post the transactional data models.
Master data is shared between many applications. Out of sync master data is a major pain point in enterprise landscapes and you really want master data to be the same across all applications. Therefore, the first focus on alignment was there. Consider the picture below:
- The top-level structure of ODM is domains. ODM objects live in domains, i.e. in name spaces. Applications ‘own’ one or more domains, i.e. they write the (master) data to Master Data Integration (MDI) service (for details see the SCP Master Data Integration blog post). Master data is written by 1 or more applications and read / consumed by many others (only the writing relations are shown above). There is a very small common domain that contains only a few types that are shared by all applications. This is what is called the ‘Shared Kernel of ODM’ in DDD terms.
- Some objects like ‘Customer’ or ‘Product’ appear in many applications since all of them deal with these entities and have some data about them. The first important point here is that there is a ‘core object’ that contains the essential attributes that are needed for the identity and that are shared by many / all writers and readers. We want to only put data in that must be the same between all / most applications. This model would e.g. be defined as a odm.Customer.
- But many applications will have additional data for their ‘Customer’ object that no one else has and no one else may need to consume it in integration. Consider e.g. LoyaltyManagement or a Marketing application. They will link to the core customer model but will have lots of additional data on customers that does not need to be modeled in ODM at all. If the LoyaltyManagement application at some point decides to expose their data in ODM as well, their model will be odm.loyalty.Customer. Even though both the core and loyalty customer model deal with the same real-world entity, their models are separate, owned by different applications and they can evolve independently. Thus, each customer object can live and evolve in their own bounded context (domain / name space). We call this the ‘shared identity pattern‘.
- A similar pattern that decouples models and reduces alignment overhead is what we call the ‘domain aspect separation pattern‘. Consider e.g. the Product model. There are many aspects to a product that are owned by other domains, e.g.
- ProductProductionAspect: Data about products that is maintained by the ‘Production’ domain and may be needed by other domains.
- ProductSalesAspect: Sales related information for a product that is needed by e.g. commerce applications.
- ProductFinanceAspect: Financial data like valuation, controlling related data etc.
These aspects are loosely coupled to the Product they pertain to but they clearly live in their own domains, i.e. the models are defined and the data is written by that domain (the application that implements the domain). The key points here are: (1) These aspects can evolve independently from the core product. (2) Alignment discussions for these aspects are only needed between the providers and consumers of the data. This gives us many small alignment discussions instead of one global one. In DDD terms, one might call this a ‘shared kernel’ for just this aspect and we then have many small shared kernels each focused on one aspect and only the directly affected participants.
- Of course, all applications need to map their internal data structures to the external ODM model and vice versa. This corresponds to the Anticorruption Layer (ACL) relationship in DDD that separates the evolution of models on both sides.
Transactional data behaves a little differently than master data, has different concerns and requires slightly different modeling patterns. These will be described in a later post.