Göm menyn

Projektbedömning

När du lämnar in ditt projekt kommer det att granskas i två omgångar, först av en handledare och sedan av examinatorn. Syftet med projektbedömningen är:

  • Att examinera dina kunskaper.

  • Att vara ett sista inlärningstillfälle där du får tips om vad du behöver tänka på.

Resultatet av bedömningen kan bli att:

  • Projektet blir godkänt. I TDDD78 och TDDE30 ges betyg 3-4-5. I 729A85 ges betyg G-VG.

    Du kan också plussa (höja betyget) vid senare inlämningstillfälle genom att fortsätta arbeta med samma projekt. Detta gäller garanterat under årets inlämningsmöjligheter, som visas på deadlinesidan. När nästa kursomgång börjar kan du behöva följa nya regler!

  • Projektet blir inte godkänt och behöver kompletteras vid senare inlämningstillfälle. Komplettering kan behövas även om det är uppenbart hur man skulle ändra koden – för det är genom att göra som man både lär sig mest och visar att man kan, inte genom att förklara hur man kunde ha gjort. Under årets inlämningstillfällen kan du fortsätta komplettera enligt årets regler. När nästa kursomgång börjar kan reglerna ändras.

Det tar ett par timmar att bedöma och kommentera ett projekt, så det är omöjligt för oss att ge en fullständig bedömning i förväg. Men i mån av tid kan handledarna titta på projektet och ge tips, vilket knappast händer under en tenta. Utnyttja detta i god tid! Fråga gärna även andra kursdeltagare om de har några minuter för att ge förslag och kommentarer.

Bedömningskriterier: Utökningar till Tetris

För att uppnå ett givet betyg i den här kursen behöver man visa upp kunskaper och färdigheter inom ett antal områden. Vår erfarenhet är att vissa av dessa områden kan vara svåra att få in i projektet. Vissa projekt leder till exempel inte på ett naturligt sätt till användning av felhantering (exceptions), och även om felhantering används någonstans kanske det inte testar just de aspekter som vi behöver examinera.

Därför har vi infört en betygsskillnad även i Tetrisuppgiften, där man behöver göra fler individuella uppgifter för att uppnå högre betyg än 3/G och därmed examineras med ytterligare djup och bredd.

Vi ger dock inte detta betyg i själva labbmomentet, delvis för att vi då skulle behöva ställa betydligt högre krav på all labbkod för att man skulle få ett av de högre betygen. I stället är huvuddelen av labbarna kvar som ett "förberedande" moment där man enbart får godkänt. Det extraarbete som man gör i Tetris räknas istället in i det individuella projektbetyget och därmed i betyget på hela kursen.

Bedömningskriterier: Programkod

Vi vill uppnå god objektorientering, bra användning av Java, och välskriven, välstrukturerad, lättläst och robust programkod.

Det går inte att i förväg ange exakt vad man måste göra för att uppnå en viss betygsnivå inom dessa områden. Detta beror dels på att vissa kriterier är svåra att mäta och kvantifiera, dels på att vissa "problem" kan kompenseras av att koden håller hög kvalitet i övrigt, och dels på att det inte går att göra en uttömmande lista på alla sätt man kan bryta mot de abstrakta principerna om bra programmering. "Hur objektorienterad" måste koden till exempel vara för betyg 3?

Här krävs istället en bedömning av handledaren och examinatorn, och ju högre betygsambition, desto högre krav ställs. Projektet är alltså som en tenta: Man kan aldrig veta exakt när man har lärt sig tillräckligt mycket för att få godkänt, eller när man har besvarat en fråga tillräckligt bra för att få full poäng. Man får jobba på till man tror man har klarat gränsen med rimlig marginal.

