There are a great many times that different pieces of software need to have knowledge that other pieces of software have, whether it be separate systems, different modules, or different components.
An example of this is “how to communicate with each other across boundaries”. If a data transfer object (DTO) needs to contain the following piece of information, where is the DTO best defined?
type Person struct {
givenNames []String
familyNames []String
birthDate time.Date
parents []Person
siblings []Person
}
There are three options available, and they each have the strengths and weaknesses.
Owner has the knowledge.
The owner here is a bit loose, essentially it means that one, and only one, piece of software has the knowledge. With communicating across boundaries this would normally be the producer, but in a client server architecture this would be the server (which could be both the producer and consumer). I’ve used the term “owner” here because the piece of code that has the definition determines when the knowledge can be changed - other users of the knowledge can request that the change happen, but the owner can deny it. If the owner decides to change, then all the other users will likely need to handle the change.
When writing Go I would place the example DTO with the definition of the interface owned by the business logic.
Pros
- DRY principle (there’s only one place that needs to be updated when a change is required)
Cons
- Creates a dependency, anybody that needs to know that piece of information needs to import that piece of software.
- Changes need to be well advertised, usually this means versioning
Each party has their own copy.
There is a school of thought where each party holds an internal version of the knowledge. In theory this means that neither party needs to know about the other parties version. In practice this only works when both systems can exchange incomplete information.
Pros
- No dependencies
Cons
- Synchronisation of changes - this can be really difficult, the systems are coupled and deployment requires that the two systems change together
- This requires an API between the two that is flexible enough to ignore differences in types, and allows extra, or missing, information/fields (eg. JSON)
A third party holds the information.
Another package, or service holds the knowledge, and both producers and consumers use it.
Pros
- DRY principle
Cons
- No clear ownership - changes need to be agreed to by everyone - usually this means versioning
- Double the dependencies, both producers and consumers need to depend on the package
- Discovering who is using a given piece of knowledge becomes more difficult
Summary.
These are the only options available, and they all have drawbacks. Sharing knowledge between systems is inevitable, and choosing the right approach is very tricky.