Texas Holdem / Cards



Relevanta dokument
Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Bankkonto - övning. Övning 2 Skriv en metod, geträntan, som returnerar räntan.

TENTAMEN I PROGRAMMERING. På tentamen ges graderade betyg:. 3:a 24 poäng, 4:a 36 poäng och 5:a 48 poäng

Programmering för språkteknologer II, HT2014. Rum

725G61 - Laboration 7 Implementation av ett API. Johan Falkenjack

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

Dagens program. Programmeringsteknik och Matlab. Objektorienterad programmering. Vad är vitsen med att ha både metoder och data i objekten?

Lösningsförslag till omtentamen för TDA540 Objektorienterad Programmering

C++ Slumptalsfunktioner + switch-satsen

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Verktyg och Utvecklingsmiljö. Jochim von Hacht

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

Föreläsning 5-6 Innehåll

F4. programmeringsteknik och Matlab

JUnit 4 - användning. Grunderna. org.junit. org.junit.test. Henrik Bergström DSV SU/KTH. Innehåller bland annat:

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

Tentamen Programmering fortsättningskurs DIT950

UML. Klassdiagr. Abstraktion. Relationer. Överskugg. Överlagr. Aktivitetsdiagram Typomv. Typomv. Klassdiagr. Abstraktion. Relationer.

Classes och Interfaces, Objects och References, Initialization

Versionshantering. Jan Erik Moström

F6 Objektorienterad design. ID1004 Objektorienterad programmering Fredrik Kilander

ID1004 Laboration 4, November 2012

JUnit. Junit Unit Testing. JUnit 3. JUnit 3 forts. Villkorskontroller i test. Exempel JUnit3

TENTAMEN OOP

LUNDS TEKNISKA HÖGSKOLA EDAA01 Programmeringsteknik fördjupningskurs Institutionen för datavetenskap HT 2015

Kopiering av objekt i Java

TENTAMEN: Objektorienterad programmering. Läs detta! Skriv din tentamenskod på varje blad (så att vi inte slarvar bort dem).

1 Uppgift 1. a) Skapar ett Company-objekt med hjälp av den överlagrade konstruktorn. Du kan själv välja värden på instansvariablerna.

Lösningsförslag till tentamen

TENTAMEN. Kurs: Objektorienterad programmeringsmetodik 5DV133 Ansvarig lärare: Anders Broberg. VT-13 Datum: Tid: kl

F8 - Arv. ID1004 Objektorienterad programmering Fredrik Kilander

Institutionen för datavetenskap HT /2008. Testning med JUnit

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Översikt MERA JAVA OCH ECLIPSE. Uttryck och tilldelning. Uttryck och tilldelning. Uttryck och tilldelning. Uttryck och tilldelning

Generiska konstruktioner. Kursbokens kapitel 13

public och private Obs: private inte skyddar mot access från andra objekt i samma klass.

TUTORIAL: KLASSER & OBJEKT

Lösningsförslag. Programmeringsmetodik, KV: Java och OOP. 17 januari 2004

JAVA Mer om klasser och objektorientering

Metoder (funktioner) Murach s: kap Winstrand Development

Recap Mera om nya typer Kort Fält. Programmering. Sommarkurs Verónica Gaspes. IDE-sektionen.

/* * * Lösningsförslag tentamen DIT950 * Datum * */ /* * -1 - */ För samtliga gäller,se föreläsningsanteckningar.

Det är principer och idéer som är viktiga. Skriv så att du övertygar examinatorn om att du har förstått dessa även om detaljer kan vara felaktiga.

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 2

Objektorienterad programmering i Java I

Fördjupad Java. Undantagshantering. Fel

Inkapsling tumregler. Åtkomstmodifikatorer, instantiering, referenser, identitet och ekvivalens, samt klassvariabler. public och private

Idag. statiska metoder och variabler. private/public/protected. final, abstrakta klasser, gränssnitt, delegering. wrapper classes

Tentamen ID1004 Objektorienterad programmering May 29, 2012

KARLSTADS UNIVERSITET 12/8/09 informatik & datavetenskap Johan Öfverberg, Kerstin Andersson Laboration 4, ISG A04 och DVG A08 HT-09

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

DAT043 - föreläsning 8

Konstruktion av klasser med klasser

Att skriva till och läsa från terminalfönstret

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Classes och Interfaces, Objects och References Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Uppgiften är att beskriva en kvadrat i ett Java program. En första version av programmet skulle kunna se ut så här:

Objektorienterad Programkonstruktion. Föreläsning 2 2 nov 2016

if (n==null) { return null; } else { return new Node(n.data, copy(n.next));

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Objektorientering. Objekt och metoder. Objektorientering. Viktiga begrepp. Klass. Objekt. Deklarativ programmering

NetBeans 5.5. Avsikt. Projektfönster

PROGRAMMERINGSTEKNIK TIN212

Tentamen i TDP004 Objektorienterad Programmering Praktisk del

TENTAMEN OOP

Klasshierarkier - repetition

Laboration 1 - Grunderna för OOP i Java

Vad kännetecknar en god klass. Vad kännetecknar en god klass. F12 Nested & Inner Classes

Det finns en referensbok (Java) hos vakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Verktyg och Utvecklingsmiljö. Föreläsning 2 Eclipse

DIAGNOSTISKT PROV. Tid. Hjälpmedel. Antaganden. Rättning. Övrigt. Diagnostiskt Prov. Klockan Inga

Laboration 3, uppgift En klass för en räknare

OOP Objekt-orienterad programmering

Objekt, Klasser, Paket m. m.

Fält av referenser. Konstruktorerna används för att skapa Bilar och Trafikljus.

I STONE. I Variabler, datatyper, typkonvertering. I Logiska och matematiska uttryck. I Metoder-returvärde och parametrar. I Villkorssatser if/else

NetBeans 7. Avsikt. Projektfönster

Objektorienterad programmering

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Innehåll. dynamisk bindning. och programmering CRC) u Arv, polymorfi och

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design Alex Gerdes, 2016

