Programmēšana

iContract: Projektēšana pēc līguma Java

Vai nebūtu jauki, ja visas jūsu izmantotās Java klases, ieskaitot jūsu pašu, izpildītu viņu solījumus? Patiesībā, vai tas nebūtu jauki, ja jūs tiešām zinātu, ko konkrētā klase sola? Ja piekrītat, lasiet tālāk - Palīdzēs noformējums pēc līguma un iContract.

Piezīme: Šī raksta piemēru koda avotu var lejupielādēt no resursiem.

Projektēšana pēc līguma

Programmas Design by Contract (DBC) programmatūras izstrādes tehnika nodrošina augstas kvalitātes programmatūru, garantējot, ka katrs sistēmas komponents attaisno cerības. Kā izstrādātājs, kas izmanto DBC, jūs norādāt komponentu līgumiem kā komponenta saskarnes daļu. Līgumā ir norādīts, ko šī sastāvdaļa sagaida no klientiem un ko klienti no tā var sagaidīt.

Bertrands Mejers izstrādāja DBC kā daļu no savas Eifeļa programmēšanas valodas. Neatkarīgi no izcelsmes DBC ir vērtīgs dizaina paņēmiens visām programmēšanas valodām, ieskaitot Java.

DBC centrā ir jēdziens apgalvojums - Būla izteiksme par programmatūras sistēmas stāvokli. Izpildes laikā mēs novērtējam apgalvojumus noteiktos kontrolpunktos sistēmas izpildes laikā. Derīgā programmatūras sistēmā visi apgalvojumi atbilst patiesībai. Citiem vārdiem sakot, ja kāds apgalvojums tiek uzskatīts par nepatiesu, mēs uzskatām, ka programmatūras sistēma ir nederīga vai bojāta.

DBC centrālais jēdziens nedaudz attiecas uz # asert makro C un C ++ programmēšanas valodā. Tomēr DBC apgalvojumus paņem ziljonu līmeni tālāk.

DBC mēs identificējam trīs dažādus izteicienu veidus:

  • Priekšnoteikumi
  • Pēcnosacījumi
  • Varianti

Apskatīsim katru sīkāk.

Priekšnoteikumi

Priekšnosacījumi norāda nosacījumus, kas jāievēro, pirms metodi var izpildīt. Kā tādus tie tiek novērtēti tieši pirms metodes izpildes. Priekšnoteikumi ietver sistēmas stāvokli un metodē nodotos argumentus.

Priekšnosacījumi nosaka pienākumus, kas programmatūras komponenta klientam jāizpilda, pirms tas var izmantot noteiktu komponenta metodi. Ja priekšnosacījums neizdodas, programmatūras komponenta klientā ir kļūda.

Pēcnosacījumi

Turpretī pēcnosacījumi nosaka nosacījumus, kas jāievēro pēc metodes pabeigšanas. Līdz ar to pēcnosacījumi tiek izpildīti pēc metodes pabeigšanas. Pēcnosacījumi ietver veco sistēmas stāvokli, jauno sistēmas stāvokli, metodes argumentus un metodes atgriešanās vērtību.

Pēcnosacījumi nosaka garantijas, ko programmatūras komponents sniedz saviem klientiem. Ja tiek pārkāpts pēcnosacījums, programmatūras komponentā ir kļūda.

Varianti

Nemainīgais norāda nosacījumu, kas jāievēro, kad klients var atsaukties uz objekta metodi. Invarianti tiek definēti kā daļa no klases definīcijas. Praksē invarianti tiek novērtēti jebkurā laikā pirms un pēc katras klases instances izpildes. Invariāta pārkāpums var norādīt uz kļūdu klientā vai programmatūras komponentā.

Apgalvojumi, mantojums un saskarnes

Visi apgalvojumi, kas norādīti klasei un tās metodēm, attiecas arī uz visām apakšklasēm. Varat arī norādīt apgalvojumus saskarnēm. Tādējādi visiem saskarnes apgalvojumiem ir jāatbilst visām klasēm, kuras ievieš saskarni.

iContract - DBC ar Java

