FEN UCN T&B - PBA/CodeContract- Intro 1 Code Contract Introduction Specification of a Person Class
Installation Download from this URL: FEN UCN T&B - PBA/CodeContract-Intro2 Choose ‘Premium Edition’ Download the documentation Install the plug-in and open Visual Studio
Visual Studio Use this namespace Add a reference (right- click on the project) to Microsoft.Contracts FEN UCN T&B - PBA/CodeContract-Intro3
Right-click on the project and choose ‘Properties’, then choose ‘ Code Contracts’ FEN UCN T&B - PBA/CodeContract-Intro4
FEN UCN T&B - PBA/CodeContract-Intro5 class Person { private String name; private int weight; public int Weight { get; private set; } [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(!name.Equals("") && weight >= 0); } [Pure] public override String ToString() { Contract.Ensures( Contract.Result () != null); return "Person(\"" + name + "\"," + weight + ")"; } [Pure] public int GetWeight() { Contract.Ensures(Contract.Result () == weight); return weight; } public void AddKgs(int kgs) { Contract.Requires(kgs >= 0); Contract.Requires(weight+kgs >= 0); Contract.Ensures(weight == Contract.OldValue(weight) + kgs); weight = weight + kgs; } public Person(String n) { Contract.Requires(n != null && !n.Equals("")); Contract.Ensures(n.Equals(name) && weight == 0); name = n; weight = } Specification and implementation are bundled together. This is not nice!!!
FEN UCN T&B - PBA/CodeContract-Intro6 Separate specification and implementation [ContractClass(typeof(IPersonContract))] interface Iperson { /// also ensures \result != null; /// [Pure] String ToString(); /// ensures \result >= 0; /// [Pure] //Contract.Ensures(Contract.Result () >= 0); int GetWeight(); /// /// requires kgs >= 0; ensures getWeight() == (\old(getWeight()) + kgs); /// void AddKgs(int kgs); } What we would like: Specification in an interface But specs in Code Contract are method calls, and method calls are not allowed in interfaces...? Telling that here is a contract
FEN UCN T&B - PBA/CodeContract-Intro7 [ContractClassFor(typeof(IPerson))] internal abstract class IPersonContract : IPerson { [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(GetWeight() >= 0); } public override String ToString() { Contract.Ensures(Contract.Result () != null); return default(string); } public int GetWeight() { Contract.Ensures(Contract.Result () >=0); return default(int); } public void AddKgs(int kgs) { Contract.Requires(kgs >= 0); Contract.Requires(GetWeight()+kgs >= 0); Contract.Ensures(GetWeight() == Contract.OldValue(GetWeight()) + kgs); } Spec in internal abstract class with dummy implementation interface Iperson { [Pure] String ToString(); int GetWeight(); void AddKgs(int kgs); } Type invariant
FEN UCN T&B - PBA/CodeContract-Intro8 class Person: Iperson { [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(!name.Equals("“) && name!= null && weight >= 0); } private String name; private int weight; public Person(String n) { Contract.Requires(n != null&& !n.Equals("")); Contract.Ensures(n.Equals(name) && weight == 0); name = n; weight = 0; } Implementation in the class Representation invariant public override String ToString() { Contract.Ensures(Contract.Result ()!= null); return "Person(\"" + name + "\"," + weight + ")"; } public int GetWeight() { Contract.Ensures(Contract.Result () == weight); return weight; } public void AddKgs(int kgs) { Contract.Ensures(weight == Contract.OldValue(weight) + kgs); weight = weight + kgs; } Constructor must establish the invariant
FEN UCN T&B - PBA/CodeContract-Intro9 static void Main(string[] args) { IPerson p = new Person("Kurt"); Console.WriteLine(p.ToString()); p.AddKgs(99); Console.WriteLine("GetWeight: "+p.GetWeight()); Console.WriteLine(p.ToString()); Console.ReadLine(); p.AddKgs(-9); Console.ReadLine(); Console.WriteLine(p.ToString()); IPerson pp = new Person(""); Console.WriteLine(pp.ToString()); Console.ReadLine(); } interface as static type class as dynamic type