miniatura|Un esquema de disseny per contracte El disseny per contracte (DbC), també conegut com a programació per contracte, programació per contracte i programació disseny per contracte, és un enfocament per dissenyar programari.

Prescribeix que els dissenyadors de programari defineixin especificacions d'interfície formals, precises i verificables per als components de programari, que ampliïn la definició ordinària de tipus de dades abstractes amb precondicions, postcondicions i invariants. Aquestes especificacions s'anomenen "contractes", d'acord amb una metàfora conceptual amb les condicions i obligacions dels contractes comercials.

L'enfocament DbC assumeix que tots els components del client que invoquen una operació en un component del servidor compliran les condicions prèvies especificades com a necessàries per a aquesta operació.

Quan aquesta suposició es considera massa arriscada (com en la computació multicanal o distribuïda), s'adopta l'enfocament invers, és a dir, que el component del servidor comprova que totes les condicions prèvies rellevants siguin certes (abans o mentre es processa la sol·licitud del component del client) i respon amb un missatge d'error adequat si no és així.

Història El terme va ser encunyat per Bertrand Meyer en relació amb el seu disseny del llenguatge de programació Eiffel i descrit per primera vegada en diversos articles a partir del 1986 i les dues edicions successives (1988, 1997) del seu llibre Object-Oriented Software Construction. Eiffel Software va sol·licitar el registre de marca per a Design by Contract el desembre de 2003, i li va ser concedit el desembre de 2004. L'actual propietari d'aquesta marca és Eiffel Software.

El disseny per contracte té les seves arrels en el treball sobre verificació formal, especificació formal i lògica de Hoare. Les contribucions originals inclouen:

Una metàfora clara per guiar el procés de disseny L'aplicació a l'herència, en particular un formalisme per a la redefinició i l'enllaç dinàmic L'aplicació a la gestió d'excepcions La connexió amb la documentació automàtica de programari

Descripció La idea central del DbC és una metàfora sobre com els elements d'un sistema de programari col·laboren entre si sobre la base d' obligacions i beneficis mutus. La metàfora prové de la vida empresarial, on un "client" i un "proveïdor" acorden un "contracte" que defineix, per exemple, que:

El proveïdor ha de subministrar un determinat producte (obligació) i té dret a esperar que el client hagi pagat la seva tarifa (benefici). El client ha de pagar la tarifa (obligació) i té dret a obtenir el producte (benefici). Ambdues parts han de complir certes obligacions, com ara lleis i reglaments, que s'apliquen a tots els contractes.

De la mateixa manera, si el mètode d'una classe en programació orientada a objectes proporciona una determinada funcionalitat, pot:

Espereu que qualsevol mòdul client que el cridi garanteixi una determinada condició en entrar-hi: la precondició del mètode, una obligació per al client i un benefici per al proveïdor (el mètode en si), ja que l'allibera de la gestió de casos fora de la precondició. Garantir una determinada propietat a la sortida: la postcondició del mètode —una obligació per al proveïdor i, òbviament, un benefici (el principal benefici de cridar el mètode) per al client. Mantenir una determinada propietat, assumida a l'entrada i garantida a la sortida: la invariant de classe.

El contracte és semànticament equivalent a una tripleta de Hoare que formalitza les obligacions. Això es pot resumir amb les "tres preguntes" que el dissenyador ha de respondre repetidament en el contracte:

Què espera el contracte? Què garanteix el contracte? Què manté el contracte?

Molts llenguatges de programació tenen eines per fer assercions com aquestes. Tanmateix, DbC considera que aquests contractes són tan crucials per a la correcció del programari que haurien de formar part del procés de disseny. De fet, DbC defensa escriure primer les assercions. Els contractes es poden escriure mitjançant comentaris de codi, aplicats per un conjunt de proves o ambdues coses, fins i tot si no hi ha cap suport lingüístic especial per als contractes.

La noció de contracte s'estén fins al nivell del mètode/procediment; el contracte per a cada mètode normalment contindrà la informació següent:

Valors o tipus d'entrada acceptables i inacceptables, i els seus significats