Līdz šim mēs runājām par DBC kopumā. Jums, iespējams, jau ir kāda ideja, par ko es runāju, bet, ja jūs esat jauns DBC lietotājs, viss joprojām var būt nedaudz miglains.

Šajā sadaļā viss kļūs konkrētāks. Reto Kamer izstrādātais iContract Java pievieno konstrukcijas, kas ļauj norādīt DBC apgalvojumus, par kuriem runājām iepriekš.

iContract pamati

iContract ir Java priekšapstrādātājs. Lai to izmantotu, vispirms jāapstrādā Java kods ar iContract, izveidojot dekorētu Java failu kopu. Tad jūs apkopojat dekorēto Java kodu kā parasti ar Java kompilatoru.

Visas iContract direktīvas Java kodā atrodas klases un metožu komentāros, tāpat kā Javadoc direktīvas. Tādā veidā iContract nodrošina pilnīgu savietojamību ar esošo Java kodu, un jūs vienmēr varat tieši sastādīt savu Java kodu bez iContract apgalvojumiem.

Parastajā programmas dzīves ciklā jūs pārvietojat sistēmu no izstrādes vides uz testa vidi, pēc tam uz ražošanas vidi. Izstrādes vidē jūs varētu instrumentēt savu kodu ar iContract apgalvojumiem un palaist to. Tādā veidā jūs varat noķert nesen ieviestās kļūdas agri. Pārbaudes vidē, iespējams, vēlēsities atstāt lielāko daļu apgalvojumu iespējotiem, taču jums vajadzētu tos izslēgt no veiktspējas kritiskajām klasēm. Dažreiz ir lietderīgi paturēt dažus apgalvojumus iespējotus ražošanas vidē, bet tikai klasēs, kas noteikti nekādā ziņā nav kritiskas jūsu sistēmas veiktspējai. iContract ļauj skaidri atlasīt klases, kuras vēlaties izmantot ar apgalvojumiem.

Priekšnoteikumi

Programmā iContract jūs ievietojat priekšnoteikumus metodes galvenē, izmantojot @pre direktīvu. Lūk, piemērs:

/ ** * @pre f> = 0.0 * / public float sqrt (float f) {...} 

Priekšnosacījuma piemērs nodrošina, ka arguments f funkcijas sqrt () ir lielāks vai vienāds ar nulli. Klienti, kuri izmanto šo metodi, ir atbildīgi par šī priekšnoteikuma ievērošanu. Ja viņi to nedara, mēs kā sqrt () vienkārši nav atbildīgi par sekām.

Izteiksme pēc @pre ir Java Būla izteiksme.

Pēcnosacījumi

Postconditions tiek pievienoti arī galvenes komentāram par metodi, kurai tie pieder. Programmā iContract @post Direktīva nosaka pēcnosacījumus:

/ ** * @pre f> = 0.0 * @post Math.abs ((return * return) - f) <0.001 * / public float sqrt (float f) {...} 

Šajā piemērā mēs esam pievienojuši pēcnosacījumu, kas nodrošina, ka sqrt () metode aprēķina kvadrātsakni f noteiktā kļūdas robežās (+/- 0,001).

iContract ievieš dažus īpašus apzīmējumus postconditions. Pirmkārt, atgriešanās apzīmē metodes atgriešanās vērtību. Izpildes laikā to aizstās ar metodes atgriešanās vērtību.

Pēcnosacījumos bieži vien ir jānošķir argumenta vērtība pirms metodes izpilde un pēc tam, ko atbalsta iContract ar @pre operators. Ja jūs pievienojat @pre izteiksmei pēcnosacījumā, pirms metodes izpildes tā tiks novērtēta, pamatojoties uz sistēmas stāvokli:

/ ** * Pievienojiet kolekcijai elementu. * * @post c.size () = [email protected] () + 1 * @post c.contains (o) * / public void append (Collection c, Object o) {...} 

Iepriekš pievienotajā kodā pirmais pēcnosacījums norāda, ka, pievienojot elementu, kolekcijas lielumam jāaug par 1. Izteiksme c @ pre attiecas uz kolekciju c pirms pievienot metodi.