OOP Objekt-orienterad programmering

Malmö högskola 2007/2008 Teknik och samhälle

Tentamen OOP

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Det finns en referensbok (Java) hos vakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Idag. Exempel, version 2. Exempel, version 3. Ett lite större exempel

SI-pass 4. Johan Brook och Jesper Persson. 25 september Diskutera och svara på om påståendena nedan är äkta sanningar eller listiga lögner.

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Chapter 4: Writing Classes/ Att skriva egna klasser.

Undantagshantering. Fördjupad Java. Fel. Undantag. Fånga Undantag. Grupper av Undantag

Undantagshantering. Fördjupad Java. Undantag. Fel. Grupper av Undantag. Fånga Undantag

Tentamen i Objektorienterad modellering och design Helsingborg

Malmö högskola 2008/2009 CTS

UML. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Att använda Java SE JDK 6

Reguljära uttryck. Reguljära uttryck. Nu kommer en siffra78 och en till SIFFRA(78) men utan 7kstuga SIFFRA(89)

Separation of Concern. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016 Johannes Åman Pohjola, 2017

Transkript:

Texas Holdem / Cards Anton Österberg anos3557 Beatrice Beta bebe5678 Caesar Gamma caga9012 Diana Delta dide3456 29 oktober 2014 1

Introduktion Vi valde att inte skriva ett av de projekt som vi blev givna utan började skriva ett klassbibliotek till ett kortspel, eller mer specifikt till texashold em poker. Vi använde oss utav Git som versionshanteringsverktyg under hela projektets gång. Ungefär halvvägs in i projektet gjordes en formell granskning av majoriteten av koden som vi hade skrivit för att senare utveckla det vi redan hade skrivit till en bättre slutprodukt. För att kolla på statistik i vår kod använde vi Eclipse Metrics Plugin som ett statiskt mått. Som dynamiskt mått för att uppmäta prestanda som ett antal olika metoder drar använde vi oss utav JVM Monitor i Eclipse. För att uppnå högst möjliga coverage använde vi oss utav EclEmma för att kolla att vi uppnådde 100coverage på våra klasser. Under kodkritik körde vi igenom våra klasser med FindBugs för att se vad vi inte redan hade hittat som kunde ändras och möjligen göras bättre. Källkod: http://81.225.210.252/texas.tar.gz EclEmma - coverage Eclipse Metrics Plugin - software metrics GIT - versionshanteringssystem JUnit - enhetstestning FindBugs - kodkritik JVM Monitor - profiler Jflap - tillståndsmaskin ANT - byggscript Eclipse inbyggda debugger - debugger 2

Slutlig design En övergripande modell över systemet. Lämpligt format är ett eller flera klassdiagram, plus eventuella andra modeller som behövs för att förstå hur systemet är uppbyggt. Diagrammen ska vara läsbara. Det är dock fullständigt okej att de är detaljerade, bara det går att zooma in ordentligt på dem. Ett tips är att börja med ett översiktligt diagram som inte innehåller mer än paket och klassnamn, och att sedan lägga till mer detaljerade diagram efter det. Vi valde att dela upp vårat projekt på ett sådant sett att det finns ett separat paket som heter Cards vilket är tänkt som ett allmänt kortspels-paket med kort, kortlekar, spelare, händer osv och sedan ett paket som är mer specifikt inriktat på kortspelet Texas Holdem. Nedan är ett klassdiagram över hela vårt projekt: 3

4

5

