Szerződésalapú programozás
|
Ez a szócikk vagy szakasz lektorálásra, tartalmi javításokra szorul. |
A szerződésalapú tervezés, más néven szerződésalapú programozás (angolul: design by contract, DbC) egy szoftvertervezési módszer.
A szerződésalapú programozás előírja, hogy a szoftvertervezőknek meg kell határozniuk a szoftverkomponensek specifikációit, amelyek kiegészítik az absztrakt adattípusok meghatározását előfeltétellel, utófeltétellel és invariánssal. Ezen specifikációkat szerződéseknek nevezik, az üzleti szerződések feltételeivel és kötelezettségeivel való hasonlóságuk miatt.
A szerződésalapú megközelítés feltételezi, hogy minden olyan kliensösszetevő, amely egy szerverösszetevőn végrehajt egy műveletet, teljesíti az adott művelethez előírt feltételeket.
Ahol ez a feltételezés túl kockázatosnak tűnik (mint a többcsatornás vagy elosztott programozás esetében), ott fordított megközelítést alkalmaznak, vagyis a szerverösszetevő teszteli minden releváns előfeltétel fennállását (a kliensösszetevő kérésének feldolgozása előtt vagy közben), és megfelelő hibaüzenettel válaszol, ahol mégsem teljesül az előfeltétel.
Történet
A kifejezést Bertrand Meyer alkotta meg az Eiffel programozási nyelv tervezésekor, és először tudományos cikkekben írta le 1986-ban,[1][2][3] majd az Object-Oriented Software Construction című könyvének két egymást követő kiadásában (1988, 1997). Az Eiffel Software 2003 decemberében kérte a Design by Contract védjegybejegyzését, amit 2004 decemberében kapott meg.[4][5] A védjegy jelenlegi[mikor?] tulajdonosa az Eiffel Software.[6][7]
A szerződéses tervezés a formális ellenőrzés, formális specifikáció és a Hoare-logika munkájában gyökerezik. Az eredeti kivitelezések tartalmazzák:
- Világos metafora a tervezési folyamat irányításához
- Alkalmazás az öröklődésre, így különösen az újradefiniálás és a dinamikus kötés formalizálása
- Alkalmazás kivételkezeléshez
- Kapcsolat az automatikus szoftverdokumentációval
Leírás
A szerződésalapú tervezés központi gondolata egy metafora arról, hogy a szoftverrendszer elemei miként működnek együtt a kölcsönös kötelezettségek és előnyök alapján. A metafora az üzleti életből származik, ahol az ügyfél és a szolgáltató szerződést kötnek, amely például meghatározza, hogy:
- A szolgáltatónak biztosítania kell egy bizonyos terméket (kötelezettség), és jogosult arra számítani, hogy az ügyfél megfizette a díját (előny).
- Az ügyfélnek meg kell fizetnie a díjat (kötelezettség), és jogosult a termék megszerzésére (előny).
- Mindkét félnek teljesítenie kell az összes szerződésre vonatkozó bizonyos kötelezettségeket, például törvényeket és rendeleteket.
Hasonlóképpen, ha az objektumorientált programozásban egy osztály metódusa biztosít egy bizonyos funkciót, akkor:
- Elvár egy bizonyos feltételt, melyet minden őt hívó modulnak biztosítania kell: kötelezettség az ügyfélnek és előny a szolgáltatónak (maga a metódus), ami lehetővé teszi, hogy ne kelljen az előfeltételen kívüli esetet kezelni.
- Garantálja az állapotot kilépéskor: az eljárás utófeltétele a szolgáltató kötelezettsége, és nyilvánvalóan haszon (a fő előny az eljárás hívása) az ügyfél számára.
- Megtart egy bizonyos tulajdonságot, amely belépéskor feltételezett és kilépéskor garantált: osztályinvariáns.
A szerződés szemantikailag megegyezik egy Hoare-hármassal, amely formalizálja a kötelezettségeket. Ezt össze lehet foglalni a „három kérdéssel”, amelyeket a tervezőnek többször meg kell válaszolnia a szerződésben:
- Mit vár a szerződés?
- Mit garantál a szerződés?
- Mit tart fenn a szerződés?
Számos programozási nyelv lehetővé teszi ilyen állítások megfogalmazását. A DbC azonban úgy ítéli meg, hogy ezek a szerződések annyira döntő fontosságúak a szoftver helyességéhez, hogy azoknak a tervezési folyamat részét kell képezniük. Valójában a DbC először az állítások felírását javasolja. A szerződések leírhatók megjegyzésekként a kódban, érvényesíthetők tesztekkel (akár mindkettő is alkalmazható), akkor is, ha a használt programozási nyelvben nem támogatott a szerződésalapú programozás nyelvi szinten.
A szerződés fogalma a metódus/eljárás szintjére terjed ki; az egyes alprogramokra vonatkozó szerződés általában a következő információkat tartalmazza:
- Az elfogadható és elfogadhatatlan bemeneti értékek vagy típusok, és azok jelentése
- Visszatérési értékek vagy típusok és jelentéseik
- A hiba- és kivételértékek vagy -típusok, amelyek előfordulhatnak, és azok jelentése
- Mellékhatások
- Előfeltételek
- Utófeltételek
- Invariánsok
- (ritkábban) Teljesítménygaranciák, pl. a futási időre vagy helyigényre
Az öröklési hierarchia alosztályai gyengíthetik (de nem erősíthetik) az előfeltételeket, és erősíthetik (de nem gyengíthetik) az utófeltételeket és invariánsokat. Ezek a szabályok hasonlítanak a viselkedésbeli altípusokhoz.
Minden osztálykapcsolat a kliensosztályok és a szolgáltató osztályok között zajlik. A kliens osztály köteles úgy hívni a szolgáltató szolgáltatásait, hogy a hívás eredménye nem sérti a szolgáltató állapotát. Ezt követően a szolgáltató köteles olyan visszatérési állapotot és adatokat szolgáltatni, amelyek nem sértik az ügyfél állapotkövetelményeit.
Például egy szolgáltató adatpuffer megkövetelheti, hogy az adatok legyenek jelen a pufferben a törlési funkció meghívásakor. Ezt követően a szállító garantálja az ügyfél számára, hogy amikor a törlési funkció befejezi a munkáját, az adatelem valóban törlődik a pufferből. Más tervezési szerződések az osztályinvariáns fogalmai. Az osztályvariáns garantálja (a helyi osztály számára), hogy az osztály állapota az egyes funkciók végrehajtása végén a meghatározott tűréshatáron belül megmarad.
A szerződések használatakor a szállítónak nem szabad ellenőrizni, hogy a szerződéses feltételek teljesülnek-e (támadó/offenzív programozás). Az az általános elképzelés, hogy a kód „keményen kudarcot vall”, a szerződés ellenőrzése pedig biztonsági háló.
A DbC „keményen kudarcot valló” tulajdonsága leegyszerűsíti a szerződéses viselkedés hibakeresését, mivel az egyes módszerek tervezett viselkedése egyértelműen meghatározásra kerül.
Ez a megközelítés lényegesen különbözik a védekező programozástól, ahol a szolgáltató felelős annak meghatározásában, hogy mit tegyünk, ha az előfeltétel nem teljesül. Gyakran előfordul, hogy a szolgáltató kivételt dob, hogy tájékoztassa a klienst az előfeltétel megszegéséről, és végső soron mindkét esetben – DbC és védekező programozás esetén is – a kliensnek kell kitalálnia, hogyan reagáljon erre. Ilyen esetekben a DbC megkönnyíti a szolgáltató munkáját.
A szerződésalapú tervezés meghatározza a szoftvermodul helyességének kritériumait is:
- Ha az osztályvariáns és az előfeltétel teljesül, mielőtt egy ügyfél meghívja a szolgáltatót, akkor az invariáns és az utófeltétel a szolgáltatás teljesítése után igaz lesz.
- A szolgáltató hívásakor a szoftvermodul nem sértheti a szolgáltató előfeltételeit.
A szerződésalapú tervezés megkönnyítheti a kód újrafelhasználását, mivel az egyes kóddarabokra vonatkozó szerződések teljes mértékben dokumentálva vannak. A modulra vonatkozó szerződések a modulok viselkedését leíró szoftver dokumentációjának tekinthetők.
Teljesítménnyel kapcsolatos következmények
A hibamentes program végrehajtása során soha nem szabad megsérteni a szerződés feltételeit. Ezért a szerződéseket rendszerint csak hibakeresési módban ellenőrzik a szoftverfejlesztés során. Később, a kiadáskor a szerződés ellenőrzése le van tiltva a teljesítmény maximalizálása érdekében.
Számos programozási nyelven a szerződéseket állításokkal adják meg. Ezeket a C/C++ alapértelmezés szerint kiadási módban eldobja; hasonlóképpen deaktiválják a C#[8] és a Java nyelven.
A Python értelmező indításakor az -O
(„optimalizálás”) kapcsolót megadva a Python kódgenerátor sem bocsát ki semmilyen bájtkódot az állításokhoz.[9]
Ez hatékonyan kiküszöböli az állítások futási idejű költségeit a kiadott kódban – függetlenül a fejlesztési módban használt erőforrások számától és számítási költségeitől –, mivel ezeket az utasításokat a fordító egyszerűen kihagyja a kiadott kódból.
Kapcsolat a szoftver tesztelésével
A szerződésalapú tervezés nem helyettesíti a rendszeres tesztelési stratégiákat, például az egységteszteket, integrációs teszteket és rendszerteszteket. Inkább a külső tesztelést kiegészíti belső öntesztekkel, amelyek aktiválhatók mind az izolált tesztekhez, mind a végleges (kiadandó) kódban egy tesztfázis alatt.
A belső öntesztek előnye, hogy felismerik a hibákat, még mielőtt az ügyfél által visszaadott hibás eredményekként jelennének meg, így a hibákat korábban és pontosabban meg lehet találni.
Az állítások felhasználása teszt oracle egyik formájának, a szerződésalapú tervezés megvalósításának egy módjának tekinthető.
Nyelvi támogatás
Azok a nyelvek, amelyek a legtöbb DbC-funkciót natív módon valósítják meg
- Ada 2012
- Ciao
- Clojure
- Cobra
- D[10]
- Eiffel
- Fortress
- Kotlin
- Mercury
- Nice
- Oxygene (korábban Chrome és Delphi Prism)[11])
- Racket (beleértve a magasabb rendű szerződéseket, és hangsúlyozva, hogy a szerződésszegéseknek a vétkest kell hibáztatniuk, és pontos magyarázattal kell szolgálniuk[12])
- Sather
- Scala[13] [14]
- SPARK (az Ada-programok statikus elemzésén keresztül)
- Vala
- VDM
Nyelvek harmadik fél támogatásával
Különböző könyvtárakat, előfeldolgozókat és egyéb eszközöket fejlesztettek ki a meglévő, a szerződésalapú programozást natívan nem támogató programozási nyelvekhez:
- Ada, a GNAT előfeltételeinek és utófeltételeinek pragmáin keresztül.
- C és C ++, a Boost.Contracttel,[15] a DBC for C előfeldolgozó, a GNU Nana, az eCv és az eCv ++ formális ellenőrző eszközökkel, vagy a Digital Mars C++ fordító, a C nyelv CTESK kiterjesztése segítségével. A Loki programkönyvtár egy ContractChecker nevű mechanizmust biztosít, amely ellenőrzi, hogy az osztály teljesíti-e szerződésalpú tervezést.
- C# (és egyéb .NET-nyelvek) Code Contracts[16] segítségével (a Microsoft Research projektje, integrálva .NET Framework 4.0-ba)
- Groovy a GContracts segítségével
- Go a dbc-vel[17]
- Java:
- Aktív:
- OVal és AspectJ
- Contracts for Java (Cofoja)
- Java Modeling Language (JML)
- Bean Validation (csak elő- és utófeltételek)[18]
- valid4j
- Inaktív/ismeretlen:
- Jtest (aktív, de úgy tűnik, hogy a DbC-t már nem támogatják)[19]
- iContract2/JContracts
- Contract4J
- jContractor
- C4J
- Google CodePro Analytix
- SpringContracts a Spring keretrendszerhez
- Jass Archiválva 2003. április 3-i dátummal a Wayback Machine-ben
- Modern Jass (utódja Cofoja)[20][21]
- JavaDbC az AspectJ használatával
- JavaTESK a Java kiterjesztésével
- chex4j javassist használatával
- nagymértékben testreszabható java-on-contracts
- Aktív:
- JavaScript, az AspectJS (konkrétan AJS_Validator), Cerny.js, ecmaDebug, jsContract, dbc-code-contracts vagy jscategory útján.
- Common Lisp, a makró eszközön vagy a CLOS metaobjektum-protokollon keresztül.
- Nemerle, makrók segítségével.
- Nim, makrók útján.
- Perl, a Class::Contract (Damian Conway) és Carp::Datum (Raphael Manfredi) CPAN-modulokon keresztül.
- PHP, a PhpDeal, Praspel vagy Stuart Herbert ContractLibje útján.
- Python, olyan csomagokkal, mint az icontract, PyContracts, Decontractors, dpcontracts, zope.interface, PyDBC vagy Contracts for Python. A PEP-316-ban a szerződésalapú tervezés állandó támogatását javasolták a Pythonban, de a javaslat állapota 2020 júniusában „elhalasztva”.[22]
- A Ruby, Brian McCallister DesignByContractje, a Ruby DBC ruby-contract vagy a contracts.ruby útján.
- Rust a contracts könyvtáron keresztül
- Tcl, az XOTcl objektumorientált kiterjesztésen keresztül.
Jegyzetek
- ↑ Meyer, Bertrand: Design by Contract, Technical Report TR-EI-12/CO, Interactive Software Engineering Inc., 1986
- ↑ Meyer, Bertrand: Design by Contract, in Advances in Object-Oriented Software Engineering, eds. D. Mandrioli and B. Meyer, Prentice Hall, 1991, pp. 1–50
- ↑ Meyer, Bertrand: Applying "Design by Contract", in Computer (IEEE), 25, 10, October 1992, pp. 40–51, also available online
- ↑ United States Patent and Trademark Office registration for "DESIGN BY CONTRACT". [2016. december 21-i dátummal az eredetiből archiválva]. (Hozzáférés: 2020. május 27.)
- ↑ United States Patent and Trademark Office registration for the graphic design with words "Design by Contract". [2016. december 21-i dátummal az eredetiből archiválva]. (Hozzáférés: 2020. május 27.)
- ↑ Trademark Status & Document Retrieval. tarr.uspto.gov
- ↑ Trademark Status & Document Retrieval. tarr.uspto.gov
- ↑ Assertions in Managed Code. msdn.microsoft.com
- ↑ Official Python Docs, assert statement
- ↑ Bright: D Programming Language, Contract Programming. Digital Mars, 2014. november 1. (Hozzáférés: 2014. november 10.)
- ↑ Hodges, Nick: Write Cleaner, Higher Quality Code with Class Contracts in Delphi Prism. Embarcadero Technologies. [2021. április 26-i dátummal az eredetiből archiválva]. (Hozzáférés: 2016. január 20.)
- ↑ Findler, Felleisen Contracts for Higher-Order Functions
- ↑ Scala Standard Library Docs - Assertions. EPFL. (Hozzáférés: 2019. május 24.)
- ↑ Strong typing as another "contract enforcing" in Scala, see discussion at scala-lang.org/.
- ↑ https://www.boost.org/doc/libs/master/libs/contract/doc/html/index.html
- ↑ Code Contracts. msdn.microsoft.com
- ↑ https://github.com/drblez/dbc
- ↑ Bean Validation specification. beanvalidation.org
- ↑ https://www.parasoft.com/wp-content/uploads/pdf/JtestDataSheet.pdf
- ↑ Archived copy. [2016. március 28-i dátummal az eredetiből archiválva]. (Hozzáférés: 2016. március 25.) p. 2
- ↑ No chance of releasing under Apache/Eclipse/MIT/BSD license? · Issue #5 · nhatminhle/cofoja. GitHub
- ↑ Terence Way: PEP 316 – Programming by Contract for Python. Python.org, 2003. május 2. (Hozzáférés: 2020. június 18.)
Fordítás
Ez a szócikk részben vagy egészben a Design by contract című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.
Kapcsolódó szócikk
További információk
- The Power of Design by Contract™. Eiffel Software. (Hozzáférés: 2020. június 18.) – a DbC legmagasabb szintű leírása, linkekkel a további forrásokhoz
- Building bug-free O-O software: An introduction to Design by Contract(TM). Eiffel Software. (Hozzáférés: 2020. június 18.) – régebbi anyag a DbC-ről
- Előnyök és hátrányok; megvalósítás az RPS-Obix-ben
- Bertrand Meyer: Applying “Design by Contract”. IEEE Computer, XXV. évf. 10. sz. (1992. október) 40–51. o. ISSN 0018-9162 Hozzáférés: 2020. június 18.
- Using Code Contracts for Safer Code. (Hozzáférés: 2020. június 18.)