4. Maintaining proper internal
state
Provider exposes ITrainScheduler
public interface ITrainScheduler
{
IList<Train> GetScheduledTrains(DateTime start, DateTime end);
void ScheduleTrain(string name, Route route);
}
As consumer
◦ Range of dates?
◦ Is there a max resultset?
◦ Can I provide an empty train name?
As provider
◦ Raise exceptions on invalid input?
◦ Debug.Assert to check internal state?
◦ Reusability??
5. Code Contracts to the rescue!
1 language agnostic API
◦ same API for C#, VB.NET, F#, …
◦ System.Diagnostics.Contracts
◦ mscorlib
Design By Contract
◦ Define expectations from caller
◦ Make promises
◦ Maintain constant proper internal state
Benefits:
◦ Testing (e.g. Pex)
◦ Documentation (e.g. SandCastle)
◦ Static checking
◦ Runtime checking
6. Very Basic concepts
Object
◦ State
◦ Behavior
Example: Dog
◦ State
◦ Age
◦ Name
◦ Color
◦ Behavior
◦ Bark
◦ Sit
◦ Drool
8. Contracts in real life
CUSTOMER
1) I want that new monitor
BIG MEDIASTORE EMPLOYEE
2) That’ll be 200€ please!
3) Thank you, your monitor will:
◦ Have a remote
◦ Be brand new
9. Preconditions before Code
Contracts
Validating input parameters
◦ If … throw ArgumentException
◦ Lots of documentation
◦ Caller doesn’t know about valid input
10. Preconditions with Code
Contracts
Validating input
◦ Validates state on method entry
◦ Burden on caller, so must be about state visible to caller
Contract.Requires(!string.IsNullOrEmpty(text));
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(text));
Legacy code
◦ Existing “If … then throw” can be integrated
◦ Contract.EndContractBlock();
11. Making promises
Postconditions
◦ Validates state on method exit
◦ Helper methods in Contracts assembly
◦ Result<T>
◦ OldValue<T>
◦ ValueAtReturn<T>
Contract.Ensures(trainCount >5);
Contract.Ensures(Contract.Result<Train>()!= null);
12. Maintaining proper state
Object Invariants
◦ Condition that holds at all (visible) time.
◦ On public method exits
[ContractInvariantMethod]
private void SomeMeaningfulName()
{
Contract.Invariant(CheckValidity());
}
13. Purity
All contract checks must have no visible side-effects to callers
Declare purity with [Pure] on
◦ Types
◦ Methods
Considered pure
◦ Implicit
◦ Property getters
◦ Operators
◦ Methods of immutable types
◦ Explicit
◦ Methods/Types declared pure
[Pure]
private bool CheckValidity(string text)
{
//logic here
}
14. Quantifiers
ForAll
◦ Condition must hold for all elements
Contract.Requires(Contract.ForAll(myEnumerable, x => x.IsValid));
Exists
◦ Condition must hold for at least one element
Contract.Requires(Contract.Exists(myEnumerable, x => x.IsChosen));
15. Asserting your state
Assert
◦ Condition must be valid
Contract.Assert(myValue == expectedValue);
Assume
◦ Runtime checker
◦ same as Contract.Assert
◦ Static checker
◦ Condition doesn’t have to be proven, it’s assumed to be true
Contract.Assume(myValue == expectedValue);
16. Debug.Assert vs
Contract.Assert
Debug.Assert
◦ Only in Debug builds
◦ No tools
◦ Works even with Code Contracts disabled
Contract.Assert
◦ Can work in release builds (configurable)
◦ Tools
◦ Does not work with Code Contracts disabled
19. Static Checking
Finds contract breaches before running
Can run in background
◦ Shows warnings for
◦ Unproven contracts
◦ Possible null references
◦ Possible out of bounds calls
◦ Redundant assumptions
◦ Implicit arithmetic obligations
20. Working with the static
checker
Can be overwhelming
Fix warnings
◦ Statistically provable
◦ Preconditions
◦ Postconditions
◦ Invariants
◦ Assumptions & Assertions
Baseline
◦ Exclude current warnings
◦ Export to file
21. Runtime Checking
On Failure:
◦ Throw ContractException
◦ Internal class
◦ “not catchable”…
◦ … except by catching general exception
◦ Assert on Failure
REMINDER: BEST PRACTICE
DO NOT CATCH GENERAL EXCEPTION
24. Contract Inheritance
Interface does not show you the behavior
Contracts are inherited
◦ Preconditions
◦ Can’t add extra ( Liskov Substition Principle )
◦ Postconditions & Invariants
◦ Can be made stronger
Making your interfaces/abstracts behave
[ContractClass(typeof(IFooContract))]
Dummy class, implementing interface
◦ Contracts in method body
[ContractClassFor(typeof(IFooContract))]
25. Usage in an existing project
Enable the baseline
◦ Stores all warnings during next run in an Xml file
◦ Warnings in the Xml file will not be shown again
27. Pex
Automated White Box Testing
◦ Parameterized Unit Tests
◦ Analyzes code under test
Analyzes Code Contracts
◦ 100% Code Contracts test coverage
◦ Tests target contract conditions
Suggests missing contracts
28. Sandcastle
MSDN style API documentation generation
◦ XML comments
◦ Enable XML documentation output
CodePlex
◦ Sandcastle
◦ Sandcastle Helpfile Builder
Includes contract documentation
29. Isolate Contracts in Seperate
Assembly
Option: generate a reference assembly
Ship when needed
◦ Limit product size
◦ Debugging
Generates <AssemblyName>.Contracts.dll
30. Future of Code Contracts
Usage
◦ Use it personally to document and test your code
◦ Great for interdeveloper use
Built-in support
◦ .NET 4.0 BCL behavior defined by Code Contracts
◦ Supported in Silverlight 4
◦ VS add-in
Third party tools supporting Code Contracts
◦ PEX, Sandcastle, Resharper
31. Resources
Code Contracts
◦ Official site
Pex
◦ Official site
◦ http://www.pexforfun.com
Sandcastle
◦ Official site
◦ Sandcastle Helpfile Builder
Expectations for Interfaces vsClasses
.NET interface’s don’t contain implementation details. But, isn’t the fact that a particular method’s argument and return value should never ever be null a concern of the interface definition and not the classes that implement it?
Code Contracts are checked in this sequence
CODESAMPLE:
Show if … throw argumentexception
Take note of the amount of documentation. ( this is a public api you’re writing )
Code Sample
CODE SAMPLE:
- show how to write postcondition
- Put emphasis on validating your own code
Worden in begin method geplaatst, check gebeurt wel degelijk op einde
Hoewel preconditions ( validating input ) gemakkelijk te implementeren is zonder Code Contracts, zijn postconditions moeilijker: oorspronkelijke waarden zelf bijhouden, wat bij foutieve staat, …
All preconditions and postconditions are expressed before the main
implementation in Code Contracts. The tools assume that anything that comes after
the last reference to Contract (apart from calls to Assert and Assume, which
we'll meet in a minute) is part of the implementation, but anything up to that point
is purely contractual and has no impact on the real work of the method. If you
mistakenly put a postcondition at the end of the method, Code Contracts will
complain of a "malformed contract."
Invariants are contracts about the state of the object
which should apply at all times that the state is visible. In other words, it's okay to
change an invariant while a public method in the class is running, but at the end of
the method the invariant should satisfied again.
Purity will be checked in the future
Contract.Assert versus Debug.Assert
- Release build kan Contract.Asserts bevatten (geen Debug.Asserts)
- Static / Runtime checker zoekt naar Contract.Asserts, niet naar Debug.Asserts
- Als Contracts disabled zijn, worden Debug.Asserts (in debug builds) wel nog uitgevoerd
Up until now, Code Contracts did not do anything. We just declared them, but as such, they do nothing.
It’s only with the Code Contract tools they actually do anything besides documenting your code.