Men vi kan ändå göra en hel del för att konkretisera de abstrakta kraven.

  1. Vi ska bryta ner önskemålen i mer konkreta aspekter av programmering och programkod. Detta ser du i "underrubrikerna" nedan.

  2. Vi kan ibland ange en uppsättning specifika krav som projektet ska uppfylla, där man normalt får komplettering om man bryter mot kravet även om projektet i övrigt håller hög kvalitet. Ibland finns det också specifika skillnader i sådana krav mellan olika betygssteg. Detta beskriver vi i rutor som denna:

    Rubrik
    • Betyg 3/G: ...

    • Betyg 4/VG/5: ...

  3. Vi har sammanställt ett antal specifika, konkreta exempel på bra och mindre bra programmering. Siffrorna nedan refererar till olika avsnitt på den sidan. Detta kan ses som en kondensering av tusentals sidor tänkbart kursmaterial till en mindre mängd konkreta tips som fokuserar just på det som brukar kunna ge problem i kursens projekt.

Avsnitt 1. Undvik fel som kan upptäckas automatiskt

En hel del potentiella problem i programkod kan upptäckas automatiskt, genom algoritmer som analyserar koden. IDEA kan göra detta åt dig. Följ instruktionerna.

Inspektera koden med korrekt profil och åtgärda eller motivera varningar enligt instruktionerna. Annars kan du få komplettering utan att handledaren går genom projektet. Att granska ett projekt med många inspektionsvarningar är slöseri med tid. IDEA kan givetvis ha fel i sina inspektioner. Som det står i instruktionerna ska man då ge en tydlig motivering till varför man anser att IDEA har fel och varför koden inte bör ändras. Detta ingår i examinationen och kan i princip ses som en tentafråga. Att inte kommentera kvarlämnade varningar, eller enbart kommentera att "jag tycker inte det behövs" eller att "IDEA har fel" utan vidare motivering, ger normalt komplettering!
I den inlämnade koden ska du inte använda @SuppressWarnings eller //noinspection för att stänga av inspektionsvarningar. Vi vill se var varningarna finns, så att vi kan gå genom motiveringarna.

Avsnitt 2, 3, 4, 5. Skriv förståelig kod

Läsbarhet är viktigt eftersom programmering ofta går ut på att utöka och ändra existerande kod. Tid som läggs ner på att göra kod lättläst och välstrukturerad, och att dokumentera, är alltså inte bortslösad utan sparas in med råge i senare utvecklingsfaser. Slutmålet är därför inte bara att skapa ett program som åstadkommer rätt saker, utan att skapa ett program som gör på rätt sätt.

Olika aspekter av detta har diskuterats under flera olika föreläsningar. På exempelsidan diskuteras detta också i flera olika sektioner:

  • [2] Allmän kodstruktur och organisation, t.ex. indelning av kod i metoder, klasser och paket.

  • [3] Kortfattad och koncis kod, som ger många exempel på hur man kan undvika upprepningar (identiska eller med variationer). Undvik Write Everything Twice – följ Don't Repeat Yourself!

  • [4] Självförklarande kod, som handlar om att göra koden lättare att läsa genom att det är uppenbart vad den gör, istället för att man kommenterar vad den gör. Till exempel är bra namngivning, och att man inför namngivna begrepp, viktigt.

  • [5] Dokumentation och kommentarer, i lagom mängd, som diskuterar hur man skriver de kommentarer som behövs även när många aspekter av koden är självförklarande.

Paketstruktur
  • Betyg 3/G: Ange alltid ett paket för din kod.

  • Betyg 4/VG/5: Dela upp projektet i lämpliga delpaket. Om det inte går att hitta lämpliga grupperingar kan det hända att projektet inte har tillräcklig omfattning, att för mycket kod ligger i en och samma klass, eller att projektstrukturen behöver justeras. Det kan också hända att projektet verkligen inte lämpar sig för uppdelning, men det är ovanligt.

Död kod
  • Betyg 3/G/4/VG/5: Ta bort död kod, det vill säga kod som aldrig kan anropas och därmed inte kan testas eller demonstreras ordentligt.

    Ta också bort bortkommenterad kod.

    (I Git kan ni fortfarande komma åt den borttagna oanvända koden om ni vill fortsätta med den senare. Det går också att skapa en egen gren (branch) just för borttagningen inför inlämningen, och byta tillbaka till huvudgrenen (master) för vidareutveckling.)

