Web
Analytics
 

Achievements

Table of Contents

Did you know that you can collapse () and expand () entire sections of these pages? Try clicking a heading! Try “scrolling” to content deep down in a page by collapsing preceeding sections.

Found a bug? Select the fauly text and hit C-x to start a GitHub issue.

1 About This page

This page gathers all the achievements on the course for your perusal. Read about what each achievement corresponds here. Some are marked TODO, meaning they are being somewhat reworked for 2018. When they are finalised, the TODO marker will disappear.

You will use the AUPortal to select goals for demonstration and track your own progress. Starting in 2018, the AUPortal points back to this page for information about each achievement. I am testing gathering all achievement on a single page to facilitate searching – I’m eager to get feedback on this design choice. An alternative would be to gather all Abstraction achievements on one page, all Inheritance achievements, on another etc.

Each achievement is tagged to reflect its grade level and demonstration form – mirroring information in the AU Portal:

Tag Meaning
G3 Achievement is mandatory for grade 3
G4 Achievement is mandatory for grade 4
G5 Achievement is mandatory for grade 5
Lab Achievement is demonstrated during lab sessions
Special See instructions for demonstration in the achievement text
Report Achievement is demonstrated as part of the project report

2 A: Abstraktion

2.1 A1: Procedurell abstraktion   G3 Lab

Tillämpa procedurell abstraktion på ett konsekvent sätt för att öka läsbarheten och undvika upprepningar. Motivera abstraktionsnivån!

Abstraktion är en av de viktigaste programmeringsprinciperna. Vi vet att djupt, djupt nere under huven är allt bara ettor och nollor (redan detta är en abstraktion!), men ovanpå dessa har vi byggt lager på lager av abstraktioner som låter oss tala om program t.ex. i termer av struktar och procedurer.

Procedurell abstraktion handlar om att separera användande från implementation. Varje procedur utför – idealiskt – en enda, välspecificerad funktion, t.ex. en viss beräkning, en förändring av programmets tillstånd, uppdaterar en datastruktur, stänger en fil, etc.

En väldöpt procedur (funktion) t.ex. open_file_for_reading() ger en tydlig beskrivning av vad den gör, men hur den gör det – dess implementation – är inkapslad och inte synlig utifrån. Använder den systemanropet fopen() eller någon annan funktion? Det skall vi strunta i! Det är inte1 inte något vi skall behöva bry oss om, och dessutom något som kan komma att ändras, eller skilja sig beroende på vilken dator jag kör programmet på.

Ta som tumregel att varje procedur skall kunna beskrivas enkelt och kortfattat. En procedur vars beteende inte går att beskrivas enkelt och kortfattat skall förmodligen brytas upp i flera mindre procedurer.

I ett nötskal handlar procedurell abstraktion alltså om att kapsla in alla “conceptual units of behaviour” i en procedur. En procedur är ungefär detsamma som en funktion och många programspråk (t.ex. C) gör ingen skilland på dem.

2.1.1 Exempel

Proceduren ritaEnCirkel(int radie, koordinat center) utför beräkningar och tänder individuella pixlar på en skärm, men i och med att dessa rutiner kapslats in i en procedur med ett vettigt namn, där indata är uttryckt i termer av koordinater och radie har vi abstraherat bort dessa detaljer, och det blir möjligt att rita cirklar tills korna kommer hem utan att förstå hur själva implementationen ser ut.

Väl utförd abstraktion döljer detaljer och låter oss fokusera på färre koncept i taget.

2.1.2 Redovisning

Du bör ha en klar uppfattning om bland annat:

  • Varför det är vettigt att identifiera liknande mönster i koden och extrahera dem och kapsla in dem i en enda procedur som kan anropas istället för upprepningarna?
  • Abstraktioner kan “läcka”. Vad betyder det och vad får det för konsekvenser?
  • Vad är skillnaderna mellan “control abstraction” (ex. if-satsen är en abstraktion) och “data abstraction” (ex. en lista är en abstraktion)? Du kan läsa om dessa koncept på t.ex. http://en.wikipedia.org/wiki/Abstraction_(computer_science).
  • Ge exempel på procedurell abstraktion i ditt program! Kritisera den! Kan den förbättras?
  • Vad är den kortfattade beskrivningen av vad funktionerna gör?
  • Ger namnen på funktionerna en bra ledning om vad funktionerna gör?
  • Finns det exempel på läckande abstraktioner, dvs. där den som anropar funktionen måste känna till hur funktionen faktiskt är implementerad för att fungera, eller förutsätter en viss implementation?
  • Låt \(f_1\), \(f_2\) och \(f_3\) vara funktioner. \(f_1\) och \(f_2\) är delar av samma bibliotek och \(f_2\) använder \(f_3\) i sin implementation. Skiljer sig nivån av abstraktion mellan dessa på något sätt? Hur?
  • Är abstraktion möjlig utan inkapsling? (Bonusfråga)


    Report a bug on this achievement? Please place an issue on GitHub.

2.2 A2: Objektorienterad abstraktion   G3 Lab

Tillämpa objektorienterad abstraktion för att dölja implementationsdetaljer bakom väldefinierade gränssnitt. Motivera abstraktionsnivån!

I samband med redovisning bör du kunna förklara skillnaden/likheterna mellan procedurell abstraktion och objektorienterad abstraktion.

Vad innebär egentligen objekt-orienterad programmering? En ledning är att OOP är ett synsätt snarare än speciella nyckelord eller konstruktioner i ett programspråk.


Report a bug on this achievement? Please place an issue on GitHub.

2.3 A3: Informationsgömning   G4 Lab

Demonstrera förståelse för designprincipen informationsgömning i ett C-program med hjälp av .c och .h-filer.

Informationsgömning på engelska översätts till “information hiding”. En viktig insikt här är att informationsgömning är en princip som är programspråksagnostisk och inte knuten till några speciella nyckelord. I Haskell kunde ni uppnå informationsgömning med hjälp av moduler som bara exporterade en del av sitt gränssnitt. Samma princip fungerar i C, men då är gränssnitt och implementation separerade i .h respektive .c-fil.

Relatera gärna till koncept från Java, som gränssnitt respektive implementation.


Report a bug on this achievement? Please place an issue on GitHub.

2.4 A8: Gränssnitt   G4 Lab

Visa hur man kan separera gränssnitt från implementation med hjälp av Java-interfaces.

Separation av gränssnitt från implementation är viktigt för att möjliggöra interna förändringar av implementationen utan att externa klienter behöver t.ex. kompileras om.

Javas interface-konstruktion är ett förtingligat gränssitt som kan knytas till en klass som implementerar det. Ett interface kan ses som ett kontrakt och implementationen av ett interface kan ses som ett löfte att uppfylla kontraktet. En klass som implementerar ett interface måste åtminstone nominellt uppfylla detta kontrakt.

Detta mål handlar inte bara om att förstå principen för hur man gör en separation av detta slag utan också varför. Det sistnämnda bör guida det praktiska användandet och kan med fördel förklaras vid en redovisning.


Report a bug on this achievement? Please place an issue on GitHub.

3 B: Arv

3.1 B4: Arv och subtypspolymorfism   G3 Lab

Make use of inheritance, overriding and super calls in a program that leverages subtype polymorfism.

3.1.1 Metodspecialisering (aka overriding)

Metodspecialisering avser när en subklass tillhandahåller en mer specifik implementation av en metod än sin superklass. Ponera klasserna Egendom och Hus där Hus ärver av Egendom. Man kan tänka sig att det finns en metod skatt() för Egendom som beräknar en viss grundskatt baserat på något givet värde, men att Hus tillhandahåller en egen implementation av skatt() som är mer specifik för just hus, t.ex. gör vissa avdrag etc. som gäller specifikt för hus. Man kan tänka sig att den mer specifika skatt()-metoden anropar den mer generella för återanvändning (räkna ut grundskatten).

Polymorfism är möjligheten att behandla olika typer av värden genom ett gemensamt gränssnitt eller möjligheten att applicera en funktion på flera olika typer av värden. Det finns många olika typer av polymorfism – studera detta begrepp vidare! I Haskell stötte ni på polymorfism till exempel i signaturen till map :: (a -> b) -> [a] -> [b]map tar en funktion från a till b ch en lista av a:n och beräknar en lista av b:n, och fungerar likadant oavsett vilka typer man använder istället för a och b.

Subtypspolymorfism avser polymorfism mellan subtyper, t.ex. Hus och Egendom ovan och husets möjlighet att uppträda/bli behandlat som en generell form av egendom. (Javas dynamiska bindning gör här att huset ändå bibehåller sitt specifika beteende.)

3.1.2 Inheritance in relation to subtype polymorphism

Inheritance facilitates (or even allows) the modularisation of definitions, which can be very useful even if a class hierarchy never branches out (meaning that no class has more than one subclass). Imagine a class hierarchy with classes \(A\), \(B\) and \(C\), such that \(A\) is a superclass of \(B\), and \(B\) is a superclass of \(C\). The implementation of a behaviour \(b\) might be split over \(A\), \(B\) and \(C\) through three separate, overriding, implementations of a method \(m\). Thus, \(m\) is defined in \(A\), \(B\) and \(C\) such that a subclass’ \(m\) overrides all its superclasses’ \(m\)’s. Through the use of super calls, \(C\)’s \(m\) may call \(B\)’s \(m\). This effectively means that a specialised method can reuse or extend a more general method in a super class. This was already referenced above: “It is possible that the more specific calculateTax()” method calls the more general method for reuse, e.g., to calculate basic tax.“

This allows us to distribute the specification of a behaviour over multiple source locations in a way that may facilitate software development and software evolution when used correctly. For example, in the above example it is immediately clear from the code that house taxation can be understood as a clean extension to property taxation. This might be even more useful if Property has several subclasses each subject to its own specific tax laws as it allows reuse (because of the modular description) of the basic property tax laws, making each delta small. In the case where the variation in taxation is greater, we might implement taxation as several methods working together, which allows a more fine-grained overriding in subclasses. Be careful to not create too unwieldy programs where the logic is hard to follow due to the implicit (possibility of) branching in dynamic dispatch. Overriding for its own sake shall be avoided.

If you find inheritance interesting, Tobias recommends a recent paper by Black, Bruce and Noble on the The Essence of Inheritance which he enjoyed immensely, especially Andrew’s presentation. Here is a(nother) recording of this presentation from WadlerFest.


Report a bug on this achievement? Please place an issue on GitHub.

3.2 B5: Liskov’s Substitution Principle   G3 Lab

Demonstrate understanding of Liskov’s substitution principle by relating it to how you have used it in your implementations of the assignments or project.

Let \(C\) and \(D\) be classes, and \(P\) be a program that uses instance of class \(C\).

Liskov’s substitution principle (LSP) states that if \(D\) is a subtype of \(C\), then we should be able to change $C$-objects for $D$-objects in \(P\) without altering any desirable property of the program.

What does that mean?

In particular, from active use in your implementations, you must demonstrate understanding of the following concepts:

  • The difference between subclass and subtype
  • The concept of overriding
  • The concept of overloading
  • Understand the rule of covariance and contravariance with respect to method parameters and returns in relation to overriding, and how it relates to weakening preconditions and strengthening postconditions
  • How the semantics of Java corresponds or deviates with the LSP

Bonus: is LSP the only possible definition of subtype?

Relate LSP to object-oriented reuse and/or software evolution and/or maintenance.

3.2.1 Incomplete Background (see lectures for complete coverage)

Överlagring (overloading) av operatorer, funktioner, metoder och konstruktorer i Java sker när de har samma namn, men olika typer på sina inparametrar, d.v.s. de har olika signatur. Ett klassiskt exempel på överlagring är +-operatorn som fungerar olika beroende på typer: "1" + "2" konkatenerar två strängar (resultatet blir strängen "12"), medan 1 + 2 adderar två heltalsliteraler (resultatet blir heltalet 3). C stöder inte överlagring alls. Många statiskt otypade programspråk stöder överlagring med avseende på antalet parametrar2