Testdriven utveckling process Alla fyra har tillämpat testdriven utveckling under större delar av projektets gång. Till en början var vi hårda på att använda testdriven utveckling men desto längre in i projektet vi kom så släppte vi på det för att få in alla funktioner i programmet. Även om vi inte var lika hårda i slutet på att tillämpa testdriven utveckling så övergav vi ändå inte det helt då vi kände att det var ett väldigt använbart verktyg. I den senare delen av projektet kom dock testfallen - tyvärr - oftast att skrivas efter att koden som skulle testas redan hade skrivits. Nedan kommer 4 olika exempel på testfall som skrivits av alla personer i projektet och den kom som togs fram med hjälp av testfallen: Elliot : PotTest 1 @Test 2 public void betsizetestfromemptypot (){ 3 Pot emptypot = new Pot (); 4 emptypot. receivebet (300, player1 ); 5 assertequals (300, emptypot. getamount ()); 6 } 7 8 @Test 9 public void betsizetestfrompositivesize () { 10 Pot positivepot = new Pot (1) ; 11 positivepot. receivebet (300, player1 ); 12 assertequals (301, positivepot. getamount ()); 13 } Elliot : Pot.receiveBet() 1 public void receivebet ( int bet, Player player ) { 2 if ( bet < 1) 6

3 throw new IllegalArgumentException ( 4 " The Bet has to be larger than 0"); 5 else { 6 amount += bet ; 7 bethistory. put ( player, this. getbethistory ( player ) + bet ); 8 } 9 } Rasmus : PotTest 1 @Test ( expected = IllegalArgumentException. class ) 2 public void testforinvalidsize () { 3 Pot invalidpot = new Pot ( -1); 4 assertequals (-1, invalidpot. getamount ()); 5 } 6 7 @Test 8 public void testpotsizeifpositiveint () { 9 Pot pot = new Pot (500) ; 10 assertequals (500, pot. getamount ()); 11 } Rasmus : Pot.Pot() 1 public Pot ( int amount ) { 2 if ( amount < 0) 3 throw new IllegalArgumentException ( 4 " The Pot has to be at least 0"); 5 this. amount = amount ; 7

6 } Emil : GameTest 1 @Test 2 public void addingoneplayertest (){ 3 Game newgame = new Game (4, 0.3, kalle ); 4 asserttrue ( newgame. getplayers (). contains ( kalle )); 5 } 6 7 @Test 8 public void addingplayerstest (){ 9 Game newgame = new Game (4, 0.3, kalle, pelle ); 10 asserttrue ( newgame. getplayers (). contains ( kalle )); 11 asserttrue ( newgame. getplayers (). contains ( pelle )); 12 } Emil : Game.Game() 1 public Game ( int bigblind, double blindsraisepercentage, Player... players ) { 2 this ( players ); 3 if ( bigblind < 1) 4 throw new IllegalArgumentException ( 5 " Error : parameter bigblind is less than 1."); 6 if ( blindsraisepercentage < 0) 7 throw new IllegalArgumentException ( 8 " Error : parameter blindsraisepercentage is less than 0."); 9 this. bigblind = bigblind ; 10 this. blindsraisepercentage = blindsraisepercentage ; 8

11 } Anton : CardTest 1 @Test 2 public void testequalsvalid (){ 3 Card card1 = new Card ( Colour. HEARTS, Rank. QUEEN ); 4 Card card2 = new Card ( Colour. HEARTS, Rank. QUEEN ); 5 asserttrue ( card1. equals ( card2 )); 6 } 7 8 @Test 9 public void testequalsinvalid (){ 10 Card card1 = new Card ( Colour. HEARTS, Rank. QUEEN ); 11 Card card2 = new Card ( Colour. HEARTS, Rank. ACE ); 12 assertfalse ( card1. equals ( card2 )); 13 card2 = new Card ( Colour. CLUBS, Rank. QUEEN ); 14 assertfalse ( card1. equals ( card2 )); 15 card2 = null ; 16 assertfalse ( card1. equals ( card2 )); 17 assertfalse ( card1. equals ("A string ")); 18 } Anton : Card.equals() 1 @Override 2 public boolean equals ( Object object ){ 3 if( object == null ) 4 return false ; 9

5 if (! object. getclass (). equals ( this. getclass ())) 6 return false ; 7 Card other = ( Card ) object ; 8 return ( this. colour. equals ( other. colour ) && this. rank. equals ( other. rank )); 9 } 10

Testdriven utveckling erfarenheter Vi har arbetat med testdriven utveckling nästan helt och hållet genom projektet vilket har gett oss en mängd erfarenheter av hur bra/dåligt det kan fungera. Till en början kändes det väldigt överflödigt och framtvingat då man arbetade med simpla metoder, klasser och konstruktioner som kändes självklara hur man skulle skriva och som alltid fungerade direkt. Desto mer vi arbetade och kom in i svårare metoder och konstruktioner så började testdriven utveckling kännas mer och mer användbart och mot slutet i projektet, speciellt när vi arbetade med klasses TexasRules, så kändes det nästan som att det hade varit omöjligt att genomföra den delen utan testdriven utveckling och testfall. Eftersom man i klassen TexasRules behövde testa väldigt specifika fall, som t ex att rätt person vinner om båda har stege men en av personerna har högre kort, så gjorde testfall att man enkelt kunde sätta upp ett eller flera komplexa fall som endast gått igenom om koden är korrekt skriven. Detta skulle vara väldigt svårt att testa utan testfall. Testdriven utveckling ledde också till att vi snabbt upptäckte fel som introducerats i koden. Detta eftersom man kunde se om ett testfall gått igenom tidigare antingen i commit-kommentarerna eller för att man själv kört dem tidigare och då också se om man kan ha introducerat något fel i en specifik del av koden. Lyckades man då inte se vilket fel man introducerat så gick det alltid att titta på versionen som commitats t ex med kommentaren testfall X går nu igenom och se hur koden såg ut i det tillfället. En ytterliggare positiv effekt av testdriven utveckling som vi inte tänkt på i förhand är att den gör koden mycket mer lättförståelig för de man arbetar med då man kan se hur koden är tänkt att fungera även om den inte i nuvarande läge fungerar. Detta leder till att man enkelt kan ta över metoder och skriva klart dem även om det inte var man själv som började skriva på den. Även om man har dokumentation om ungefär vad metoden ska göra, så ger testfallen mycket med information om exakt hur metoden ska bete sig och vilket resultat som förväntas. Vi har förstås också fått uppleva några utav baksidorna med testdriven utveckling. Det är tidskrävande, speciellt att skriva bra tester som ger god täckningsgrad och täcker alla ekvivalensklasser. Det krävs god disciplin för att inte slarva och börja övergå i ad-hoc-testning, speciellt under tidspress, något som vi kanske inte kan säga att vi alltid lyckats med. Det är inte heller alla gånger som vi varit helt överens om hur vi ska prioritera testbarhet kontra inkapsling. Oftast har vi lyckats finna någon kompromiss där t.ex. privata metoder har varit testbara via publika metoder där den privata anropas. 11