Repetitiv kod

Genom att abstrahera, parameterisera och generalisera kan man på kortare tid skriva kortare, mer lättläst och mer utökningsbar kod utan onödiga upprepningar. Detta är alltså viktigt av många anledningar.

  • Betyg 3/G: Upprepad / repetitiv kod accepteras i små mängder. Alltför repetitiv och ineffektiv kod ger ofta komplettering, även när det inte gäller "exakt" upprepning. Gå genom all din kod och undersök om det finns något du tycker borde kunna uttryckas effektivare, kod där det känns som om du inte borde ha behövt skriva så mycket som du gjorde. Antagligen behövde du inte det!

  • Betyg 4/VG/5: Upprepad / repetitiv kod bedöms hårdare.

  • Detta är en vanlig källa till komplettering eller betygssänkning!

Dokumentation och kommentarer
  • Betyg 3/G: Projektbeskrivningens implementationsavsnitt måste ge en bra översikt över programmet, typiskt på 3–6 sidor (givet att det mesta är text). Detta är en del av examinationen som delvis ersätter en tenta.

    Koden måste också vara tillräckligt lättförståelig. Första steget är alltid att skriva självförklarande kod, men oftast krävs också en del kommentarer, både när det gäller varför man gör något och hur man gör det.

    Med detta sagt vill vi också säga att vi har sett extremt stora variationer i hur man kommenterar sina projekt. Vissa kommenterar alldeles för lite, medan andra ligger mycket över våra krav. Meningen är inte att varje fält, metod och kodstycke ska ha den perfekta och fullständiga beskrivningen, utan man behöver arbeta tillräckligt med kommentarerna för att den som läser koden ska få tillräckligt med information så man klart och tydligt förstår vad som händer och varför.

  • Betyg 4/VG/5: Varje klass ska kommenteras med en övergripande Javadoc-kommentar som beskriver klassen (syfte, användning, relation till andra klasser, ...). Kommentarerna ska vara tillräckligt informativa för att man ska kunna få en rimlig förståelse för klasserna helt utan att läsa någon programkod! Javadoc-formatet beskrivs i en kursbok du har valt, eller t.ex. i Oracles egen dokumentation. Självklart kan även andra kommentarer behövas.

    Dessutom ska alla eventuella publika fält Javadoc-dokumenteras ordentligt. (Sådana fält ska normalt undvikas.)

Avsnitt 6. Korrekt objektorientering

Programmera objektorienterat. Ta chansen att demonstrera att du har lärt dig begreppen som ingår i kursen och vet hur de ska användas. Detta är ju kursens mål! Om ett problem kan lösas på ett OO-sätt eller ett icke-OO-sätt ska du använda OO-lösningen, om den inte är uppenbart sämre.

Använd också objektorientering på korrekt sätt. Vissa aspekter av korrekt användning av objektorientering diskuteras under [6] Korrekt objektorientering.

Globala variabler och Singleton
  • Betyg 3/G/4/VG/5: Undvik globala variabler (icke-konstanta static-fält) och Singleton-mönstret. I undantagsfall kan detta vara den bästa lösningen, men det är mycket vanligare att det leder till komplettering.

Avsnitt 7. Korrekt användning av ärvning, polymorfism

Typhierarkier, ärvning och polymorfism är kraftfulla verktyg, men de ska inte användas till allt, och det finns ett antal fallgropar som har diskuterats under kursens gång. Några viktiga aspekter diskuteras vidare under [7] Ärvning, polymorfism med mera.

Avsnitt 8. Korrekt inkapsling / synlighet

Vi har diskuterat hur man kan göra medlemmar privata eller "skyddade" (protected) för att till exempel gömma implementationsdetaljer. Under [8] Inkapsling och synlighet påminner vi om några saker att tänka på.

Avsnitt 9. Korrekt användning av typer