Specialisering (overriding) av metoder och konstruktorer sker när en subklass tillhandahåller en konstruktor med kompatibel signatur (detta avser regler för hur typer på returer och parametrar får ändras – se kovarians och kontravarians). En skillnad mellan metodspecialisering och konstuktorspecialisering i Java är att i fallet konstruktorer måste åtminstone en konstruktor anropas per klass i en klasshierarki, d.v.s. om klassen Hus är en subklass till Egendom måste alla konstruktorer i Hus anropa en konstruktor i Egendom (givet att en sådan finns). Notera att ett sådant anrop måste stå först i konstruktorn eftersom objekt initieras i stigande specialiseringsordning, d.v.s. mest generella klass först (alla delar som hör till Object), sedan näst mest generella (Egendom i föreliggande exempel) och sist det mest specifika (här Hus).


Report a bug on this achievement? Please place an issue on GitHub.

3.3 B6: Genomskärande åtaganden och arv   G4 Lab

Förklara hur arv har använts i ett program för att separera genomskärande åtaganden.

Fördjupa dig i konceptet “genomskärande åtaganden.”

Genomskärande åtaganden är en försvenskning av begreppet Cross-cutting concerns. Ett åtagande är här något som (en del av) programmet måste göra, “ett stycke funktionalitet” slarvigt uttryckt, som kan vara “direkt” (beräkna \(X\)) eller “indirekt” (logga händelse under beräkning av \(X\) så att programmets beteende kan följas vid en krasch).

Separation av åtaganden (eng. separation of concerns) handlar om att inte blanda (eng. tangle) de olika implementationerna av olika funktionalitet. Om man t.ex. vill ändra på hur den ovan nämnda loggningen går till skall man inte behöva blanda in implementationen av beräkningen av \(X\).

You can also look at “shotgun surgery” (code smell) to see a common side-effect of cross-cutting concerns implemented badly.

Överkurs för den intresserade: Jämför med aspektorienterad programmering!


Report a bug on this achievement? Please place an issue on GitHub.

4 C: Planering

4.1 C7: Planering och uppföljning   G3 Special

Planering och uppföljning är en viktig aspekt av kursen – programutveckling är ofta svårt på grund av osäkerhet och svårigheter att uppskatta tidsåtgång. Lättrörliga processer, som den som vi använder för att driva kursen, är ett sätt att motverka detta genom kontinuerlig uppföljning och en feedbackloop som visar om man underskattar eller överskattar tid.

Kurswebben beskriver den process som du skall använda, som är löst baserad på Scrum och personal Kanban.

Varje sprint skall du lägga upp en plan:

  • Vilken inlämningsuppgift skall du göra
  • Vilka mål skall du ta inom ramarna för den uppgiften
  • Hur många mål du borde ta för att komma i mål med kursen

Dessa tre beslut kan hänga ihop. Till exempel kanske du saknar ett visst mål på nivå 4 som gör att det känns vettigare att göra en specifik uppgift – eller inte.

I början när du sitter med uppgiften är det som minst tydligt för dig exakt vilka mål som är lämpliga att redovisa. Du kanske ser 3 stycken men din plan säger att du skall nå 6. Det blir viktigt att du bevakar detta – går tillbaka till målbeskrivningarna, kanske sitter kvar med en gammal uppgift och kollar om den inte kan tänkas redovisa något.

Genom att göra en plan – X mål klar på Y tid – och bevaka hur det går (fortare eller långsammare än X/Y?) kan du få en känsla för hur du ligger till hela tiden.

Detta mål examineras genom inlämning av en komplett burndown chart efter fas 2. Den skall innehålla samtliga sprintar, det uppsatta målet, idealet, utfallet och hur du har planerat om. Du kan med fördel använda kursens spreadsheet för burndown charts. Om du skickar en länk till ditt spreadsheet, glöm inte att göra den publik så att den går att komma åt! Om du har planerat varje program får du gärna inkludera den planeringen också!

Skicka ditt burndown chart på epost till ioopm@it.uu.se enligt följande instruktioner:

  • Ämnesraden skall vara [IOOPM] C7. Den första raden i mejlet skall vara ditt användarnamn till unix-systemet på formen fornamn.efternamn.NNNN. Eftersom vi kommer ta emot mellan 100 och 150 mejl är det viktigt att det går lätt att hitta rätt mejl snabbt.
  • Tillsammans med din burndown-chart, skriv en kort beskrivning så att det går att förstå det utan att du står brevid och förklarar.
  • Skriv också om hur du upplever att jobba på detta sätt, vad som är svårt och vad du får ut av det. Var ärlig! Om du bara tycker det har varit ett hinder, skriv det. Det viktiga är att du uttrycker en åsikt i frågan!

Report a bug on this achievement? Please place an issue on GitHub.

5 D: Dokumentation

5.1 D9: Dokumentation   G3 Lab

Dokumentera icke-triviala modulers gränssnitt så att någon utomstående kan programmera mot dem.

Bra dokumentation är av största vikt vid utveckling. Vid en kort kurs som denna är det svårt att uppleva nyttan med dokumentation som man själv skriver eftersom det inte hinner gå tillräckligt lång tid under kursen för att sådant man utvecklat skall falla tillräckligt i glömska. (Ta gärna fram någon gammal inlämningsuppgift i Haskell från PKD och försök följa logiken och ändra i den.)

  • Det är svårt att balansera mängden dokumentation som krävs för att beskriva något. Vem vänder man sig till? Vad kan man förvänta sig hos den som läser? Vad vill denne åstadkomma?
  • Vad är en bra balans mellan för lite information och för mycket? Vad är en lämplig detaljnivå?
  • Hur mycket av den interna implementationen bör man beskriva? Varför?
  • Hur beskriver man komplexa och tvetydiga processer?

I funktionella språk som Haskell är pre- och postvillkor bra sätt att dokumentera förväntningar och löften på ett sätt som inte exponerar onödiga detaljer. Program skrivna i imperativa språk har i regel tonvis med sido-effekter (även på låg nivå i C, t.ex. minne som allokeras eller frigöra) – vad får det för konsekvens för pre- och postvillkor?

Här är bra länkar att starta med:


Report a bug on this achievement? Please place an issue on GitHub.

6 E: Genericitet

6.1 E10: Implementera genericitet genom void-pekare   G3 Lab

Använd void-pekare i C-program för att uppnå genericitet på ett relevant sätt, t.ex. en datasamling som kan lagra godtyckligt data

Det är inte en bra idé att ha kopior av kod med någon liten förändring, t.ex. en separat implementation av en heltalslista och en flyttalslista. Den underliggande logiken är densamma, och hittar man ett fel i en kopierad del måste man komma ihåg att ändra på samma ställe i alla kopior, etc.

I C använder man s.k. void-pekare för att göra en datastruktur generell, t.ex. gå från en lista av heltal till en lista som kan hålla godtyckligt data. Detta är ett extremt vanligt C-idiom som även förekommer i C:s standardbibliotek. En void-pekare är en pekare till en minnesplats med okänt innehåll, dvs. C-kompilatorn vet inte vad som finns där och hur man skall använda minnet, eller hur stort det är. Visa att du behärskar dessa idom och förstår deras konsekvenser genom att använda dem på ett lämpligt sätt i ett program.

Vid redovisning, börja med att förklara vad genericitet är och varför det kan vara bra i vissa sammanhang.


Report a bug on this achievement? Please place an issue on GitHub.

6.2 E11: Parametrisk polymorfism och typsäkerhet   G3 Lab

Använd parametrisk polymorfism för ökad “statisk typsäkerhet” vid interaktion med Javas standardbibliotek.

Typsäkerhet avser att ett värde alltid används på tillåtet sätt, t.ex. att en bit minne som råkar hålla en baseballspelare med ett heltal för skostorlek på bytes 8–11 används på detta sätt. C är inte ett typsäkert språk vilket tillåter oss att t.ex. spara strängen "Hej" på skostorlekens plats, och sedan läsa dessa fyra bytes som en (abnorm) sko. Java är ett typsäkert språk, och priset man betalar för detta är kontroller under programmets körning som orsakar undantag om en operation skulle leda till ett typfel.

Ponera en lista i Java där elementpekarna är av typen Object. En sådan lista kan innehålla vad data som helst, men vanligt är att man är intresserad av en lista av basebollspelare etc.

Javas stöd för parametrisk polymorfism (även kallat generics) tillåter oss att skapa datastrukturer parametriserade över typer; parametrar vilka måste instantieras vid användande av strukturerna. Javas standardbibliotek formligen kryllar av klasser med typparametrar. Typparametrarna tillåter oss att uttrycka i kod att “detta är en lista av hermeliner” vilket medger möjligheten att signalera kompileringsfel om man försöker smyga in katt ibland hermelinerna.

Visa att du förstår konceptet parametrisk polymorfism och hur det kan användas för att flytta fel från körning (undantag) till kompilering (kompileringsfel).


Report a bug on this achievement? Please place an issue on GitHub.

6.3 E12: Designa med parametrisk polymorfism   G4 Lab

Designa med parametrisk polymorfism för att göra relevanta delar av ett program mer generellt.

Vid designen av en eller flera klasser – dra nytta av parametrisk polymorfism för att slippa ange en typ vid definitionen (detta är en äppellåda) och istället ange den vid användandet av lådan (detta är en låda, som i detta fall råkar innehålla enbart äpplen).

En informell guldstjärna utgår för användanden som inte är samlingsklasser (collections).

Java använder något som kallas type erasure – vad får det för konsekvenser för vad du kan göra med parametrisk polymorfism?


Report a bug on this achievement? Please place an issue on GitHub.

7 F: Imperativ Programmering

7.1 F13: Iteration vs. rekursion   G3 Lab

Visa en översättning mellan en rekursiv och en iterativ lösning av samma problem samt – om du använder sådana – diskutera för- och nackdelar med sido-effekter.

Är någon av lösningarna bättre (vad betyder bättre?)? I så fall, varför skulle man någonsin vilja använda den andra lösningen?

Tänkvärt: Alla iterativa lösningar kan beskrivas med rekursion men gäller det omvända? Ibland ger rekursion en “historik” över vilken väg genom en datastruktur man tagit som försvinner vid en naiv översättning till iteration.

Kan rekursiva funktioner vara iterativa? Vad är egentligen definitionen av att något är iterativt eller rekursivt?

Rekursiva datastrukturer som t.ex. träd är bra för att demonstrera detta.


Report a bug on this achievement? Please place an issue on GitHub.

7.2 F14: Svansrekursion   G4 Lab

(Eng. tail recursion)

Använd svansrekursion för rekursiva funktioner med potentiellt stort djup.

Svansrekursion är rekusion där varje rekursivt anrop kommer som det sista funktionen gör. Beakta följande, icke-svansrekursiva funktion:

int sum(int *numbers[], int num_siz)
{
  if (num_siz > 0)
    {
      int rest = sum(numbers+1, num_siz-1);
      return *numbers + rest;
    }
  else
    {
      return 0;
    }
}
int%20sum%28int%20%2Anumbers%5B%5D%2C%20int%20num_siz%29%0A%7B%0A%20%20if%20%28num_siz%20%3E%200%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20int%20rest%20%3D%20sum%28numbers%2B1%2C%20num_siz-1%29%3B%0A%20%20%20%20%20%20return%20%2Anumbers%20%2B%20rest%3B%0A%20%20%20%20%7D%0A%20%20else%0A%20%20%20%20%7B%0A%20%20%20%20%20%20return%200%3B%0A%20%20%20%20%7D%0A%7D%0A