Ekvivalensklassuppdelning subtractchips En kort presentation av vad ni valt ut för att tillämpa ekvivalensklassuppdelning på. Ni ska kort motivera valet, och ge tillräckligt med information för att det ska gå att bedöma er. Detta avsnitt och de tre föjande (till och med testmatrisen) ska finnas för samtliga delar ni tillämpat ekvivalensklassuppdelning på. Då vi inte hittade några självklara metoder att köra ekvivalensklassuppdelning vid en första anblick så valde vi att göra det på några klasser som används relativt ofta och/eller som är väldigt viktiga att ingenting får gå fel i. subtractchips är en metod som är väldigt viktigt att den fungerar som den ska och returnerar rätt värde vid rätt tillfälle då det annars kan leda till att en person som ej har råd att betala en viss summa till potten ändå kan få fortsätta den rundan. Vi valde därför att genomföra ekvivalensklassuppdelning på denna metod för att se till att vi inte missat något även fast det inte resulterade i jätte många ekvivalensklasser. 12

Ekvivalensklasser subtractchips Samtliga ekvivalensklasser för denna del presenterade på ett tydligt sätt. public boolean subtractchips(int bet) Ekvivalensklass Invalida interval Ekvivalensklass Valida interval a int bet <= 0 c int bet 0 < bet <= chips b int bet > chips 13

Testfall subtractchips Testfallen som ni fått fram från ekvivalensklasserna. Observera att vi inte vill ha någon kod här, utan bara en tydlig presentation av testfallen i någon lämplig tabellform. id Namn Input(int bet) Result 1 addtopottestsuccess() 1 true 2 addtopottestsuccess() chips true 3 add0chipstopottest() 0 false 4 addtopottestfail() chips+1 false 14

Testmatris subtractchips En testmatris som visar sambandet mellan ekvivalensklasserna och testfallen för denna del. a b c 1 x 2 x 3 x 4 x 15

Ekvivalensklassuppdelning - Game-konstruktor En kort presentation av vad ni valt ut för att tillämpa ekvivalensklassuppdelning på. Ni ska kort motivera valet, och ge tillräckligt med information för att det ska gå att bedöma er. Detta avsnitt och de tre föjande (till och med testmatrisen) ska finnas för samtliga delar ni tillämpat ekvivalensklassuppdelning på. - Vi valde att göra en ekvivalensklassuppdellning på Game-konstruktorn då den tar emot relativt många parametrar, iallfall om man jämför med resten av projektet, och löper därför en större risk att få olika slags fel. Den är också en väldigt viktig del av hela biblioteket då det är objekt av denna klass som skapas när man vill starta ett Texas Holdem-spel vilket gjorde att den kändes som en självklar metod att tillämpa ekvivalensklassuppdelning på. 16

Ekvivalensklasser Game-konstruktor Samtliga ekvivalensklasser för denna del presenterade på ett tydligt sätt. Ekvivalensklass Valida intervall a int bigblind >0 b double blindsraidepercentage >=0 c Player... players * Ekvivalensklass Invalida intervall d int bigblind <=0 e double blindsraidepercentage <0 f Player... players null 17

Testfall Game-konstruktor Testfallen som ni fått fram från ekvivalensklasserna. Observera att vi inte vill ha någon kod här, utan bara en tydlig presentation av testfallen i någon lämplig tabellform.? 18

Testmatris Game-konstruktor En testmatris som visar sambandet mellan ekvivalensklasserna och testfallen för denna del. 19

Granskning En kort presentation av den del av koden ni valt ut för att göra en formell granskning av och processen ni använt er av inklusive eventuella checklistor, scenarier, edyl. Ni ska kort motivera valen, och ge tillräckligt med information för att det ska gå att bedöma er. Vi valde att göra en granskning på vårat projekt i ett relativt tidigt stadie för att underlätta fortsatt arbete och undvika att vi missar stora fel och missförstånd. När vi genomförde vår granskning så gjorde vi det på hela paketet cards som då innehöll klasserna Deck,Colour,Rank och Card samt klasserna Pot och Player i paketet texasholdem. Då klassen game var väldig tom och inte i närheten av färdig kände vi att det inte var någon mening med att granska den ännu vilket är varför vi lämnade den utanför granskningen. När vi genomförde granskningen valde vi att alla personer räknades som rollen reviewer då vi alla hade åsikter och fel vi hittat i koden men vi delade samtidigt upp oss i olika roller utöver det. Rasmus var sekreterare som skrev ner alla fel/punkter vi tog upp medan Emil var moderatorn i granskningen. Vi jobbade sedan på de sättet att vi tog en klass i taget där Emil läste koden rad för rad och när någon hade ett fel eller något annat att ta upp så gjorde man det och vi diskuterade då om det är något som ska ändras och isåfall vad vi skulle kunna göra. Vissa fel kom vi på vad som skulle ändras direkt och skrev upp det medanandra punkter lämnade vi öppna för diskussion när vi sedan skulle rätta felen efter att granskningen var klar. 20

Granskningsrapport En lista över de påträffade felen och hur pass allvarliga ni bedömer dem. Granskning: 8/10 Commit: 8b02afa79f6373217c9b3d89462695a7d34eb4b cards Card / Colour / Deck / Rank Rank:14 Value och rank missförstånd kan uppstå mellan variabelnamnet och metodnamnet. Rank:5 Funderingar över hur vi ska lösa hantering av att Rank.ACE kan vara 1 i enum-klassen Rank.java. Detta sågs inte vara något allvarligt och bestämdes att det skulle lösas direkt där det behövdes, t ex vid uträkning av kombinationen CardCombination.STRAIGHT. Colour:13 Enum-klassen Colour går nu att använda en getvalue metod på även fast vi är osäkra på hur ranking mellan olika färger går till i Texas Hold Em och andra kortspel. Detta anses ganska allvarligt då det kan leda till felaktiga uträkningar i vinnande händer osv. Colour:13, Rank:14 getvalue-metoden har skyddsnivån public i enum-klassen Colour men protected i enumklassen Rank vilket, den borde ha samma skyddsnivå i båda klasserna vilket är något som ska korrigeras. Deck:11-22 Byta plats på konstruktorerna i klassen Deck för bättre läsbarhet. texasholdem Action / Game / Player / Pot Player:33 Implementation av clearhand() i Game-klassen istället för player? Player:41 Returtyp int på addchips(), behövs det? Player:45 Ska addtopot returnera en boolean? Exception vid i>chips? Pot:12 If-satsen i konstruktorn som tar emot en parameter för klassen Pot måste ändras så att du kan skapa en pot med 0 chips i, för tillfället så får man ett exception då vilket inte är meningen. Detta ses som relativt allvarligt då inget ska hindra dig från att skapa en pot med 0 chips i. 21

