Integration of software systems is a challenging job. Our company has several systems that are connected. I have observed that adding Microsoft Code Contracts improves the speed of diagnosing problems, and improves the readability of our integration code. I noticed this when we wrote custom workflow activity code, and installed it within our Microsoft CRM system. I wrote about that in an earlier article.
This article describes the same benefit applied to another integration point.
Consider two systems, with shared data that must remain synchronized (consistent). We wrote a CRM plugin that will help keep the systems synchronized. So when a person updates the CRM system, it will call the web services of the second system, and make the appropriate changes there. One of the benefits of this approach is that, when it works, the systems remain synchronized at all times. However, there are several challenges to integrating systems in this way. These include
- Transaction reliability (ACID (atomicity, consistency, isolation, durability)
- Error display and usability (How do we present errors occurring in the external system)
- Data quality and consistency of business rules (Is last name required in both systems? What is the greatest length that all systems can handle?)
Code contracts are one small part of a solution to address these issues.
Regarding transactional reliability:
Let’s imagine that we are performing a transaction that involves two systems. If a user enters data that is accepted by one system, but later rejected by the other system, then any changes must be rolled back. But these systems are on different platforms, integrated via web services. So rolling back is not quite as easy as it might be in a single database. When possible, it is better to add powerful preconditions on the operation, that prevalidate the information across all systems, to increase the probability that the transaction, once started, will complete successfully. Of course, it may be that this prevalidation deserves to become a first-class part of the system’s behavior. In that case, implementing it as a precondition is not appropriate. Especially in situations where contracts may be disabled for production deployments. Notice that whether we actually use Code Contracts, the concepts of preconditions and postconditions are still powerful tools for understanding what must be done to enhance reliability of the transaction.
Regarding data quality:
If one systems can handle last names of up to 25 characters, and another can handle last names of up to 50 characters, guess what the safest maximum length is? (25). Typically, when someone is coding to a web service across platforms, this information may not be readily apparent. You can assist programmers in following the rules by encoding the rules as contracts at the call site. In Microsoft CRM, we typically put such rules in a plugin so that they are enforced regardless of whether someone is using the CRM user interface or the CRM web services.
In some cases, code contracts are the appropriate tool to express and enforce rules at interfaces between platforms. By blocking invalid calls from one platform to another, the risks associated with rollback are reduced.
In other cases, code contracts may not be appropriate, but the conceptual ideas are just as valid: Preconditions proactively block invalid calls, postconditions verify success. In these cases, the concepts are so important that the product code itself is coded to implement them. It is not done as Code Contracts because it must never be turned off or removed by a configuration option.
So even in cases where you do not use Code Contracts, the study of structured assertions give insight into ways of constructing more reliable software.