Under [9] Korrekt användning av typer påminner vi om några aspekter av användning av typer, bland annat vad gäller generics (generiska typer som List<E>) och wrappertyper (objekt som lagrar enstaka primitiva värden, som Integer och Boolean).

Avsnitt 10. Felhantering och robusthet

Skriv robusta program. Hantera till exempel eventuella fel som kan uppstå på ett bra sätt, särskilt när det gäller problem som direkt kan triggas av en användare. Vanliga misstag och fallgropar visas under [10] Felhantering och robusthet.

Resurshantering

När man läser in resurser via t.ex. ClassLoader.getSystemResource() kan det hända att de saknas. Man får då null tillbaka, vilket kan leda till NullPointerException senare i koden.

Detta behöver inte hanteras, eftersom det i så fall beror på felaktiga resursnamn eller problem med själva installationen av programmet. Det är att jämföra med att klassfiler saknas i installationen, vilket vi inte heller har separat felhantering för.

Felhantering

Med "upptäckta fel" menar vi dels undantag (exceptions) som fångas efter att de uppstår i egen kod eller andras kodbibliotek, dels andra typer av fel som man upptäcker på andra sätt, t.ex. genom att man själv kontrollerar om användaren ger felaktig input eller om en metod signalerar fel genom att returnera null.

  • Betyg 3/G: Upptäckta fel får inte bara ignoreras.

    Om ett fel beror på användarens input, t.ex. att användaren har matat in felaktig information i en dialogruta, valt en fil som inte kan öppnas eller har styrt en spelare utanför skärmen, ska det hanteras genom att användaren får en ny chans att ge korrekt input.

    I övriga fall är det önskvärt att fel hanteras korrekt enligt kraven för betyg 4 nedan, men acceptabelt (för betyg 3/G) att helt enkelt skriva ut en stacktrace och avsluta programmet. Då demonstrerar du att du vet var felen kan uppstå och var de borde hanteras, och undviker många farliga följdfel.

    Att ignorera fel och fortsätta är inte acceptabelt för betyg 3/G.

  • Betyg 4/VG: Upptäckta fel ska hanteras korrekt. Detta innebär bland annat att fel ska hanteras på rätt plats, att man inte får "fånga och ignorera / glömma bort" felen, att man ska tänka på potentiella följdfel (om jag fångar felet här och fortsätter, vad händer då?), och att man vid behov ska ge rimliga felmeddelanden till användaren. Läs vidare i de specifika tipsen!

    Om det är helt orimligt att programmet ska kunna fortsätta köra efter felet, är det acceptabelt att helt enkelt skriva ut en stacktrace och avsluta programmet. I övrigt ska fel hanteras enligt bästa förmåga.

  • Betyg 5: Exceptions som fångas ska dessutom loggas med hjälp av Javas loggningssystem (java.util.logging), tillsammans med rimliga felmeddelanden.

11. Korrekta designmönster

Att använda designmönster är inget krav, men om du gör det ska de användas korrekt. Exempel finns under [11] Designmönster.

Varning: MVC-mönstret (Model/View/Controller) är ofta för komplicerat att applicera på projekten. Detta mönster användes i Tetris, där vi helt separerade datamodellen (Board) från grafisk visning. Detta var relativt enkelt då Tetris har en enkel modell. Skriver man till exempel ett spel med många olika spelare och andra entiteter som ska visas på skärmen, kan det vara bättre att låta varje sådan klass ha hand om både modell och grafisk visning. Med andra ord, att låta Player både hålla reda på var spelaren är, hur många liv den har, och hur den ska se ut och kanske animeras. Annars är det lätt att man får en alltför centraliserad lösning med en enda utritningsklass som ska känna till hur allt ska se ut, vilket istället bryter mot decentraliseringsprinciper.

12. Körbara program

Projektet ska resultera i ett färdigt program som kan "levereras" för enkel installation och körning på någon annans dator – till exempel hos handledaren som ska testa inlämningen. Detta ställer ytterligare krav på programmet, som diskuteras under [12] Körbara program.

