Recently, I started to use Code contracts for .net. The idea of code contracts itself is great in my opinion, but the implementation is very unpleasant.
The main reasons I don't like it are:
Contract.Require()
inside my procedures. ContractAbbreviator
s have so many restrictions (like, I cannot put them in a separate assembly and I cannot use parameters) that it makes them less usable. There are no attributes, and no extension methods, so my code becomes very verbose. For example, if I just want to check that my return value of type Dictionary<string, string>
is not null, I need to add a monster such as Contract.Ensure(Contract.Result<Dictionary<string, string>> != null)
. It's not even readable.ccrewriter
—it cannot chew half of assemblies, and it cannot survive .net 4.0 assemblies in the .net 4.5 runtime.Debug.Assert
—you just add them everywhere you feel you need. But it turns out that I need to prove everything to the static checker, which is advanced, for sure, but the checker is stupid sometimes and can't resolve many obvious code constructions (like while
). And there's no instrument to just say to the analyzer "I know what I'm doing, just ignore this contract violation".string.NotNullOrEmpty
this includes string != null
. Or if I have my own big procedure checking a file path, I cannot explain to the analyzer that it's for sure not null and not empty. The ContractAbbreviator
attributes help a little bit, but all this verbosity goes there and it still looks dirty and stupid.Is there any advanced alternative to Code Contracts which has fewer flaws?
I don't know of any alternatives, but I perhaps I can address a few of your issues. I work in a team that uses contracts in all our code (~1000 modules) and run static analysis on every checkin as well as in VS.
Code ugliness. We have separate interfaces for (almost) everything, along with abstract classes implementing those, joined by ContractClass and ContractClassFor attributes. The contracts are in the abstract ContractClassFor-classes which makes the actual implementation code almost free from code contracts.
Static analyzer slowness is often due to not enough contracts, which forces the analyzer to do more work to find out if contracts can be broken.
Static checker false Alarms. I have had a few, but not to an extent where it has become a problem. Again, if you have too few contracts, the static checker might not be able to complete the analysis in time.
Static analyzer slowness can be debugged with these MSBuild options, which will show which methods take the most time to analyze.
msbuild myproject.sln /p:CodeContractsExtraAnalysisOptions="-show progress -stats=!! -stats slowMethods"
If you're certain that some condition always holds, then you can use Contract.Assume(condition) to instruct the static checker to assume that this is the case. Eg.
Contract.Assume(mystring != null && mystring != "")
or maybe just Contract.Assume(!string.IsNullOrEmpty(mystring))
Regarding the use of Debug.Assert, I think it's a huge advantage to have the static checking instead of just making my application crash at the customers site. This way, I can remove the risk of having the application crash before I release the product. Maybe I misunderstand you, but I really don't think your comparison makes sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With