code contract

39
CODE CONTRACT Larry Nung

Upload: larry-nung

Post on 14-Jun-2015

122 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Code contract

CODE CONTRACTLarry Nung

Page 2: Code contract

AGENDA

IntroductionDesign By Contract(DbC)

Code Contract

ContractsPreconditions

Postconditions

Object Invariants

Contract.Assert & Contract.Assume

Contract.ForAll & Contract.Exists

Interface & Abstract Method Contracts

Contract Reference Assembly

ReferenceQ & A

Page 3: Code contract

INTRODUCTION

Page 4: Code contract

Design By Contract(DbC) 要求軟體設計者為軟體組件定義正式的,精

確的並且可驗證的介面。 明確描述雙方的權利與義務。 降低程式的錯誤發生率。 提高程式的品質。

Page 5: Code contract

提升自動測試程度

CODE CONTRACT

Page 6: Code contract

提升自動測試程度

靜態驗證

CODE CONTRACT

Page 7: Code contract

提升自動測試程度

靜態驗證

執行階段驗證

CODE CONTRACT

Page 8: Code contract

提升自動測試程度

靜態驗證

執行階段驗證

文件產生

CODE CONTRACT

Page 9: Code contract

CODE CONTRACT

可以透過設定啟用 / 關閉 Intellisense 提示強化

Page 10: Code contract

CODE CONTRACT

Framewrok 4.0+

Namespace System.Diagnostics.Contracts

Assemble

Page 11: Code contract

CODE CONTRACT

Page 12: Code contract

CODE CONTRACT

void Test(List<object> array, int index, object value) { Contract.Requires(index >= 0); Contract.Ensures(array.Count == Contract.OldValue(array.Count) + 1); array.Insert(index, value); }

Page 13: Code contract

CODE CONTRACTprivate void Test(List<object> array, int index, object value){

List<object> Contract.Old(array);

int Contract.Old(Count); __ContractsRuntime.Requires(index >= 0, null, "index >= 0");

try {

Contract.Old(array) = array;

} catch (Exception exception1) {

if (exception1 == null) { throw; }

}

try {

Contract.Old(Count) = array.Count;

} catch (Exception exception2) {

if (exception2 == null) { throw; }

}

array.Insert(index, value);

if (__ContractsRuntime.insideContractEvaluation <= 4) {

try {

__ContractsRuntime.insideContractEvaluation++;

__ContractsRuntime.Ensures(Contract.Old(array).Count == (Contract.Old(Count) + 1), null, "array.Count == Contract.OldValue(array.Count) + 1");

} finally {

__ContractsRuntime.insideContractEvaluation--;

}

}

}

Page 14: Code contract

CONTRACTS

Page 15: Code contract

PRECONDITIONS

用來驗證進入方法或是屬性時所必須滿足的需求條件

使用 Contract.Requires 方法表示

Contract.Requires(x != null );

Contract.Requires<ArgumentNullException>(x != null, "x is null");

if(x == null) throw new ArguementNullException(); Contract.EndContractBlock();

Page 16: Code contract

POSTCONDITIONS

用來驗證方法或屬性中止時所需滿足的需求條件

標準後置條件

Contract.Ensures( this .F > 0 );

例外後置條件

Contract.EnsuresOnThrow<T>( this.F > 0 );

Page 17: Code contract

POSTCONDITIONS

特殊後置條件 ( 方法傳回值、前置狀態值、與輸出參數 )

Contract.Ensures(0 < Contract.Result<int>());

void IArray.Insert(int index, Object value){ Contract.Requires(index >= 0); Contract.Requires(index <=

((IArray)this).Count); Contract.Ensures(((IArray)this).Count ==

Contract.OldValue(((IArray)this).Count) + 1); }

Page 18: Code contract

POSTCONDITIONS

前置狀態值不得參考方法的傳回值與用傳址方式帶入的參數

Contract.OldValue(Contract.Result<int>() + x) // ERROR

如數量詞範圍相依於方法傳回值,前置狀態值不得相依於數量詞的繫結變數

Contract. ForAll (0,Contract. Result<int>(),i => Contract.OldValue(xs[i]) > 3 ); // ERROR

Page 19: Code contract

POSTCONDITIONS

除 ForAll 或 Exists 外,前置狀態值不得出現在匿名委派的主體中

Method( ... (T t) => Contract.OldValue(... t ...) ... ); // ERROR

前置狀態值除非是當方法呼叫的索引子或引數使用,否則不得在 ForAll 或 Exists 呼叫中參考匿名委派的參數

Contract. ForAll (0, xs .Length, i => Contract.OldValue(xs[i]) > 3); // OK