Inläsning av data och bilder
  • Betyg 3/G: Projektets filer får läsas in via vanlig filhantering. Detta gäller alltså filer som finns med projektet från början, t.ex. bilder och spelbanor.

  • Betyg 4, VG, 5: Javas stöd för resurser ska användas om du behöver läsa in filer (bilder, ljud, banor, inställningar osv.) som tillhör och "levereras med" programmet. Använd alltså ClassLoader.getSystemResource(). På det sättet undviker vi att behöva ange var filerna finns i en specifik installation, och filerna kan hämtas även om hela programmet råkar vara packat i en JAR-fil (liknande ZIP-fil). Om du även skriver till en fil behöver du inte använda resurser för den filen, eftersom du i så fall ändå måste veta var filen är placerad.

Användande av andras kod

Följande regler gäller när man använder kod som man inte har skrivit själv (ensam).

Användande av andras kod

För klassbibliotek i kompilerat format gäller följande:

  • Du får gärna använda alla klasser i standardbiblioteket för Java 11.

  • Du får också använda MigLayout och GSON, som vi har refererat till under föreläsningar och/eller i labbarna. Du måste då lägga till själva JAR-filerna i det incheckade projektet och lägga till dem som libraries i IDEA-projektet. Följ instruktionerna för IDEA, eller den enklaste varianten: "You can also create a new library from JAR files located within a project content root. Select these files in the Project tool window, and then select Add as Library from the context menu". Du behöver inte tala om för oss att du använder dessa välkända bibliotek.

    När du lämnar in detta projekt kan du alltså inte använda verktyg som Maven eller Gradle för att automatiskt hantera beroenden. Verktygen är visserligen bra, men sätter käppar i hjulen för vår kodinspektion.

  • Du får gärna använda andra fullständiga klassbibliotek som du laddar ner från nätet, under följande förutsättningar:

    • Klassbiblioteken får inte vara ramverk som "tar över" projektet. Det måste vara din kod som driver allt framåt, medan klassbiblioteket får hjälpa till med isolerade deluppgifter – t.ex. att hantera uppritning av rörliga figurer på skärmen.

    • Du kan inte räkna med att de som granskar ditt projekt är bekanta med det klassbibliotek du använder. I implementationsbeskrivningen i projektmallen behöver du därför vara extra noggrann med att beskriva ramverken och dess användning i ditt projekt, och du kan behöva fler sidor än det angivna antalet. Missar du det kan du få tillbaka projektet för komplettering av dokumentationen.

    • Klassbiblioteken ska läggas till som JAR-filer i projektet och checkas in. De ska inte ligga med som källkod (se nästa punkt).

För okompilerad källkod du hittar på nätet gäller följande viktiga regler, som måste följas för att du inte ska riskera misstanke om fusk / plagiat (där vi är skyldiga att anmäla alla misstankar):

  • Du får använda enskilda fullständiga klasser vars källkod du hittar på nätet, under förutsättning att du lägger dem i ett paket vars namn innehåller "borrowedcode" (exakt så) eller lägger till "BorrowedCode" i klassnamnet. Du kan t.ex. lägga dem i package se.liu.liuid123.game.graphics.borrowedcode om ditt LiU-ID är liuid123, eller döpa en klass till MyListenerBorrowedCode. Detta mönster används sedan i automatisk kodanalys!

    Regeln gäller även om du modifierar den kod du hittar.

  • Du får använda enskilda kodfragment som du hittar på nätet. Om kodfragmenten är längre än 2-3 rader ska de göras till separata metoder vars namn innehåller "borrowedcode", t.ex. "borrowedcode_dijkstras_algorithm()". Detta mönster används sedan i automatisk kodanalys! Är kodfragmenten högst 3 rader kan det räcka med en kommentar som innehåller texten "borrowedcode".

    Regeln gäller även om du modifierar den kod du hittar.

  • Du får givetvis inspireras av enskilda enklare kodrader du hittar på nätet, och om du anser att du faktiskt har lärt dig tillräckligt för att skriva detta själv utan att "titta på facit", får du använda sådan egenskriven kod utan att ange en källa. Men om det handlar om enstaka rader som du inte anser att du helt och fullt kan skriva på egen hand, är det bättre att ta det säkra före det osäkra och ange inspirationen.