Varianti

Izmantojot iContract, klases definīcijas galvenes komentārā var norādīt invariantus:

/ ** * Pozitīvais skaitlis ir vesels skaitlis, kas tiek garantēts kā pozitīvs. * * @inv intValue ()> 0 * / klase PositiveInteger paplašina veselu skaitli {...} 

Šajā piemērā nemainīgais garantē, ka Pozitīvais skaitlisvērtība vienmēr ir lielāka vai vienāda ar nulli. Šis apgalvojums tiek pārbaudīts pirms un pēc jebkuras šīs klases metodes izpildes.

Objekta ierobežojuma valoda (OCL)

Lai gan iContract apgalvojuma izteiksmes ir derīgas Java izteiksmes, tās tiek modelētas pēc objektu ierobežojumu valodas (OCL) apakškopas. OCL ir viens no standartiem, ko uztur un koordinē Object Management Group jeb OMG. (OMG rūpējas par CORBA un ar to saistītajām lietām, ja jums pietrūkst savienojuma.) OCL bija paredzēts noteikt ierobežojumus objektu modelēšanas rīkos, kas atbalsta vienoto modelēšanas valodu (UML), citu OMG sargātu standartu.

Tā kā iContract izteicienu valoda tiek modelēta pēc OCL, tā nodrošina dažus uzlabotus loģiskos operatorus, kas pārsniedz pašas Java loģiskos operatorus.

Kvantifikatori: visi un pastāv

iContract atbalsta visiem un pastāv kvantifikatori. The visiem kvantifikators norāda, ka nosacījumam jāatbilst katram kolekcijas elementam:

/ * * @invariant forall IEmployee e in getEmployees () | * getRooms (). satur (e.getOffice ()) * / 

Iepriekš minētais nemainīgais nosaka, ka katrs darbinieks ir atgriezies getEmployees () ir birojs istabu kolekcijā, kuru atgriezis getRooms (). Izņemot visiem atslēgvārds, sintakse ir tāda pati kā pastāv izteiksme.

Šeit ir piemērs, izmantojot pastāv:

/ ** * @post pastāv IRoom r vietnē getRooms () | r.isAvailable () * / 

Šajā pēcnosacījumā ir noteikts, ka pēc saistītās metodes izpildes kolekciju atgrieza getRooms () būs vismaz viena pieejama istaba. The pastāv turpina kolekcijas elementa Java tipu - IRoom piemērā. r ir mainīgais, kas attiecas uz jebkuru kolekcijas elementu. The iekšā pēc atslēgvārda seko izteiksme, kas atgriež kolekciju (Uzskaitīšana, Masīvsvai Kolekcija). Pēc šīs izteiksmes seko vertikāla josla, kam seko nosacījums, kas ietver elementa mainīgo, r piemērā. Nodarbināt pastāv kvantifikators, kad nosacījumam jāatbilst vismaz vienam kolekcijas elementam.

Abi visiem un pastāv var izmantot dažāda veida Java kolekcijām. Viņi atbalsta Uzskaitīšanas, Masīvssmiltis Kolekcijas.

Ietekme: nozīmē

iContract nodrošina nozīmē operatoram, lai norādītu veidlapas ierobežojumus: "Ja A atbilst, tad ir jāievēro arī B." Mēs sakām: "A nozīmē B." Piemērs:

/ ** * @invariant getRooms (). isEmpty () nozīmē getEmployees (). isEmpty () // nav istabu, nav darbinieku * / 

Tas nemainīgais izsaka, ka tad, kad getRooms () kolekcija ir tukša getEmployees () arī kolekcijai jābūt tukšai. Ņemiet vērā, ka tajā nav norādīts, kad getEmployees () ir tukšs, getRooms () jābūt arī tukšam.

Varat arī apvienot tikko ieviestos loģiskos operatorus, lai izveidotu sarežģītus apgalvojumus. Piemērs:

/ ** * @variants visiem IEmployee e1 pakalpojumā getEmployees () | * visi IEmployee e2 iekļauti getEmployees () | * (e1! = e2) nozīmē e1.getOffice ()! = e2.getOffice () // viens birojs uz darbinieku * / 