Pot:9 bethistory i Pot borde sättas till final då det inte ska skapas flera av den utan bara tömma den redan skapade mapen. Pot:28 Metoden checknull i Pot visar sig vara överflödig och ska tas bort. Pot:43 bettopot-metoden borde byta namn till någon som bättre representerar dess funktion, t ex recievebet. Player:60 Metoden getingame i klassen Player borde borde byta namn till isingame för att bättre representera sin funktion. Player:45 addtopot-metoden borde byta namn för att bättre representera sin funktion eller göras om så att mer av denna funktionalitet ligger i Game-klassen och det enda som görs i den här metoden är att ta bort de chipsen som spelare bettar. Player:45 Byte av varibelnamn i metoden addtopot från i till bet för att öka läsbarheten. 22

Granskning erfarenheter En diskussion om vilka era erfarenheter ni dragit av att tillämpa granskning. Det finns inget rätt eller fel här. Enda sättet att bli underkända är att bara fuska över punkten och bara säga något pliktskyldigt. Ni förväntas förhålla er till såväl kursboken som utdelat material och IEEE Std 1028. Vi tyckte att vi drog väldigt stor nytta av den granskning vi gjorde då den hittade vissa fel som är näst intill omöjliga för ett program att göra. Vi upptäckte t ex många fel som hade att göra med dålig namngivning på metoder och attribut vilket ledde till missförstånd om man inte själv varit den som skrivit koden. Vi upptäckte också några mer strukturella fel och överflödiga metoder vilket är lättare för en människa att bedömma än ett program. På det sättet vi genomförde granskningen så fick vi också igång en väldigt bra diskussion mellan alla medlemmar i projektet då alla fick tycka till på samma punkt samtidigt, den som skrivit koden kanske inte alltid hade den bästa ideén vilket gjorde att vi då fick en allmänt bättre kod som alla var nöjda med. Gruppen fick även en överblick på den kod som redan hade skrivits och kunde lättare se vad som skulle prioriteras efter det att granskningen hade genomförts. 23

Tillståndsbaserad testning När vi disskuterade vilken del av programmet att använda för den tillståndsbaserade testningen så stod valet mellan boolean-attributet inround i klassen Player, eller hela Game-klassen. Tillslut valde vi attributet inround, med motivationen att inround s tillstånd var tillräckligt viktiga för att skapa många testfall, men samtidigt tillräckligt avgränsande så att denna del inte blev för stort. Game-klassen hade helt enkelt för många kombinationer av tilstånd för att vara passande. När vi ritade upp flödesdiagramet för inround så märkte vi att inround var beroende på om Player hade några chips eller inte. Dvs om Player inte hade chips, så agerar klassen Player annorlunda i båda inround tillstånden, och därför måste vi inkludera detta på något sätt. Vi började fundera på om vi skulle ha två tillståndsmaskiner gentemot varandra, med broar mellan de olika tillstånderna, men vi kom fram till att den implementationen var överflödig, då om Player får slut på chips utan att vara inround så borde den Playern inte finnas kvar i programmet överhuvudtaget. Så vi gjorde istället ytterligare ett tillstånd som vi kallade Zero chips för att vissa att Player befinner sig i den enda relevanta kombinationen av tillstånd: den när Player är ingame, men har inga chips kvar (dvs gått all-in). När vi var klara med diagramet disskuterade vi vilket täckningskriteruim vi skulle använda oss utav. Valet var denna gång mellan state coverage eller path coverage. I efterhand insåg vi hur dum denna disskussion egentligen var, då path coverage automatiskt uppnår state coverage, så det blev självklart path coverage. Tankegångarna var att det faktiskt inte var tillstånden i sig som var det viktiga att testa, utan övergångarna mellan de olika tillstånden var de som var viktiga. Modellen som vi designade visar på hur klassen hanterar en spelare i vårt system och vilka tillstånd denne spelare kan befinna sig i. 24

25

26

Testfall för tillståndsbaserad testning Testfallen som ni fått fram från tillståndsmaskinen. Observera att vi inte vill ha någon kod här, utan bara en tydlig presentation av testfallen i någon lämplig tabellform. Det ska enkelt gå att mappa testfallen till tillståndsmaskinen. Eftersom att vi använde testdriven utveckling när vi skrev Player och Game klasserna så hade vi redan i princip testfall för boolean ingame, och därför så skapade vi en egen test-klass som vi enbart använde som en kompletering. Vi var lite osäkra på hur många testfall vi skulle göra. Skulle vi ha få testfall, där varje testfall täcker flera vägar, eller skulle vi ha ett testfall för varje individuell väg? Vi beslöt oss för att göra många testfall som testade en individuell sak, då om det blir fel på någon av de mittersta vägarna så kommer få fast långa testfall att inte testa de vägarna efter den misslyckade vägen. På det här sättet är det garanterat att vi täcker alla vägar, oberoende på vilka vägar som misslyckas eller inte. testfallen i någon lämplig tabellform 27

