Dealing with Loose Coupling in a Service-Oriented Architecture (Page 1 of 5 )
4.2.4 Weak Type Checking
Another good example of the complexity of loose coupling has to do with the question of whether and when to check types. Most of us have probably learned that the earlier errors are detected, the better. For this reason, programming languages with type checking seem to be better than those without (because they detect possible errors at compile time rather than runtime).
However, as systems grow, things change. The problem is that type checking takes time and requires information. In order for the SOA infrastructure (ESB) to check types, it needs to have some information about those types. If, for example, types are described using XML, the ESB will need the corresponding XML schema file(s). As a consequence, any modifications of the interface will not only affect both the provider and the consumer(s), but also the ESB. This means that mechanisms and processes will be required to synchronize updates with the ESB. And if the ESB uses adapters for each provider and consumer, you might have to organize the deployment of these updates to all adapters. This is possible, but it leads to tighter dependencies than a policy where interface modifications affect only providers and consumers. For this reason, it might be a good idea to make the ESB generic. In general, interface changes should only affect those who use the interface as a contract, not those who transfer the corresponding data. If the Internet had had to validate the correctness of interfaces, it would never have been able to scale.
Now, you might come to the conclusion that you should always prefer generic interfaces to strict type checking in large systems. The extreme approach would be to introduce just one generic service for each system, so that the service interfaces never change: all you change are implementations against the interface. Note, however, that at some stage, your system will have to process data, and whether you can rely on that data being to some extent syntactically correct will affect your code. So, in places where business data gets processed, strong type checking helps. The only question is how stable the data is.
Say, for example, that your services exchange some string attributes. If the attributes are pretty stable, a typed service API that specifies each attribute explicitly is recommended. When a new attribute comes into play, you can introduce a new (version of the) service with the additional attribute. On the other hand, if the attributes change frequently, a key/value list might make sense. The right decision to make here depends on so many factors that a general rule is not useful. For these kinds of scenarios, you have to find the right amount of coupling as the system evolves. Note, however, that explicit modeling of attributes makes it easier to write code that processes the data (for example, you can easily map data in different formats when composing services in so-called orchestration engines). On the other hand, having no generic approach would be a very bad mistake when binary compatibility is a must. For example, a technical header provided for all service messages should always have some ability to be extended over the years without breaking binary compatibility (see Section 15.4).