Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o...

29
Programowanie za pomocą kontraktów Design by Contract

Transcript of Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o...

Page 1: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Programowanie za pomocą kontraktów

Design by Contract

Page 2: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

4 czeKourUwagzniszPrzycgram

Przerwca 1rou (ELgi: starzczona czyną k

mowania

zypa1996, 1

LA3), Grt nieudprzez o

katastroa z raki

adek2:34 Gujana Fdany -oficera ofy byłoiety Aria

k rakGMT; mFrancusrakietabezpie

o użycieane 4.

iety iejsce sska

a zeszłaeczeńste niezmStraty 5

Ariastartu: k

a z kurstwa kosmienion500 00

ane kosmod

su i zossmodronego op0$.

drom

stała omu. pro-

Page 3: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Poprawne współużywanie modułów programowych

Brak formalizacji semantyki modułów jest przyczy-ną niepoprawnego używania modułów programo-wych.

At the time of the failure, the software in the two SRIs was doing a data conversion from 64-bit floating point to 16-bit integer. The floating point number had a value greater than what could be represented by a 16-bit signed integer; this resulted in an overflow software exception. Code was reused from the Ariane 4 guidance system. The Ariane 4 has different flight characteristics in the first 30 seconds of flight and exception conditions were generated on both inertial guidance system (IGS) channels of the Ari-ane 5.

Kod będący przyczyną wypadku rakiety Ariane 5:

ccoonnvveerrtt ((hhoorriizzoonnttaall__bbiiaass:: DDOOUUBBLLEE)):: IINNTTEEGGEERR Procedura ta działała poprawnie w rakiecie Ariane 4, której parametry lotne ograniczały wartości pa-rametru: horizontal_bias, do przedziału, który gwarantował poprawne działanie procedury. Powyższa procedura została przeniesiona do oprogramowania rakiety Ariane 5, której parametry lotne powodowały przekroczenie poprawnych war-tości parametru horizontal_bias.

Page 4: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Poszukiwanie nowej metodyki programowania

Poprawność składniowa współużywalnych modu-łów może być zweryfikowana przez kompilator. Poprawność semantyczna ujawnia się dopiero w trakcie działania programu. Przyczyną katastrofy Ariane 5 była wykorzystanie procedury, o nieznanych własnościach seman-tycznych. W związku z tym, niespełniony został niejawny kontrakt na sposób korzystania z kodu. W wyniku analizy systemowej i podczas projekto-wania powstaje specyfikacja, która koncentruje się na składni programów, a nie ich semantyce. X27 # element1_st # element2_sz # element3_tp + ps(El) + pp() : El

Page 5: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Poszukiwanie nowej metodyki programowania

Poprawność składniowa współużywalnych modu-łów może być zweryfikowana przez kompilator. Poprawność semantyczna ujawnia się dopiero w trakcie działania programu. Przyczyną katastrofy Ariane 5 była wykorzystanie procedury, o nieznanych własnościach seman-tycznych. W związku z tym, niespełniony został niejawny kontrakt na sposób korzystania z kodu. W wyniku analizy systemowej i podczas projekto-wania powstaje specyfikacja, która koncentruje się na składni programów, a nie ich semantyce. X27 # element1_st # element2_sz # element3_tp + ps(El) + pp() : El

Stos # storage # size # top + push(Element) + pop() : Element

Page 6: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Specyfikacja semantyki programów

Kontrakt: • Warunki poprawnego korzystania z obiektów • Zobowiązania obiektów – semantyka progra-

mów Kontrakt na metodę push() klasy Stos:

Zobowiązania Gwarancje Klient Musi spełnić warunki

początkowe Stos nie jest pełny, wstawiany element nie jest pusty

Korzysta z warun-ków końcowych Na szczycie stosu pojawi się nowy element

Dostawca Musi spełnić warunki końcowe Zapamiętuje podany element na szczycie stosu

Może założyć speł-nienie warunków początkowych Nie musi weryfiko-wać przepełnienia stosu i poprawności elementu

Page 7: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Analiza systemowa za pomocą kontraktów

1. Specyfikacja ADT (Abstract Data Type) z języ-