Kodkritiksystem En presentation av de problem som hittats med hjälp av verktyg för statisk analys och en diskussion av dem enligt anvisningarna. Det räcker alltså inte med att bara lista problemen, ni måste förhålla er till dem också. Tänk också på att ni ska göra detta både på koden som den såg ut före granskningen och på koden efter att ni rättat det som kommit fram under granskningen. Vi körde FindBugs vid ett flertal tillfällen under utvecklingen med olika resultat men den slutsatsen vi ändå kunde dra av detta var att FindBugs var en av de minst användbara verktygen vi testat oss på, när den användes för första gången precis innan den första granskningen så hittade den inte ett enda fel, även när känsligheten drogs upp på max och vi bad den rapportera allt den möjligen kunde hitta. Det fanns dock inga större fel vid denna punkt men vi hittade ändå rätt mycket saker som vi behövde ändra när vi körde vår formella granskning som FindBugs ej hade hittat. Många av de felen vi hittade hade dock med namngivning och liknande att göra vilket är svårare för ett program att hitta. Vi körde också FindBugs efter vi gjort korrigeringar efter granskningen men hittade då heller inga fel. Vi körde däremot FindBugs mot slutet av projektet också och då hittade den dessa fel : 1. TexasRules.java:32 texasholdem.texasrules.equals(object) always returns false [Scary(7), High confidence] 2. TexasRules.java:128 Potentially dangerous use of non-short-circuit logic in texasholdem.texasrules.hasfullhouse(hand) [Of Concern(15), High confidence] 3. Hand.java:10 Class cards.hand implements Cloneable but does not define or use clone method [Of Concern(16), Normal confidence] 4. TexasRules.java:12 texasholdem.texasrules implements Comparator but not Serializable [Of Concern(19), Normal confidence] 5. Game.java:175 Dead store to amountoferrors in texasholdem.game.distributechip(arraylist) [Of Concern(20), Low confidence] 28

6. Hand.java:36 Confusing to have methods cards.hand.addtohand(card[]) and cards.player.addtohand(card[]) [Of Concern(19), Low confidence] 29

Statiska mått En presentation och diskussion kring ett antal lämpliga statiska mått på koden. Att vi inte specificerar exakt vilka mått som ska tas upp beror på att olika verktyg har olika uppsättningar, men vi förväntar oss fler och mer intressanta mått än bara rena storleksmått som LOC, #klasser, #metoder, etc. Även här är det viktigt att förhållas sig till måtten, inte bara lista dem. Number of Classes: 8 (exklusive testfall, interface och enums) 1. cards: 5 2. texasholdem: 3 Total Lines of Code: 2014 1. testfall: 1140 (56,6%) 2. texasholdem: 476 (23,6%) 3. cards: 398 (19,7%) Det som kan vara intressant med resultaten för Number of Classes och Total Lines of Code är det faktum att paketet texasholdem har färre klasser än cards, men fler antal rader kod. Man bör kanske fundera på varför det har blivit så, och fråga sig om det verkligen är bra. Detta är något som i sin tur står i korrelation till de metrics som följer. Lack of Cohesion (mean): 0,403 1. Game: 0,806 2. Player: 0,795 3. CardGame: 0,717 30

Kanske inte helt oväntat så är den största klassen, Game, den som har högst avsaknad av coheshion. Intresasnt är att i ett tidigare skede så var Game och CardGame en och samma klass, och trots denna uppdelning så har båda dessa vuxit på ett sätt som kanske inte är önksvärt. Både Game och CardGame börjar få lite God-klass-tendenser och bör ses över. Vi har sagt att om vi väljer att fortsätta att utveckla vårt bibliotek så kommer en ytterliggare uppdelning av någon (eller alla) av de tre klasserna vara aktuellt. Player sticker ut lite som är en ganska liten klass jämfört med de andra två (ca 60 LoC jämfört med 230 respektive 110) men trots det så har den rätt stor avsaknad av cohesion. De flesta av klassens metoder arbetar antingen på variablen chips eller objektet hand, men ingen av klassens metoder arbetar på båda dessa. Resultat är med andra ord inte så förvånande. Eftersom att hantering av chips inte är en funktion som är generell för alla kortspel, så bör vi kanske överväga att avlägsna chips-hanteringen från den generella klassen Player och lägga in i en separat klass, möjligen en subklass. MacCabe Cyclomatic Complexity (mean): 1,632 1. Pot:handOutChips() - 9 2. TexasRules:hasCombination() - 9 3. Game:placeBlinds() - 7 4. Game:playerAction() - 7 Den relativt sett höga komplexiteten på några av de metoder som finns ger kanske en fingervisning om att det finns utrymme för förbättring. Metoderna handoutchips och placeblinds skulle förmodligen kunna refaktoriseras och delas upp i flera mindre metoder för att minska komplexiteten något, även om komplexiteten i sig gör det svårare. Metoderna hascombination och playeraction har lika hög komplexitet som de nyss nämnda, men detta främst till följd av att de har switch-satser, varför de kan vara en än större utmaning att dela upp dem i flera mindre metoder. Number of Parameters (mean): 0,667 1. Pot:handOutChips(Player player, int chipswon, int playerswon) - 3 31

