Sharing a domain model between different software modules.

184 views Asked by At

Consider the following situation.

Three apps A,B and C must cooperate together: A is an external, third party app while B and C are in-house apps (so we have control over B and C, not over A). B replies to requests made by A, using both logics contained in C and B itself. Think about B as a layer between A and C.

There are some underlying common concepts that A,B and C understand and use.

Suppose the key task here is to decouple everything, so that if tomorrow we want to use A1 instead of A, all the interactions between B and C stay fixed (and, respectively if we want to use C1 instead of C, all the interactions between B and A stay fixed).

The question is about the datamodel design for B and C. Two solutions come to my mind:

  1. Shared datamodel: we introduce a datamodel D in a different project. D contains the "in house" version of the common concepts and is used by B and C: an A-version of the concept is mapped to a D-version and can be used and understood by both B and C. If tomorrow we want to use A1 instead of A, we simply re-write the adapter. If instead we want to get rid of C, we write C1 using the common datamodel D.
  2. Replicated datamodel: both B and C have its own version of the datamodel. We now have two adapters: one between A and B and one between B and C. If tomorrow we want to change either A or C then we rewrite the respective adapter.

Is there any best practice for dealing with this situation? Is there any alternative to 1. and 2.? Is there any intrinsic problem with either 1. and 2.?

Edit Following request I'll try to give a more explicit example (of course everything here is fictional. Also forgive my horrible fantasy).

ACME ltd is a used car retail company, needing detailed information regarding every car bought and to-be resold. This process is outsourced, so they expose a simple DTO with two classes ACME.CarInfoRequest and ACME.CarInfoResponse (containing proper fields). In particular there is the business concept of ACME.Car.

ACME is outsourcing to INITECH inc, a car data provider. INITECH has a big and updated database containing car info and also features a live connection to the police records to check if the car is stolen. INITECH has one main app to interface with the customer and uses a different app to communicate with the police: the INIMAIN app and the INIPOLICE app. Both apps have the underlying concept of "Car".

The question is: should INITECH use a shared datamodel and let INIMAIN and INIPOLICE add it as a dependency or should implement mirrors in the two apps? In other words the two solutions could be:

1) INITECH builds INIDATA project. INIDATA contains INIDATA.Car to represent the concept of "car". Both INIMAIN and INIPOLICE add INIDATA as a dependency and use the same INIDATA.Car. When INIMAIN and INIPOLICE speak about a "Car", no translation is required (as they both refers to the same INIDATA.Car). On the other hand, INIMAIN maps the info contained in ACME.Car into INIDATA.Car via an adapter.

2) INIMAIN has its own representation of INIMAIN.Car (and respectively INIPOLICE has INIPOLICE.Car). When INIMAIN wants INIPOLICE to ask the info about a car, first translates from INIMAIN.Car to INIPOLICE.Car. Then when INIPOLICE replies, INIMAIN translates everything back from INIPOLICE.Car to INIMAIN.Car. Of course ACME.Car is still mapped into INIMAIN.Car via an adapter.

Hope it's more clear now (even if probably the example is awkward, again forgive my limited fantasy).

1

There are 1 answers

0
Chetan Kinger On BEST ANSWER

The question is: should INITECH use a shared datamodel and let INIMAIN and INIPOLICE add it as a dependency or should implement mirrors in the two apps

The answer to this question depends on the list of services that INTECH plans to provide to its customers.

  1. If accessing police records is the only service that INTECH plans to provide its customers, it is only logical that both the INIMAIN and INIPOLICE modules share a single INDATA.car domain model (since there is only one data model that needs to be supported i.e, the data model understood by the external police application that INPOLICE will speak to)
  2. On the other hand, if INTECH plans to provide more services such as insurance details of the car through the CARINSURANCE module that talks to external insurance data service, it would make more sense that INPOLICE and CARINSURANCE modules have their own data models that are modeled as per the external services they speak to (Police record external service and insurance record external service will usually have their own request model). In this case, INTECH should have INDATA.PoliceCar and INDATA.InsuranceCar data models and INMAIN would mapACME.car to either INDATA.PoliceCar or INDATA.InsuranceCar depending on what type of information is being requested by ACME

It all boils down to whether INTECH plans to provide a single service or multiple services to its customers. If this is difficult to determine in the near future, it would make more sense to stick to a single data model shared by INPOLICE and INMAIN rather than over-designing for a use-case that INTECH might never ever encounter.