Valors o tipus de retorn i els seus significats

Valors o tipus de condicions d'error i excepció que es poden produir i els seus significats

Efectes secundaris

Condicions prèvies

Postcondicions

Invariants

(més rarament) Garanties de rendiment, p. ex., pel temps o l'espai utilitzats

Les subclasses d'una jerarquia d'herència poden debilitar les precondicions (però no enfortir-les) i enfortir les postcondicions i els invariants (però no debilitar-los). Aquestes regles s'aproximen a la subtipificació comportamental.

Totes les relacions de classe són entre classes client i classes proveïdor. Una classe client està obligada a fer crides a les característiques del proveïdor on l'estat resultant del proveïdor no sigui violat per la crida del client. Posteriorment, el proveïdor està obligat a proporcionar un estat de retorn i dades que no infringeixin els requisits d'estat del client.

Per exemple, una memòria intermèdia de dades d'un proveïdor pot requerir que les dades siguin presents a la memòria intermèdia quan es crida una funció d'eliminació. Posteriorment, el proveïdor garanteix al client que quan una funció d'eliminació acabi la seva feina, l'element de dades s'eliminarà, efectivament, de la memòria intermèdia. Altres contractes de disseny són conceptes d'invariant de classe. L'invariant de classe garanteix (per a la classe local) que l'estat de la classe es mantindrà dins de les toleràncies especificades al final de cada execució de la funció.

Quan s'utilitzen contractes, un proveïdor no hauria d'intentar verificar que es compleixen les condicions del contracte (una pràctica coneguda com a programació ofensiva), la idea general és que el codi hauria de "fallar completament", amb la verificació del contracte com a xarxa de seguretat.

La propietat "fail hard" de DbC simplifica la depuració del comportament dels contractes, ja que el comportament previst de cada mètode està clarament especificat.

Aquest enfocament difereix substancialment del de la programació defensiva, on el proveïdor és responsable d'esbrinar què fer quan es trenca una precondició. Molt sovint, el proveïdor genera una excepció per informar al client que la precondició s'ha trencat, i en ambdós casos (tant en DbC com en programació defensiva) el client ha d'esbrinar com respondre-hi. En aquests casos, DbC facilita la feina del proveïdor.

El disseny per contracte també defineix els criteris de correcció d'un mòdul de programari:

Si la precondició I l'invariant de la classe són certes abans que un client cridi un proveïdor, aleshores l'invariant I la postcondició seran certes després que s'hagi completat el servei. Quan es fan trucades a un proveïdor, un mòdul de programari no ha de violar les condicions prèvies del proveïdor.

El disseny per contracte també pot facilitar la reutilització de codi, ja que el contracte per a cada fragment de codi està completament documentat. Els contractes per a un mòdul es poden considerar com una forma de documentació de programari per al comportament d'aquest mòdul.

El disseny per contracte pot tenir un aspecte semblant a aquest:int f(const int x) pre(x != 1) // a precondition assertion post(r : r == x && r != 2) // a postcondition assertion; r names the result object of f { contract_assert(x != 3); // an assertion statement return x; }

Implicacions de rendiment Les condicions contractuals no s'haurien de violar mai durant l'execució d'un programa sense errors. Per tant, els contractes normalment només es comproven en mode de depuració durant el desenvolupament del programari. Més tard, en el llançament, les comprovacions de contractes es desactiven per maximitzar el rendiment.

En molts llenguatges de programació, els contractes s'implementen amb assert. Les assercions es compilen per defecte en mode de llançament en C/C++, i de manera similar es desactiven en C# i Java.

Si s'inicia l'intèrpret de Python amb "-O" (per a "optimitzar") com a argument, el generador de codi Python tampoc emetrà cap bytecode per a les assercions.

Això elimina eficaçment els costos d'execució de les assercions en el codi de producció, independentment del nombre i la despesa computacional de les assercions utilitzades en el desenvolupament, ja que el compilador no inclourà aquestes instruccions en la producció.

Referències

Categoria:Programari Categoria:Desenvolupament de programari