4.1! Hoe snel loopt iemand de 100 meter?!
4.2! Tijdsschatting! Analogie & Decompostie! Empirische schatting! Plan 2.0 & Plan 2.1! Conclusie! TicTacToe! Code Hergebruik => TestCase! HTML Uitvoer => polymorfisme! Undo => Lijsten & polymorfisme! 4.
4.3! "Ontwikkel" vereisten! Vereisten! Betrouwbaarheid! Aanpasbaarheid! Technieken! Testen + Contracten! Objectgericht ontwerp! Tijdsschatting!
4.4! Schatting door analogie! Analogie! Schatting = tijd gelijkaardig project! Wanneer gelijkaardig?! Zelfde probleemdomein! Zelfde mensen! Zelfde technologie! Empirisch! gespendeerde tijd voorbije projecten dient als basis voor schatting volgende!
4.5! Y! Empirische schatting (project)! y = a x b! (b ±= 1)! Schat totale duur van project op basis van vorige projecten! Ontwikkeltijd! Legende! = Voorbij! = Prognose! Grootte project! X!
4.6! Schatting door decompositie! Decompositie! Schatting = tijd componenten + integratiekost! Tijd componenten?! cfr. opgeleverde componenten! Integratiekost?! constant (mits testen en OO)! Empirisch! gespendeerde tijd eerste componenten dient als basis voor schatting volgende!
4.7! Y! Empirische schatting (component)! y = m x! Schat duur van één component op basis van opgeleverde componenten! Ontwikkeltijd component! Legende! = Opgeleverd! = Prognose! Grootte component! X!
4.8! Grootte en Tijd! x = Grootte Component?! # stappen + #uitzonderingen in use case! y = Ontwikkellingstijd?! Zie tijdsbladen! vergelijking benaderende rechte! y = mx! Na oplevering n componenten: (x n, y n )!=> m = y n / x n! Schatting y n+1 voor grootte x n+1!!=> y n+1 = m.x n+1!
4.9! Vuistregel! Empirische schatten is de basis voor een realistische planning.! Waarom?! Betere controle over aanpassingen aan de planning! Hoe?! Hou tijdsbladen nauwkeurig bij! Maak prognose op basis van gespendeerde werk in het verleden!
4.10! Use Case Grootte! player play #stappen = 5! #uitzond. = 1! grootte = 6! Use Case 1: play!! Steps! 1. Two players start up a game (First is "O"; other is "X")! 2. WHILE game not done! 2.1 Current player makes move! 2.2 Switch current player! 3. Anounce winner! Exceptions! 2.1. [Illegal Move] System issues a warning => continue from step 2.1!
4.11! Voorbeelden! Zie voorbeelden in PlanTmpl20 & PlanTmpl21!
4.12! Conclusie! Betrouwbare prognoses zijn belangrijk! Hou tijdsbladen nauwkeurig bij!! Schatten impliceert fouten! Voorzie een redelijke marge! Vertrouw niet blindelings op de cijfertjes!
4.13! Code Hergebruik! TicTacToeTest setup()! teardown()! init()! fail(msg: ARRAY OF CHAR)! should(b: BOOLEAN, msg: ARRAY OF CHAR): BOOLEAN! shouldnot(b: BOOLEAN, msg: ARRAY OF CHAR): BOOLEAN! comparefiles(filename1, filename2: ARRAY OF CHAR): BOOLEAN! testbasicplayer(verbose: BOOLEAN): BOOLEAN! testlegalmoves(verbose: BOOLEAN): BOOLEAN! testrealgame(verbose: BOOLEAN): BOOLEAN! testoutputgame(verbose: BOOLEAN): BOOLEAN! TicTacToeTest is groot! code leesbaarheid! hergebruik? copy + delete + insert! Aanpasbaarheid :(!
4.14! Code Hergebruik! UnitTest setup()! teardown()! init()! fail(msg: ARRAY OF CHAR)! should(b: BOOLEAN, msg: ARRAY OF CHAR): BOOLEAN! shouldnot(b: BOOLEAN, msg: ARRAY OF CHAR): BOOLEAN! comparefiles(filename1, filename2: ARRAY OF CHAR): UnitTest BOOLEAN! is superklasse! bevat algemene code! hergebruik? subklasse per TicTacToeTest te testen component/klasse! setup()! teardown()! init()! TicTacToeTest is subklasse! testbasicplayer(verbose: BOOLEAN): BOOLEAN! erft algemene code! testlegalmoves(verbose: BOOLEAN): BOOLEAN! overschrijft setup, init & teardown! testrealgame(verbose: BOOLEAN): BOOLEAN! bevat alleen relevante code! testoutputgame(verbose: BOOLEAN): BOOLEAN!
4.15! Vuistregel! Hollywood Principle! wij roepen jouw op als we je nodig hebben! Waarom?! Uitbreiding van bibliotheken via subklasses! Hoe?! Superklasse in bibliotheek legt protocol van oproepen vast! Subklassen kunnen gedrag uitbreiden!
Generisch Unittest Protocol! : UnitTest object under test 2.16! setup("testxxx") testxxxx() UnitTest setup(testcase:!array OF CHAR)! run()! teardown()! should ( ): BOOLEAN! shouldnot ( ): BOOLEAN! run()! NEW(); init(); xxx1ststimulus! shouldnot(xxx1stobservation)! xxx2ndstimulus! should(xxx2ndobservation)! Evaluatie Criteria! Obj. Collaboratie! teardown() Betrouwbaarheid!
4.17! Vuistregel! Klassen die vaak herbruikt worden hebben preciese contracten! Waarom?! Betere betrouwbaarheid door precieze beschrijving interface! Hoe?! Leg de normale volgorde van oproepen vast! Specifieer volgorde via de respectievelijke pre- en postcondities!
4.18! Oproepvolgorde voor UnitTest! Initialized! Init()! SetUp()! Setup! Run()! Running! TornDown! TearDown()!
4.19! PROCEDURE (atest : UnitTest) Init;! Contracten voor UnitTest!!(* postcondition (120): atest^.isinitialized() *)!(* postcondition (120): ~ atest^.issetup() *)!!(* postcondition (120): ~ atest^.isrunning() *)!(* postcondition (120): atest^.istorndown() *)! PROCEDURE (atest : UnitTest) SetUp (testcase: ARRAY OF CHAR);!!(* precondition (100): atest^.isinitialized() *)!(* precondition (100): atest^.istorndown() *)!!(* precondition (100): LEN(testCase) < MaxTestCaseLength *)!!(* postcondition (120): atest^.issetup() *)!(* postcondition (120): ~ atest^.istorndown() *)! PROCEDURE (atest : UnitTest) Run;!!(* precondition (100): atest^.isinitialized() *)!(* precondition (100): atest^.issetup() *)!!(* postcondition (120): ~ atest^.issetup() *)!(* postcondition (120): atest^.isrunning() *)! PROCEDURE (atest : UnitTest) TearDown;!!(* precondition (100): atest^.isinitialized() *)!(* precondition (100): atest^.isrunning() *)!!(* postcondition (120): ~ atest^.isrunning() *)!(* postcondition (120): atest^.istorndown() *)!
4.20! Vuistregel! Schrijf testcode als subklasse(n) van UnitTest! Waarom?! Betere onderhoudbaarheid van de testcode! Hoe?! Maak een subklasse van UnitTest per te testen component! Overschrijf Init(), SetUp(), TearDown(), Run ()!
4.21! HTML Uitvoer (TTT16b)! player play <<extends>> play HTML output Use Case 3: play HTML output! Extension of use case 1! Steps! use case 1 + additional steps! afer 2.2! during 3! 2.3 write game on HTML (table)! 3 write winner on HTML text! (Erg gelijkaardig aan use case 2)! => inheritance & polymorfisme?!
4.22! PROCEDURE (atictactoe: TicTacToe) writehtmlon* (VAR w: Texts.Writer);!! BEGIN!!Texts.WriteString(w, "<P>");!!!Texts.WriteString(w, "TicTacToe game after move ");!!Texts.WriteInt(w, atictactoe.nrofmoves, 0);!!Texts.WriteString(w, "</P>");Texts.WriteLn(w);!!Texts.WriteString(w, "<TABLE BORDER>");Texts.WriteLn(w);!!FOR i := 0 TO 2 DO!!!Texts.WriteString(w, " <TR>");Texts.WriteLn(w);!!!FOR j := 0 TO 2 DO!!!!Texts.WriteString(w, " <TD>");!!!!!!!!END;! "Ongeveer" gelijk! aan writeon! => duplicatie!
4.23! PROCEDURE (atest: TicTacToeTest) testoutputgame* (!!!writehtml: BOOLEAN): BOOLEAN;!!!IF writehtml THEN!!!!Texts.WriteString(w, "<HTML>");Texts.WriteLn(w);!!!Texts.WriteString(w, "<HEAD>");Texts.WriteLn(w);!!!!!END;!!WHILE atest.agame.notdone() DO!!!aTest.aGame.doMove();!!!IF writehtml THEN atest.agame.writehtmlon(w);!!!!else atest.agame.writeon(w); END;!!END;!!IF writehtml THEN!!!Texts.WriteString(w, "</BODY></HTML>");Texts.WriteLn(w);!!END;!!!! => complexe conditionele logica!
4.24! Vuistregel! Vermijd code duplicatie! & complexe logica! Refactor:! code duplicatie: gelijkaardige code in de superklasse; verschillen in subklassen! complexe logica: normaal geval in de superklasse; speciale gevallen in de subklassen!
4.25! TicTacToe! TicTacToe writeon()! writehtmlon()! TicTacToeTest! TicTacToeTest testoutputgame()! Splits Klassen (TTT16)! TicTacToeOutput! Evaluatie Criteria! printobjecten/iterators! TicTacToeOutput startpage()! endpage()! startboard()! endboard()! startrow(row: CHAR)! endrow()! boardlocation(row, column, marker: CHAR)! TicTacToeHTMLOutput
PROCEDURE (atest: TicTacToeTest) testoutputgame* (!!!writehtml: BOOLEAN): BOOLEAN;!!!Texts.OpenWriter(w);!!output.init ();!!output.startpage(w);!!while atest.agame.notdone() DO!!!aTest.aGame.doMove();!!!aTest.aGame.writeOn(w, output)!!end;!!output.endpage(w);!!! complexe condities =>! polymorfisme! 4.26!
4.27! PROCEDURE (atictactoe: TicTacToe) writeon* (VAR w: Texts.Writer;!!output: TicTacToeOutput.TicTacToeOutput);! BEGIN!!output.startSentences(w);!!Texts.WriteString(w, "TicTacToe game after move ");!!Texts.WriteInt(w, atictactoe.nrofmoves, 0);!!output.endSentences(w);!!output.startBoard(w);!!FOR i := 0 TO 2 DO!!!!!!output.startRow(w, CHR(ORD("1") + i));!!!for j := 0 TO 2 DO!!!!output.boardLocation( );!!!END;!!!output.endRow(w);!!!!!END;! output.endboard(w);! extra parameter! controleert verschil! verschillen in! gedupliceerde code! =>! polymorfisme!
4.28! Undo! player play <<extends>> play with undo option Use Case 4: play with undo option! Extension of use case 1! Steps! use case 1 + additional steps! afer 2.1! 2.1.1 current player undo move! 2.1.2 goto 2 (restart while loop)!
4.29! Undo Algoritme?! Hou een lijst bij met verloop spelstatus!!!tictactoedata* = RECORD (OOLists.NodeDesc)!!!!nrOfMoves: INTEGER;!!!!board: ARRAY 3, 3 OF CHAR;!!!!players: ARRAY 2 OF Player;!!!!lastCol, lastrow, lastmark : CHAR;!!!!theWinner: Player;!!!END;! Herbruik bestaande code! Maar! Klassen die vaak herbruikt worden hebben preciese contracten!
4.30! PROCEDURE (l : List) Init ();! Contracten voor OOLists?! PROCEDURE (l : List) LocateFirst ();! PROCEDURE (l : List) LocateLast ();! PROCEDURE (l : List) LocateNode (n: Node);! PROCEDURE (l : List) LocatePrev ();! PROCEDURE (l : List) LocateNext ();! PROCEDURE (l : List) InsertBefore (new: Node);! PROCEDURE (l : List) InsertAfter (new: Node);! PROCEDURE (l : List) Delete ();! PROCEDURE (l : List) GetNode (): Node;! PROCEDURE (l : List) Enumerate (P: NodeProc);! PROCEDURE (n : Node) NodeInfo ();! Contracten? Moeilijk want interface zonder predicaten!
4.31! Lijst met predicaten! PROCEDURE (l : List) Init ();!!(* postcondition (120): l^.isinitialized() *)! PROCEDURE (l : List) Includes (n: Node): BOOLEAN;!!(* precondition (100): l^.isinitialized() *)! PROCEDURE (l : List) Insert (new: Node);!!(* precondition (100): l^.isinitialized() *)!!(* postcondition (120): l^.includes(new) *)! PROCEDURE (l : List) Delete (old: Node);!!(* precondition (100): l^.isinitialized() *)!!(* postcondition (120): ~ l^.includes(new) *)! Evaluatie Criteria! Reuse (lijsten)! Contracten? Makkelijker want interface met veel predicaten!
4.32! Vuistregel! Prefereer een interface met predicaten! Waarom?! Betere betrouwbaarheid door eenvoudige contracten! Hoe?! Specifieer predicaten voor hoofdfunctionaliteit component! Roep predicaten op in pre- en post-condities!
4.33! Testen! Vuistregels! Schrijf testcode als subklasse(n) van UnitTest! Ontwerpen! Vermijd code duplicatie & complexe logica! Hollywood Principle wij roepen jouw op als we je nodig hebben! Klassen die vaak herbruikt worden hebben preciese contracten! Prefereer een interface met predicaten! Plannen! Empirische schatten is de basis voor een realistische planning!