I detta fall används stacken som en temporär lagringsplats för alla temporära resultat. Vi kan skriva om funktionen på detta svansrekursiva vis:

int sum(int *numbers[], int num_siz, int acc)
{
  if (num_siz > 0)
    {
      return sum(numbers+1, num_siz-1, acc + *numbers);
    }
  else
    {
      return acc;
    }
}
int%20sum%28int%20%2Anumbers%5B%5D%2C%20int%20num_siz%2C%20int%20acc%29%0A%7B%0A%20%20if%20%28num_siz%20%3E%200%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20return%20sum%28numbers%2B1%2C%20num_siz-1%2C%20acc%20%2B%20%2Anumbers%29%3B%0A%20%20%20%20%7D%0A%20%20else%0A%20%20%20%20%7B%0A%20%20%20%20%20%20return%20acc%3B%0A%20%20%20%20%7D%0A%7D%0A

I detta fall behövs ingen stack för att lagra tempoära värden (varför?) och som en konsekvens av detta kan en bra kompilator skriva om funktionen så att den kan köra i konstant minnesutrymme (mer eller mindre tranformera koden till en loop).

Kan en/din C-kompilator göra så-kallad “tail call-optimisation”? Under vilka omständigheter? Hur kan du pröva det?

Om din kompilator inte garanterar att svansrekursion transformeras till loopar – kan det vara problematiskt? Hur?

För att bli godkänd på detta mål måste du även visa hur du skriver om en rekursiv funktion på svansrekursivt vis.

Och slutligen: är svansrekursiva funktioner iterativa?


Report a bug on this achievement? Please place an issue on GitHub.

8 G: Inkapsling

8.1 G15: Aliasering   G3 Lab

Använd kopiering eller liknande för att undvika aliaseringsproblem i ett C- eller Javaprogram.

Aliaseringsproblem uppstår då pekare oavsiktligt pekar ut samma objekt/data så att en förändring via en pekare blir synlig via en annan pekare på ett överraskande sätt. I C är ett klassiskt exempel på aliaseringsproblem inläsning av strängar i en buffer som skrivs över vid varje ny inläsning. (Ett bra sätt att angripa detta mål är att vara vaksam på när du drabbas av denna bugg och använd det för att redovisa målet.)

Aliasering innebär att data kan delas mellan objekt. Detta är kraftfullt (en förändring via en pekare blir synlig för alla andra som har en pekare till samma data) men också väldigt farligt (en förändring via en pekare…) om man är slarvig med vad som delas och inte. Problematiskt är att kod som delar data och kod som inte delar data är identisk. T.ex. ett cirkelobjekt som har en pekare till ett punktobjekt som representerar dess center flyttas om dess centerpunkt flyttas. Om många punkter skapas på samma koordinat kan det vara effektivt att de delar denna punkt, men om de skall flytta sig individuellt uppstår problem om de inte har separata kopior av punkten.

Nu följer några tankar kring ägarskap, d.v.s., vilka objekt som hör till vilka andra objekt. Ett objekts (denna term omfattar även C-struktar) representation är de “subobjekt” som bygger upp ett sammansatta objekt. En länkad listas representation innehåller t.ex. dess länkobjekt eftersom dessa ägs av listan, men inte listdatat eftersom det inte är en del av själva listobjektet.

Representationsläckage är ett exempel på ett aliaseringsproblem och uppstår när subobjekt är synliga utanför det objekt till vilket de konceptuellt tillhör. Om man t.ex. kunde få ett handtag till en länk i en sorterad länkad lista utanför listan kan man göra borttagningar eller insättningar som förstör listans sorteringsordning. Det är vanligt att subobjekt flyttas mellan objekt och byter ägare, eller skapas utanför objektet och flyttas in i det vid initiering, vilket kan leda till representationsläckage om man inte är aktsam.

Mainstreamprogramspråk saknar koncept för ägarskap. På senare tid har Rust dykt upp som ett spännande alternativ och som har ägarskap som ett centralt koncept.


Report a bug on this achievement? Please place an issue on GitHub.

8.2 G16: Namn-baserad inkapsling   G3 Lab

Använd åtkomstmodifierare för att styra synligheten hos variabler och metoder.

Styr åtkomst till både privata metoder och data på ett lämpligt sätt och motivera användandet. Resonera också kring varför namnbaserad inkapsling inte är ett garanterat skydd mot aliasering.

Använd:

  • public
  • private
  • protected eller motivera varför inte
  • package protection (saknar nyckelord)

Vad är Javas standard för inkapsling? Är det vettigt? Varför/varför inte?


Report a bug on this achievement? Please place an issue on GitHub.

8.3 G17: Nästlade och inre klasser   G4 Lab

Använd nästlade och inre klasser för att kapsla in privata beståndsdelar i ett sammansatt objekt.

Notera den syntaktiskt subtila men relativt viktiga skillnaden mellan inre och nästlade klasser. Ett annat namn på sammansatta objekt är aggregat.

Inre och nästlade klasser är ett viktigt sätt att definiera objekt som består av komplicerade aggregat av flera objekttyper, men där man vill skydda/dölja de ingående delarna utifrån.


Report a bug on this achievement? Please place an issue on GitHub.

9 H: Objekt, identitet och struktur

9.1 H18: Jämförelsemetoden equals()   G5 Lab

Implementera stöd för strukturell likhet med hjälp av equals() i Java.

I Java-program används metoden equals() för att jämföra två godtyckliga objekt oavsett typ. Denna metod bör uppfylla ett antal regler:

  1. a.equals(b) == true implicerar b.equals(a) == true
  2. a.equals(b) == false implicerar b.equals(a) == false
  3. Signaturen för equals() skall vara Object -> boolean

Man kan diskutera om equals()-metoden bör förlita sig på föränderligt tillstånd eller ej. Ett problem med detta är att två objekt som är lika enligt equals() senare kan ändras till att inte vara lika längre, vilket kan leda till problem om man förlitar sig på den “redan uträknade likheten” senare i programmet.

Hur “lika” definieras kan vara olika – ibland används begreppet identisk för att avse att A och B är samma objekt; ibland används konceptet strukturellt lika eller ekvivalenta för att avse att A och B är två olika objekt men som ändå i enligt den gällande formen av likhet kan anses vara “utbytbara”, t.ex. A och B är två olika kakburkar som innehåller samma kaka.

Överkurs: tänk på relationen mellan equals() och hashcode() och fundera över varför man ofta bör definiera en hashcode()-metod om man också definierar en equals()-metod.


Report a bug on this achievement? Please place an issue on GitHub.

9.2 H19: Skillnaden mellan identitet och ekvivalens   G3 Lab

Demonstrera förståelse för skillnaden mellan identitet och ekvivalens genom att demonstrera implementationer av båda koncepten och motivera valet av definition av likhet.

Vad menas med att två objekt/värden är identiska? Vad menas med att två objekt/värden är ekvivalenta? Hur implementerar man det ena och det andra?


Report a bug on this achievement? Please place an issue on GitHub.

9.3 H20: Värdeöverföring   G3 Lab

Redovisa förståelse för skillnaden mellan värdesemantik och referenssemantik med hjälp av ett kodexempel.

Slå upp termerna, pröva gärna även engelska: “value semantics” respektive “reference semantics”. Se även parameteröverföring.

När använder man vilken typ av värdeöverföring? Fungerar C och Java annorlunda? Finns det fördelar/nackdelar med hur C och Java fungerar?


Report a bug on this achievement? Please place an issue on GitHub.

9.4 H21: Abstrakta klasser, metoder och interface   G5 Lab

Redovisa förståelse för abstrakta klasser och metoder, samt deras relation till Java-interface.

Beakta bland annat:

  • Hur skiljer de sig?
  • Hur är de lika?
  • När används de och vad har de för konsekvenser på programmen i vilka de används?
  • Varför är multipelt arv mellan interface tillåtet och väldefinierat medan multipelt implementationsarv inte är det? (I Java, alltså.)

Report a bug on this achievement? Please place an issue on GitHub.

10 I: Metodik

10.1 I22: Defensiv programmering   G3 Lab

Förklara innebörden av, och tillämpa på ett konsekvent sätt, defensiv programmering i ett program.

Studera konceptet defensiv programmering. Vid tillämpning, använd checklistan som finns i kursmaterialet och fundera på hur man kan kritisera den.


Report a bug on this achievement? Please place an issue on GitHub.

10.2 I23: Undantagshantering   G3 Lab

Fånga på lämpliga platser och hantera på ett lämpligt sätt kontrollerade och okontrollerade (relevanta) undantag i ett program.

Fundera över vad som är en lämplig plats och hur man på ett lämpligt sätt hanterar ett fel. Är det t.ex. någonsin relevant att fånga ett NullPointerException? Vilka fel kan t.ex. hanteras utan att programmet snarare borde följa principen “crash, don’t trash”?

För att bli godkänd måste du kunna

  • kasta och fånga undantag,
  • kunna resonera kring lämpligheten av varför undantag fångas där de görs, och vad som lämpligen ska hända när detta sker, samt
  • förstå skillnaden mellan kontrollerade och okontrollerade undantag.

Report a bug on this achievement? Please place an issue on GitHub.

10.3 I24: Olika metoder för felhantering   G4 Lab

Ett generellt problem i systemutveckling är hur fel skall hanteras. Ofta uppstår felen i en del av programmet där det inte är lämpligt att hantera dem; t.ex. ett fel som uppstår djupt nere i ett bibliotek på grund av felaktigt indata från en annan modul, som rimligen är den plats som skulle kunna “åtgärda detta problem”. Ibland måste ett fel propageras hela vägen upp till användaren som måste åtgärda problemet, eller göra ett val mellan olika sätt att hantera den uppkomna situationen, och i andra fall kan man bara ignorera/undertrycka problemet. Tyvärr kan det vara så att samma fel hanteras på olika sätt i olika program, så det är ibland svårt eller omöjligt att bygga in åtgärder direkt där felet uppstår, speciellt om man skriver ett bibliotek eller kod som skall kunna återanvändas.

Hur relaterar ovanstående till följande koncept:

  • Crash don’t trash
  • Defensiv programmering
  • Undantagshantering (till exempel i Java)
  • Hur fel hanteras i C med errno

Ge exempel på hur dessa koncept använts i dina olika inlämningsuppgifter, och vad konsekvensen av att byta mellan dem i ett program skulle bli.


Report a bug on this achievement? Please place an issue on GitHub.

10.4 I25: Egendefinierade undantag   G4 Lab

Utöver föregående mål, demonstrera fördjupad förståelse för undantagshantering i Java genom att kasta existerande och egendefinierade kontrollerade och okontrollerade undantag i ett program.

Demonstrera med relevanta undantag, gärna i ett program du redan har skrivit under en tidigare sprint.


Report a bug on this achievement? Please place an issue on GitHub.

11 J: Minneshantering

11.1 J26: Allokering på stacken vs. på heapen   G3 Lab

Demonstrera förståelse för skillnaden mellan allokering på stacken och allokering på heapen med hjälp av ett C-program.

Läs C: addendum om stack & heap

Pröva gärna också att t.ex. jämföra prestanda mellan ett program som allokerar mycket på stacken med ett som allokerar mycket på heapen (t.ex. genom att skriva om nedanstående rekursiva fibonacci-program där samtliga heltal mallokeras på heapen). Vad får det för effekt på uträkningens prestanda?

#include<stdio.h>
#include<stdlib.h>

int *heap_int(int i)
{
  int *result = malloc(sizeof(int));
  *result = i;
  return result;
}

int *fib(int *n)
{
  if (*n == 0)
    {
      return heap_int(0);
    }
  else
    {
      if (*n == 1)
        {
          return heap_int(1);
        }
      else
        {
          return heap_int(*fib(heap_int(*n-1)) + *fib(heap_int(*n-2)));
        }
    }
}