2. Game:Game(int bigblind, double blindsraisepercentage, Player... players) - 3 Vi har överlag lyckats hålla nere antalet parametrar för metoderna i vårt bibliotek. Kontruktorn ovan behöver dessutom bara två av de tre argumenten då den sista är en varargs som inte är obligatorisk. Method Lines of Code (mean): 4.313 1. Pot:handOutChips() - 34 2. Game:distributeChip() - 22 3. Game:placeBlinds() - 14 Som man kanske hade kunnat gissa så kan man se ett samband mellan MacCabe Cyclomatic Complexity och Method Lines of Code där en mer komplex metod kan utgöra ett motstånd för att bryta upp den i flera mindre metoder. Dessa statiska mått är var och för sig, av ganska begränsad nytta, men tillsammans ger de en ganska god bild av vilka förbättringar som köras på projektet som helhet och enskilda klasser och metoder. Pizza metric index: 1 Vi har inte råd att äta mer pizza. 32

Täckningsgrad En översikt över vilken täckningsgrad era testfall uppnått. Denna kan antagligen tas rakt av från verktyget ni använt för att mäta den. Om ni inte uppnått fullständig täckning så ska detta förklaras och motiveras. - Vi har närmast 100% täckningsgrad. Det finns två klasser som inte riktigt når hela vägen. I det ena fallet handlar det om klassen Deck som har en metod setseed som matar ett SecureRandom-objekt med ny data för seeden. Metoden är protected och anropas aldrig i dagsläget av någon annan metod i paketet då vi är osäkra på om vi faktiskt behöver den eller inte. Det kan faktiskt vara så att vi kommer ta bort metoden, men fram till dess att vi är helt säkra på att det är rätt beslut får den ligga kvar. Den andra klassen som inte har 100% täckningsgrad är TexasRules. Det är helt enkelt för att vi har kommit fram till att stora delar av koden måste skrivas om, och vi ser ingen poäng med att försöka få full täckning för kod som vi kommer ta bort. 33

34

Profiler En kort presentation av hur ni gått tillväga för att testa koden med en profiler och vilka resultat ni fick fram. Vi skrev ett profilertest där ett antal huvudmetoder loopas igenom ett flertal gånger så att processen håller på ett tag så att vi kunde se hur mycket våra metoder påverkar datorns prestanda. Vi försökte använda NetBeans först, men då det inte funkade blev vi tvugna att använda Eclipse egna profiler (JVM monitor). <insert screenshoot here> Det första vi märkte av resultatet var att metoden drawcards() (poängtera pluralet dvs inte drawcard()) drog absolut mest CPU kraft gemfört med alla andra metoder. Vi disskuterade om varför det kunnat ha blivit så, och vi kom fram till två teorier. Den första är att drawcards() använder sig utav securerandomint, vilket vi har förstått är en väldigt komplicerad klass, och därför drar mycket CPU-kraft. Den metod som drar näst mest kraft är drawcard(), som också använder sig utav securerandomint, vilket stödjer denna teori. Den andra teorin vi hade var att drawcards() anroppades absolut mest gånger utav alla andra metoder, vilket i sin tur resulterar i en mycket större sammanlagd CPU-kraft, vilket är vad profilen vissar. Men vi kom också fram till att med den informationen profilern givit oss så kan vi inte komma fram till ett garanterat svar. Kanske om profilern tillät oss att köra endast ett game (vi försökte, men programmet avslutades så snabbt att vi inte kunde se CPU-kraftsmätningarna) istället för flera tusen så skulle vi kunna komma närmare vilken teori som stämmer, eller alternativt om profilern lät oss gå djupare till exakt vilka sub-metoder av varje anropp som tar mest kraft skulle det också ge någon klarhet. Men denna information gav inte profilern, och detta tillåter oss endast att spekulera. All in all tycker vi att profilern var den näst mest oanvändbara testningsmetoden vi använde oss utav, då det är mycket tydligt att det är menade för större projekt, och gav inte tillräckligt med detaljrik information för att vara till värde för oss. 35

Byggscript Byggscriptets första (seriösa) version, och den slutliga. I den första versionen av byggscriptet var ambitionen främst att det skulle göra ungefär samma sak som den standard-byggscripten som eclipse skapar för ett projekt. Med andra ord, kompilera alla klasser och dess beroenden. Det gick ganska bra fram till dess att testfallen inkluderades, då det krävdes externa bibliotek (JUnit) för att kompilera dessa. Så småningom fick vi även det att fungera. I den färdiga versionen så körs även testfallen, och om desa går igenom skapas även en jar-fil för respektive paket. 36

1 <? xml version =" 1.0 "? > 2 <project name=" texas " default =" buildtest " basedir ="." > 3 <property name=" build. dir " location =" bin " / > 4 <property name=" srccards. dir " value=" src / cards " / > 5 <property name=" srctexasholdem. dir " value=" src / texasholdem " / > 6 <property name=" srctest. dir " value=" test " / > 7 8 <property name=" test. report. dir " location =" testreports " / > 9 10 <path id=" junit. class. path " > 11 <pathelement location =" ${ eclipse }/ plugins / org. junit */* junit. jar " / > 12 <pathelement location ="/ home / anton / dokument / eclipse / plugins / org. junit_4.11.0. v201303080030 / junit. jar " / > 13 <pathelement location =" ${ eclipse }/ plugins /* org. hamcrest.*. jar " / > 14 <pathelement location =" ${ build. dir }" / > 15 </ path > 16 17 <target name=" buildcards " description =" Build package cards " > 18 <mkdir dir =" ${ build. dir }" / > 19 <javac includeantruntime =" false " destdir =" ${ build. dir }" source =" 1.7 " target =" 1.7 " > 20 <src path=" ${ srccards. dir }"/ > 21 </ javac > 22 </ target > 23 24 <target name=" buildtexas " description =" Build package texas " depends =" buildcards " > 25 <javac includeantruntime =" false " destdir =" ${ build. dir }" source =" 1.7 " target =" 1.7 " > 26 <src path=" ${ srctexasholdem. dir }"/ > 27 </ javac > 28 </ target > 29 30 <target name=" buildtest " description =" Build test cases " depends =" buildtexas " > 31 <mkdir dir=" ${ build. dir }/ test " / > 32 <javac includeantruntime =" false " destdir =" ${ build. dir }/ test " source =" 1.7 " target =" 1.7 " > 33 < classpath refid =" junit. class. path " / > 34 <src path=" ${ srctest. dir }"/ > 35 </ javac > 36 </ target > 37 </ project > Kod 1: build.xml, första versionen 37

