On Wednesday, February 17, 2010, I gave a 90 minute presentation to the Minnesota Visual Studio User Group, on the use of Microsoft Code Contracts to improve software quality. Approximately 17 programmers attended. I used several Visual Studio solutions and several PowerPoint presentations. All of the materials can be downloaded from my download section. In addition, I have summarized several of the questions that were asked by the participants. For each question, I have included the answer that I gave them, as well as additional thoughts I had after further reflection. If any of you are giving presentations on the topic of code contracts, feel free to use any of the slides or sample code.
You have demonstrated how to use a precondition. But I don’t see why I shouldn’t simply use my traditional “if(x) then (do y)” statement to validate arguments.
Answer I gave:
You are correct that the precondition is functionally equivalent to the more common form of the argument validation. However, the code contracts precondition, Contract.Requires(x), can be recognized by the static checker in an effort to identify potential defects in your code. Furthermore, there are many other assertion types available with code contracts including postconditions and class invariants. The toolset also includes a static checker, as well as capabilities to customize the behavior of the contract failure handler. If I had shown you some of the other assertions earlier in the presentation, you would probably not be asking this question.
In future presentations, I may give a more comprehensive early code demonstration that includes sample of all the different types of assertions. This will set the tone and establish broader boundaries for the mental model that the audience establishes early.
I’m concerned about performance. You indicated that sometimes, postconditions can be expensive.
Answer I gave:
You can adjust the level of assertion checking. This would allow you to exclude the postconditions in order to improve performance if that were necessary.
But if I vary the run-time checking level in different environments, I am afraid that my testing process will experience error messages that differ from the production environment. This would be unacceptable.
Answer I gave:
Actually, in practice, I leave all of the contracts in my production code in order to improve the detection and reporting of defects in unusual situations we did not anticipate in our testing. Our applications have not yet suffered from performance issues related to contracts.
I wish I had asked more questions of the participant. After all, if they were to have three environments: development, testing, and production; and they wanted their testing environment to resemble production as closely as possible, they could enable run-time checking in the development environment, and then use identical reduced run-time checking in both the testing and production environments.
What only occurred to me later was the fact that the error reporting behavior as experienced by the users should be nearly identical regardless of whether code contracts are enabled or disabled. After all, I made a point of explaining that the logic of the application should not vary based upon contract failures. This rule even applies to the application exception handling backstop. In other words, a programmer should never allow contract failure exceptions to bubble up and be displayed directly to the users. Instead, the application backstop should treat contract failure exceptions just like other unexpected exceptions like out of memory exceptions, network connection failure exceptions, etc.
When I think about your example of using code contracts to encapsulate business rules like “account balance should never be negative,” I think about anti-patterns that code contracts might encourage such as the duplication of the business rule.
Answer I gave:
I have been using code contracts liberally for years, and I don’t recall feeling like the presence of contracts introduced duplication that created entropy or friction in the development process.
It is certainly possible that if code contracts were to become widely popular, and were to be adopted by people who did not have in-depth training in the proper use, I’m sure there would be some creative abuses of the techniques and technology. In that circumstance I expect we would discover several new anti-patterns as novice users applied the technologies in ways they were not intended. However, that is the least of my worries at this stage in the adoption of the practices and technologies. For programmers who already follow best practice guidelines of validating arguments, the simple use of preconditions should be a comfortable step in gaining familiarity the code contracts library.
Again, I wish I had asked the user for more clarification on the question. I assumed their greatest concern was duplication of code, which would result from encoding a business rule in a contract as well as encoding it somewhere in the application. In that scenario, it would have been good for me to mention that contracts can be based upon helper methods. If they were really concerned about having duplication in that way, they could create helper methods that would be used both by application flow logic as well as by contracts.
Do contracts eliminate the need for negative test cases?
I was just checking to see whether you are still awake while reading this. You should know by now that I am too long-winded to give a terse answer like that.
What I really said was that whenever a contract is expressing a business rule, you should have a test for it, because all business rules and requirements should have tests to verify them. On the other hand, I do not necessarily write tests to verify all contracts. In fact, some contracts cannot be easily tested while the code is correct, unless you use a powerful tool like TypeMock, to inject faulty code behavior.
You tell me I should not a call method without respecting the precondition. But how am I supposed to respect the precondition of don’t know what it is? Must always examine the code? Is there documentation available?
The code contracts team has been working on the documentation capabilities of the product. The one I go, they are building integration with Sandcastle. They are also working to embed XML comments associated with the contracts so that the contract information can appear as IntelliSense in Visual Studio to remind programmers of the contracts. The static analyzer can also help detect when you have failed to honor preconditions.
Oh, and of course you should also look at the method contracts of any method you are hoping to call, unless you are already familiar with the requirements of that method.
Can you put postconditions at the end of the method?
Then I will probably avoid using postconditions because it feels peculiar to put them at the beginning of the method.
I was surprised that somebody would avoid using postconditions simply because of the odd location. This is the second presentation where someone has expressed a dislike for the location of postconditions. I definitely would like to come up with a better answer or way to present the material so that users can feel better about the location of postconditions. In fact, I can now think of a better answer due to one of the earlier questions about documentation. “By putting the postconditions right underneath the preconditions, but all together at the top of the method, it makes it easier for a programmer to quickly review all of the contracts on a method in one place.” For me, you could put it sidewise and I would still use them. But I have a solid understanding of the theory too. If this is someone’s first introduction, they may be irked at a few things that seem odd.
I’m afraid to use postconditions. I fear that the impact on performance will be bad because of their complexity.
Remember, you can turn them off for release versions if they truly pose a performance issue. But keep in mind, it just because they are sometimes expensive, this does not mean that they will actually have a material impact on the performance of your application. So you should verify that before you turn them off.
At first, I was concerned that the participants would avoid using postconditions altogether because of their fear that the performance impact would grind their application to a screeching halt. But as I think about it more, each person has to decide for themselves whether their situation is sensitive to the performance impact of their contracts.
One strategy might be to include all the contracts in the initial release of the product, if adoption will be slow or controlled. In this scenario, the contracts would allow you to more easily diagnose unusual cases as the product experienced usage by a diverse number of end-users for the first time. Later, these uncommon defects have been repaired, and the product has demonstrated its stability and reliability, you could release a newer version with more limited contracts enabled.
Summary of Presentation
I was delighted with the quality of the questions, and the dialogue that followed. For those who are considering whether to give a presentation like this, I would like to summarize several common questions or concerns
- This code contracts stuff is intriguing, but there are so many things I have to learn. Why should I take my scarce time to pursue this?
- I am afraid that the use of contracts will introduce a performance penalty in my application.
- How do I integrate the practice of writing contracts with my practice of writing unit tests?
- I don’t like where the postconditions are located in the source code.
- What do you mean the static checker makes mistakes? I expect it to be as reliable as the compiler.
Those of us who use contracts on a regular basis know that there are good answers to each of these questions or comments. But I have not always been very articulate in answering them. If you have some different ideas on how to respond, I welcome your comments.