Recently, I blogged that two coupled services should have declared, visible, and open coupling. I was promptly asked how.
First off, when you have two services, why would they be coupled? Isn’t the POINT that your services are decoupled? Sure. That’s the point. But the business doesn’t always work that way. Sometimes, your services are coupled because the business is coupled.
Here’s an example.
Let’s say that our company (Contoso) has a couple of co-op marketing programs. This kind of program is fairly common these days. You make an arrangement with a business partner. They include a reference to your product in their advertising, and you provide some money to pay for the ad. A good example that most folks will recognize: Intel has a co-op marketing program. Any ad that specifically mentions that a machine has an Intel chip in it, and displays the Intel logo, earns a reimbursement from Intel for the costs of producing and running the ad. As a result, we all seen (and heard) the “Intel Inside” brand quite frequently. The program works.
Now, let’s look at this from a business side. I’m going to pick on two closely related use cases. Signing up to be a partner of any kind, and signing up to be a member of the co-op partner programs.
Contoso has lots of relationships with partners. We have partners in the supply chain, in manufacturing, as well as in distribution and retail. Each of our partners needs to be uniquely identified, so we have a system where we record the basic information about a partner: legal entity name, DUNS number, Government Tax Id, Street Address, and other information needed to correctly identify this company. Attached to this record, we may have information about contacts, directors/owners, and people that we recognize as contract signatories.
Seperately, we will have a system that records the information specific to the co-op programs. It will contain the list of programs, eligibility rules, claim constraints, claim history, and measures of visibility and effectiveness of the co-op programs. The partner identified in this system has to also exist in the core partner system, but not the other way around. In other words, in order to be eligible, you have to be a partner in some way, but not all partners are eligible. The supplier of cardboard boxes should not be able to claim co-op marketing funds for our product, for example.
So, what kind of service is “create co-op partner”? First off, it is a composite service. It needs to orchestrate between two lower-level services. For the sake of argument, I’ll call the lower level services “partner-master” and “add-to-co-op-master”.
If I send data to a service that creates a co-op partner, and I don’t know the id in the partner master system, then I need to look the partner up, and if they are not found, create them in the partner master system, then take their partner id and add them to the co-op system. I may not want to do any of that if they are not eligible to join the co-op system.
Adding data to the co-op system itself is done in the ‘add-to-co-op-master’ service. This service simply requires the existence of a ‘partner master’ id. Of course, to be defensive, it will need to check to see if that id is valid or have some other way to trust the caller.
And here’s where we get to the notion of a declared coupling. The ‘create co-op partner’ service needs to have a way to declare, even if it is just in text, that it is responsible for checking the ‘partner-master’ service, looking for duplicates and creating the partner if necessary. There needs to be data that shows the coupling of this composite service. In the best of all possible worlds, This data would be available in the contract header information (although I don’t know of any standard way to do that).
In addition, there needs to be a way for the ‘add-to-co-op-master’ service to trust the partner id that comes in on a call, without actually calling the ‘partner-master’ service. Perhaps it will only accept calls that have an ID if the call comes from a known composite service or from a known IP address? Perhaps digital signatures are required? Trust has to be established.
It is important that the fine-grained ‘add-to-co-op-master’ service NOT directly call the ‘partner-master’ service. This would be unnecessary coupling.
So, recap, the rules to making this coupling open and visible:
— In the header of any composite service, declare the child services that will be called, with sufficient reference data for the system that is asking for data to drill down and find out about the called service.
— If a service has data reference requirements, it can limit the list of eligible callers to a known collaborator (like a known composite service). It should not call other fine-grained services to validate inbound data.
— The only services that can call other services are composites, and composites can only call other services in a rules-defined order. They should not perform their own data storage or data validation operations, relying only on underlying services to provide these capabilities.
It’s not dissimilar to the notions of ‘good practice’ that evolved out of object-oriented programming when it started to get off the ground. Things like naming rules and style considerations, all of which were designed to make code easier to read and use. The same goes for service coupling. If we follow these basic rules, we can minimize coupling and keep it contained in an open and controlled location.
In response to a question about application-level authentication, I am updating this post to include a link to an MSDN article that discusses this aspect in rich detail. I highly recommend this ‘Patterns and Practices’ article.