För samarbete med andra grupper gäller följande:

  • Det är fullt tillåtet att diskutera gemensamma lösningar på ett problem, t.ex. hur man strukturerar en del av koden, så länge som varje projektgrupp skriver sin egen kod.

  • Om man faktiskt skriver koden tillsammans, och sedan utgår från en gemensam fil, räknas detta som lånad kod enligt ovan!

Omfattning

Omfattningen ska motsvara projekttiden på runt 80 timmar/person. Omfattningen innebär inte bara "kodvolym" utan beror mycket på komplexitet, variation, och så vidare. Detta kriterium är av naturen mycket svårt att specificera närmare. Vad vi kan säga i förväg är:

  • Vi kan så klart inte godkänna ett projekt som ser ut att motsvara 25 timmars arbete – men hög kvalitet och bra användning av OO kan ändå till en viss del väga upp en mindre omfattning.

  • Projekt som är tillräckligt omfattande för 3/G brukar rent statistiskt ha minst 800 rader kod (exklusive tomrader, kommentarer osv). Många projekt från de senaste åren var flera gånger större.

    Detta betyder inte att vi bedömer omfattning efter antal kodrader!. Vi tar också hänsyn till komplexitet och variation. Men den kod som har uppfyllt dessa kriterier har oftast också blivit minst 800 rader lång.

  • Smart är bättre än långt. En smart och effektiv lösning är oftast bättre än en lång. Ineffektiv kod, t.ex. upprepningar av nästan identisk kod, har ofta lett till komplettering.

  • Vår rekommendation: Fokusera på kvalitet, funktionalitet och att utnyttja era 80(+80) timmar väl. Om du funderar över projektets omfattning, diskutera med en erfaren handledare i god tid.

Bedömningskriterier: Projektbeskrivning

Den slutliga projektbeskrivningen ska använda den mall vi tillhandahåller och ska så klart innehålla all den information som vi har begärt genom instruktionerna i mallen.

Projektbeskrivningen innehåller flera avsnitt som ska testa din förståelse av olika aspekter hos objektorienterad programmering. Olika betyg kräver olika omfattning i vissa avsnitt. Detaljerade förklaringar av vad du ska beskriva finns i mallen!

Krav Betyg 3/G Betyg 4 Betyg VG Betyg 5

Visa insikt i programdesign, hur man tänker när man strukturerar sina program, genom att dokumentera ett visst antal designbeslut. I koden syns ju bara slutresultatet – i beskrivningen får du en chans att visa mer om processen bakom besluten.

2 beslut 4 beslut 6 beslut 8 beslut

Visa förståelse för hur UML-diagram kan användas genom att inkludera ett visst antal diagram i förklaringarna av projektets struktur. Diagrammen kan t.ex. skapas i IDEA.

Varje diagram ska illustrera en specifik "intressant" aspekt av projektstrukturen och åtföljas av en beskrivning enligt instruktionerna i mallen. Metoder och fält ska bara finnas med i diagrammen om de är relevanta och diskuteras i texten (undvik dem om du bara vill illustrera klasstrukturen).

1 diagram 2 diagram 3 diagram 4 diagram

Ge oss tillräckligt med information! Se detta som tentafrågor där du försöker ge tillräckligt med information för att verkligen visa upp breda och djupa kunskaper.

För att minska risken för komplettering får du gärna lämna in ett eller två extra "svar" i varje avsnitt. Siktar du på femma kan du t.ex. beskriva 9-10 designbeslut istället för 8, så att du har en liten marginal om något av dem inte skulle bli "godkänt".

Bedömningskriterier: Inlämning

Vid inlämning ska du följa alla inlämningsinstruktioner. Annars kan din inlämning återlämnas utan granskning.


Sidansvarig: Jonas Kvarnström
Senast uppdaterad: 2019-06-10