Návrh podle kontraktu
Návrh podle kontraktu (anglicky Design by Contract, DbC), nebo též kontraktové programování je relativně dlouho známým, avšak stále nedoceněným přístupem k tvorbě spolehlivého programového vybavení.[1]
Předepisuje, aby návrháři softwaru definovali formální, přesné a verifikovatelné specifikace rozhraní pro softwarové komponenty, které rozšiřují běžnou definici abstraktních datových typů o předběžné podmínky, následné podmínky a invarianty. Tyto specifikace se označují jako „smlouvy“ („kontrakty“), v souladu s pojmovou metaforou s podmínkami a závazky obchodních kontraktů.
DbC přístup předpokládá, že všechny klientské komponenty, které volají operaci na serverové komponentě splní předběžné podmínky specifikované jako požadovaný pro tuto operaci.
Tam, kde je tento předpoklad považován za příliš riskantní (jako v případě vícekanálových nebo distribuovaných výpočtů), používá se inverzní přístup, což znamená, že serverová komponenta testuje, zda všechny relevantní předběžné podmínky platí (před zpracováním požadavku klientské komponenty' nebo v jeho průběhu), a pokud tomu tak není, odpoví vhodným chybovým hlášením.
Historie
editovatTento termín poprvé použil Bertrand Meyer v souvislosti se svým návrhem programovacího jazyka Eiffel a poprvé jej popsal od roku 1986 v různých článcích[2][3][4] a ve dvou po sobě následujících vydáních (v letech 1988 a 1997) své knihy Object-Oriented Software Construction. Společnost Eiffel Software požádala o registraci obchodní známky Design by Contract v prosinci 2003, a známku vlastní[5][6] od prosince 2004.[7][8]
Návrh podle kontraktu má kořeny v práci na formální verifikaci, formální specifikaci a Hoareho logice. Mezi původní příspěvky patří např:
- Jasná metafora pro vedení procesu návrhu
- Aplikace na dědičnost, zejména formalismus pro redefinici a dynamickou vazbu
- Aplikace na zpracovávání výjimek
- Spojení s automatickou softwarovou dokumentací
Popis
editovatÚstřední myšlenkou DbC je metafora o tom, jak prvky softwarového systému vzájemně spolupracují na základě vzájemných závazků a výhod. Tato metafora pochází z obchodního života, kde se „klient“ a „dodavatel“ dohodnou na „kontraktu“, která definuje např. toto:
- Dodavatel musí poskytnut určitý produkt (závazek) a má právo očekávat, že klient zaplatí jeho odměnu (výhodu).
- Klient musí zaplatit poplatky (závazek) a je oprávněn získat produkt (výhodu).
- Obě strany musí splnit určité závazky, např. zákony a předpisy, které se vztahují na všechny kontrakty.
Podobně, pokud metoda třídy v objektově orientovaném programování poskytuje určitou funkčnost, může:
- Očekávat, že určitá podmínka bude při vstupu zaručena každým klientským modulem, který ji volá: předběžná podmínka metody je závazek klienta, a výhoda pro dodavatele (samotnou metodu), protože ho zbavuje nutnosti řešit případy, kdy předběžná podmínka není splněna.
- Zaručení určité vlastnosti při výstupu: následná podmínka metody je závazek pro dodavatele, a výhoda (hlavní výhoda volání metody) pro klienta.
- Zachovat určitou vlastnost, předpokládanou při vstupu a zaručenou při výstupu: invariant třídy.
kontrakt je sémanticky ekvivalentní s Hoareho trojicí, která formalizuje závazky. Lze ji shrnout do „tří otázek“, na které musí designer v kontraktu opakovaně odpovídat:
- Co kontrakt očekává?
- Co kontrakt zaručuje?
- Co kontrakt zachovává?
Mnoho programovacích jazyků má nástroje pro vytváření takovýchto tvrzení (asercí). DbC však považuje tyto kontrakty za natolik zásadní pro korektnost softwaru, že by měly být součástí procesu návrhu. DbC v podstatě prosazuje, aby se nejprve napsala tvrzení.[zdroj?] Kontrakty mohou být zapsány pomocí komentářů v kódu, vynuceny sadou testů nebo obojím, a to i v případě, že by pro kontrakty neexistovala žádná speciální jazyková podpora.
Pojem kontraktu se rozšiřuje až na úroveň metod a procedur; kontrakt pro každou metodu bude obvykle obsahovat následující informace:[zdroj?]
- Přijatelné a nepřijatelné vstupní hodnoty nebo typy, a jejich významy
- Návratové hodnoty nebo typy, a jejich významy
- Hodnoty nebo typy chyb a výjimek, které se mohou objevit, a jejich významy
- Vedlejší účinky
- Předběžné podmínky
- Následné podmínky
- Invarianty
- Záruky výkonu (vzácněji), například na spotřebovaný čas nebo prostor
Podtřídy v hierarchii dědičnosti mohou oslabovat předběžné podmínky (ale ne je posilovat) a posilovat následné podmínky a invarianty (ale ne je oslabovat). Tato pravidla se blíží behaviourálnímu podtypování.
Všechny vztahy tříd jsou mezi klientskými a dodavatelskými třídami. Klientská třída se zavazuje volat dodavatelské funkce, pokud výsledný stav dodavatele není porušen klientským voláním. Dodavatel je následně povinen poskytnout návratový stav a data, která neporušují stavové požadavky klienta.
Například vyrovnávací paměť pro data dodavatele může vyžadovat, aby v ní byla data přítomna v okamžiku volání funkce mazání. Následně dodavatel klientovi zaručí, že když funkce mazání skončí svou práci, datová položka bude skutečně smazána z vyrovnávací paměti. Dalšími návrhovými kontrakty jsou koncepty invariantu třídy. Invariant třídy zaručuje (pro lokální třídu), že stav třídy bude v rámci specifikovaných tolerancí zachován na konci každého provedení funkce.
Při používání kontraktů by se dodavatel neměl pokoušet ověřit, zda jsou podmínky kontraktu splněny — tato praxe je známa jako ofenzivní programování — obecnou myšlenkou je, že kód musí „selhat natvrdo“, přičemž ověření kontraktu je záchrannou sítí.
Vlastnost „tvrdého selhání“ zjednodušuje ladění chování kontraktu, protože zamýšlené chování každé metody je jasně specifikováno.
Tento přístup se podstatně liší od defenzivního programování, kde dodavatel je odpovědný za vyhodnocení, co dělat, když předběžná podmínka není splněna. Nejčastěji dodavatel vyhodí výjimku, aby klienta informoval, že předběžná podmínka nebyla splněna, a v obou případech — u DbC i defenzivního programování — musí klient zjistit jak na to reagovat. V takových případech DbC dodavateli usnadňuje práci.
Návrh podle kontraktu také definuje kritéria korektnosti softwarového modulu:
- Pokud je invariant třídy a předběžná podmínka pravdivá předtím, než je dodavatel zavolán klientem, pak invariant a následná podmínka bude splněno po dokončení služby.
- Při volání dodavatele by softwarový modul neměl porušovat předběžné podmínky dodavatele.
Návrh podle kontraktu může také usnadňovat opětovné použití kódu, protože kontrakt pro každou část kódu je plně dokumentovaný. Kontrakty modulu lze považovat za určitou formu dokumentace chování modulu.
Důsledky pro výkon
editovatBěhem provádění bezchybného programu nesmí být podmínky kontraktu nikdy porušené. Kontrakty se proto při vývoji softwaru obvykle kontrolují pouze v režimu ladění. V sostré verzi softwaru jsou kontroly smluv vypnuty, aby se maximalizoval výkon.
V mnoha programovacích jazycích jsou kontrakty implementovány pomocí asercí. Aserce jsou implicitně vypuštěny při vytváření produkčního softwaru v jazycích C/C++, a podobně jsou deaktivovány v jazycích C#[9] a Java.
Spuštění interpretu Pythonu s parametrem „-O“ (jako „optimalizovat“) také způsobí, že generátor kódu nebude emitovat žádný bytecode pro aserce.[10]
Tám se efektivně odstraňují náklady na aserce v produkčním vydání softwaru - bez ohledu na počet a výpočetní náklady asertů použitých při vývoji — protože překladač žádné takové instrukce do produkčního kódu nezahrne.
Vztah k testování softwaru
editovatNávrh podle kontraktu nenahrazuje obvyklé strategie testování, např. unit testing, integrační testování a systémové testování. Spíše doplňuje externí testování interními autotesty, které lze aktivovat jak pro izolované testy tak pro produkční kód během fáze testování.
Výhodou interních autotestů je, že mohou odhalit chyby dříve než se projeví jako neplatné výsledky pozorované klientem. To umožňuje dřívější a podrobnější detekci a odstraňování chyb.
Použití asercí lze považovat za formu testovacího orákula, způsob testování implementace návrhu podle kontraktu.
Podpora v programovacích jazycích
editovatJazyky s nativní podporou
editovatK jazykům, které implementují většinu DbC vlastností nativně patří:
- Ada 2012
- Ciao
- Clojure
- Cobra
- jazyk D[11]
- Dafny
- Eiffel
- Fortress
- Kotlin
- Mercury
- Oxygene (dříve Chrome a Delphi Prism[12])
- Racket (včetně kontraktů vyššího řádu, a zdůrazňuje, že porušení kontraktu musí identifikovat viníka a musí obsahovat přesné vysvětlení[13])
- Sather
- Scala[14][15]
- SPARK (pomocí statické analýzy programů v Adě)
- Vala
- Vienna Development Method (VDM)
Kromě toho má standardní kombinace metod v Common Lisp Object System kvalifikátory metod :before
, :after
a :around
, které mimo jiné umožňují zápis kontraktů jako pomocných metod.
Jazyky s podporou třetích stran
editovatPro existující programovací jazyky bez nativní podpory návrhu podle kontraktu byly vyvinuty různé knihovny, preprocesory a jiné nástroje:
- Ada, používá GNAT pragmata pro předběžné a následné podmínky.
- C
- DBC pro C Preprocesor
- GNU Nana
- eCv nástroje pro formální verifikaci
- C++:
- Boost.Contract
- eCv++ nástroje pro formální verifikaci
- Digital Mars C++ překladač pomocí CTESK rozšíření jazyka C
- Knihovna Loki poskytuje mechanismus pojmenovaný ContractChecker, které ověřuje, zda třída splňuje návrh podle kontraktu.
- DBC C++ Návrh podle kontraktu pro C++
- C# (a jiné .NET jazyky), pomocí Code Contracts[16] (a Microsoft Research projekt integrovaný do .NET 4.0)
- Groovy pomocí GContracts
- Go pomocí dbc nebo gocontracts
- Java:
- aktivní:
- OVal s AspectJ
- Contracts for Java (Cofoja)
- Java Modeling Language (JML)
- Bean Validation (pouze předběžné a následné podmínky)[17]
- valid4j
- SafeR (s bezpečnými referencemi)
- Neaktivní/neznámé:
- Jtest (aktivní, ale zdá se, že DbC již není podporováno)[18]
- iContract2/JContracts
- Contract4J
- jContractor
- C4J
- Google CodePro Analytix
- SpringContracts pro Spring Framework
- Jass Archivováno 3. 4. 2003 na Wayback Machine.
- Modern Jass (následník je Cofoja)[19][20]
- JavaDbC pomocí AspectJ
- JavaTESK s využitím rozšíření Javy
- chex4j pomocí javassist
- vysoce přizpůsobitelné java-on-contracts
- aktivní:
- JavaScript, pomocí decorator-contracts, AspectJS (konkrétně AJS_Validator), Cerny.js, ecmaDebug, jsContract, dbc-code-contracts nebo jscategory.
- Common Lisp pomocí maker nebo metaobject protokolu CLOS.
- Nemerle pomocí maker.
- Nim pomocí maker.
- Perl pomocí CPAN modulů Class::Contract (autor Damian Conway) nebo Carp::Datum (autor Raphael Manfredi).
- PHP pomocí PhpDeal, Praspel nebo Stuart Herbert's ContractLib.
- Python pomocí balíčků jako deal, icontract, PyContracts, dpcontractsnebo zope.interface. Trvalá úprava Pythonu pro podporu Návrhu podle kontraktu byla navržena v PEP-316 v roce 2003, ale byla odložena.
- Ruby pomocí DesignByContract Briana McCallistera, Ruby DBC ruby-contract nebo contracts.ruby.
- Rust pomocí crate contracts.
- Swift pomocí cocoapod Jima Boyda.
- Tcl pomocí objektově orientovaného rozšíření XOTcl.
Odkazy
editovatPoznámky
editovat- ↑ PITNER, Tomáš. Návrh podle kontraktu – klasická metodika a moderní nástroje [online]. [cit. 2024-08-06]. Dostupné online.
- ↑ 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.
- ↑ Trademark Status & Document Retrieval - 78342277 [online]. USPTO Trademark Application and Registration Retrieval. Dostupné online.
- ↑ Trademark Status & Document Retrieval - 78342308 [online]. USPTO Trademark Application and Registration Retrieval. Dostupné online.
- ↑ United States Patent and Trademark Office registration for "DESIGN BY CONTRACT" [online]. [cit. 2009-06-22]. Dostupné v archivu pořízeném dne 2016-12-21.[nedostupný zdroj]
- ↑ United States Patent and Trademark Office registration for the graphic design with words "Design by Contract" [online]. [cit. 2009-06-22]. Dostupné v archivu pořízeném dne 2016-12-21.[nedostupný zdroj]
- ↑ Assertions in Managed Code [online]. Microsoft Developer Network, 2016-11-15. Dostupné v archivu pořízeném z originálu dne 2018-08-22.
- ↑ Official Python Docs, assert statement
- ↑ BRIGHT, Walter. D Programming Language, Contract Programming [online]. Digital Mars, 2014-11-01 [cit. 2014-11-10]. Dostupné online.
- ↑ Hodges, Nick. Write Cleaner, Higher Quality Code with Class Contracts in Delphi Prism [online]. Embarcadero Technologies [cit. 2016-01-20]. Dostupné v archivu pořízeném dne 2021-04-26.
- ↑ Findler, Felleisen Contracts for Higher-Order Functions
- ↑ Scala Standard Library Docs - Assertions [online]. EPFL [cit. 2019-05-24]. Dostupné online.
- ↑ Silné typování jako další "contract enforcing" pro jazyk Scala, viz diskuze na scala-lang.org/.
- ↑ Code Contracts [online]. Microsoft Developer Network. Dostupné v archivu pořízeném z originálu dne 2018-11-15.
- ↑ Bean Validation specification [online]. beanvalidation.org. Dostupné online.
- ↑ Software Testing Help from the Experts | Parasoft Resources [online]. Dostupné v archivu pořízeném z originálu dne 2022-10-09.
- ↑ Archived copy [online]. [cit. 2016-03-25]. Dostupné v archivu pořízeném dne 2016-03-28. p. 2
- ↑ No chance of releasing under Apache/Eclipse/MIT/BSD license? · Issue #5 · nhatminhle/cofoja [online]. GitHub. Dostupné online.
Reference
editovatV tomto článku byl použit překlad textu z článku Design by contract na anglické Wikipedii.
Literatura
editovat- Mitchell, Richard, a McKim, Jim: Design by Contract: by example, Addison-Wesley, 2002
- Kniha en:Computer Programming/Design by Contract ve Wikiknihách popisující DBC způsobem blízkým původnímu modelu.
- McNeile, Ashley: A framework for the semantics of behavioral contracts. Sborník Second International Workshop on Behaviour Modelling: Foundation and Applications (BM-FA '10). ACM, Nový York, NY, USA, 2010. Tento článek diskutuje zobecněné pojmy Kontrakt a Substitutability.
Související články
editovat- Softwarové inženýrství založené na komponentách
- Korektnost (matematická informatika)
- Defenzivní programování
- Fail-fast systém
- Formální metody
- Hoareho logika
- Modulární programování
- Silné typování
- Testováním řízený vývoj
Externí odkazy
editovat- The Power of Design by Contract(TM) Nejvyšší úrovně popisu DbC, s odkazy na další prostředky.
- Building bug-free O-O software: An introduction to Design by Contract(TM) Starší materiál o DbC.
- Benefits and drawbacks; implementation in RPS-Obix
- Using Code Contracts for Safer Code