// OBSERVERA!
// Detta program läcker minne som ett såll -- det frigör inte några allokerade pekare
int main(int argc, char **argv)
{
  if (argc < 2)
    {
      puts("Usage: ./fib-rec 5");
    }
  else
    {
      int *n = heap_int(atoi(*(argv+1)));
      printf("fib(%d) = %d\n", *n, *fib(n));
    }
  return 0;
}
%23include%3Cstdio.h%3E%0A%23include%3Cstdlib.h%3E%0A%0Aint%20%2Aheap_int%28int%20i%29%0A%7B%0A%20%20int%20%2Aresult%20%3D%20malloc%28sizeof%28int%29%29%3B%0A%20%20%2Aresult%20%3D%20i%3B%0A%20%20return%20result%3B%0A%7D%0A%0Aint%20%2Afib%28int%20%2An%29%0A%7B%0A%20%20if%20%28%2An%20%3D%3D%200%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20return%20heap_int%280%29%3B%0A%20%20%20%20%7D%0A%20%20else%0A%20%20%20%20%7B%0A%20%20%20%20%20%20if%20%28%2An%20%3D%3D%201%29%0A%09%7B%0A%09%20%20return%20heap_int%281%29%3B%0A%09%7D%0A%20%20%20%20%20%20else%0A%09%7B%0A%09%20%20return%20heap_int%28%2Afib%28heap_int%28%2An-1%29%29%20%2B%20%2Afib%28heap_int%28%2An-2%29%29%29%3B%0A%09%7D%0A%20%20%20%20%7D%0A%7D%0A%0A%2F%2F%20OBSERVERA%21%0A%2F%2F%20Detta%20program%20l%C3%A4cker%20minne%20som%20ett%20s%C3%A5ll%20--%20det%20frig%C3%B6r%20inte%20n%C3%A5gra%20allokerade%20pekare%0Aint%20main%28int%20argc%2C%20char%20%2A%2Aargv%29%0A%7B%0A%20%20if%20%28argc%20%3C%202%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20puts%28%22Usage%3A%20.%2Ffib-rec%205%22%29%3B%0A%20%20%20%20%7D%0A%20%20else%0A%20%20%20%20%7B%0A%20%20%20%20%20%20int%20%2An%20%3D%20heap_int%28atoi%28%2A%28argv%2B1%29%29%29%3B%0A%20%20%20%20%20%20printf%28%22fib%28%25d%29%20%3D%20%25d%5Cn%22%2C%20%2An%2C%20%2Afib%28n%29%29%3B%0A%20%20%20%20%7D%0A%20%20return%200%3B%0A%7D%0A

Report a bug on this achievement? Please place an issue on GitHub.

11.2 J27: Manuell minneshantering   G3 Lab

Demonstrera förståelse för minneshantering i C genom att skriva ett program med dynamiska strukturer som är fritt från minnesläckage och argumentera för varför det är så (och verifiera med valgrind).

Redogör bland annat för:

  • Hur uppstår minnesläckage?
  • Vilken del av ett program ansvarar för att frigöra minne?
  • När avgör man att en bit allokerat minne är “färdiganvänt” och går att frigöra?
  • Vad kan hända om ett allokerat utrymme frigörs “för tidigt”?
  • På vilket sätt hjälper valgrind dig att undvika minnesläckage?

Report a bug on this achievement? Please place an issue on GitHub.

11.3 J28: Manuell vs. automatisk minneshantering   G4 Lab

Förklara skillnaden mellan C:s manuella minneshantering och hur Java hanterar minne och beskriv för ett lämpligt Java-program när minne allokeras och frigörs.

Redovisa bland annat för:

  • När är ett objekt att betrakta som skräp som kan städas bort?
  • När städas skräp bort?
  • Hur kan jag som programmerare ta reda på när ett visst objekt städats bort?
  • Finns det någon typ av minnesfel som jag kan få i C med pekare som jag inte kan få med referenser i Java?
  • När allokeras minne och hur tar Java reda på hur många bytes ett visst objekt kräver?
  • Hur tar jag som programmerare reda på hur många bytes ett visst objekt kräver?

Javas automatiska skräpsamlare kan konfigureras på många sätt, så tänk dig för varenda gång du säger “så här fungerar Javas GC”.

Bonus: hur fungerar “weak references”? Hur relaterar de till pekare?


Report a bug on this achievement? Please place an issue on GitHub.

11.4 J29: Jämför två metoder för automatisk skräpsamling   G5 Special

Lämpliga metoder avser t.ex.:

  • olika former av mark-sweep GC
  • reference counting
  • generational GC

Beskriv övergripande hur de valda metoderna fungerar. Diskutera deras för- och nackdelar. Lämpliga aspekter att beakta för en jämförelse omfattar bland annat följande koncept:

  • throughput
  • latency
  • jitter

11.4.1 Redovisning

Detta mål har varit populärt att redovisa i form av en essä (X59) tidigare år. (Det går också bra att göra genom en diskussion med en av huvudlärarna på ett labbpass.)


Report a bug on this achievement? Please place an issue on GitHub.

12 K: Modularisering

12.1 K30: Gränssnitt mellan moduler   G3 Lab

Specificera tydliga gränssnitt mellan moduler i ett program som bör brytas ned i flera moduler (och implementera).

Börja med att förklara vad modularisering är och varför det är viktigt!

Att dela upp ett program i mindre beståndsdelar är i regel att föredra framför ett monolitiskt program. En anledning till detta är att det underlättar parallellutveckling – dvs. flera programmerare kan vara inblandade i ett projekt samtidigt och jobba på olika delar och därigenom förkorta utvecklingtiden (och öka kvaliteten).

Naturligtvis duger det inte med att göra vilken uppdelning som helst! Man bör beakta vad som är en naturlig uppdelning; ett program som modellerar ett brädspel kanske kan delas upp i en modul för spelets logik (hur pjäserna interagerar med brädet och varandra) och en modul för spelets grafik. Genom att separera logiken från grafiken underlättar man också för ett framtida utbytande av spelets grafik.

Pröva din modulariseringsstrategi genom att implementera ett program och notera vilka förändringar du måste göra när din insikt i programmet fördjupas.


Report a bug on this achievement? Please place an issue on GitHub.

12.2 K31: Coupling & cohesion   G4 Lab

Givet ett icke-trivialt program uppdelat i moduler som i ovanstående mål, resonera kring begreppen coupling och cohesion för några av modulerna.

Termerna “low coupling” och “high cohesion” beskriver två egenskaper som krävs för att ett program skall anses välmodulariserat. Med low coupling avses att två moduler endast skall vara löst sammanknutna, så att det är möjligt att byta ut en av dem utan att göra några egentliga förändringar i den andra. Med high cohesion avses att alla delar som finns i en modul skall ha en “hög grad av samhörighet”, dvs. att alla delar av modulen avser samma aspekt av programmet. (Varför?)

Termerna ovan är enkla att beskriva separat från faktisk kod, men för att förstå dem måste du kunna relatera dem till din egen kod, beskriva coupling mellan moduler, cohesion inom moduler, och eventuellt göra motiverade förändringar i den tidigare designen.


Report a bug on this achievement? Please place an issue on GitHub.

12.3 K32: Separation of concerns   G5 Lab

Utveckla resonemanget i K31 med en diskussion om separation of concerns och hur detta har uppnåtts (alt. kan/inte kan) i programmet i fråga.

Undersök termen/begreppet “separation of concerns” (leta bland annat men inte enbart i litteraturen om aspekt-orienterad programmering). Vad betyder detta begrepp? Relatera det till diskussionen om coupling och cohesion i föregående mål.


Report a bug on this achievement? Please place an issue on GitHub.

13 M: Pekare

13.1 M36: C:s array-notation och pekararitmetik   G3 Lab

Arrayer i C är i regel inget mer än en behändig notation för pekararitmetik. Demonstrera att du förstår likheterna mellan pekare till konsekutiva minnesblock av element av en typ, och arrayer i C i ett i övrigt vettigt program.

Tips: Argumentvektorn till main-funktionen.


Report a bug on this achievement? Please place an issue on GitHub.

13.2 M37: Använda pekare för att skapa länkade strukturer   G3 Lab

En länkad struktur är en struktur uppbygd av separat-allokerade objekt som pekar till varandra, t.ex. en länkad lista eller ett träd. Länkade strukturer växer och krymper dynamiskt, dvs. deras storlek varierar med körning och under körning och kräver i regel minnesallokering på heapen.


Report a bug on this achievement? Please place an issue on GitHub.

13.3 M38: Värdeöverföring via pekare   G3 Lab

Använd pekare till stackvariabler för värdeöverföring mellan funktionsanrop.

Läs C: addendum om stack & heap som finns bland extramaterialet.

Referenssemantik och värdesemantik tas upp redan i kom-igång-uppgiften.


Report a bug on this achievement? Please place an issue on GitHub.

13.4 M39: Pekare till pekare   G4 Lab

Använd pekare till pekare (dubbelpekare) på ett lämpligt sätt i ett program.

En pekare till en pekare är en väldigt kraftfull mekanism som kan vara förvirrande ibland (t.ex. att man blandar ihop vad de olika pekarna pekar på).

Tips: iteratorer till datasamlingar som ger möjlighet att länka in och länka ur.

Argumentvektorn i main-funktionen är visserligen en pekare till en pekare, men skall inte användas för demonstration här.


Report a bug on this achievement? Please place an issue on GitHub.

14 N: Pragmatics

14.1 N40: Kompilering, länkning och interpretering   G3 Lab

Demonstrera på lämpligt sätt förståelse för termerna kompilering, länkning, interpretering och JIT-kompilering och hur dessa används i C och Java.

Fundera över skillnaderna mellan länkning i C och Java och när länkning sker.

Ledning: med hjälp av enkla prestandamätningar kan man mäta tiden för JIT-kompilering och även dess inverkan på prestanda hos kod efter att den kompilerats.


Report a bug on this achievement? Please place an issue on GitHub.

14.2 TODO N41: Bindning   G4 Lab

Förklara statisk och dynamisk bindning och exemplifiera med programkod.

  • Hur påverkas möjligheten att återanvända kod?
  • Blir det enklare/svårare att resonera om vad kod gör med statisk/dynamisk bindning?
  • Finns det en prestandaaspekt? Är den relevant?
  • Hur binder C?
  • Hur binder Java?

Report a bug on this achievement? Please place an issue on GitHub.

15 O: Profilering och Optimering

15.1 TODO O42: Profilering och optimering 1/3   G3 Lab

Använda profileringsverktyg för att visa var ett redan skrivet program tillbringar mest tid.

Observera att dessa mål passar särskilt bra under projektet.

“Premature optimisation is the root of all evil” är ett citat från Donald Knuth. Ett delmål i denna kurs är att lära sig att använda tillämpliga verktyg för att förstå ett programs beteende under körning med avseende på prestanda, dvs. efter att programmet är implementerat ta fram det data som sedan krävs för att göra en faktisk optimering.

Lämpligen tar du fram vilka delar av programmet som tar längst tid att köra respektive körs flest gånger. Några frågor att besvara:

  • Vad är lämplig granularitetsnivå på “delarna” som nämns ovan – och varför?
  • Hur tar du fram detta data?
  • Hur vet du att datat är “rätt”?
  • Hur kan du använda datat?

Observera att det är dumt att profilera ett grafiskt program typ lagerhanteraren eftersom 99% av körtiden är väntan på I/O. Däremot kan man profilera delar av lagerhanteraren. Ta insättning i det binära sökträdet som ett exempel. Skriv ett litet program som använder samma binära sökträd och gör 1 miljon insättning av varor i databasen och sedan 1 miljon sökningar. Det är mer intressant att profilera.