Ierobežojumi, mantošana un saskarnes

iContract izplata ierobežojumus mantošanas un saskarnes ieviešanas attiecībās starp klasēm un saskarnēm.

Pieņemsim, ka klase B pagarina klasi A. Klase A nosaka invariantu, priekšnoteikumu un pēcnosacījumu kopumu. Tādā gadījumā klases nemainīgie un priekšnoteikumi A attiecas uz klasi B kā arī metodes klasē B jāatbilst tādiem pašiem pēcnoteikumiem kā klasē A apmierina. Klasei varat pievienot ierobežojošākus apgalvojumus B.

Iepriekš minētais mehānisms darbojas arī saskarnēs un ieviešanā. Pieņemsim A un B ir saskarnes un klase C īsteno abus. Tādā gadījumā, C ir pakļauts abu saskarņu nemainīgajiem, priekšnoteikumiem un pēcnosacījumiem, A un B, kā arī tie, kas noteikti tieši klasē C.

Sargieties no blakusparādībām!

iContract uzlabos jūsu programmatūras kvalitāti, ļaujot jau agri noķert daudzas iespējamās kļūdas. Bet jūs varat arī iešaut sev kājā (tas ir, ieviest jaunas kļūdas), izmantojot iContract. Tas var notikt, iContract apgalvojumos izsaucot funkcijas, kas rada blakusparādības, kas maina jūsu sistēmas stāvokli. Tas noved pie neparedzamas uzvedības, jo pēc tam, kad jūs sastādīsit kodu bez iContract instrumentiem, sistēma rīkosies citādi.

Steka piemērs

Apskatīsim pilnu piemēru. Es esmu definējis Kaudze interfeiss, kas nosaka manas iecienītās datu struktūras pazīstamās darbības:

/ ** * @inv! isEmpty () nozīmē top ()! = null // nav atļauts izmantot nevienu nulles objektu * / publiskā interfeisa kaudze {/ ** * @pre o! = null * @post! isEmpty () * @post top () == o * / void push (Object o); / ** * @pre! isTukšs () * @post @return == top () @ pre * / Object pop (); / ** * @pre! isTukšs () * / Objekta augšdaļa (); boolean isTukšs (); } 

Mēs piedāvājam vienkāršu saskarnes ieviešanu:

importēt java.util. *; / ** * @inv isEmpty () nozīmē elements.size () == 0 * / public class StackImpl īsteno Stack {private final LinkedList elements = new LinkedList (); public void push (Object o) {elements.add (o); } public Object pop () {final Object popped = top (); elements.removeLast (); atgriešanās izlēca; } public Object top () {return elements.getLast (); } public boolean isEmpty () {return elements.size () == 0; }} 

Kā redzat, Kaudze ieviešana nesatur iContract apgalvojumus. Drīzāk visi apgalvojumi tiek veikti saskarnē, kas nozīmē, ka skursteņa komponenta līgums ir definēts saskarnē kopumā. Vienkārši apskatot Kaudze saskarne un tās apgalvojumi, Kaudzeuzvedība ir pilnībā noteikta.

Tagad mēs pievienojam nelielu testa programmu, lai iContract darbotos:

public class StackTest {public static void main (String [] args) {final Stack s = new StackImpl (); s.push ("viens"); s.pop (); s.push ("divi"); s.push ("trīs"); s.pop (); s.pop (); s.pop (); // izraisa apgalvojuma izgāšanos}} 

Pēc tam mēs palaižam iContract, lai izveidotu kaudzes piemēru:

java -cp% CLASSPATH%; src; _contract_db; instr com.reliablesystems.iContract.Tool -Z -a -v -minv, pre, post> -b "javac -classpath% CLASSPATH%; src" -c "javac -classpath % CLASSPATH%; instr "> -n" javac -classpath% CLASSPATH%; _ contract_db; instr "-oinstr / @ p / @ f. @ E -k_contract_db / @ p src / *. Java 

Iepriekš minētais apgalvojums prasa nelielu skaidrojumu.

$config[zx-auto] not found$config[zx-overlay] not found