Contract. ForAll (0, xs .Length, i => Contract.OldValue(i) > 3 ); // ERROR

Page 20: Code contract

OBJECT INVARIANTS

用來驗證總是需要滿足的不變條件

使用 ContractInvariantMethodAttribute  屬性搭配Contract .Invariant 去做驗證

public int MyProperty { get; set; } …[ContractInvariantMethod] void ObjectInvariant() { Contract.Invariant(MyProperty >= 0); }

Page 21: Code contract

OBJECT INVARIANTS

Page 22: Code contract

OBJECT INVARIANTSpublic int MyProperty

{

[CompilerGenerated]

get

{

int Contract.Result = this.<MyProperty>k__BackingField;

if (!this.$evaluatingInvariant$)

{

__ContractsRuntime.Ensures(Contract.Result >= 0, null, "MyProperty >= 0");

}

return Contract.Result;

}

[CompilerGenerated]

set

{

if (!this.$evaluatingInvariant$)

{

__ContractsRuntime.Requires(value >= 0, null, "MyProperty >= 0");

}

this.<MyProperty>k__BackingField = value;

if (!this.$evaluatingInvariant$) { }

this.$InvariantMethod$();

}

}

Page 23: Code contract

CONTRACT.ASSERT & CONTRACT.ASSUME

Contract.Assert(this.privateField > 0);

Contract.Assert(this.x == 3, "Why isn't the value of x 3?");

Page 24: Code contract

CONTRACT.ASSERT & CONTRACT.ASSUME

Contract.Assume(this.privateField > 0);

Contract.Assume(this.x == 3, "Static checker assumed this");

Page 25: Code contract

CONTRACT.FORALL & CONTRACT.EXISTS

public int Foo<T>(IEnumerable<T> xs){

Contract.Requires(Contract.ForAll (xs , x => x != null) );

}

public int Foo<T>(T[] xs){

Contract. Requires ( Contract.ForAll (0,xs.Length,index => xs[index] != null));

}

Page 26: Code contract

CONTRACT.FORALL & CONTRACT.EXISTS

public int Foo<T>(IEnumerable<T> xs){

Contract.Requires(Contract.Exists(xs , x => x != null) );

}

Page 27: Code contract

INTERFACE & ABSTRACT METHOD CONTRACTS

Page 28: Code contract

INTERFACE & ABSTRACT METHOD CONTRACTS[ContractClass(typeof(IFooContract))]

interface IFoo {

int Count { get; }

void Put(int value);

}

[ContractClassFor(typeof(IFoo))]

abstract class IFooContract : IFoo {

int IFoo.Count {

get {

Contract.Ensures(0 <= Contract.Result<int>());

return default(int); // dummy return

}

}

void IFoo.Put(int value) {

Contract.Requires(0 <= value);

}

}

Page 29: Code contract

INTERFACE & ABSTRACT METHOD CONTRACTS[ContractClass(typeof(FooContract))]

abstract class Foo {

public abstract int Count { get; }

public abstract void Put(int value);

}

[ContractClassFor(typeof(Foo))]

abstract class FooContract : Foo {

public override int Count {

get {

Contract.Ensures(0 <= Contract.Result<int>());

return default(int); // dummy return

}

}

public override void Put(int value) {

Contract.Requires(0 <= value);

}

}

Page 30: Code contract

CONTRACT REFERENCE ASSEMBLY

Page 31: Code contract

CONTRACT REFERENCE ASSEMBLY

Page 32: Code contract

CONTRACT REFERENCE ASSEMBLY

Page 33: Code contract

CONTRACT REFERENCE ASSEMBLY

Page 34: Code contract

REFERENCE

Page 35: Code contract

REFERENCE

Code Contracts (1) - 概念與簡介 https://

msdn.microsoft.com/zh-tw/library/dn606159.aspx Code Contracts (2) - 三大合約

https://msdn.microsoft.com/zh-tw/library/dn606157.aspx

Code Contracts (3) - Contract.Assert & Contract.Assume https://

msdn.microsoft.com/zh-tw/library/dn606156.aspx

Page 36: Code contract

REFERENCE

Code Contracts (4) - Contract.ForAll & Contract.Exists https://

msdn.microsoft.com/zh-tw/library/dn606166.aspx Code Contracts (5) - 介面合約與抽象方法合約

https://msdn.microsoft.com/zh-tw/library/dn722305.aspx

Code Contracts (6) - Contract Reference Assembly https://msdn.microsoft.com/zh-tw/library/dn7223

06.aspx

Page 37: Code contract

Q&A37

Page 38: Code contract

QUESTION & ANSWER

38

Page 39: Code contract

THE END