SW_03 Implementace a testování
Implementace Cílem implementace je doplnit navrženou architekturu (kostru) aplikace o programový kód a vytvořit tak kompletní systém. Implementační model specifikuje jak jsou jednotlivé elementy (objekty a třídy) vytvořené v etapě návrhu implementoványve smyslu softwarových komponent, kterými jsou zdrojové kódy, spustitelné kódy, data a podobně. 2
Implementace Softwarová komponentaje definována jako fyzicky existujícía zaměnitelnáčást systému vyhovující požadované množině rozhraní a poskytující jejich realizaci. 3
SW komponenty Podle typu softwarových komponent hovoříme ozdrojovém kódu-částech systému zapsaném v programovacím jazyce, binárním kódu-(přeloženém do strojové kódu procesoru) a spustitelném kódu,ostatních částech reprezentovaných databázovými tabulkami, dokumenty apod. 4
SW komponenty Jestliže jsme ve fázi analýzy a návrhu pracovali pouze s abstrakcemidokumentovanýmiv podobě jednotlivých diagramů, pak v průběhu implementace dochází k jejich fyzickérealizaci. Implementační model se tedy také zaměřuje na specifikacitoho, jak budou tytokomponenty fyzicky organizovány podle implementačního prostředía programovacího jazykaposkytujícího konkrétní mechanizmus strukturovánía modularizace. 5
SW komponenty Ke splnění těchto cílů nabízí jazyk UML prostředky, kterými jsou v tomto případě tyto dva následující diagramy: Diagram komponent ilustrující organizaci a závislosti mezi softwarovými komponentami. Diagram nasazení upřesněný nejen ve smyslu konfigurace technických prostředků, ale především z hlediska rozmístění implementovaných softwarových komponent na těchto prostředcích. 6
Mapování elementů logického modelu na komponenty Důsledná a přesná specifikaceobjektů a jejich tříd v etapě návrhu umožňuje automatické generování zdrojových kódů dle následující tabulky. Tabulka má dva sloupce, první z nich odpovídá elementům jazyka UML, druhý popisuje jejich zobrazení v programovacím jazyce (Java). 7
Tabulka mapování 8
Mapování elementů logického modelu na komponenty Jediné co nelze přímo odvodit z diagramů UML jsou těla metod, kód který je proveden v odezvě na přijatou zprávu a také jaká je fyzická struktura vytvářených souborůreprezentujících softwarové komponenty. Vše ostatní lze automaticky vygenerovat doslova bez účasti týmu programátorů. Pro názornost, z následujícího diagramu tříd se pokusíme vytvořit požadované softwarové komponenty. 9
Diagram tříd 10
Zdrojové, binární a spustitelné komponenty Ukázka vytvoření komponent se zahájí částí týkající se zdrojových komponent, tedy souborů vytvořených pomocí použitého programovacího jazyka. První krok bude rozhodnout o fyzické organizacitěchto zdrojových souborů definovaných pomocí diagramu komponent. 11
Diagram komponent-zdrojový kód 12
Příklad Z výsledného diagramu tříd specifikující jádro aplikace prodeje automobilu vytvořme diagram komponent. Třídy Automobil, Objednávka, Sklad, Vybranýa Specifikovanýbudou každá obsažena v samostatném souboru totožného názvu s koncovkou.javaoznačující, že se jedná o kód zapsaný v programovacím jazyce Java. Hierarchii tříd popisující část doplňků (s využitím návrhového vzoru Kompozit) umístíme do jediného souboru odpovídající svým názvem supertřídědoplněk. 13
Příklad Relace závislosti nazvané jako <<import>> označují použití komponent z jiných subsystémů(balíčků), zatímco relace nazvané jako <<friend>> označují, že dané komponenty spadají do společného balíčku. V jazyce Java to znamená, že se nacházejí jejich soubory ve společném adresáři. 14
Příklad Pokud máme k dispozici vývojové nástroje typu CASE(Computer AidedSoftware Engineering), pak lze nechat tyto zdrojové kódy takovým nástrojem vygenerovat. Postup vytváření zdrojových kódů vychází z tabulky mapování elementů jazyka UML na zdrojový kód jazyka Java. Jediné co je nutné doplnit, co nelze automaticky či jednoduše vytvořit, jsou těla metod reprezentované algoritmy operací. 15
Příklad Tyto lze alespoň hrubým způsobem specifikovatjednak ze sekvenčních diagramů definujících operace, ale především pak ze stavových diagramů popisujících detailně chování objektů. 16
Zdrojový kód Objednávka 17
Implementace tříd Třída Objednávka využívá tříd Automobil a Sklad umístěných v balíčcích auta a sklad. Proto dle specifikace v diagramu komponent je nutné tyto třídy importovat. Atributy zákazníka cenajsou implementovány v podobě instančních proměnných stejně jako asociace na instance jiných tříd pojmenované jako specifikovaný, vybraný(jména rolí instance třídy Automobil) a sklad. Metody, jak vyplývá z diagramu tříd, jsou dvě vyplň a vlož. 18
19
Implementace tříd Za pozornost v této části implementace stojí způsob, jakým jazyk Java realizuje rozhraní. K tomuto účelu slouží klíčové slovo implements, které v definici třídy specifikuje, která rozhraní (v našem případě Vybranýs Specifikovaný) jsou v rámci dané třídy implementována. Z hlediska samotné třídy platí, že musí definovat metody deklarované v rámci rozhraní, tedy specifikace z rozhraní Specifikovaný a jerezervována rezervujz rozhraní Vybraný. V případě chybějících implementací těchto metod překladač jazyka Java bude hlásit chybu. 20
21
Implementace tříd Poslední z příkladů implementace zdrojových komponent dokumentuje způsob jakým je v jazyce Java řešena relace generalizace (dědičnost). Jedná se použití klíčového slova extends, které uvozuje supertřídudané třídy. Tedy např. třída Výbavaje podtřídou třídy Doplněk. 22
Komponenty Binární komponenty (komponenty přeložené do strojového kódu daného procesoru) mají také svůj diagram komponent obvykle vyjadřující z jakých zdrojových souborů jsou požadované binární vytvořeny. 23
Binární komponenty 24
Diagram komponent: běh programu 25
Příklad V našem příkladu ke spuštění třídy Databáze autpotřebujeme jednak virtuální stroj jazyka Java (java.exe) a jeho knihovny (rt.jar). Konfigurační parametry fontů jsou uloženy v textovém souboru (font.properties). Samotná aplikace využívá služeb databázového serveru (sql.exe) pracujícího s databází aut strukturovanou v relačních tabulkách (Automobily). 26
Implementace Posledním úkolem, který činí etapu implementace kompletní je zpřesnění diagramů nasazení. Vlastní zpřesnění spočívá v umístění spustitelnýcha datovýchkomponentna jednotlivé technické prostředky reprezentované počítači. 27
28
Testovánía nasazení SW produktu Testování se provádí z pohledu tří základních dimenzí reprezentovaných kvalitou, funkcionalitou a výkonností systému. Testování se týká všech vytvářených modelů a jejich diagramů. 29
Testování Principy používané při testování jsou následující: Testy se plánují pro každou iteraci a zahrnují integrační testy a testy systémové. Integrační testy se provádí pro každý vytvořený produkt během iterace, zatímco systémový test se provádí pouze na konci iterace, kdy vzniká spustitelná verze vyvíjeného produktu. 30
Testování Testy se navrhují a následně implementují v podobě testovacích úloh, které jednoznačně definují co se má ověřit. Hovoříme o testovacích procedurách, které specifikují jak se má test provádět, nebo se vytváří spustitelné testovací komponenty umožňující automatizaci procesu ověřování. 31
Testování Výsledky provedených testů jsou systematicky zpracovávány a vadné části jsou opakovaně testovány a případně zaslány zpět do toků činností jako je analýza, návrh nebo implementace s cílem nedostatky odstranit. 32
Cíle procesu verifikace a validace Verifikaceje proces testování hledající odpověď na otázku, zda-lisoftwarový produkt je vytvářen správně. Jinak řečeno, hledáme nedostatkyv samotném softwarovém systému. Validaceje proces testování hledající odpověď na otázku, zda-livytvářený software je správný. Jinými slovy, zda-li implementuje požadovanou funkcionalitu. 33
Verifikace a validace Z uvedeného vyplývá, že může nastat situace, kde systém je perfektně verifikován, ale je k ničemu, neboť nesplňuje zadavatelem specifikovanou funkcionalitu. Na druhou stranu systém splňuje všechny funkce, ale je nestabilní nebo pomalý. 34
Verifikace a validace Kromě verifikace a validace také rozlišujeme mezi statickým a dynamickým ověřováním: Statické techniky se zabývající testováním vytvořených modelů a jejich diagramů, čili umožňují pouze ověřit korespondenci mezi vytvořeným systémem a jeho specifikací. 35
Verifikace a validace Dynamické techniky zkouší již implementovaný produkt cestou jeho spuštění a tímověřují i jeho užitečnost a kvalitu. 36
Modelytestování Na rozdíl od předchozích modelů, které byly definovány různými typy diagramů, pro testování nemá jazyk UML k dispozici žádný diagram. Model testování je dán souborem: testovacích úloh definujících co se má u systému testovat, testovacích procedur specifikujících postupy pro provedení testovacích úloh, testovacích komponent, které automatizují testovací procedury. 37
Testovací úloha Testovací úloha specifikuje způsob testování systému zahrnující informace o tom, co se má testovat s jakými vstupy a za jakých podmínek. 38
Testovací úloha funkční test V podstatě existují dva typy nejběžněji používaných testovacích úloh: 1. Testovací úlohy určené k ověření případů užití nebo jejich specifických scénářů. Takové úlohy ověřují výsledky interakce aktéra se systémem. Tento tzv. black-box test ověřuje z vnějšku pozorovatelné chování systému. 39
Testovací úloha konstrukční test 2. Testovací úlohy specifikující jak ověřovat realizaci případů užití. Tyto úlohy ověřují interakce mezi komponentami implementující případ užití. Tento tzv. white-box test je určen k ověření vnitřní interakcí daného systému. 40
Testovací procedura Testovací proceduraspecifikuje jak provést jednu nebo více testovacích úloh nebo jejich částí. Testovací procedury lze specifikovat pomocí: instrukcí popisujícími jak ručně provést danou testovací úlohu, popisu jak vytvořit spustitelnou testovací komponentu, specifikace jak použít nástroj pro automatické testování. 41
Testovací komponenty Testovací komponenty automatizují jednu nebo více testovacích procedur nebo jejich části. Testovací komponenty jsou používány k ověření komponent tvořících implementační model cestou poskytnutí požadovaných vstupů, řízení a sledování běhu ověřované komponenty a vytvoření výsledné zprávy o průběhu testu. K vytvoření testovacích komponent se mohou používat různé skriptovací jazyky nebo k tomuto účelu vytvořené systémy automatizované verifikace. 42
JUnitpřiklad na použití
Zadání příkladu Převod mezi římskými a arabskými číslicemi. Platí následující pravidla: hodnoty písmen se až na výjimky sčítají (I, II, VIII) Písmena vyjadřující mocniny se mohou opakovat max. 3. Písmena vyjadřující 5, 50, 500 se neopakují. Písmena římského čísla se vyjadřují od největšího po nejmenší, záleží na pořadí.
Zadání příkladu Pro každou hodnotu existuje pouze jeden správný zápis římskými číslicemi. Pomocí římských číslic lze zapsat čísla v rozsahu 1 3999.
Vytvoření kostry třídy Třída Roman bude obsahovat dvě statické metody pro převod toroman(int)a fromroman(string). bude-li vstupní parametr toroman(int)mimo rozsah, vyvolá se výjimka IllegalArgumentException. bude-li argument metody fromroman(string) obsahovat nepřípustný znak, vyvolá se výjimka NumberFormatException.
public class Roman { public static int fromroman(string s) throws NumberFormatException { int vysl = 0; return vysl; public static String toroman(int i) throws IllegalArgumentException { String vysl= ""; return vysl; 47
public class RomanTest extends TestCase{ public RomanTest(String name) { // musí specifikovat konstruktor super(name); protected void setup() { // počáteční nastavení protected void teardown() { // úklid po testování // testy postupně doplnované... // obyčejně deklarovaná statická metoda suite // v jejímž rámci se vytvoří seznam testů public static Test suite() { return new TestSuite(RomanTest.class); public static void main(string[] args) { junit.textui.testrunner.run(suite()); 48
// Pro vytvoření seznamu testů se většinou používá příkaz: return new TestSuite(RomanTest.class); //do seznamu testů se zahrnou všechny metody začínající řetězcem test // preferovaný způsob TestSuite seznamtestu = new TestSuite(); seznamtestu.addtest(new RomanTest( testtoromanknownvalues ); seznamtestu.addtest(new RomanTest( testfromromanknownvalues );... return seznamtestu; 49
Testy správnosti nadefinujeme dva testy: testtoromanknownvalues() a testfromromanknownvalues()
class Dvojice { int arab; String roman; Dvojice(int arab, String roman) { this.arab = arab; this.roman = roman; ; Dvojice knownvalues[] = { new Dvojice(1,"I"), new Dvojice(2,"II"), new Dvojice(3,"III"), new Dvojice(4,"IV"), new Dvojice(5,"V"), new Dvojice(6,"VI"), new Dvojice(7,"VII"), new Dvojice(8,"VIII"), new Dvojice(9,"IX"), new Dvojice(10,"X"), new Dvojice(50,"L"), new Dvojice(100,"C"), new Dvojice(500,"D"), new Dvojice(1000,"M"), new Dvojice(31,"XXXI"), new Dvojice(148,"CXLVIII"), new Dvojice(3940,"MMMCMXL"), new Dvojice(3999,"MMMCMXCIX"), ; 51
public void testtoromanknownvalues() { for(int i=0; i<knownvalues.length; i++){ String vysl= Roman.toRoman(knownValues[i].arab); assertequals(knownvalues[i].roman, vysl); public void testfromromanknownvalues() { for(int i=0; i< knownvalues.length; i++){ int vysl= Roman.fromRoman(knownValues[i].roman); assertequals(knownvalues[i].arab, vysl); 52
Testy výjimek Testy výjimek otestují, zda se v případě chybných vstupních parametrů bude zahlášena chyba metody. Odchytávání výjimek se provádí v kódu testu, v Odchytávání výjimek se provádí v kódu testu, v případě, že se výjimka neobjeví, ohlásí se chyba pomocí metody JUnit fail(string textchyby)
public void testtoromanexception() { int badvalues[] = {0, -1, 4000; for(int i=0; i<badvalues.length; i++){ try{ String vysl= Roman.toRoman(badValues[i]); catch(illegalargumentexception e) { continue; fail("expected IllegalArgumentException"); // test vyjimky public void testillegalcharacters() { String badvalues[] = {"I ", "i", "a", "mm", "d", "MCi"; for(int i=0; i< badvalues.length; i++) { try { int vysl= Roman.fromRoman(badValues[i]); catch (NumberFormatException e) { continue; fail("expected IllegalArgumentException for: "+ badvalues[i]); ; 54
public void testsanity() { for(int i= 1; i< 4000; i++){ int vysl = Roman.fromRoman(Roman.toRoman(i)); assertequals(i, vysl); 55
Vlastní třída a testování Do třídy Roman metody toroman() -doplnit test intervalu hodnot public static String toroman(int i) throws IllegalArgumentException { if((i>3999) (i<= 0)) throw new IllegalArgumentException(); else { return vysl;
Vlastní třída a testování Dále je třeba doplnit třídu Dvojice a tabulku pro převod a doplnit odpovídajícím způsobem metodu toroman() Výpis třídy Roman Výpis třídy RomanTest
public class Roman { public static int fromroman(string s) throws NumberFormatException { int vysl = 0; return vysl; public static String toroman(int i) throws IllegalArgumentException { if((i>3999) (i<= 0)) throw new IllegalArgumentException(); else { int cislo =i; String vysl= ""; while(cislo >0) { for(int j=0; j< tabulka.length; j++){ if(cislo >= tabulka[j].arab) { vysl= vysl+ tabulka[j].roman; cislo= cislo- tabulka[j].arab; break; return vysl; static class Dvojice { int arab; String roman; Dvojice(int arab, String roman){ this.arab = arab; this.roman = roman; 58
static Dvojice tabulka[] = { new Dvojice (1000, "M"), new Dvojice (900, "CM"), new Dvojice (500, "D"), new Dvojice (400, "CD"), new Dvojice (100, "C"), new Dvojice (90, "XC"), new Dvojice (50, "L"), new Dvojice (40, "XL"), new Dvojice (10, "X"), new Dvojice (9, "IX"), new Dvojice (5, "V"), new Dvojice (4, "IV"), new Dvojice (1, "I"), ; 59
public class RomanTest extends TestCase{ class Dvojice { int arab; String roman; Dvojice(int arab, String roman) { this.arab = arab; this.roman = roman; ; Dvojice knownvalues[] = { new Dvojice(1,"I"), new Dvojice(2,"II"), new Dvojice(3,"III"), new Dvojice(4,"IV"), new Dvojice(5,"V"), new Dvojice(6,"VI"), new Dvojice(7,"VII"), new Dvojice(8,"VIII"), new Dvojice(9,"IX"), new Dvojice(10,"X"), new Dvojice(50,"L"), new Dvojice(100,"C"), new Dvojice(500,"D"), new Dvojice(1000,"M"), new Dvojice(31,"XXXI"), new Dvojice(148,"CXLVIII"), new Dvojice(3940,"MMMCMXL"), new Dvojice(3999,"MMMCMXCIX"), ; 60
public RomanTest(String name) { super(name); protected void setup() { protected void teardown() { // testy postupne doplnovane public void testtoromanknownvalues() { for(int i=0; i<knownvalues.length; i++){ String vysl= Roman.toRoman(knownValues[i].arab); assertequals(knownvalues[i].roman, vysl); public void testfromromanknownvalues() { for(int i=0; i< knownvalues.length; i++){ int vysl= Roman.fromRoman(knownValues[i].roman); assertequals(knownvalues[i].arab, vysl); 61
// test vyjimky public void testtoromanexception() { int badvalues[] = {0, -1, 4000; for(int i=0; i<badvalues.length; i++){ try{ String vysl= Roman.toRoman(badValues[i]); catch(illegalargumentexception e) { continue; fail("expected IllegalArgumentException"); // test vyjimky public void testillegalcharacters() { String badvalues[] = {"I ", "i", "a", "mm", "d", "MCi"; for(int i=0; i< badvalues.length; i++) { try { int vysl= Roman.fromRoman(badValues[i]); catch (NumberFormatException e) { continue; fail("expected IllegalArgumentException for: "+ badvalues[i]); ; 62
public void testtoomanyrepeatednumerals() { String badvalues[] = {"MMMM", "VV", "LL", "CCCC", "DD", "IIII"; for(int i=0; i< badvalues.length; i++) { try { int vysl= Roman.fromRoman(badValues[i]); catch (NumberFormatException e) { fail("expected IllegalArgument for: "+ badvalues[i]); ; public void testrepeatedpairs() { String badvalues[] = {"CMCM", "CDCD", "IVIV", "IXIX", "XLXL"; for(int i=0; i< badvalues.length; i++){ try { int vysl= Roman.fromRoman(badValues[i]); catch (NumberFormatException e){ continue; fail("expected IllegalArgumentException for: "+ badvalues[i]); 63
public void testmalformedantecedent() { String badvalues[] = {"IIMMCC", "VX", "DCM", "CMM", "CMD", "IXIV", "MCMC", "XCX", "IVI", "LM", "LD", "LC"; int vysl; for(int i= 0; i< badvalues.length; i++ ){ try { vysl= Roman.fromRoman(badValues[i]); catch(numberformatexception e){ continue; fail("expected IllegalArgumentException for: "+ badvalues[i]+ " (" + vysl); ; public void testsanity() { for(int i= 0; i< 4000; i++){ int vysl = Roman.fromRoman(Roman.toRoman(i)); assertequals(i, vysl); 64
// zaklad public static Test suite() { return new TestSuite(RomanTest.class); public static void main(string[] args) { junit.textui.testrunner.run(suite()); 65
Typování Abstrakce představuje nejdůležitější princip pro opětovnou použitelnost. Jedná se o nahrazení konkrétní datové entity, abstraktnější datovou entitou. Uvedená abstrakce nabývá většinou jedné ze dvou následujících forem: generalizace typování
Generalizace Generalizací se rozumí zobecnění specializované datové entity do obecnější datové entity; mezi těmito entitami se stanoví relace generalizace. Specifické vlastnosti relace generalizace: existuje jen mezi datovými entitami (třídami), nepřenáší se na instance, způsobuje dědění datových atributů a relací z obecnější do specializovanější datové entity, každá instance od obecnější entity dědí pouze strukturu datových atributů, nikoli však obsah,
Generalizace je to relace typu nebo existuje-li k jedné obecnější datové entitě více specializovanějších entit, daná instance se vytvoří právě k jedné z nich.
Diagramy Osoba a Lokalita Osoba atributy: jméno, rok narození Muž atributy: počet manželek (zdědí jméno, rok narození) Žena atributy: počet narozených dětí (zdědí jméno, rok narození)
Typování Při typování se místo obecnější datové entity definuje datová entita, která reprezentuje typ této datové entity. Tím, že se při typování obecnější datová entita specializuje ne datovou entitou jako při generalizaci, ale instancemi typové datové entity, vytvořená instance dědí nejen strukturu datových atributů obecnější datové entity, ale zároveň i jejich obsah. Uvedené datové entity jsou spojeny asociací. První příklad typování osob, druhý příklad typování lokalit.
Typování osob a lokalit TypOsobyjsou instance Muž(jméno, rok narození, počet manželek) a Žena(jméno, rok narození, počet narozených dětí) a instance od třídy Osoba pak patří buď pod Muže nebo Ženu. Hodnoty datových atributů zůstávají stejné pro všechny specializované instance.
Objednávka / Produkt (lepší příklad) ProductType (Objednávka) obsahuje všechny plánované položky (plánovaná váha, plánované složení příměsí). Instance od ProductTypepak představují různé objednávky lišící se různou hodnotou plánovaných položek. Instance od třídy Productjsou vždy svázány s konkrétní instancí třídy ProductTypea liší se v hodnotách skutečných položek (skutečná váha, skutečné složení příměsí).
Typování& generalizace 1/2 Typování je podobné generalizaci. V obou případech je využit princip obecnější datové entity. Při generalizaci se tato obecnější datová entita specializuje pomocí konkrétnějších datových entit. Při typování se obecnější datová entita specializuje instancemi typové datové entity. Při typování tak instance typové datové entity odpovídají konkrétnějším datovým entitám u generalizace.
Typování & generalizace 2/2 Typování se používá v případě, že seznam typů se mění a je malá důležitost dědění. Generalizace se používá v případě, že seznam specializovanějších entit statický a je větší důležitost dědění. Při generalizaci instance specializovanější datové entity dědí strukturu datových atributů od obecnější datové entity. Při typování specializovanější instance dědí od obecnější instance nejen strukturu datových atributů, ale zároveň i jejich obsah.
Typování Datové entity typ se vzájemnými relacemi patří do meta úrovně (směrnice, obecné zákony). Standardní entity vyjadřují operační úroveň (každodenní skutečnost). Mezi operativní úrovní a metaúrovníexistuje vzájemný vztah operativní úroveň zachycuje konkrétní případy, které musí (měly by být) splňovat pravidla předepsaná metaúrovní.
Stratifikované typování Instance od třídy TypUniversityjsou např. VŠB-TU,SU nebo OU. Ty mají konkrétní různé hodnoty jmen rektorů. V rámci instancí VŠB-TU se pak vytváří instance EkF, nebo FEI se svými děkany a společným rektorem. Pro SU a OU je to podobné. V rámci instancí fakult se vytváří konkrétní instance kateder např. katedra matematických metod, informatiky v ekonomii pro EkFnebo informatiky a matematiky pro FEI.
Relace mezi pracovními kategoriemi a pracovními vztahy Generalizace nepružné řešení Typování vhodné řešení
Flexibilní reprezentace organizační struktury Podobné řešení platí i pro organizační strukturu firem. Výsledné řešení odpovídá vzorům z článku o politikách
public class Objednavka { private int plancas; private double planmnozstvi; private Koruny plancena; public Objednavka(int cas, double mnozstvi, Koruny castka) { plancas = cas; planmnozstvi = mnozstvi; plancena = castka; public int getplancas() { return plancas; public double getplanmnozstvi() { return planmnozstvi; public Koruny getplancena() { return plancena; public String tostring() { return String.format("Planovany cas: %d planovane mnozstvi: %.2f planovana cena: %s", getplancas(), getplanmnozstvi(), getplancena().tostring()); public void tisk() { System.out.println(this.toString()); 79
public class Skutecnost { private int skutcas; private double skutmnozstvi; private Koruny skutcena; public Skutecnost(int cas, double mnozstvi, Koruny cena){ skutcas = cas; skutmnozstvi = mnozstvi; skutcena = cena; // skutcena = new Koruny(cena); public int getskutcas() { return skutcas; public double getskutmnozstvi() { return skutmnozstvi; public Koruny getskutcena() { return skutcena; public String tostring() { return String.format("%s \nskutecny cas: %d skutecne mnozstvi: %.2f " + "skutecna cena: %s", Objednavka.this.toString(), getskutcas(), getskutmnozstvi(), getskutcena().tostring()); public int rozdilcas() { return Objednavka.this.getPlanCas() - getskutcas(); Objednávka 80
public double rozdilmnozstvi() { return Objednavka.this.getPlanMnozstvi() - getskutmnozstvi(); public Koruny rozdilcena() { return Objednavka.this.getPlanCena().minus(getSkutCena()); public void tisk() { System.out.println("Plan: " + Objednavka.this.toString() + "\nskutecnost: "+ this.tostring()); public void tiskrozdilu(){ System.out.println("Rozdil cas: " +rozdilcas() + "\nrozdil mnozstvi: " + rozdilmnozstvi() + "\nrozdil cena: " + rozdilcena()); public Skutecnost getskutecnost(int cas, double mnozstvi, Koruny cena){ return new Skutecnost(cas, mnozstvi, cena); 81
public class ObjednavlaTest { public static void main(string[] args) { Objednavka objednavka = new Objednavka(12, 52.36, new Koruny(53.21)); Objednavka.Skutecnost sk1 = objednavka.getskutecnost(13, 49.83, new Koruny(55.20)); objednavka.tisk(); sk1.tisk(); sk1.tiskrozdilu(); 82