Návrh podle kontraktu

Schéma návrhu 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.

Tento 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ř:

Ú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?]

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

[editovat | editovat zdroj]

Bě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

[editovat | editovat zdroj]

Ná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

[editovat | editovat zdroj]

Jazyky s nativní podporou

[editovat | editovat zdroj]

K jazykům, které implementují většinu DbC vlastností nativně patří:

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

[editovat | editovat zdroj]

Pro existující programovací jazyky bez nativní podpory návrhu podle kontraktu byly vyvinuty různé knihovny, preprocesory a jiné nástroje:

  1. PITNER, Tomáš. Návrh podle kontraktu – klasická metodika a moderní nástroje [online]. [cit. 2024-08-06]. Dostupné online. 
  2. Meyer, Bertrand: Design by Contract, Technical Report TR-EI-12/CO, Interactive Software Engineering Inc., 1986
  3. Meyer, Bertrand: Design by Contract, in Advances in Object-Oriented Software Engineering, eds. D. Mandrioli and B. Meyer, Prentice Hall, 1991, pp. 1–50
  4. Meyer, Bertrand: "Applying "Design by Contract"", in Computer (IEEE), 25, 10, October 1992, pp. 40–51.
  5. Trademark Status & Document Retrieval - 78342277 [online]. USPTO Trademark Application and Registration Retrieval. Dostupné online. 
  6. Trademark Status & Document Retrieval - 78342308 [online]. USPTO Trademark Application and Registration Retrieval. Dostupné online. 
  7. 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]
  8. 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]
  9. Assertions in Managed Code [online]. Microsoft Developer Network, 2016-11-15. Dostupné v archivu pořízeném z originálu dne 2018-08-22. 
  10. Official Python Docs, assert statement
  11. BRIGHT, Walter. D Programming Language, Contract Programming [online]. Digital Mars, 2014-11-01 [cit. 2014-11-10]. Dostupné online. 
  12. 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. 
  13. Findler, Felleisen Contracts for Higher-Order Functions
  14. Scala Standard Library Docs - Assertions [online]. EPFL [cit. 2019-05-24]. Dostupné online. 
  15. Silné typování jako další "contract enforcing" pro jazyk Scala, viz diskuze na scala-lang.org/.
  16. Code Contracts [online]. Microsoft Developer Network. Dostupné v archivu pořízeném z originálu dne 2018-11-15. 
  17. Bean Validation specification [online]. beanvalidation.org. Dostupné online. 
  18. Software Testing Help from the Experts | Parasoft Resources [online]. Dostupné v archivu pořízeném z originálu dne 2022-10-09. 
  19. Archived copy [online]. [cit. 2016-03-25]. Dostupné v archivu pořízeném dne 2016-03-28.  p. 2
  20. No chance of releasing under Apache/Eclipse/MIT/BSD license? · Issue #5 · nhatminhle/cofoja [online]. GitHub. Dostupné online. 

V tomto článku byl použit překlad textu z článku Design by contract na anglické Wikipedii.

Literatura

[editovat | editovat zdroj]
  • 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 | editovat zdroj]

Externí odkazy

[editovat | editovat zdroj]