home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 November / Chip_2001-11_cd1.bin / obsahy / Chip_txt / txt / 190-195.txt < prev    next >
Text File  |  2001-09-30  |  19KB  |  189 lines

  1. jazyky C/C++ a Java
  2. Prosadit svou
  3. AnglickΘ sloveso to assert znamenß podle slovnφku tvrdit, prosazovat nebo postulovat; v podob∞ asertivita Φi asertivnφ chovßnφ je koneckonc∙ znßme i v ΦeÜtin∞ a takΘ dalÜφ nßrodnφ jazyky si pro tento v²znam n∞jakou odvozeninou z p∙vodn∞ latinskΘho kmene vypomßhajφ. Mo₧nß vßs vÜak p°ekvapφ, ₧e to platφ i pro n∞kterΘ jazyky programovacφ...
  4.  
  5. Programßto°i pou₧φvajφcφ jazyk C znajφ makro assert, kterΘ slou₧φ p°i lad∞nφ; nynφ bude podobn² nßstroj k dispozici takΘ v jazyce Java. Ne₧ se k n∞mu dostaneme, zopakujeme si, jak je to s asercemi v C a v C++, abychom mohli ob∞ konstrukce porovnat.
  6.  
  7. Jazyky C a C++
  8. Jazyk C obsahuje u₧ od dßvn²ch dob makro assert()(vzdor nepsanΘmu pravidlu o identifikßtorech maker se pφÜe mal²mi pφsmeny). Jeho deklaraci najdeme v hlaviΦkovΘm souboru assert.h, v jazyce C++ vyhovujφcφm standardu ISO 14882 takΘ v hlaviΦkovΘm souboru cassert.
  9. Pou₧itφ
  10. Pou₧itφ makra assert v C/C++ vypadß takto:
  11. #include <assert.h>
  12. /* ... */
  13. assert(v²raz);
  14. Zde v²raz p°edstavuje podmφnku, jejφ₧ spln∞nφ po₧adujeme - nebo spφÜe prosazujeme; tento v²raz se za b∞hu programu vyhodnotφ (pokud toto makro nevy°adφme z Φinnosti, jak si povφme dßle). Je-li nenulov², nic se nestane, jinak program vypφÜe zprßvu, kterß mß typicky tvar
  15. Assertion failed: V²raz, file jmΘno, line Φφslo. 
  16. a okam₧it∞ skonΦφ. (Mo₧nß jeÜt∞ p°ipojφ zprßvu Abnormal program termination, zßle₧φ na p°ekladaΦi.)
  17. To znamenß, ₧e chceme-li nap°. ve zdrojovΘm souboru C:\WORK\TEST.C na °ßdku 5 otestovat podmφnku x > y, napφÜeme
  18. assert(x>y);
  19. Bude-li tato podmφnka spln∞na, nic se nestane a program pob∞₧φ v klidu dßl. Jestli₧e vÜak spln∞na nebude, program v tomto mφst∞ vypφÜe
  20. Assertion failed: x>y, file C:\WORK\TEST.C, line 5. 
  21. a skonΦφ.
  22. Po odlad∞nφ se asercφ v programu zbavφme velice jednoduÜe: do zdrojovΘho souboru vlo₧φme jeÜt∞ p°ed °ßdku #include <assert.h> deklaraci
  23. #define NDEBUG
  24. a tφm vÜechna makra assert() v tomto zdrojovΘm souboru deaktivujeme. (Pozor: P°ekladaΦ C/C++ musφ nejprve narazit na definici makra NDEBUG a teprve pak na definici makra assert(), jinak aserce z Φinnosti nevy°adφ.)
  25. Implementace
  26. Standard jazyka C p°edepisuje chovßnφ makra assert(), nikoli jeho implementaci; podobnΘ to je i v jazyce C++. To znamenß, ₧e v r∙zn²ch p°ekladaΦφch se m∙₧eme setkat s r∙zn²mi implementacemi.
  27. P°edevÜφm je asi jasnΘ, ₧e vy°azenφ asercφ pomocφ makra NDEBUG se bude opφrat o podmφn∞nou kompilaci:
  28. #ifdef NDEBUG
  29.     #define assert(x) ((void)0)
  30. #else
  31.     #define vlastnφ_aserce
  32. #endif
  33. Je-li definovßno makro NDEBUG, nahradφ se vÜechny aserce v²razem ((void)0); p°ipojφme-li za makro assert() st°ednφk, stane se z n∞j v²razov² p°φkaz, kter² nic ned∞lß a kter² bude p°ekladaΦ nejspφÜ ignorovat. Pokud vÜak makro NDEBUG nenφ definovßno, nahradφ se assert() p°φkazem, kter² zp∙sobφ v²pis zprßvy a ukonΦenφ programu.
  34. Pro implementaci vlastnφ_aserce je obvykle k dispozici pomocnß funkce, kterß se jmenuje _assert(), _assertfail(), _assert_error() nebo n∞jak podobn∞ a kterß mß zpravidla prototyp
  35. int _assert(char* vyraz, char* soubor, int radka);
  36. Tato funkce se postarß o v²pis chybov²ch zprßv a o ukonΦenφ programu.
  37. Podrobn∞jÜφ rozbor problΘm∙, na kterΘ lze p°i hledßnφ vhodnΘho tvaru vlastnφ_aserce narazit, nenφ cφlem tohoto Φlßnku; zßjemce odkazuji na knihu [1], kap. 2.6. 
  38. V dneÜnφch p°ekladaΦφch se setkßvßme zpravidla s implementacφ zalo₧enou na operßtorech ?: nebo ||:
  39. #define assert(e)\
  40.   ((e) ? (void)0 : (void)_assert ("Assertion failed: "\
  41.   #e, __FILE__, __LINE__))
  42. nebo
  43. #define assert(e)\
  44.  (void)((e) || _assert("Assertion failed: "\
  45.   #e, __FILE__, __LINE__))
  46. Prvnφ °eÜenφ vyu₧φvß toho, ₧e p°i pou₧itφ operßtoru ?: se nejprve vyhodnotφ prvnφ operand (podmφnka), a podle toho, zda je spln∞na (nenulovß), nebo nenφ, se vyhodnotφ jen druh², nebo jen t°etφ operand. Pokud je podmφnka spln∞na, provede se op∞t (void)0.
  47. DruhΘ °eÜenφ je zalo₧eno na tom, ₧e je-li ve v²razu a || b prvnφ operand nenulov², druh² se ji₧ nevyhodnotφ (tzv. ne·plnΘ vyhodnocenφ logickΘho v²razu). Ob∞ °eÜenφ vyu₧φvajφ operßtor preprocesoru #, kter² zm∞nφ parametr e na znakov² °et∞zec, a tak umo₧nφ vytisknout zßpis podmφnky, kterß nebyla spln∞na. Zßpis 
  48. "Assertion failed: " #e
  49. p°edstavuje dv∞ °et∞zcovΘ konstanty vedle sebe, mezi nimi₧ jsou pouze bφlΘ znaky, a proto je p°ekladaΦ automaticky spojφ v jedinou °et∞zcovou konstantu.
  50. StarÜφ p°ekladaΦe
  51. Ve starÜφch p°ekladaΦφch jazyka C se lze setkat s implementacφ vlastnφ_aserce v podob∞
  52. #define assert(e) if(!(e)){\
  53.    fprintf(stderr, "Assertion failed: %s,"\
  54. " file %s, line %d",\
  55. #e, __FILE__, __LINE__);\
  56.    exit(1);\
  57.  }\
  58.  else
  59. jejφ₧ "v²hodou" bylo, ₧e za nφ Ülo vynechat st°ednφk. V C++ se ovÜem tato konstrukce m∙₧e za jist²ch okolnostφ chovat nep°φpustn²m zp∙sobem. Je-li nap°. Napis objektov² typ, prob∞hne funkce
  60. void f(int x, int y)
  61. {
  62.  assert(x>y); // zde je st°ednφk
  63.  Napis n("Ahoj");
  64.  // n∞jakΘ dalÜφ p°φkazy
  65. }
  66. p°i tΘto implementaci makra assert v C++ jinak ne₧ funkce
  67. void f(int x, int y)
  68. {
  69.  assert(x>y) // chybφ st°ednφk
  70.  Napis n("Ahoj");
  71.  // n∞jakΘ dalÜφ p°φkazy
  72. }
  73. kterß se liÜφ jen vynechan²m st°ednφkem za makrem assert(). (V prvnφm p°φpad∞ se bude destruktor instance n volat a₧ p°i ukonΦenφ funkce f(), ve druhΘm p°φpad∞ ihned po ukonΦenφ konstruktoru; navφc ve druhΘm p°φpad∞ nebude v dalÜφch p°φkazech instance n dostupnß. To vypl²vß z pravidla pro p°φkaz if v C++, kterΘ °φkß, ₧e p°φkaz za podmφnkou, stejn∞ jako p°φkaz za else, se v₧dy pova₧uje za blok, a¥ je nebo nenφ uzav°en do zßvorek {}.)
  74.  
  75. Jazyk Java
  76. Na setkßnφ Java One v San Franciscu na poΦßtku lΘta 2001 ohlßsil James Gosling, hlavnφ "pachatel" Javy, plßnovanΘ rozÜφ°enφ tohoto jazyka: verze JDK 1.4 bude obsahovat mechanismus aserce [2]. Jeho ·Φel je velice podobn² ·Φelu asercφ v C a C++. Dodejme, ₧e v souΦasnΘ dob∞ lze zφskat beta verzi JDK 1.4 Standard Edition na internetu na adrese [3].
  77. (Na tomtΘ₧ setkßnφ J. Gosling takΘ oznßmil, ₧e ve verzi JDK 1.5 by m∞ly b²t k dispozici generickΘ konstrukce, tedy jakßsi analogie Üablon z C++. O tom ale snad n∞kdy pozd∞ji.)
  78. Syntaxe
  79. Pou₧itφ asercφ v Jav∞ je velice podobnΘ jako v jazyce C. Mßme na vybranou dv∞ mo₧nosti:
  80. assert v²raz1;
  81. assert v²raz1 : v²raz2;
  82. V obou variantßch musφ b²t v²raz1 typu boolean, jinak p°ekladaΦ ohlßsφ chybu. Jeho hodnota se vypoΦte; je-li true, nic se nestane, v opaΦnΘm p°φpad∞ vznikne v²jimka typu java.lang.AssertionError. Pokud pou₧ijeme druhou variantu, p°edß se v²raz2 konstruktoru t°φdy AssertionError. (Tato t°φda mß sedm konstruktor∙ s r∙zn²mi typy parametr∙. Jeden je bez parametr∙, dalÜφch p∞t mß jeden parametr n∞kterΘho z primitivnφch typ∙ a poslednφ konstruktor mß parametr typu Object; tedy v²raz2 m∙₧e b²t vlastn∞ jakΘhokoli typu.)
  83. T°φda v²jimky je odvozena od t°φdy Error; to znamenß, ₧e ji nemusφme specifikovat v seznamu v²jimek v deklaracφch metod a nemusφme ji zachycovat a oÜet°ovat. Zachytφ ji JVM, vypφÜe o tom zprßvu a ukonΦφ program.
  84. Implementace
  85. Jazyk Java neobsahuje preprocesor, tak₧e nenabφzφ makra a ani mo₧nost podmφn∞nΘho p°ekladu. Proto bylo nutno definovat assert jako novΘ klφΦovΘ slovo. To s sebou ovÜem nese urΦitΘ problΘmy - starÜφ programy mohly pou₧φvat assert jako identifikßtor. Proto mß p°ekladaΦ java verze 1.4 p°epφnaΦ -source 1.4, kter² urΦuje, jak se mß slovo assert chßpat. P°φkazem
  86. java -source 1.4 Pokus.java
  87. p°elo₧φme soubor Pokus.java s asercemi.
  88. O tom, zda se aserce uplatnφ za b∞hu programu, rozhodujφ p°epφnaΦe p°i spouÜt∞nφ virtußlnφho stroje JVM. Pou₧ijeme-li p°epφnaΦ -da (psavci mohou pou₧φt -disableassertions), aserce se p°i b∞hu neuplatnφ, p°epφnaΦ -ea nebo -enableassertions zp∙sobφ, ₧e se aserce uplatnφ. Tyto p°epφnaΦe umo₧≥ujφ explicitn∞ stanovit, pro kterΘ balφky - a dokonce pro kterΘ jednotlivΘ t°φdy - se majφ aserce uplat≥ovat. Cel² tvar p°epφnaΦe -ea je bu∩
  89. -ea:jmΘno_balφku...
  90. (konΦφ t°emi teΦkami), nebo 
  91. -ea:jmΘno_t°φdy
  92. P°itom jmΘno t°φdy je kvalifikovanΘ jmΘnem balφku. P°epφnaΦ -da se pou₧φvß podobn∞. Chceme-li nap°.  v balφku B1 povolit aserce ve t°φd∞ Pokus, kterß je pomocnou t°φdou v programu, jeho₧ hlavnφ t°φdou je Hlavni, spustφme tento program p°φkazem
  93. java -ea:B1.Pokus Hlavni
  94. P°φkazovß °ßdka m∙₧e obsahovat vφce p°epφnaΦ∙ -ea a -da. Zpracovßvajφ se p°ed zavedenφm programov²ch t°φd do pam∞ti a platφ pro vÜechny zavßd∞Φe (class loader). Platφ i pro systΘmovΘ t°φdy, kterΘ nemajφ zavßd∞Φ. Poznamenejme, ₧e povolφme-li p°epφnaΦem -ea aserce v urΦitΘm balφku, povolφme je tφm i ve vÜech jeho "podbalφcφch", pokud je tam explicitn∞ nezakß₧eme pomocφ p°epφnaΦe -da. To umo₧≥uje velmi p°esn∞ urΦit, ve kter²ch Φßstech programu majφ b²t aserce aktivnφ a ve kter²ch ne. 
  95. Vedle toho majφ t°φdy zavßd∞Φ∙ v JDK 1.4 implicitnφ nastavenφ pro aserce, kterΘ je false (aserce nejsou aktivnφ), a toto nastavenφ lze m∞nit programov∞ pro cel² zavßd∞Φ, pro jednotlivΘ balφky a pro jednotlivΘ t°φdy pomocφ nov²ch metod 
  96. public void setDefaultAssertionStatus(boolean enabled);
  97. public void setPackageAssertionStatus(String packageName, boolean enabled); 
  98. public void setClassAssertionStatus(String className, boolean enabled);
  99. Pro nßvrat k implicitnφmu stavu slou₧φ metoda
  100. public void clearAssertionStatus();
  101. Odstra≥ovßnφ asercφ
  102. Zatφmco v C/C++ jsou aserce zalo₧eny na podmφn∞nΘ kompilaci, a proto po p°ekladu s definovan²m makrem NDEBUG prost∞ zmizφ z programu, v Jav∞ jsou vyjßd°eny p°φkazem a budou souΦßstφ bajtovΘho k≤du p°elo₧enΘho programu, a¥ je pou₧ijeme nebo ne. V rozsßhlejÜφch programech mohou zp∙sobit i zv∞tÜenφ soubor∙ .class, kterΘ v prost°edφ internetu nemusφ b²t zanedbatelnΘ.
  103. Pokud bychom cht∞li aserce z programu v Jav∞ po odlad∞nφ odstranit, ani₧ bychom museli podstatn²m zp∙sobem zasahovat do zdrojovΘho k≤du, lze pou₧φt nßsledujφcφ trik, kter² se v Jav∞ pou₧φvß i v jin²ch situacφch mφsto podmφn∞nΘ kompilace:
  104. static final boolean asertuj=true;
  105. // ...
  106. if(asertuj) assert(x>y);
  107. Pokud aserce pot°ebujeme, ponechßme statickΘ konstant∞ asertuj hodnotu true. Po odlad∞nφ programu staΦφ hodnotu tΘto konstanty zm∞nit na false  a program znovu p°elo₧it. Proto₧e podmφnka v p°φkazu if nenφ spln∞na a tato skuteΦnost je znßma ji₧ v dob∞ p°ekladu, m∙₧e p°ekladaΦ odstranit nejen aserci, ale i p°φkaz if.
  108.  
  109. Pou₧φvßnφ asercφ
  110. V tΘto Φßsti se podφvßme, jak se aserce pou₧φvajφ, k Φemu se hodφ a k Φemu ne. VÜe, co zde bude °eΦeno, berte jako doporuΦenφ; v ₧ßdnΘm p°φpad∞ nejde o neporuÜitelnß pravidla.
  111. VedlejÜφ efekty
  112. P°i pou₧φvßnφ asercφ bychom m∞li mφt na pam∞ti, ₧e v²raz, jeho₧ platnost testujeme, se vyhodnotφ jen v p°φpad∞, ₧e aserce budou aktivnφ. Jestli₧e je vy°adφme, v²raz se nevyhodnotφ. Znamenß to tedy, ₧e by nem∞l mφt ₧ßdn² vedlejÜφ efekt - nem∞l by nap°. obsahovat p°i°azenφ, operßtory ++, -- ap.
  113. Kontrola kontraktu
  114. Ve°ejn∞ p°φstupnΘ metody tvo°φ, jak znßmo, rozhranφ t°φd. Podobn∞ funkce exportovanΘ z modulu v klasickΘm modulßrnφm programovßnφ tvo°φ rozhranφ tohoto modulu. Ka₧dß z t∞chto metod nebo funkcφ oΦekßvß parametry, kterΘ spl≥ujφ jistΘ vstupnφ neboli p°edb∞₧nΘ podmφnky (preconditions), a zavazuje se vrßtit v²sledek, kter² spl≥uje jistΘ v²stupnφ podmφnky (postconditions). O tom se n∞kdy hovo°φ jako o principu kontraktu.
  115. N∞kterΘ programovacφ jazyky, nap°. Eiffel, umo₧≥ujφ specifikovat tyto podmφnky deklarativn∞. O jejich kontrolu se pak starß p°ekladaΦ, kter² do programu vlo₧φ k≤d, jen₧ ov∞°φ, zda jsou spln∞ny, a pokud ne, vyvolß v²jimky. Java, C ani C++ tuto mo₧nost nenabφzejφ, nenφ ale problΘm naprogramovat si tuto kontrolu "ruΦn∞". P°itom se pou₧φvajφ bu∩ aserce, nebo v²jimky. Mohlo by se zdßt, ₧e tyto dva mechanismy v Jav∞ spl²vajφ, nicmΘn∞ "b∞₧nΘ" v²jimky v programu zachycujeme a oÜet°ujeme (a pou₧φvßme je i v "ostrΘ" verzi programu), kde₧to aserce nezachycujeme; aserce slou₧φ k urΦenφ mφsta chyby, kde nenφ spln∞na n∞jakß zßsadnφ podmφnka, v pr∙b∞hu lad∞nφ.
  116. Poznßmka: V tomto oddφlu budeme pro struΦnost termφnem "funkce" oznaΦovat jak samostatnou funkci v C/C++, tak metodu objektovΘho typu v C++ nebo v Jav∞. Bude-li pot°eba, pou₧ijeme samoz°ejm∞ p°esn∞jÜφ oznaΦenφ.
  117. Vstupnφ podmφnky
  118. Pro testovßnφ vstupnφch podmφnek ve ve°ejn∞ p°φstupn²ch metodßch se aserce p°φliÜ nehodφ. Podobn∞ se nehodφ pro testovßnφ vstupnφch podmφnek ve funkcφch exportovan²ch z modul∙. Tyto podmφnky zpravidla testujeme explicitn∞ pomocφ p°φkaz∙ if, a pokud nejsou spln∞ny, volßme chybovΘ procedury, vyvolßvßme v²jimky (jinΘ ne₧ AssertError) nebo vracφme hodnotu, kterß indikuje chybu.
  119. Podφvejme se na p°φklad: Funkce, kterß poΦφtß faktorißl celΘho Φφsla n (souΦin 1*2*3*...*n), oΦekßvß jako vstupnφ parametr nezßpornΘ Φφslo typu int. 
  120. // V²poΦet faktorißlu v C++
  121. int f(int n) throw(range_error)
  122. {
  123.     // Kontrola vstupnφch podmφnek
  124.     if(n < 0) throw range_error("faktorißl: n < 0");
  125.     int s = 1;
  126.     while(n>1) s *= n--;
  127.     return s;
  128. }
  129. D∙vod, proΦ nepou₧φvßme aserce, je jednoduch²: pou₧itφ t∞chto funkcφ nemß jejich tv∙rce Φasto pod kontrolou. K poruÜenφ kontraktu - tedy k zadßnφ nesprßvn²ch hodnot parametr∙ - m∙₧e dojφt z mnoha d∙vod∙: proto₧e u₧ivatel programu zadal nesprßvnΘ hodnoty v n∞jakΘm °φdicφm prvku grafickΘho u₧ivatelskΘho rozhranφ programu, proto₧e jsou poÜkozena data na disku, proto₧e Üum poÜkodil data p°enßÜenß po sφti atd. (VÜimn∞te si, ₧e Φasto nejde o chybu programu, ale o problΘm zp∙soben² u₧ivatelem programu nebo technick²m za°φzenφm. Nemusφ to vÜak b²t pravidlo.) Kv∙li takov²m problΘm∙m nesmφ sluÜn² program skonΦit a lakonicky oznßmit, ₧e na °ßdce tΘ a tΘ je n∞co Üpatn∞; m∞l by oznßmit u₧ivateli, ₧e zadal Üpatnß data, a umo₧nit mu zadat je znova, m∞l by se znovu pokusit o p°eΦtenφ souboru z disku, m∞l by si vy₧ßdat opakovanΘ zaslßnφ dat po sφti atd. 
  130. Navφc nßhlΘ ukonΦenφ programu m∙₧e mφt za nßsledek poÜkozenφ dat a z toho plynoucφ velkΘ materißlnφ Ükody. TradiΦnφ mechanismus v²jimek poskytuje mo₧nost se t∞mto rizik∙m vyhnout.
  131. Pro testovßnφ vstupnφch podmφnek u funkcφ, kterΘ nejsou ve°ejn∞ p°φstupnΘ, kterΘ tedy tvo°φ "implementaΦnφ detaily" t°φd nebo modul∙, lze aserce s jistou opatrnostφ pou₧φt. Tyto funkce toti₧ zpravidla volßme z t∞l ve°ejn∞ p°φstupn²ch funkcφ, a proto lze oΦekßvat, ₧e hodnoty p°edßvan²ch parametr∙ jsou ji₧ p°ekontrolovßny. NesprßvnΘ hodnoty parametr∙ pak pravd∞podobn∞ signalizujφ chybu v programu, a proto je pou₧itφ aserce na mφst∞.
  132. V²stupnφ podmφnky
  133. P°i kontrole v²stupnφch podmφnek je situace jinß. Funkce nebo metoda obdr₧ela data, kterß proÜla vstupnφ kontrolou, a tedy m∙₧eme p°edpoklßdat, ₧e jsou sprßvnß. Jestli₧e nejsou spln∞ny v²stupnφ podmφnky, doÜlo k poruÜenφ kontraktu na stran∞ funkce - je tedy naprogramovßna chybn∞ a aserci je vhodnΘ pou₧φt. (P°φΦinou m∙₧e b²t nedostateΦnß prov∞rka vstupnφch parametr∙, kterß nezachytila Üpatnou hodnotu parametr∙, ale i to je chyba tΘto funkce.)
  134. Jako p°φklad si ukß₧eme op∞t funkci pro v²poΦet faktorißlu, tentokrßt v Jav∞ (JDK 1.4). Proto₧e hodnotou faktorißlu je souΦin vÜech Φφsel od 1 do n, kde n je parametr (nebo 1, mß-li parametr hodnotu 0), musφ b²t v²sledek kladn². 
  135. // V²poΦet faktorißlu, tentokrßt v Jav∞
  136. // NezbytnΘ je JDK 1.4
  137. public static long f(int n) 
  138. throws IllegalArgumentException
  139. {
  140.   if(n < 0) throw 
  141. new IllegalArgumentException(
  142. "faktorißl - parametr je " + n);
  143.   long s = 1;
  144.   while(n>1)s *= n--;
  145.   assert(s > 0); // Test v²stupnφch podmφnek
  146.   return s;
  147. }
  148. Spustφme-li tuto funkci s parametrem 100, skonΦφ chybou - prom∞nnß s bude obsahovat 0, nebo¥ p°i v²poΦtu doÜlo k p°eteΦenφ (v²sledek se nevejde do rozsahu typu long.) To znamenß, ₧e je n∞co Üpatn∞ - zde je to test vstupnφch podmφnek, kter² sice zachytφ zßpornß Φφsla, ale neodhalφ Φφsla, jejich₧ faktorißl je p°φliÜ velk² a nevejde se do rozsahu typu v²sledku.
  149. ProgramovΘ invarianty
  150. Pod tφmto oznaΦenφm se skr²vajφ podmφnky, kterΘ musφ v programu v₧dy platit (p°esn∞ji: musφ platit po dokonΦenφ urΦit²ch operacφ). 
  151. P°edstavme si nap°., ₧e nßÜ program p°evßdφ penφze z jednoho ·Φtu na druh². Pokud p°evod prob∞hne sprßvn∞, bude souΦet hotovostφ na obou ·Φtech p°ed p°evodem stejn² jako po p°evodu. SouΦet hotovostφ je tedy programov²m invariantem - veliΦinou, kterß se nem∞nφ a jejφ₧ nem∞nnost je rozumnΘ p°i lad∞nφ prov∞°it pomocφ aserce.
  152. Jin²m p°φkladem m∙₧e b²t v²poΦet dΘlek stran troj·helnφka. Pro n∞, jak znßmo, musφ platit tzv. troj·helnφkovß nerovnost, kterß °φkß, ₧e souΦet dvou stran je v₧dy v∞tÜφ ne₧ strana t°etφ. 
  153. JednotlivΘ hodnoty stran a, b a c vrßtφ funkce Vypocti(). Sprßvnost programu lze v mφst∞, kde dostaneme vÜechny t°i strany, ov∞°it asercφ
  154. double a = Vypocti();
  155. double b = Vypocti();
  156. double c = Vypocti();
  157. assert((a+b>c) && (b+c>a) && (a+c>b));
  158. A¥ jsou strany troj·helnφka jakΘkoli, troj·helnφkovß nerovnost pro n∞ musφ platit. Uvedenß podmφnka je tedy op∞t invariantem programu. (Zde je situace podobnß jako u v²stupnφch podmφnek, test ale m∙₧e b²t kdekoli, nejen na konci funkce.)
  159. Situace, kterΘ "nemohou nastat"
  160. P°i psanφ programu obΦas narazφme na situace, kterΘ - je-li program sprßvn² - nemohou nastat. M∙₧e jφt nap°φklad o p°φkaz switch, kter² neobsahuje alternativu default, proto₧e k tomu - alespo≥ zdßnliv∞ - nenφ d∙vod. P°i lad∞nφ je rozumnΘ tyto "nemo₧nΘ" alternativy oÜet°it asercemi.
  161. Podφvejme se na p°φklad. Pokud jsme programovali sprßvn∞, musφ funkce f() vrßtit celoΦφselnou hodnotu v rozmezφ 1 a₧ 4, a v zßvislosti na vrßcenΘ hodnot∞ volßme n∞kterou z dalÜφch funkcφ:
  162. switch(f())
  163. {// P°ikaz switch bez default
  164. case 1: Pripad1(); break;
  165. case 2: Pripad2(); break;
  166. case 3: Pripad3(); break;
  167. case 4: Pripad4(); break;
  168. }
  169. P°i lad∞nφ je ale rozumnΘ p°idat sem jeÜt∞ alternativu default, kterß ukonΦφ program, pokud se stane n∞co neoΦekßvanΘho a funkce f() vrßtφ hodnotu, kterß nele₧φ v oΦekßvanΘm rozmezφ:
  170. switch(f())
  171. {// P°idßno default s asercφ
  172. case 1: Pripad1(); break;
  173. case 2: Pripad2(); break;
  174. case 3: Pripad3(); break;
  175. case 4: Pripad4(); break;
  176. default: assert((f() >= 1) && (f() <= 4)); break
  177. }
  178.  
  179. Co dodat
  180. Aserce jsou v souΦasnΘm C/C++ ·Φinn²m nßstrojem pro lad∞nφ program∙ a zdß se, ₧e stejn∞ platnΘ budou i v Jav∞. Je ale nutno poznamenat, ₧e v odlad∞nΘm programu nemajφ co d∞lat. Jestli₧e u₧ivateli oznßmφ zakoupen² program Assertion failed nebo n∞co podobnΘho a bez dalÜφho vyptßvßnφ skonΦφ, nelze se divit, kdy₧ u₧ivatel vyhledß autora programu a bude chtφt svΘ penφze zp∞t. (Je ovÜem otßzka, zda to nenφ po°ßd lepÜφ, ne₧ nechat Üpatn∞ navr₧en² program b∞₧et dßl a dovolit mu tak pßchat t°eba i velkΘ Ükody. Jak znßmo, Murphyho zßkon je nekompromisnφ...)
  181.  
  182. Miroslav Virius
  183.  
  184. infotipy
  185. [1] Virius, M.: Pasti a propasti jazyka C++. Grada Publishing 1997
  186. [2] http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html
  187. [3] http://java.sun.com/j2se/
  188.  
  189.