15.1.1 Profilera ett C-program

Man kan använda verktyget gprof för att mäta körtiden hos ett C-program. Det finns flera tutorials på näten, t.ex. denna: http://www.thegeekstuff.com/2012/08/gprof-tutorial/.

15.1.2 Profilera ett Java-program

Se t.ex. denna screencast.


Report a bug on this achievement? Please place an issue on GitHub.

15.2 O43: Profilering och optimering 2/3   G4 Lab

Med ledning resultatet från föregående mål, optimera programmet på ett förtjänstfullt sätt.

Observera att dessa mål passar särskilt bra under projektet.

Optimera programmet med hjälp av profilen ovan, motivera ansatsen och demonstrera och förklara prestanda-ökningen med hjälp av en ny profil för det optimerade programmet

I nödfall kan man bli godkänd på detta mål trots att man inte kan jaga fram en prestandaökning om den optimering man gjort (som visat sig vara en “falsk optimering”) intuitivt verkar vara en optimering.

Observera att det är dumt att optimera ett interaktivt program som t.ex. Assigment 2. Däremot kan man optimera delar av dess underliggande modell. Ta hashtabellen som ett exempel. Implementation av dynamisk storleksförändring (“Adapting the Number of Buckets”) är ett utmärkt exempel på en optimering som förändrar tiden för insättning och borttagning.

Sedan får man demonstrera uppdateringen kanske genom att göra \(N\) insättningar av element och göra \(M\) sökningar med de olika sorteringsimplementationerna och jämföra (för stora värden på \(N\) och \(M\) för att se skillnad – millisekunder är inte stora nog).


Report a bug on this achievement? Please place an issue on GitHub.

15.3 O44: Profilering och optimering 3/3   G5 Lab

Samma som mål de två ovanstående målen, men beakta också minnesanvändning.

Observera att dessa mål passar särskilt bra under projektet.

Beakta inte enbart exekveringstid och frekvens, men minnesåtgången för strukturer och funktioner/metoder och – möjligen ännu viktiga – hur åtkomst till minnet sker. Kanske finns det någon samband mellan lång exekveringstid och suboptimalt minnesanvändande?

Kan man minska exekveringstiden genom att ändra hur minnet används?


Report a bug on this achievement? Please place an issue on GitHub.

16 P: Kodgranskning

16.1 TODO P45: Gör en informell kodgranskning under fas 1   G3 Lab

Gör en informell kodgranskning på ett program utvecklat av ett annat kodpar i samma grupp (det får inte finnas några överlappningar i medlemmar mellan granskande par och par som blir granskat). Syftet med en kodgranskning är att hitta defekter och förbättra kodens kvalitet. Följ ett kodgranskningsprotokoll och ta anteckningar.

Ge synpunkter på koden genom GitHubs issue tracker som finns för varje repo, eller genom att kommentera enskilda rader. Se till att använda en särskild version av programmet så att ni kan hitta tillbaka till just den vid redovisning, och för att undvika att programmet ändras samtidigt som ni gör granskningen.

Ute i arbetslivet gör man detta av flera anledningar:

  • Kvalitetssäkring
  • Utvecklare blir modigare när man delar ansvar för korrekthet
  • När man vet att någon måste läsa koden skriver man ofta bättre kod
  • Man sprider kunskap om vad som händer i projektet till fler

Det är en viktig färdighet att kunna kritisera någons kod utan att kritisera personen (och likaså att ta kritik!). Vidare blir man också ansvarig för koden som man OK:ar vilket gör att man måste vara noggrann och inte luras att tro att målet är att säga “vilken bra kod” till de man granskar.

16.1.1 Redovisning

Du redovisar detta under en labb genom att visa upp ditt kodgranskningsprotokoll och issue log. Ha koden tillgänglig för frågor från examinatorn. Minns att det är du som skall driva redovisningarna, inte examinatorn.


Report a bug on this achievement? Please place an issue on GitHub.

16.2 P46: Gör en informell kodgranskning under fas 2   G3 Lab

Gör en informell kodgranskning på ett program utvecklat av ett annat kodpar i samma grupp (det får inte finnas några överlappningar i medlemmar mellan granskande par och par som blir granskat). Syftet med en kodgranskning är att hitta defekter och förbättra kodens kvalitet. Följ ett kodgranskningsprotokoll och ta anteckningar.

Ge synpunkter på koden genom GitHubs issue tracker som finns för varje repo, eller genom att kommentera enskilda rader. Se till att använda en särskild version av programmet så att ni kan hitta tillbaka till just den vid redovisning, och för att undvika att programmet ändras samtidigt som ni gör granskningen.

Ute i arbetslivet gör man detta av flera anledningar:

  • Kvalitetssäkring
  • Utvecklare blir modigare när man delar ansvar för korrekthet
  • När man vet att någon måste läsa koden skriver man ofta bättre kod
  • Man sprider kunskap om vad som händer i projektet till fler

Det är en viktig färdighet att kunna kritisera någons kod utan att kritisera personen (och likaså att ta kritik!). Vidare blir man också ansvarig för koden som man OK:ar vilket gör att man måste vara noggrann och inte luras att tro att målet är att säga “vilken bra kod” till de man granskar.

16.2.1 Redovisning

Du redovisar detta under en labb genom att visa upp ditt kodgranskningsprotokoll och issue log. Ha koden tillgänglig för frågor från examinatorn. Minns att det är du som skall driva redovisningarna, inte examinatorn.


Report a bug on this achievement? Please place an issue on GitHub.

16.3 P47: Åtgärda defekter efter en kodgranskning   G4 Lab

In addition to the previous goal, make a pull request with changes and cooperate with the owners of the receiving code base until the pull request has been successfully merged. Note that it is the code of the other team that should be improved.

If the code you were reviewing in the previous goal was next to perfect, maybe the improvements here will be restricted to catching spelling errors in comments. In most cases, however, there are some real issues. For example:

  1. Repeated logic that can be broken out and moved to functions of their own
  2. Functions that should be private aren’t private
  3. Behaviour that does not correspond to its description in comments
  4. Code that could segfault under certain circumstances
  5. Tests miss important corner cases (compare with your own!)
  6. Code that miscalculates or otherwise misbehaves under certain circumstances

How much work to do is an interesting question. Sadly, the answer isn’t so easy to give. The goal of this exercise is to practise proposing fixes to errors and communicating them through the proper channels which in this case is GitHub.

If you feel that you need support in knowing when enough is enough, then here are guidelines:

For each thing that you find, rate its severity on a scale \(1--3\). There is no objective scale, so here are some examples.

Severity Example
1 Improving description in a comment
1 Fixing spelling errors in a comment
1 Improving names of variables in a function (or name of a function)
2 Finding a DRY violation and solving it (e.g., through extracting functions)
2 Hardening correct code by e.g., adding initialisation, braces, etc. in a function
2 Moving a structs, adding static annotations in a file, etc.
3 Improving tests by additional cases for an important test
3 Finding and fixing bugs in a function

Ideally, the sum of the severity of your fixes should total at least 10. State the severity for each issue you file and prepare to motivate it to a TA if questioned.


Report a bug on this achievement? Please place an issue on GitHub.

16.4 P48: Stäm av ett program mot en refactoringkatalog   G5 Lab

Enkla refactoringmönster avser t.ex. namnändringar, och att flytta tillstånd och/eller beteenden från en plats till en annan. Både Netbeans och Eclipse har inbyggt stöd för refactoring. En bra utgångpunkt för att lära sig om refactoring är http://refactoring.com.

Finns det några “bad smells” i det program som ni just har granskat? Vilka då? Vad är lämpliga ändringar? Föreslå dem via GitHubs issue tracker på samma sätt som tidigare. Nämn gärna det refactoringmönster som ändringarna brukar!

Notera: Ni behöver självklart inte stämma av programmet mot hela katalogen.


Report a bug on this achievement? Please place an issue on GitHub.

17 Q: Testning

17.1 Q49: Enhetstestning   G3 Lab

Ta fram lämpliga enhetstester, motivera dem, och förklara vad testerna visar.

Det står dig fritt fram att använda Cunit, JUnit, eller motsvarande. Detta kan redovisas både under projektet eller tidigare. Ett tips är att börja skriva tester från sprint 2 eftersom tester tenderar att förkorta utvecklingstiden så fort man blivit varm i kläderna med språket man programmerar i.

Enhetstester fokuserar på enskilda funktioner och metoder. Ett bra enhetstest kan köras helt automatiserat, är läsbart och prövar endast en enda logisk funktion/koncept. Enhetstester har flera funktioner, bl.a. gränssnittsdokumentation genom exempel, stöd vid debuggning av kod genom dokumentation av felaktiga indata, och i testdriven utveckling (TDD) skrivs testerna före koden de skall testa för att bena ut specifikationer och sätta fingret på oklarheter.


Report a bug on this achievement? Please place an issue on GitHub.

17.2 Q50: Mät och resonera kring testkvalitet   G4 Lab

Hur vet man att de test man har är “bra”? Hur vet man vad testen egentligen testar? Använd ett lämpligt verktyg för att t.ex. mäta code coverage, d.v.s. hur stor del av koden som faktiskt testas av testen. Vilka andra kvalitetsmått på tester finns? Måste man testa sina tester? Måste man testa testernas tester? Blir inte detta en oändlig regression?

Använd t.ex. Gcov för att mäta code coverage för era tester.


Report a bug on this achievement? Please place an issue on GitHub.

17.3 TODO Q51: Andra verktyg för felsökning   G5 Report

Använd Findbugs på ett eller flera av de Javaprogram som du har utvecklat under kursen och studera resultatet. Hittar du buggar i programmet? Får du s.k. “false positives”, alltså rapporter om fel som inte är fel i praktiken?

Använd också American Fuzzy Lop, en fuzzer, t.ex. på din lagerhanterare, för att hitta gränsfall som du inte har tänkt på.

Redovisa genom att diskutera ditt resultat med en lärare eller huvudassistenten.


Report a bug on this achievement? Please place an issue on GitHub.

18 TODO R–V: Verktyg

18.1 R52: Debuggning med GDB   G3 Lab

Avser att kunna använda GDB (eller lldb) för att stega genom ett C-programs exekvering och sätta breakpoints (ex. b, c, s, n), skriva ut variablers värden, en backtrace, navigera en backtrace med up/down. Redovisa genom att återskapa ett förlopp från en skarp buggjakt med de relevanta stegen och förklara buggen.

Du kan lämpligen redovisa detta i samband med att du får ett svårfunnet segfault!


Report a bug on this achievement? Please place an issue on GitHub.

18.2 S53: Extrahera dokumentation ur kod   G3 Lab

Använda doxygen eller JavaDoc för att extrahera kommentarer från kod till lämplig API-dokumentation.

Endast lämpligt att demonstrera i ett större program med flera moduler där gränssnitten behövts dokumenteras. När du demonstrerar, visa också att du kan lägga till, ändra etc. i informationen och generera ny dokumentation, samt visa på både välmotiverat kortfattade och utförliga hjälpavsnitt i dokumentationen.

Du kan bara redovisa detta mål på kod från sista C-uppgiften, sista Java-uppgiften eller projektet.


Report a bug on this achievement? Please place an issue on GitHub.

18.3 T55: Använda Emacs för editering   G3 Lab

Avser förmåg att använda Emacs utan mus för att navigera och editera text, öppna filer, bläddra mellan och hantera buffrar, använda kill & yank och mark-stacken.

Du är klar att redovisa detta mål när du känner att du löser problem tack vare Emacs och inte trots Emacs.

Installera Emacs på din dator hemma om du inte redan har Emacs där tills ditt muskelminne har memorerat alla viktiga kommandon.

