Separation of
concerns and decoupling
To facilitate standardized contracts, they must be decoupled
as much as possible. Decoupling can be achieved by designing the contract
first, regardless of technology, back end, consumer etcetera.
A number of different coupling types can be identified.
Generally speaking we distinguish positive and negative coupling types.
Positive coupling types are encouraged whereas negative coupling types should
be avoided. Negative coupling is anything on which the contract can form
dependencies. In other words, contract-to-* coupling is considered negative
coupling and *-to-contract coupling is considered positive coupling as this
reduces the amount of dependencies the contract can form.
A way of achieving contracts independent of consumers and
implementation is by designing the contract first. If the contract-first
approach is not followed the risk exists that a number of different kinds of
negative coupling find their way into the contract.
Now that we have identified positive and negative coupling
types, the following can be considered positive coupling:
- Consumer-to-contract
- Logic-to-contract
The directly negative coupling types are:
- Contract -to-consumer (contract depends on one
or more consumers of the service)
- Contract-to-logic (contract depends on the
implemented logic’s interface
- Contract-to-functional (contract only supports
specific functional context ie. parent process)
Indirectly another set of negative coupling types can exist,
ie:
- Logic-to-implementation(logic depends on how the
logic is implemented)
- Logic-to-technology (logic depends on the
technology on which it is implemented)
Because the contract can depend on the logic, the contract
can indirectly depend on implementation or technology. Examples of negative
coupling are situations where contracts are generated from implemented
components or classes, or components generated to expose a database
implementation.
Regardless of the coupling type, any negative coupling type
from contract-to-logic will inadvertedly also expose an indirect level of
coupling to the consumer of the service. Ie. the consumer might need to
populate parts of a message to our service which represents ie. a tablename or
fieldname of the underlying back end or database implementation. This will
result in unnecessary changes to cascade though our services into the consumers
and should be avoided in general.
Again, a fairly simple way of avoiding these kinds of
problems is by following the contract-first approach. Another advantage of
contract-first approach is that once the contract is defined (and hopefully
also standardized as described in section 2), is that delivery streams of both
service provider as well as service consumer can make their design and
implementations in parallel, as the interface of the service is predefined with
a clear purpose, context and meaning. This would facilitate a quicker delivery
model than ie. a straight-forward sequential approach where service
implementation had to be finished before the contract can be shared. This would
benefit any project manager, scrum manager etc. as there is no sequential
dependency before the consumer of a service can start designing and developing.
This provides flexibility to the project delivery lifecycle.