CodeContracts permite especificar contratos (precondiciones, postcondiciones e invariantes) en .NET para documentar y verificar el comportamiento de métodos y clases. Estos contratos se definen mediante atributos y pueden evaluarse en tiempo de ejecución o compilación para validar el código. Las interfaces también pueden definir contratos a través de clases de contrato. La herramienta admite análisis estático, pruebas unitarias y documentación de contratos.
2. Algunas cosillas a comentar… Introducción Precondiciones Postcondiciones Invariantes Métodos puros (pero no castos) Sandcastle!
3. Introducción Que es CodeContracts? Actualmente… un proyecto de Microsoft Research http://research.microsoft.com/en-us/projects/contracts/ 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.
4. Introducción Para qué sirve CodeContracts? 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
5. 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
7. 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!
8. 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
9. 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
10. 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!
11. 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.
12. Postcondiciones Métodos Contract.Ensures Contract.EnsuresOnThrow<TEx> Assert o lanzan excepción ContractException si la postcondición no se cumple
13. 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?
14. Postcondiciones intFoo(int i) { Contract.Requires(i >= 0); varret = i + 1; Contract.Ensures(ret > 0); returnret; } 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 >
15. 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
16. Invariantes Se definen un método decorado con el atributo [ContractInvariantMethod] Lista de llamadas a Contract.Invariant con las condiciones a cumplir
17. 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
18. 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
19. 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.Ensurespueden llamar a métodos, pero deben ser siempre métodos puros.
20. 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]
21. 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).
22. 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
23. CustomRewriter Usar un customrewriter permite cambiar el comportamiento cuando un contrato no se cumple… ... P.ej. Guardarlo en un log El customrewriter es una clase estática pública que debe contener determinados métodos Desde VS podemos indicar que customrewriter usar
24. CustomRewriter 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
25. UnitTests 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]
26. UnitTests 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
27. UnitTests 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
28. Sandcastle Con la última versión (¡por fin!) podemos documentar los contratos!!! CodeContracts lleva un “parche” para SandCastle para entender nuevos tagsxml relacionados con contratos… <requires>, <ensures>, <pure>,….
29. ¿Preguntas ?Estooo… pero facilillas, eh?? ;-) Recuerda que en www.codecamp.es podrás encontrar todo el material de las sesiones del CodeCamp