18.3.1 Varför har vi detta mål?

Av flera goda skäl, men inte som ett statement eller som en rekommendation för resten av ditt liv.

18.3.2 Jag dör om jag inte får använda vim!

Då är det ok. Men vim alltså. Emacs eller vim effektivt sett.


Report a bug on this achievement? Please place an issue on GitHub.

18.4 T56: Konfigurera Emacs för programmering   G4 Lab

Utöver föregående mål, dra nytta av Emacs inbyggda stöd för programmering.

Avser stöd för kompilering och felsökning, textkomplettering el. snippets, samt användande av tags eller motsvarande för att navigera kod.

Några startpunkter att titta på:

C/C++ Development Environment for Emacs
https://tuhdo.github.io/c-ide.html
Emacs: What’s the Best Setup for Coding
http://ergoemacs.org/emacs/emacs_whats_best_setup_for_xyz.html

Report a bug on this achievement? Please place an issue on GitHub.

18.5 U57: Byggverktyget Make   G3 Lab

Många program har komplicerade byggberoenden – för att kunna bygga prg måste vi länka a och b, och för att kunna länka dem måste vi bygga dem. För att bygga a kanske vi måste länka c och d etc.

Programmet make är ett utmärkt verktyg för att hantera byggberoenden. Titta i Shaws bok för en minimal intro till make. Det finns också en svensk lathund om make i kursmaterialet. Make gås också igenom på föreläsning.

Du bör använda make från dag ett på kursen! Det är nämligen en vanlig källa till fel att man kompilerar ett program utan att kompilera om alla dess delar, etc.

Du bör inte redovisa detta mål förrän tidigast i sprint 2 – eller varför inte under projektet?

För att redovisa målet måste du bland annat redovisa just beroenden, eftersom det är det som make löser. Det betyder att ha byggregler som beror av varandra. T.ex. om \(A\) är beroende av \(B\), vi ändrar \(A\) men inte \(B\) så skall bara \(A\) kompileras om, inte \(B\).


Report a bug on this achievement? Please place an issue on GitHub.

18.6 V58: Grundläggande terminalkommandon   G3 Lab

Att kunna navigera i terminalen är grundläggande som utvecklare. Det är standard att behöva logga in på maskiner på andra sidan jorden och kolla i loggar, starta om tjänster, etc. Drift och utveckling hänger samman, och det är sällan man har fönstersystem att tillgå (och ändå mer sällan som det vore vettigt att använda dem).

_Detta mål kan du inte redovisa vid kursens början. Observera att detta mål skiljer sig genom att det innehåller en uppgift som du skall använda för att redovisa._

18.6.1 Du bör kunna använda följande:

  • man, apropos, whatis
  • cd
  • ls
  • mkdir, rmdir
  • grep
  • find
  • xargs
  • &&
  • &
  • C-z, C-c och C-d (ung. suspend, abort och quit)
  • fg
  • bg
  • cut
  • tr
  • uniq
  • cp
  • omdirigering, pipes och miljövariabler.

18.6.2 Titta också gärna på verktyg som

  • ack
  • tmux
  • awk
  • sed
  • zsh
  • ps
  • top, htop
  • curl
  • ssh, scp
  • shell scripting

TIPS! Om du väntar till projektet med att redovisa detta mål kommer det gå per automatik. Givet förstås att du inte har undvikit terminalen fram till dess…

Filen http://wrigstad.com/ioopm/v58.zip innehåller ett antal kataloger och filer i samma format som jag får era kodprov. Lösningar som funkar med nedanstående exempel kommer nog att funka mot innehållet i v58.zip.

v58.zip ser ut ungefär så här:

(genererad med hjälp av kommandot tree)

.
├── elica842
│   ├── uppgift1
│   │   └── passed.txt
│   └── uppgift2
│       └── missing.txt
└── writo649
    ├── uppgift1
    │   └── passed.txt
    └── uppgift2
        └── fail.txt

I denna struktur finns det en katalog som motsvarar en person, t.ex. writo649, och under denna en katalog för varje uppgift som innehåller de inlämnade filerna, samt resultatet av rättningen. Utifrån exemplet ovan kan vi se att writo649 klarade av uppgift 1 men inte uppgift 2; elica842 klarade av uppgift 1 och för uppgift 2 finns inga uppgifter: den har inte lämnats in (missing.txt). (Det kan finnas andra filer med vilka andra namn som helst, de är utelämnade i exemplet ovan.)

Uppgiften består i att ta fram:

  1. En fil a.txt som innehåller alla godkända på uppgift 1
  2. En fil b.txt som innehåller alla godkända på uppgift 2
  3. En fil c.txt som innehåller namn och epostadress för alla i a.txt och b.txt

Varje uppgift bör lösas med ett kommando i terminalen. Notera att uppgift 3 kan bygga på att filerna a.txt och b.txt redan finns.

Facit från exemplet ovan:

a.txt
elica842
writo649

b.txt
<tom fil>

d.txt
Elias Castegren         elias.castegren@it.uu.se
Tobias Wrigstad         tobias.wrigstad@it.uu.se

(det är inte petnoga med tabbar, etc.)

För att konvertera t.ex. writo649 till ett namn och en epostadress kan du använda kommandot “student” som finns på våra Linux-system: /it/sw/misc/bin/student.

Lämpliga kommandon för denna uppgift är:

  • find
  • xargs
  • grep
  • uniq
  • cut eller awk
  • cat
  • |
  • >
  • <
  • man för att läsa på om ovanstående

Använd gärna tree för att se trädstrukturen.

18.6.3 Ledning

Varje kommando spottar ut radorienterad text. Arbetsflöden skapas genom att kommandon “pipe:as ihop”, kommand1 | kommando2 där all output från kommando1 blir input till kommando2. Diverse hjälpprogram används för att “massera texten” t.ex. om kommando1 listar A,B,C,D,E och vi vill ha C kan vi använda t.ex. cut -d , -f 3 för att säga “tolka detta som fält separerade av , och ta fält 3”.

Ett år stötte vi på en student på kursen som hade blandat ihop ^C och ^Z och som därför hade 50+ instanser av lagerhanteraren igång eftersom han, varje gång han trodde att han slog ihjäl programmet med ^Z, bara hade pausat det.

Det löste vi geschwint så här:

ps aux | grep ~whoami~ | grep ./lagret | cut -b 10-14 | xargs kill
(1)      (2)             (3)             (4)            (5)

Steg (1) tar fram en lista över processer:

root        27002  0.0  0.0 175880 15736 ?        Ss   dec05   0:00 ...
foobar      27005  0.0  0.1 199584 18480 ?        S    dec05   0:00 ...
foobar      27007  0.0  0.1 309656 32528 ?        S    dec05   0:01 ./lagret
root        27110  0.0  0.0   4496   780 ?        S    09:45   0:00 ...
foobar      27111  0.3  0.0  92592 10912 ?        S    09:45   1:41 ...

… som skickas till steg (2) som filtrerar (grep:ar) fram alla rader som matchar resultatet av whoami (foobar ovan). Resultatet:

foobar      27005  0.0  0.1 199584 18480 ?        S    dec05   0:00 ...
foobar      27007  0.0  0.1 309656 32528 ?        S    dec05   0:01 ./lagret
foobar      27111  0.3  0.0  92592 10912 ?        S    09:45   1:41 ...

… som skickas till steg (3) som filtrerar ytterligare:

foobar      27007  0.0  0.1 309656 32528 ?        S    dec05   0:01 ./lagret

… som skickas till steg (4) som tar fram numret på processerna:

27007

… som skickas till steg (5) som för vart och ett av numren som trillar in (i detta fall endast ett) kör “kill <numret>”. Alltså, kommandot ps aux | grep whoami | grep ./lagret | cut -b 10-14 | xargs kill utför slutligen

kill 27007

… vilket i det skarpa läget förra året blev över 50 anrop till kill, och alla lagerprogram stoppades.

Pröva gärna själv, men ersätt kill med echo för att inte slå ihjäl något program!

18.6.4 Om programmet student inte finns/inte fungerar

Skapa en fil student.sh med följande innehåll:

#!/bin/sh
finger $1 | head -n 1 | awk -F: '{ print $3 }' | cut -c 2-

Gör den exekverbar:

chmod a+x student.sh

Gör klart uppgiften men använd student.sh istället för student


Report a bug on this achievement? Please place an issue on GitHub.

19 TODO X: Kommunikation

19.1 X59: Essä   G4 Special

Redovisa ett mål på nivå 4 eller 5 skriftligt genom en essä.

Skriftlig framställning är en viktig del av samtliga kurser på universitetet. Det är oerhört viktigt och användbart att kunna lägga upp en text eller ett resonemang, och veta hur man skall rikta sig till en specifik målgrupp.

Inte alla mål på nivå 4/5 är kanske lämpliga att redovisa via en essä (t.ex. inte labbhandledningen). Om du är osäker, hör med en av lärarna eller huvudassistenterna först. Det är tillåtet att redovisa fler en ett mål (max 3) om de kan redovisas med en sammanhängande historia. Se till att få detta godkänt i förväg! Uppsatsen blir förstås längre i detta fall och maxlängdkravet nedan gäller ej.

Betrakta formkrav och språkliga krav som lika viktiga som ämneskraven. Du får skriva på svenska eller engelska. De språkliga kraven är lika höga oavsett språk.

Här är några tips:

  • För mycket text på en sida utan rubriker blir ogenomträngligt och osexigt
  • Tänk alltid igenom vad ditt syfte är och vad du vill förmedla till läsaren (vad skall läsaren ta med sig)
  • Fråga för varje “kapitel” eller stycke vad de har för relation till det ovan nämnda budskapet – om det är oklart kan man fråga sig om det är motiverat att ha kvar
  • En text skrivs eller läses sällan linjärt
  • 66-72 tecken per rad är en optimal radlängd för ögat att följa
  • Hur du formger din text är också en del av budskapet och hjälper till att driva hem poängerna
  • Slarvfel och stavfel får dig tråkigt nog att framstå som oseriös och dum
  • Använd verktyg (t.ex. M-x flyspell i Emacs) men förstå deras begränsningar
  • Använd textverktyg som gör det enkelt att göra förändringar i layout utan för mycket handpåläggning
  • “Bara för att du har skrivit det är det inte en bra idé att ha det kvar i texten”
  • När man granskar en text skall man läsa den både “nära” (hur skall den här meningen vara) och “på avstånd” (kanske poängen blir tydligare om man ändrar ordningen på kapitel 1 och 2)
  • Be alltid någon annan läsa igenom texten och förklara för dig vad det faktiskt står i den
  • Uppsala Universitet ger dig som student tillgång till professionell skrivhjälp, även för en uppgift som denna
  • Du skall berätta en story och storyn hjälper läsaren att förstå och knyta samman allt.
  • Bara för att du gjorde \(X\) före \(Y\) behöver de inte komma i den ordningen i texten, även om det antyder att du gjorde dem i omvänd ordning

Fundera över vad för slags ton man bör hålla i en essä, hur man klara av att vara saklig utan att bli tråkig, och fundera över vilken din stil är.

Det stilistiska är alltid viktigt, oavsett om man skriver ett sms eller en avhandling. Nedanstående briljanta citat kan förhoppningsvis både skänka glädje och inspirera:

This sentence has five words. Here are five more words.
Five-word sentences are fine. But several together become
monotonous. Listen to what is happening. The writing is
getting boring. The sound of it drones. It's like a stuck
record. The ear demands some variety. Now listen. I vary the
sentence length, and I create music. Music. The writing
sings. It has a pleasant rhythm, a lilt, a harmony. I use
short sentences. And I use sentences of medium length. And
sometimes, when I am certain the reader is rested, I will
engage him with a sentence of considerable length, a
sentence that burns with energy and builds with all the
impetus of a crescendo, the roll of the drums, the crash of
the cymbals-sounds that say listen to this, it is important.

                                                 -- Gary Provost