1 <? xml version =" 1.0 "? > 2 <project name=" texas " default =" buildjarfiles " basedir ="." > 3 <property name=" build. dir " location =" bin " / > 4 <property name=" cards. src. dir " location =" src / cards " / > 5 <property name=" texasholdem. src. dir " location =" src / texasholdem " / > 6 <property name=" test. src. dir " location =" test " / > 7 <property name=" test. report. dir " location =" testreports " / > 8 <property name=" jar. dir " location =" jar " / > 9 <property name=" eclipse " location ="/ home / anton / dokument / eclipse " / > 10 11 <path id=" junit. class. path " > 12 <fileset dir=" ${ eclipse }/ plugins " includes =" org. junit */* junit. jar " / > 13 <fileset dir=" ${ eclipse }/ plugins " includes =" org. hamcrest */* junit. jar " / > 14 <fileset dir=" ${ eclipse }/ plugins " includes =" org. hamcrest. core *. jar " / > 15 <pathelement location =" ${ build. dir }" / > 16 </ path > 17 18 <target name=" clean " description =" Delete previous jar and class files " > 19 <delete includeemptydirs =" true " dir=" jar " / > 20 <delete includeemptydirs =" true " dir=" bin " / > 21 </ target > 22 23 <target name=" compilecards " description =" Compile package cards " depends =" clean " > 24 <mkdir dir =" ${ build. dir }" / > 25 <javac includeantruntime =" false " destdir =" ${ build. dir }" source =" 1.7 " target =" 1.7 " > 26 <src path =" ${ cards. src. dir }"/ > 27 </ javac > 28 </ target > 29 30 <target name=" compiletexas " description =" Compile package texasholdem " depends =" compilecards " > 31 <javac includeantruntime =" false " destdir =" ${ build. dir }" source =" 1.7 " target =" 1.7 " > 32 <src path=" ${ texasholdem. src. dir }"/ > 33 </ javac > 34 </ target > Kod 2: build.xml, slutgiltliga versionen (1/2) 38

1 <target name=" compiletest " description =" Compile test cases " depends =" compiletexas, compilecards " > 2 <javac includeantruntime =" false " destdir =" ${ build. dir }" source =" 1.7 " target =" 1.7 " > 3 < classpath refid =" junit. class. path " / > 4 <src path =" ${ test. src. dir }"/ > 5 </ javac > 6 </ target > 7 8 <target name=" runtestcases " description =" Run test cases " depends =" compiletest " > 9 <junit showoutput =" true " printsummary =" true " fork=" yes " haltonfailure =" yes " > 10 < classpath refid =" junit. class. path " / > 11 <classpath > 12 <pathelement location =" ${ build. dir }"/ > 13 </ classpath > 14 <formatter type=" plain " usefile =" false " / > 15 <batchtest todir=" ${ test. report. dir }" > 16 < fileset dir =" ${ build. dir }" > 17 < include name ="* Test. class " / > 18 </ fileset > 19 </ batchtest > 20 </ junit > 21 </ target > 22 23 <target name=" buildjarfiles " description =" Build.jar - files " depends =" compilecards, compiletexas, compiletest, runtestcases " > 24 <mkdir dir =" ${ jar. dir }" / > 25 <jar destfile ="${ jar. dir }/ cards. jar " basedir ="${ build. dir }/ cards " includes ="*. class " /> 26 <jar destfile =" ${ jar. dir }/ texasholdem. jar " basedir =" ${ build. dir }/ texasholdem " includes ="*. class " / > 27 </ target > 28 29 </ project > Kod 3: build.xml, slutgiltliga versionen (2/2) 39

I tillstånd Båge Till tillstånd Testfall q0: Not in round Enter round q1: In round notinroundtoinround_enterroundtest() q0: Not in round Check q2: Illegal state notinroundtoillegalstate_checktest() q0: Not in round All in q2: Illegal state notinroundtoillegalstate_allintest() q0: Not in round Raise q2: Illegal state notinroundtoillegalstate_raisetest() q0: Not in round Call q2: Illegal state notinroundtoillegalstate_calltest() q0: Not in round Fold q2: Illegal state notinroundtoillegalstate_foldtest() q1: In round Fold q0: Not in round inroundtonotinround_foldtest() q1: In round Round over q0: Not in round inroundtonotinround_roundovertest() q1: In round Call q1: In round inroundtoinround_calltest() q1: In round Check q1: In round inroundtoinround_checktest() q1: In round Raise q1: In round inroundtoinround_raisetest() q1: In round All in q3: Zero chips inroundtozerochips_allintest() q3: Zero chips Call q2: Illegal state zerochipstoillegalstate_call() q3: Zero chips All in q2: Illegal state zerochipstoillegalstate_allin() q3: Zero chips Fold q2: Illegal state zerochipstoillegalstate_fold() q3: Zero chips Raise q2: Illegal state zerochipstoillegalstate_raise() q3: Zero chips Check q2: Illegal state zerochipstoillegalstate_check() q3: Zero chips Won round q0: Not in round zerochipstonotinround_wonround() q3: Zero chips Lost round q4: Out of game zerochipstonotingame_lostround() 40