Upload
eduard-tomas
View
895
Download
0
Embed Size (px)
DESCRIPTION
Presentació que vaig donar al CodeCamp 2009 de Tarragona sobre Code Contracts!
Citation preview
Code Contracts
Somos desarrolladores, no futbolistas… los contratos están para cumplirlos
Eduard Tomà[email protected]
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