En begränsning är att essän skall vara på ca 7500 tecken. Längre är inte bättre, men det man skriver måste vara av en viss volym för att tillräckligt intressanta frågeställningar om skriftlig framställning skall uppkomma.

19.1.1 Inlämning

Du lämnar in genom att skicka en genererad PDF från LaTeX-källkod till ioopm@it.uu.se, samt en länk till en katalog i ditt repo där källan finns. Kommentarer kommer antingen direkt i PDF:en eller som issues i GitHub, beroende på omständigheterna.

19.1.2 Examination

Examinationen av essän sker i form av små seminariegrupper där alla läser och kommenterar på varandras essäer. Mer information om detta anslås senare under kursen.


Report a bug on this achievement? Please place an issue on GitHub.

19.2 TODO X60: Välstrukturerad presentation 1   G3 Special

Under 2019 examineras detta som en del av projektets slutpresentation. Varje person blir alltså individuellt godkänd eller ej på seminariets presentation i och med detta mål. Om man schabblar bort presentationen, eller inte är närvarande får man ett extra redovisningstillfälle, efter att kursen är klar, förmodligen 1-2 månader senare.

Muntlig framställning är lika viktig som skriftlig. En presentation kan lätt bli tråkig om den som talar är oengagerad, och en talares nervositet smittar av sig på åhörarna som då tänker på allt annat än budskapet. Att läsa innantill från ett papper är döden, även om den text man skrivit är fantastisk. Man måste göra den levande!

En talare som glider in i oväntade kläder eller har ett “tick” drar lätt uppmärksamheten till detta istället för till sitt budskap. Det kan vara en bra idé att undvika läderbyxorna (för någon definition av läderbyxor) och om det inte går, själv berätta varför man måste ha dem på sig just idag, så åhöraren får det ur sitt system.

En presentation har på samma sätt som en skriven text ett budskap och man måste vara noga med hur man lägger upp presentationen för att vara säker på att åhöraren kan följa med. Det blir ännu viktigare att berätta vad man skall säga, och sammanfatta hela tiden vad man har sagt.

Bilder är bra, speciellt om man tänker sig att de skall användas som studiematerial senare, men de kan lätt göra presentationen stelbent och inflexibel.

Som ämne skall du välja något som du själv är passionerad kring. (Vi har sett allt från Counter Strike-taktiker till hur man gör för att få gratis öl på nationerna.) Presentationen skall ta 7 minuter och vi räknar med ca 3 minuters muntlig feedback.

Fundera över vad för slags presentation du skall ge. Kolla t.ex. här för inspiration och vägledning.

Fundera över vad du tycker är svårt med en presentation och fokusera på det. Tycker du att det är svårt att berätta en sammanhängande historia – jobba med det. Är det svåra att stå inför folk – jobba med det.

Några tips:

  • Ha inte för mycket text på varje bild
  • Bilder kan vara bärare av mycket information, men kräver stor eftertanke vid skapandet
  • Använd animationer etc. sparsamt
  • Undvik att backa eller på annat sätt hoppa fram och tillbaka i presentationen
  • Det är viktigt att vara engagerad – om du skall prata om något måste du övertyga dig själv om att det är spännande, för varför skulle man annars lyssna på dig?
  • Be inte om ursäkt
  • Lyssna på dig själv – säger du “ehm…” mellan varje mening eller “alltså” i början av varje mening? Går det att arbeta bort?

Du kommer att presentera både inför andra studenter och lärare. Anmälan till presentationstillfällen kommer ut i Piazza. Dessa tillfällen kommer att vara parallella med uppföljningsmöten eller lektioner.


Report a bug on this achievement? Please place an issue on GitHub.

19.3 TODO X61: Running Group Meetings Responsibly   G3 Special New2019

Participate in five group meetings throughout the course and hand in the corresponding reports.

The group meetings serve as a way for students to come up for air, talk about what’s hard, what’s possible, exchange useful advice etc. The course website includes useful information about group meetings on the Team page.

To tick off this goal, you must participate in all the meetings for your group. Follow the instructions for running meetings and hand in the report, which should contain the names of everyone present at the meeting. Email the report to ioopm@it.uu.se and CC your coach who takes care of checking who is present and eventually ticking this goal off for you.

You must keep track of what meetings you have or have not attended. If you fail to show up for a meeting, take this up with the coach first, who will likely refer you to the head teacher who will give you an extra assignment instead.


Report a bug on this achievement? Please place an issue on GitHub.

19.4 X62: Kommunikation 1:1   G5 Special

Visa förmåga att förmedla kunskap genom att handleda ett pass.

Att hålla en presentation utan förberedelser är vanligt – jämför t.ex. med “elevator pitch” eller när någon frågar om något som man känner till. Vid labbhandledning är det vanligt att man måste berätta om olika koncept etc.

Även om man inte kan en viss aspekt av kursen bör man kunna hjälpa någon med en diskussion, både lyssna och tala.

Redovisning sker inför en av kursens lärare eller seniora assistenter som delvis följer med dig och lyssnar på dina förklaringar etc. till andra. Observera att du inte själv får ta redovisningar utan bara ge handledning!

Du skall göra (minst) fyra handledningar för olika studenter. Du och de studenter du handleder skall fylla i den här blanketten, så skriv ut och ta med dig den. Som avslutning blir det en kort diskussion med läraren/assistenten som examinerar målet.

Ett bra sätt att förbereda sig är att sätta sig in i labassens roll genom att titta på hur (särskilt de seniora) labassarna gör.

När du vill redovisa detta mål, maila till ioopm@it.uu.se. Du kommer att få (förslag på) en tid då du kan göra handledningen.

Det blir lätt fullt i slutet av kursen, så var ute i god tid!


Report a bug on this achievement? Please place an issue on GitHub.

19.5 TODO X63: Kommuniktion 1:M   G3 Special New2019

Present yourself—both to your fellow group members and to the head teachers.

In a plain text email to ioopm@it.uu.se, describe:

  • Yourself in 2 sentences without talking about university or computers. (Background, interests, etc.)
  • What is your computing and programming background?
  • What is your goal with this course – what would you like to get out of it?
  • What are the current plans for your future? What would you like to do or work with? What motivates you?
  • Attach a clear picture of your face (This last bit is important to help us connect names and faces when emailing or discussing online!)

Also present the same at the first meeting with your group!


Report a bug on this achievement? Please place an issue on GitHub.

20 TODO Y: Mjukvaruutveckling / Programvaruteknik

20.1 Y64: Använd en namngiven utvecklingsprocess och reflektera över utkomsten   G3 Report

Redovisning sker genom en gemensam (för alla medlemmar i projektet) skriftlig beskrivning av den valda processen (på hög nivå) samt en reflektion över dess styrkor och svagheter i projektrapporten. Om ni skulle starta om projektet imorgon – vad skulle ni behålla och vad skulle ni göra annorlunda (och hur)?

Visa också upp projektets burndown chart för samtliga sprintar.

Några frågor att starta med:

  • Vilken process valdes? Varför?
  • Hur följdes processen?
  • Hur fungerade processen?
  • Var antalet sprintar lämpligt?
  • Var längden på sprintarna bra?
  • Var planeringen optimistisk/pessimistisk/bra?
  • Låg planeringen på en lagom detaljnivå?
  • Kunde man se tendenser till att över- eller underskatta vissa tasks?
  • Tidsfördelning?

Report a bug on this achievement? Please place an issue on GitHub.

20.2 Y65: Skriv konsekvent bra kod   G3 Report

Under kursens gång har kodkvalitet beaktats åtskilliga gånger. Under projektet skall ni skriva kod av hög kvalitet! Vad betyder det? (Läsbarhet? Underhållsbarhet? Prestanda? Korrekthet? Testbarhet? Etc…) Hur har det tagit sig uttryck i ert system? Vad har det fått för konsekvenser?

Hur har ni sett till att koden är läsbar för alla i teamet? (Notera att läsbarhet är mycket mer än bara formattering och var måsvingarna sitter…)