kiem formalnej specyfikacji (VDM, Z, logika Hoare'a, itp)

2. UML z językiem OCL (Object Constraint Lan-guage)

Formalizacja specyfikacji ADT Semantyki algebraiczne

Formalny zapis pełnej specyfikacji abstrakcyjnego typu danych z zastosowaniem semantyk algebra-icznych, obejmuje pięć elementów:

nazwę ADT z opcjonalną listą parametrów gene-rycznych; predefiniowane ADT niezbędne do definicji se-mantyki ADT; interfejs ADT zdefiniowany jako zbiór sygnatur operacji; dziedziny poszczególnych operacji zdefiniowane jako warunki początkowe operacji; semantykę ADT wyrażoną w postaci aksjoma-tów;

Page 8: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Nazwa ADT

gdzie G - jest formalnym parametrem generycznym

Specyfikacja ADT z parametrami generycznymi repre-zentuje cały zbiór specyfikacji ADT dla wszystkich po-tencjalnych wartości parametru generycznego.

W powyższym przypadku specyfikacja reprezentuje zbiór ADT: STACK[int], STACK[float], STACK[String], STACK[Osoba], itd.

Predefiniowane ADT

określają ADT o predefiniowanej semantyce, które będą wykorzystane do definicji semantyki danego ADT.

ADT name: STACK [G]

Domains: boolean

Page 9: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Interfejs ADT

Interfejs ADT jest wyspecyfikowany jako zbiór sygnatur wszystkich operacji właściwych dla ADT. Operacje ADT są podzielone na dwie klasy: operacji modyfikujących stan ADT (ang. modifier) i operacji realizujących niemo-dyfikujący dostęp do stanu ADT (ang. accessor) (dla uproszczenia w dalszych rozważaniach przyjęto, że te dwa zbiory operacji są rozłączne, a operacje odczytują-ce stan zwracają jedynie pojedyncze wartości). Typami parametrów wejściowych operacji są: • definiowany ADT, dla wszystkich operacji za wyjąt-

kiem konstruktora; • predefiniowane ADT; • parametry generyczne.

Typami zwrotnymi operacji są: • definiowany ADT, dla operacji klasy modifier; • predefiniowane ADT, dla operacji klasy accessor; • parametry generyczne, dla operacji klasy accessor.

Oznaczenie: → służy do wskazania operacji o ograni-czonej dziedzinie parametrów wejściowych.

Functions: • put: STACK[G]×G → STACK[G] - modifier • remove: STACK[G] → STACK[G] - modifier • item: STACK[G] → G - accessor • empty: STACK[G] → BOOLEAN - accessor • new: → STACK[G] - modifier

Page 10: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Operacje o ograniczonej dziedzinie

Dla każdej operacji o ograniczonej dziedzinie parame-trów wejściowych należy zdefiniować warunek począt-kowy określający warunki niezbędne dla poprawnego wykonania operacji. Warunki początkowe odwołują się do stanu wystąpień ADT lub do wartości parametrów wejściowych.

Warunki początkowe są definiowane jako wyrażenia lo-giczne, które muszą być prawdziwe w momencie wywo-ływania operacji. Definicje warunków początkowych opierają się na składni operacji ADT.

Preconditions: • remove(s) require not empty(s) • item(s) require not empty(s)

Page 11: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Semantyka ADT

Semantyka ADT jest definiowana w postaci zbioru ak-sjomatów definiujących zależności między operacjami ADT. Aksjomaty są definiowane w postaci wyrażeń lo-gicznych, które muszą być spełnione dla wszystkich sta-nów potencjalnych wystąpień ADT. Definicje aksjomatów wykorzystują składnię operacji ADT zdefiniowaną w sek-cji Functions.

Zbiór aksjomatów powinien opisywać kompletną seman-tykę ADT. To znaczy dla każdej operacji modyfikującej stan ADT powinno się określić zbiór wartości wszystkich operacji odczytujących stan ADT. W sumie dla n opera-cji modyfikujących i m odczytujących stan ADT należało-by zdefiniować m∗n aksjomatów. Jednak, nie zawsze jest to możliwe. Aksjomaty powinny być formułowane w sposób jak naj-bardziej ogólny. Na przykład:

not empty(put(s,x)) vs.

not empty(put(new,x))

Axioms: • item(put(s,x)) = x • remove(put(s,x)) = s • empty(new) • not empty(put(s,x))

Page 12: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Pełna specyfikacja ADT

Specyfikacja ADT STACK ADT NAME • STACK [G] DOMAINS • Boolean FUNCTIONS • put: STACK[G]×G → STACK[G] • remove: STACK[G] → STACK[G] • item: STACK[G] → G • empty: STACK[G] → BOOLEAN • new: → STACK[G]

AXIOMS • item(put(s,x)) = x • remove(put(s,x)) = s • empty(new) • not empty(put(s,x)) PRECONDITIONS • remove(s) require not empty(s) • item(s) require not empty(s)

Page 13: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Kompletność definicji ADT

Po czym rozpoznań, że specyfikacja semantyki ADT jest kompletna. Reguła mówiąca, że dla m operacji modyfiku-jących i n odczytujących stan ADT należy zdefiniować m∗n aksjomatów ma ograniczony zasięg stosowalności. Niektórych aksjomatów nie można zdefiniować ze względu na niespełnienie warunków początkowych. Z tego powodu nie można określić wartości aksjomatu:

item(new)

Dla innych aksjomatów nie można bezpośrednio określić ich wartości:

item(remove(s))=? empty(remove(s))=?

Specyficzne relacje między operacjami ADT: na przykład przemienność lub komutatywność, pozwalają ograniczyć zbiór aksjomatów.

Page 14: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Poprawność wyrażeń definiowanych na ADT

Składnia operacji ADT określa sposób konstruowania poprawnych składniowo wyrażeń na ADT.

put(new,x)

empty(remove(put(put(new,x1),x2)))

item(new)

Poprawność składniowa nie gwarantuje poprawności semantycznej. Zapytania - wyrażenia, których wartości zwrotne nie są typu ADT:

item(put(new,x))

empty(remove(put(put(new,x1),x2)))

item(new)

Definicja semantycznej poprawności wyrażeń Niech f(x1, …, xn) będzie poprawnym składniowo wyra-żeniem, odwołującym się do jednej lub więcej operacji jakiegoś ADT. Wyrażenie to będzie semantycznie po-prawne wtedy i tylko wtedy, gdy wszystkie wartości xi są (rekurencyjnie) poprawne poprzez spełnienie warun-ków początkowych operacji.

Page 15: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Kompletność definicji ADT

Możliwe jest formalne dowodzenie kompletności i spój-ności specyfikacji poszczególnych ADT.

Definicja kompletności specyfikacji ADT Specyfikacja ADT typu T jest kompletna wtedy i tylko wtedy, gdy zdefiniowany zbiór aksjomatów pozwala dla dowolnego poprawnego składniowo wyrażenia e: • stwierdzić semantyczną poprawność wyrażenia; • jeżeli wyrażenie e jest poprawne i jest zapytaniem,

wyznaczyć wartość tego wyrażenia.

Definicja spójności ADT Specyfikacja ADT typu spójna wtedy i tylko wtedy, gdy dla dowolnego poprawnego składniowo zapytania e, aksjomaty ADT pozwalają na wyznaczenie, co najwyżej jednej wartości e.

Page 16: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Programowanie za pomocą kontraktów - Asercje

Język specyfikacji semantyki oprogramowania Asercje są wyrażeniami logicznymi opisującymi semantykę klas. Asercje są wykorzystywane do definiowania: • warunków początkowych – określających po-

prawne wartości parametrów wejściowych meto-dy i stanu obiektu, niezbędnych dla poprawnego działania metody;

• warunków końcowych – określających poprawne wartości parametrów wyjściowych metody i sta-nu obiektu gwarantowanych po zakończeniu działania metody;

• niezmienników klas – określających dopuszczal-ne stany wystąpień klasy przez cały czas ich ży-cia.

Page 17: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Specyfikacja poprawności oprogramowania

Przykład:

Warunek początkowy: { x >= 0 } Program: x := x + 5 Warunek końcowy: { x >= 5 }

Warunki początkowe i końcowe związane z metodami klasy opisują kontrakt miedzy klasą (modułem) i jej klien-tami. Kontrakt ten wiąże klasę tak długo, jak wywołania metod klasy spełniają warunki początkowe. Wtedy klasa powinna zagwarantować, że jej stan końcowy i parame-try wyjściowe są zgodne warunkami końcowymi.

• Niespełnienie warunków początkowych oznacza błąd po stronie klienta klasy.

• Niespełnienie warunków końcowych oznacza błąd po stronie dostawcy klasy.

Formuła poprawności oprogramowania – logika Hoare’a:

{ V } S { P } Jeżeli warunek początkowy V (hipoteza) jest spełniony bezpośrednio przed wykonaniem programu S, wtedy warunek końcowy P (teza) będzie spełniony po wyko-naniu programu S.

Page 18: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Użyteczność formuły poprawności

Użyteczność formuły poprawności jest zależna od jej si-ły. Siła formuły poprawności oprogramowania jest od-wrotnie proporcjonalna do siły warunku początkowego i wprost proporcjonalna do siły warunku końcowego.

1. { False } S { … }

Warunek początkowy False jest najsilniejszą możliwą asercją. Warunek ten nigdy nie jest spełniony, nieza-leżnie od stanu początkowego. Każde wywołanie S będzie niepoprawne. W związku z tym, każdy pro-gram jest poprawny z powyższą specyfikacją. { False } null { … } { False } for i =1 to 100 do y := y + y i ; end; { … }

2. { True} S { … }

Wszystkie wywołania modułu S są poprawne.

3. { … } S { True }

Warunek końcowy True jest najsłabszą możliwą asercją. Każde pomyślne zakończenie programu S jest poprawne niezależnie od jego wyniku.

4. { x >= 9 } y := x + 5 { y = x + 5 }

Powyższy warunek końcowy jest przykładem bardzo silnej asercji. Dla danej wartości początkowej x ist-nieje tylko jedno poprawne rozwiązanie.

Page 19: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Asercje w języku Eiffel Asercje umożliwiają na deklaratywną specyfikację wa-runków poprawności semantyczne kodu programów: class STACK [G] – składnia Eiffel item: G is

require -- warunki początkowe not_empty: not empty

do …

end put (x: G) is

require -- warunki początkowe not_full: not full -- wymaganie implementacji

do …

ensure -- warunki końcowe not_empty: not empty added_to_top: item = x one_more_item: count = old count + 1

end remove is

require -- warunki początkowe not_empty: not empty

do …

ensure -- warunki końcowe not_full: not full one_fewer_item: count = old count – 1

end end

Page 20: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Asercje a defensywny styl programowania

Deklaratywna definicja warunków poprawnego wykona-nia: zamiast proceduralnej implementacji wykrywania i ob-sługi błędów:

class STACK [G] … remove is

require -- warunki początkowe not_empty: not empty

do …

ensure -- warunki końcowe not_full: not full one_fewer_item: count = old count – 1

end end

class STACK [G] … remove is

do if empty then

print (“Błąd: próba pobrania z pustego stosu”)else

count := count – 1 end

end

Page 21: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Niezmienniki klas Warunki początkowe i końcowe są cechami poszczegól-nych metod klasy. Niezmienniki klas są cechami całej klasy, to znaczy muszą być spełnione przez wszystkie metody klasy.

S1 S2 S4S3

s.new s.put(x) s.put(y) s.item s.remove

cykl życia obiektu

class STACK [G] … invariant

count_non_negative: count >= 0 count_bounded: count <= capacity consistent_with_array_size: capacity = array.size empty_if_no_elements: empty = (count = 0) item_at_top: (count>0) implies (array(count) = item)

end

Page 22: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Asercje w Javie Asercja jest instrukcją języka służącą do testowania za-łożeń programisty, co do stanu programu w określonym momencie jego działania.

Każda asercja zawiera wyrażenie logiczne, które w po-prawnym stanie programu powinno być prawdziwe. Nie-spełnienie asercji jest zgłaszane jako specjalny wyjątek.

Składnia: assert wyrażenie_logiczne;

lub assert wyrażenie_logiczne: wyrażenie;

Drugi argument (wyrażenie) umożliwia przekazanie dodatkowych informacji do procedury obsługi błędu.

Page 23: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Typowe zastosowania asercji • Niezmienniki wewnętrzne – kontrola wewnętrznej

poprawności programów • Niezmienniki przepływu sterowania – kontrola po-

prawności • Warunki początkowe, końcowe i niezmienniki klas

– programowanie przez kontrakt

Niezmienniki wewnętrzne Zamiast: if (i % 3 == 0) { ... } else if (i % 3 == 1) { ... } else { // tu wiemy, że (i % 3 == 2) ... }

Powinno być: if (i % 3 == 0) { ... } else if (i % 3 == 1) { ... } else { assert i % 3 == 2 : i; ... }

Page 24: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Niezmienniki przepływu sterowania

Zastosowanie asercji false w miejscu programu, do którego nigdy nie powinno znaleźć się sterowa-nie. void funkcja() { for (...) { if (...) return; }

// Sterowanie nigdy nie powinno osiągnąć // tego punktu

assert false; }

Page 25: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Warunki początkowe, końcowe i niezmienniki klas

class Stos { static final int PUSTY = -1; private Object magazyn [ ]; private int rozmiar; private int szczyt_stosu; ... public Object push (Object element) { assert szczyt_stosu < rozmiar – 1; magazyn[++szczyt_stosu]=element; return element; assert szczyt_stosu != PUSTY; } public Object pop ( ) { assert szczyt_stosu != PUSTY return magazyn[szczyt_stosu--]; } }

Page 26: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Włączanie i wyłączanie asercji Ze względów wydajnościowych asercje domyślnie nie są weryfikowane w trakcie działania programu. Programista musi explicite zażyczyć sobie weryfikacji asercji podczas kompilacji programu za pomocą opcji:

-enableassertions lub –ea

Argument tej opcji określa zasięg weryfikacji asercji:

• brak argumentów – weryfikacja asercji we wszystkich klasach programu (za wyjątkiem klas systemowych)

• nazwa pakietu – we wszystkich klasach danego pa-kietu

• nazwa klasy – w danej klasie

java -ea:com.wombat.fruitbat... BatTutor

Weryfikacja asercji w klasach systemowych jest odblo-kowywana za pomocą przełącznika:

-enablesystemassertions lub -esa

Page 27: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Stosowanie asercji języku Java • Asercje powinny być używane głównie w czasie

debugowania kodu, ponieważ aerscje zgłaszają predefiniowany typ wyjątku AssertionError.

• Można zablokować wyłączenie asercji static { boolean assertsEnabled = false; assert assertsEnabled = true; if (!assertsEnabled) throw new RuntimeException("Asserts

must be enabled!!!"); }

• W ramach asercji nie wolno wykonywać fragmentów użytkowego kodu

// akcja jest zawarta w asercji assert names.remove(null);

// akcja wyciągnięta przed asercję // działa niezależnie od uaktywnienia asercji

boolean nullsRemoved = names.remove(null); assert nullsRemoved;

• Poprawna redefinicja asercji w łańcuchu

dziedziczenia nie jest wspierana przez kompilator, odpowiedzialność spoczywa na programiście.

Page 28: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Asercje w języku C++

W języku C++ dostępne jest makro: assert(). Służy ono do diagnostyki działania programów. W przypadku niespełnienia warunku logicznego podanego jako argu-ment makra, do standardowego strumienia stderr wy-słany będzie odpowiedni komunikat i następnie zostanie wywołana funkcja abort(). Przykład: #include <stdio.h> #include <assert.h> int main () { FILE * datafile; datafile=fopen ("file.dat","r"); assert (datafile);//czy udało się otworzyć plik  // jakieś działania na pliku ... fclose (datafile); return 0; }

Page 29: Programowanie za pomocą kontraktówfc.put.poznan.pl/materials/138-7---programowanie-przez...przez o atastro z raki dek 2:34 G ujana F any-ficera fy było ety Aria rak MT; m rancus

Asercje w języku C#

W języku C# w czasie testowania programów można ko-rzystać z klasy systemowej Debug. Jedną z metod tej klasy jest metoda Assert. public static void MyMethod(Type type, Type baseType) { Debug.Assert(type != null,

"Type parameter is null", "Can't get object for null type"); // Perform some processing. }