Microsoft Code Contracts

Post on 13-Jun-2015

897 views 0 download

description

Presentació que vaig donar al CodeCamp 2009 de Tarragona sobre Code Contracts!

Transcript of Microsoft Code Contracts

Code Contracts

Somos desarrolladores, no futbolistas… los contratos están para cumplirlos

Eduard Tomàseduard.tomas@raona.com

www.codecamp.es

Algunas cosillas a comentar…

• Introducción• Precondiciones• Postcondiciones• Invariantes• Métodos puros (pero no castos)• Sandcastle!

www.codecamp.es

Introducción

• Que es Code Contracts?– Actualmente… un proyecto de Microsoft Research– http://research.microsoft.com/en-us/projects/con

tracts/

– En un futuro… Parte integral de .NET 4.0• Aunque… la beta1 de VS2010 tiene una versión

desactualizada

• Última versión (hasta ahora): 03 Sep 2009.

www.codecamp.es

Introducción

• Para qué sirve Code Contracts?– Librería para poder especificar contratos en .NET– Independiente del lenguaje (C#, F#, VB.NET)– Basada en atributos

– Se puede instalar sobre VS2008 o sobre VS2010 Beta 1

www.codecamp.es

Introducción

• La evaluación de contratos NO está activa por defecto– Puede habilitarse para DEBUG y/o RELEASE

• Solo precondiciones• Solo precondiciones y postcondiciones• Todo

• También podemos especificar el comportamiento por defecto– Assert o excepción Contract.Exception

www.codecamp.es

Introducción

• Contratos– Permiten especificar• Precondiciones

• Postcondiciones

• Invariantes de objeto

www.codecamp.es

Precondiciones

• Condiciones que la llamada a un método debe satisfacer

• Si no se cumplen la llamada no es válida– No debería compilar

• El llamante debe poder comprobar que su llamada cumple las precondiciones– Debe conocerlas… y poderlas comprobar!

www.codecamp.es

Precondiciones

• Se representan mediante la llamada al método Contract.Requires.

• Si la condición especificada en Requires no se cumple, la precondición no és válida…

• … Ya, y entonces… ¿qué ocurre?– Por defecto: Assert o excepción

www.codecamp.es

Precondiciones

• Contract.Requires(condición)– Assert o lanza Contract.Exception si la condición

no se cumple– Nota: Contract.Exception es interna.

• Contract.Requires<TEx>(condición)– Assert o lanza TEx si condición no se cumple

www.codecamp.es

Precondiciones

• Cuantificadores– Especificar Contratos sobre elementos de una

colección• ForAll -> Se cumple si todos los elementos de la

colección cumplen una condición• Exists -> Se cumple el contrato si un elemento de la

colección cumple la condición

– Pero… ya tenemos Linq!

www.codecamp.es

Postcondiciones

• Se evalúan cuando se retorna de un método– Puede retornarse de un método de dos maneres• Correctamente (return o fin)• Por error (excepción)

– Puede haber precondiciones distintas en función de si se sale correctamente o por error.

www.codecamp.es

Postcondiciones

• Métodos – Contract.Ensures– Contract.EnsuresOnThrow<TEx>

– Assert o lanzan excepción ContractException si la postcondición no se cumple

www.codecamp.es

Postcondiciones

• Postcondiciones se colocan al principio del método…

• … pero se evalúan cuando se sale del método

• Problema: Como acceder al valor de retorno?

www.codecamp.es

Postcondiciones

• No compila porque Ensures no está al principio del método

• … pero si lo pongo al principio NO PUEDO acceder a ret, porque no está definida!– Contract.ReturnValue<T >

int Foo(int i) { Contract.Requires(i >= 0); var ret = i + 1; Contract.Ensures(ret > 0); return ret; }

www.codecamp.es

Invariantes

• La invariante es un conjunto de condiciones que deben cumplirse siempre en el ciclo de vida de un objeto

• Las invariantes se comprueban después de cada llamada a un método público del objeto

www.codecamp.es

Invariantes

• Se definen un método decorado con el atributo [ContractInvariantMethod]

– Lista de llamadas a Contract.Invariant con las condiciones a cumplir

www.codecamp.es

Interfaces

• Las interfaces pueden definir contratos– Las interfaces no pueden tener código…– … donde ponemos las llamadas a Contract?– En cada clase?• No porque entonces el contrato sería de cada clase, no

de la interfaz!

– Solución• Clase de contratos

www.codecamp.es

Interfaces

• Clase de contratos– Clase que implementa una interfaz de forma

explícita y contiene sólo los contratos para la interfaz

– Clases que implementan la interfaz no deben redefinir los contratos…

– Atributos [ContractClass] y [ContractClassFor] sirven para identificar la clase de contrato

www.codecamp.es

Métodos puros

• Un método puro es un método que no tiene efectos laterales visibles para el llamante– No modifican el estado del objeto

• Contract.Requires y Contract.Ensures pueden llamar a métodos, pero deben ser siempre métodos puros.

www.codecamp.es

Métodos puros

• Se consideran métodos puros– Getters de propiedades– Operadores– Cualquier método que pertenezca a las clases de• System.Diagnostics.Contracts.Contract• System.String• System.IO.Path• System.Type

– Cualquier método decorado con [Pure]

www.codecamp.es

Herencia de contratos

• Si una clase B es derivada de A los contratos definidos en A se aplican a B, y…

– Los métodos redefinidos en B no pueden añadir precondiciones

– Los métodos redefinidos en B si pueden añadir postcondiciones

– Los invariantes se heredan (en la clase B se comprueban los de A y B automáticamente).

www.codecamp.es

Análisis estático

• Existe una herramienta que realiza análisis estático de los contratos– Es una tarea compleja, y la mayoría de contratos

no pueden comprobarse en tiempo de compilación

www.codecamp.es

Custom Rewriter

• Usar un custom rewriter permite cambiar el comportamiento cuando un contrato no se cumple…– ... P.ej. Guardarlo en un log

• El custom rewriter es una clase estática pública que debe contener determinados métodos– Desde VS podemos indicar que custom rewriter

usar

www.codecamp.es

Custom Rewriter

• Métodos “comunes”– Requires -> Se ejecuta cuando se evalúa un

Requires– Requires<E> -> Se ejecuta cuando se evalúa un

Requires y no se lanzan Asserts– ReportFailure -> Se ejecuta cuando falla una

validación de contrato y debe reportarse el fallo

www.codecamp.es

Unit Tests y Contratos (i)

• Usar Contract.Requires y desmarcar la checkbox de Asserts – Se lanzarán ContractException– Poco interesante ya que• ContractException es privada, no podemos usar

[ExpectedException]

www.codecamp.es

Unit Tests y Contratos (ii)

• Usar Requires<TEx> en lugar de Requires– Podemos usar [ExpectedException] – Modificamos el comportamiento en run-time de

nuestros contratos – Funciona para precondiciones pero no para

postcondiciones ni invariantes

www.codecamp.es

Unit Tests y Contratos (iii)

• Usar ContractFailed– Evento que se lanza cuando falla un contrato– No modificamos el comportamiento en run-time

de nuestros contratos – Funciona para cualquier tipo de violación de

contrato

www.codecamp.es

Sandcastle

• Con la última versión (¡por fin!) podemos documentar los contratos!!!

• Code Contracts lleva un “parche” para SandCastle para entender nuevos tags xml relacionados con contratos…– <requires>, <ensures>, <pure>,….

¿Preguntas ?Estooo… pero facilillas, eh?? ;-)

Recuerda que en www.codecamp.es podrás encontrar todo el material de las sesiones del CodeCamp