Använd gärna ett verktyg (t.ex. astyle för att automatiskt formattera kod på ett enhetligt sätt.

20.2.1 Ni får använda någon av följande kodstandarder

Det går bra att välja en annan om man har en bra och utförlig motivation och får OK i förväg.

För en längre text om läsbarhet, se The Art of Readable Code.

Observera att högkvalitativ kod inte är detsamma som att följa en kodstandard.


Report a bug on this achievement? Please place an issue on GitHub.

20.3 Y66: Tillämpa kodgranskning löpande   G3 Report

Tidigare under kursen har ni tillämpad kodgranskning på helt nya program som inte skrivit. Under projektet får ni äntligen tillfälle att tillämpa kodgranskning på ett liknande sätt som används ute i verkligheten: istället för helt ny kod får ni ofta titta på kod som fixar något i existerande kod, eller bygger vidare på existerande kod som ni känner till.

I projektet arbetar ni med branches eller forks från master. Ni kan ha branches i ert delade repo, eller personliga (privata) forks i era egna privata repon. Innan något commitas till master skall ni granska koden – alltså någon som inte skrev koden skall läsa igenom den och trycka på mergeknappen.

Ute i arbetslivet gör man detta av flera anledningar:

  • Kvalitetssäkring
  • Utvecklare blir modigare när man delar ansvar för korrekthet
  • När man vet att någon måste läsa koden skriver man ofta bättre kod
  • Man sprider kunskap om vad som händer i projektet till fler

Redovisa i projektrapporten hur denna typ av kodgranskining har fungerat och relatera till den typ som gjordes under tidigare faser, som var mindre disciplinerad och inte rörde er egen kod.

Om ni skulle starta om projektet imorgon – vad skulle ni behålla och vad skulle ni göra annorlunda (och hur)?

Det är frivilligt att använda kodgranskningsprotokoll här.


Report a bug on this achievement? Please place an issue on GitHub.

20.4 Y67: Delta aktivt i ett programmeringsprojekt   G3 Report

Delta aktivt och reflektera över ditt deltagande. Fokusera på projektet, inte på produkten (även om produkten kan helt negligeras).

Redovisning sker genom en skriftlig personlig (enskild) reflektion som inkluderas i projektrapporten.

Fundera bl.a. på:

  • How do I function in a team? Where are my strengths and weaknesses?
  • How should I try to adapt the way I work to work better in a team?
  • What motivates me? What demotivates me? How do I stay motivated in a project?
  • How good am I at estimating how long a task will take? What is the process that produce my estimations?
  • What role do I want to play in a team?
  • Hur fungerar du i ett team? Faller du in i ett särskilt mönster, eller tar du återkommande en särskild roll?
  • Får du ut något av att jobba i en grupp, eller jobbar du helst ensam?
  • Jämför hur mycket du lärt dig under projektarbetet kontra kursens övriga delar, och fundera över hur du bäst lär dig saker.
  • Hur har det gått att logga arbetstid?
  • “Biggest fail” och “biggest win”, dvs. det största problem som du stötte på och det smartaste eller bästa du gjorde.

Report a bug on this achievement? Please place an issue on GitHub.

20.5 TODO Y68: Redovisa en fungerande projektuppgift   G3 Report

Se övriga Y-mål som alla hör till projektet!

Utöver att vara ett seriöst försök att implementera specifikationen fullständigt, modulo “frivilliga utökningar” skall ert program:

  • fungera på avsedda plattformar
  • inte göra odokumenterade eller omotiverade avsteg från specifikationen
  • vara fritt från minnesläckage (verifieras t.ex. med valgrind)
  • inte krascha vid körning med valid indata
  • skydda sig från felaktig indata på lämpligt sätt och i lämplig utsträckning
  • inte behöva kompileras om när indata ändras
  • ha ett lämpligt förhållningssätt till NIH och DRY

Ytterligare icke-funktionella krav är att:

  • kodens indentering lyfter fram kontrollflödet
  • ingen “machokodning” (t.ex. omotiverade oneliners)
  • återkommande logik är utbruten och inkapslad i funktioner
  • namn på filer, variabler, funktioner, etc. skall hjälpa läsaren att förstå deras innebörd, och beteende (t.ex. vilka värden som är rimliga, eller vad man kan förvänta sig från ett funktionsanrop)
  • har tydligt dokumenterade gränssnitt som går att förstå utan att läsa koden och helst är formaterade med Doxygen eller JavaDoc
  • programmet går att bygga och testa med en makefil
  • programmet har enhetstester för alla viktiga funktioner
    • som inte bara skrevs efter att programmet var klart “för att ha tester”
    • som använder cunit
    • där varje test prövar en sak, och flera tester görs ej i samma testfunktion
  • konsekvent tillämpa en kodstandard
  • ha en vettig git log
  • överensstämma med aktiviteter på Trello

Lämna in detta program genom att skriva i readme.md-filen i roten på gruppens GitHub-repo vilken commit som var inlämningen, alltså:

20.5.1 Tagga projektuppgiften med project_done


Report a bug on this achievement? Please place an issue on GitHub.

20.6 Y69: Tillämpa regressionstestning under projektet   G3 Report

Regressionstester är till för att fånga buggar och fel som uppstått i system efter förändringar. Det är inte helt ovanligt att gamla buggar återuppstår (kanske i ny skepnad) i och med att nya vägar skapats genom programmet. Om man har 100 tester och skall göra en förändring i ett program, börjar vi med att skapa en baseline genom att köra de 100 testerna och ser hur många/vilka som passerar. Efter förändringen gör vi samma och jämför.

Ta fram en uppsättning regressionstester för en del av ett program, motivera dem, och förklara vad testerna visar. (Ett test är inte ett test om det inte är automatiserat, minst make test.)

En uppsättning regressionstester är ingenting man tar fram på en eftermiddag, utan de växer fram gradvis över tid. Vi kan t.ex. tänka oss att alla tester i den första sprinten under projektet är regressionstester. Att hantera och administrera regressionstester handlar inte bara om att ta fram nya tester vid behov (vilka?) utan också om ta bort tester (varför och när – kanske aldrig kommer upp under projektet).

Regressionstestning är viktigt för underhåll av kod eller vidareutveckling av en stor kodbas där effekterna av en förändring är svåra och kostsamma att spåra “manuellt”. Om man har en uppsättning regressionstester kan man köra dessa mellan förändringar för att se om förändringarna fått tester att misslyckas (alternativt börja fungera).

Regressionstester kan ha många olika format, bl.a. existerande enhetstest eller integrationstest, såväl som testfall skapade i samband med buggrapporter och buggfixar. I stora system kan regressionstesterna lätt bli svårhanterligt många.

Integrationstestning är konsten att ta olika moduler och visa att de fungerar tillsammans. Integrationstestning är separat från enhetstestning som försöker visa funktioner i enskilda moduler, och kan också vara betydligt mer komplicerat än enhetstestning eftersom det kan vara svårt att koppla samman moduler eller påvisa i vilken modul ett fel uppstår.


Report a bug on this achievement? Please place an issue on GitHub.

21 TODO Z: Inlämningsuppgifter (Inluppar)

21.1 DONE Z100: Inlupp 1   G3 Lab

21.1.1 Redovisa förståelse för grundläggande imperativ programmering i C

Detta mål är knutet till den första inlämningsuppgiften. Tekniskt sett är detta inte ett mål på samma sätt som de vanliga målen, men vi undviker ytterligare ett system för bokhållning om vi gör detta till ett mål.

För att vara färdig med inlämningsuppgiften skall du ha utfört alla steg i uppgiftsbeskrivningen förutom de som uttryckligen är frivilliga.

Programmet skall:

  • Använda för uppgiften lämpliga abstraktioner
  • “Skydda sig” från fel (du skall kunna förklara hur fel hanteras, och motivera valet av mekanism/strategi)
  • Dokumentera alla publika gränssnittsfunktioner så att en annan programmerare skulle kunna använda implementationen
  • Använda korrekt namngivning (t.ex. ioopm_)
  • Vara indenterat på ett sådant sätt att kontrollflödet är synligt
  • Ha relevanta enhetstester som kan köras automatiskt
  • Kunna byggas med make eller liknande verktyg
  • Inte ha minnesläckage eller använda oinitierat minne
  • Inte krascha vid körning med valid indata
  • Inga ha några globala variabler
  • Inga magiska nummer (t.ex. 128 står överallt i koden)
  • Ingen “machokodning” (t.ex. omotiverade oneliners)
  • Återkommande logik är utbruten och inkapslad i funktioner
  • Namn på filer, variabler, funktioner, etc. skall hjälpa läsaren att förstå deras innebörd, och beteende (t.ex. vilka värden som är rimliga, eller vad man kan förvänta sig från ett funktionsanrop)

Inlämningsinstruktioner finns i uppgiftstexten!


Report a bug on this achievement? Please place an issue on GitHub.

21.2 DONE Z101: Inlupp 2   G3 Lab

21.2.1 Redovisa förståelse för grundläggande imperativ programmering i C

Detta mål är knutet till den första inlämningsuppgiften. Tekniskt sett är detta inte ett mål på samma sätt som de vanliga målen, men vi undviker ytterligare ett system för bokhållning om vi gör detta till ett mål.

För att vara färdig med inlämningsuppgiften skall du ha utfört alla steg i uppgiftsbeskrivningen förutom de som uttryckligen är frivilliga.

Programmet skall:

  • Använda för uppgiften lämpliga abstraktioner
  • “Skydda sig” från fel (du skall kunna förklara hur fel hanteras, och motivera valet av mekanism/strategi)
  • Dokumentera alla publika gränssnittsfunktioner så att en annan programmerare skulle kunna använda implementationen
  • Använda korrekt namngivning (t.ex. ioopm_)
  • Vara indenterat på ett sådant sätt att kontrollflödet är synligt
  • Ha relevanta enhetstester som kan köras automatiskt
  • Kunna byggas med make eller liknande verktyg
  • Inte ha minnesläckage eller använda oinitierat minne
  • Inte krascha vid körning med valid indata
  • Inga ha några globala variabler
  • Inga magiska nummer (t.ex. 128 står överallt i koden)
  • Ingen “machokodning” (t.ex. omotiverade oneliners)
  • Återkommande logik är utbruten och inkapslad i funktioner
  • Namn på filer, variabler, funktioner, etc. skall hjälpa läsaren att förstå deras innebörd, och beteende (t.ex. vilka värden som är rimliga, eller vad man kan förvänta sig från ett funktionsanrop)

Inlämningsinstruktioner finns i uppgiftstexten!


Report a bug on this achievement? Please place an issue on GitHub.

21.3 TODO Z103: Inlupp 3   G3 Lab

21.3.1 Redovisa förståelse för grundläggande objektorienterad programmering i Java

Detta är det första Java-program som skrivs på kursen. Precis som i början av C-fasen ställer vi inte några höga krav på att man skall skriva idiomatiskt korrekt Java redan här, utan fokus ligger på att få ett fungerande program som:

  • inte kraschar vid körning med valid indata
  • skyddar sig från felaktig indata på lämpligt sätt och i lämplig utsträckning
  • inte behöva kompileras om när indata ändras
  • inte ha en massa halvtomma arrayer utan använda länkade strukturer för minneseffektivitet
  • ha ett lämpligt förhållningssätt till NIH och DRY

Ytterligare icke-funktionella krav är

  • inga globala variabler
  • inga magiska nummer (t.ex. 128 står överallt i koden)
  • kodens indentering lyfter fram kontrollflödet
  • ingen “machokodning” (t.ex. omotiverade oneliners)
  • återkommande logik är utbruten och inkapslad i egna metoder eller klasser
  • namn på filer, variabler, funktioner, etc. skall hjälpa läsaren att förstå deras innebörd, och beteende (t.ex. vilka värden som är rimliga, eller vad man kan förvänta sig från ett funktionsanrop)
  • har tydligt dokumenterade gränssnitt som går att förstå utan att läsa koden och helst är formaterade med Doxygen eller JavaDoc
  • programmet går att bygga och testa med en makefil (make all och make test)

Inlämningsinstruktioner finns i uppgiftstexten!


Report a bug on this achievement? Please place an issue on GitHub.

21.4 TODO Z104: Inlupp 4   G3 Lab

21.4.1 Redovisa förståelse för objektorienterad programmering i Java

Detta är det andra Java-program som skrivs på kursen. Precis som senare i C-fasen ställer vi högre krav på idiomatiskt korrekt Java än för föregående program. Förutom att programmet skall fungera korrekt skall det som vanligt:

  • inte kraschar vid körning med valid indata
  • skyddar sig från felaktig indata på lämpligt sätt och i lämplig utsträckning
  • inte behöva kompileras om när indata ändras
  • ha ett lämpligt förhållningssätt till NIH och DRY

Med icke-idiomatisk Java avses för enkelhets skull:

  • följ Javas namngivningsstandard (camelCasing, Klasser/Interface har stor begynnelsebokstav, metoder liten begynnelsebokstav)
  • endast en klass per fil, förutom inre och nästlade klasser
  • equals()-metoder skall vara symmetriska (a.equals(b) == b.equals(a))
  • använd public static final för konstanter eller enums

Ytterligare icke-funktionella krav är

  • inga globala variabler
  • inga magiska nummer (t.ex. 128 står överallt i koden)
  • kodens indentering lyfter fram kontrollflödet
  • ingen “machokodning” (t.ex. omotiverade oneliners)
  • återkommande logik är utbruten och inkapslad i egna metoder eller klasser
  • namn på filer, variabler, funktioner, etc. skall hjälpa läsaren att förstå deras innebörd, och beteende (t.ex. vilka värden som är rimliga, eller vad man kan förvänta sig från ett funktionsanrop)
  • har tydligt dokumenterade gränssnitt som går att förstå utan att läsa koden och helst är formaterade med Doxygen eller JavaDoc
  • programmet går att bygga och testa med en makefil (make all och make test)
  • programmet har enhetstester för alla viktiga metoder
    • som inte bara skrevs efter att programmet var klart “för att ha tester”
    • som använder junit
    • där varje test prövar en sak, och flera tester görs ej i samma testfunktion

Vidare måste en annan grupp ha granskat uppgiften innan den kan bli helt godkänd (jämlikt P45).

Ändring 2016: meningen “Vidare måste en annan grupp ha granskat uppgiften innan den kan bli helt godkänd (jämlikt P45).” ersätts av “Vidare vore det väldigt trevligt, stimulerande för djuplärningen, och kanske också positivt för programmets kvalitet, om en annan grupp har granskat uppgiften innan den redovisas (jämlikt P45).”

Inlämningsinstruktioner finns i uppgiftstexten!


Report a bug on this achievement? Please place an issue on GitHub.


Questions about stuff on these pages? Use our Piazza forum.

Want to report a bug? Please place an issue here. Pull requests are graciously accepted (hint, hint).

Nerd fact: These pages are generated using org-mode in Emacs, a modified ReadTheOrg template, and a bunch of scripts.

Ended up here randomly? These are the pages for a one-semester course at 67% speed on imperative and object-oriented programming at the department of Information Technology at Uppsala University, created by Tobias Wrigstad.

Footnotes:

1
Iallafall i normal- och idealfallet.
2
Tekniskt sett är detta samma sak som att funktionen har en annan typ.

Author: Tobias Wrigstad

Created: 2019-12-02 Mon 13:31

Validate