Göm menyn

TDDE10 Objektorienterad programmering i Java

Kodkonventioner

Kod som skrivs under kursens gång ska följa Oracles kodkonventioner. Nedan följer en sammanfattning av dem på svenska. Inlämnad kod som inte följer kodkonventionerna ger komplettering. Längst ner har vi även lagt till en del praktiska tips om hur man skriver bra java-kod.

  1. Filer, mappar och filnamn

    Javafiler skall heta samma som den klass som definieras inne i filen. Normalt sätt lägger man aldrig mer än en klass per fil.

    Klassen MyCoolProgram skall alltså ligga på filen MyCoolProgram.java.

    Vanligtvis finns hela projektets källkod i mappen src. Oftast har man dock undermappar i denna som motsvarar javapaket. Att lägga saker direkt i src är mindre vanligt, då hamnar de klasserna i "default-paketet". Att göra så är okej nu när du lär dig (om inget annat anges i laborationen) men du bör vänja dig vid att dina klasser ska ligga i riktiga paket.

  2. Deklarationsordning i klassen.

    I din klass kommer du vilja deklarera många olika saker. Alla klasser (och interface) behöver inte ha allt, men en naturlig ordning är följande:

    1. Eventuell javadoc för klassen
    2. Deklaration av klassnamnet eller interfacenamnet.
    3. Klassvariabler (publika först, sedan protected, sedan private.)
    4. Instansvariabler (publika först, sedan protected, sedan private.)

      (Undvik helst "package private", alltså att utelämna synlighet eftersom det är otydligt huruvida du verkligen vill ha det eller bara har glömt skriva public/protected/private).

    5. Konstruktorer

      Om du har flera konstruktorer och de anropar varandra. Lägg dem så att anropen sker "uppåt". Man kan anropa en konstruktor i den egna klassen med nyckelordet this.

    6. Metoder.

      Grupperade efter funktionalitet. T.ex. kan en privat hjälp-metod med fördel placeras direkt efter en publik metod som använder den. Målet här är att uppnå så god läslighet som möjligt.

  3. Indentering och kodformatering

    • Undvik rader som är längre än 80 tecken.
    • Ha blanksteg mellan operatorer och dess operander. T.ex. är
      x = 3 * 5 + 2; 
      Är mycket trevligare att läsa än:
      x=3*5+2; // UNDVIK!
      Tänk på att detta även gäller kommaoperatorn i parameterlistor. Ett undantag från detta är unära operatorer så som ! och ++.
    • Indentera konsekvent med ett fixt antal blanksteg (kan variera mellan text-editorer).
    • Använd blanka rader där koden annars skulle bli för köttig. T.ex. skall alla metoder ha minst en blankrad mellan sina kroppar.
    • Man har ett mellanslag mellan nyckelord och efterföljande parentespar.
    • Man har INTE ett mellanslag mellan ett metodnamn och efterföljande parameterlista.
    • Startkrullparentes sitter alltid på samma rad som satsen eller deklarationen. Med minst ett mellanslag före.
    • Slutkrullparentes sitter alltid först på sin rad, förutom när man deklarerar en tom kropp, t.ex:
             int doesNothing() {} 
  4. Kommentarer

    • Gödsla inte med kommentarer. Kommentera endast när något var särskilt svårt att lösa, eller behöver förklaras för läsaren.
    • Skilj på vanliga kommentarer (görs med //, eller blockkommentarer med /*) och javadoc. Vanliga kommentarer beskriver implementation, javadoc skall dokumentera vad klasser/metoder gör utifrån sett.
  5. Deklarationer

    • Håll dig till att deklarera en variabel per rad. D.v.s. undvik:
      int x, y; // UNDVIK!
      Och skriv istället:
      int x;
      int y;
    • Deklarera alltid variabler så lokalt som möjligt. Om en variabel endast används inne i ett underprogram skall det vara en lokal variabel, inte en instansvariabel. Om en variabel bara används inne i en loop, så skall den vara deklarerad i det blocket, inte utanför.
  6. Satser

    • Ha aldrig mer än en sats per rad.
    • Satsen return behöver inte ett eget parentespar efter sig.
    • If-satser ser ut på följande sätt:
      
             if (condition) {
                 statements;
             }
      
             if (condition) {
                 statements;
             } else {
                 statements;
             }
      
             if (condition) {
                 statements;
             } else if (condition) {
                 statements;
             } else {
                 statements;
             }
           
    • If-satser skall ALLTID ha ett efterkommande block. Även om språket tillåter att skriva if-satser utan block så skall man INTE göra följande (eftersom detta lätt leder till buggar):
      
             if (x == 3)
                something();
      
    • for-satser ser ut på följande sätt:
      
             for (initialization; condition; update) {
                 statements;
             }
      
    • while-satser ser ut på följande sätt:
      
             while (condition) {
                 statements;
             }
      
    • do-while-satser ser ut på följande sätt:
      
             do {
                 statements;
             } while (condition);
      
    • Precis som if-satser bör loopar alltid ha ett tillhörande block, även om blocket skulle vara tomt.
    • switch-satser ser ut på följande sätt:
      
             switch (condition) {
             case ABC:
                 statements;
                 /* falls through */
             case DEF:
                 statements;
                 break;
             case XYZ:
                 statements;
                 break;
             default:
                 statements;
                 break;
             }
      

      Rekommendationen är att undvika switch-satser då deras struktur är lite "hoppig" och kan vara svår att följ och lätt att göra fel på.

    • try-catch-satser ser ut på följande sett:
      
             try {
                 statements;
             } catch (ExceptionClass e) {
                  statements;
             }
      
             try {
                 statements;
             } catch (ExceptionClass e) {
                 statements;
             } finally {
                 statements;
             }
      
  7. Namngivning

    • Paketnamn skrivs oftast med små bokstäver, men kan variera.
    • Klassnamn skall vara substantiv, börja med stor bokstav och ha "CamelCase", d.v.s. varje nytt ord skrivs direkt intill med begynnande stor bokstav. T.ex. MyCoolClassName
    • Interface skall namnges som klasser.
    • Metoder skall vara verb, börja med liten bokstav och ha "camelCase".
    • Variabelnamn skall vara substantiv, börja med liten bokstav och ha "camelCase". Variabelnamn skall inte börja med understräck eller $-tecken. Variabelnamn skall vara meningsfulla så att man förstår vad de skall användas till. Variabelnamn får vara korta om den kontexten där de används är mycket simpel.
    • Konstanter. Variabler som är deklarerade som static final (konstanter) skall ha stora bokstäver och "SNAKE_CASE". T.ex.
      static final int NO_OF_MONTHS_PER_YEAR = 12.
  8. Praktiska tips

    • Definiera (ge ett värde till) en variabel så snart som det är möjligt. Det går oftast på en gång. Att slentrianmässigt låta variabler vara null är oftast ett gott recept på trubbel senare.
    • Referera inte till en klassmetod som om den vore en instansmetod. T.ex:
      
             classMethod();             // OK
             AClass.classMethod();      // OK
             anObject.classMethod();    // UNDVIK!
      
    • Undvik att kedja tilldelningar, även om det går. T.ex:
    • 
             x = y = z;  // UNDVIK!
      
    • Använd parenteser där det är eller kan vara förvirrande i vilken ordning saker sker. T.ex:
      
             if (a == b && c == d)     // UNDVIK!
             if ((a == b) && (c == d)) // OK
           
    • Gödsla inte med parenteser där ordningen är uppenbar eller inte spelar någon roll.
    • Undvik förkortade if-satsen. Den är väldigt sällan lämplig att använda.
    • Undvik att använda nyckelordet continue, det inför ofta ett konstigt hopp i koden. Samma sak gäller break, men denna är svårare att undvika ibland.
    • Använd nyckelordet this när du refererar till en medlem hos det egna objektet (instansvariabel eller instansmetod). Du kan utelämna det om det är tydligt vad man menar utan det.
    • Där generiska typer används är det en god idé att alltid vara noga med att sätta dit de generiska parametrarna. Fr.o.m. java 8 kan kompilatorn inferera (gissa sig till) typen på vissa ställen (nedan, mellan de tomma < >-hakarna)
      
             ArrayList<Animal> myList = new ArrayList<>();
      
      Sätter man inte dit hakarna så blir den generiska typen av typ Object, vilket lätt leder till buggar i koden och många varningar om typkonverteringar.
    • Metoder som överskuggar bör alltid använda taggen @Override. T.ex:
               @Override
      	 void myOverridingMethod() {
           
      Har man med detta så får man en automatisk kontroll av kompilatorn att metoden verkligen överskuggar något i superklassen, om inte får man ett kompileringsfel. Utelämnas @Override och har gjort fel på metodnamn eller parametrar så blir det ju en helt ny metod i klassen, detta får man ingen varning om och buggar uppstår.
    • Dynamisk typkontroll (operatorn instanceof) bör användas mycket sparsamt! Vanligtvis beror sådana typkontroller på att man har lagt funktionalitet på fel ställe i koden. Om det går bör man flytta över ansvaret på den klass som man kontrollerar efter.
    • Nyckelordet var kan användas för att låta kompilatorn gissa sig till deklarationstypen på en variabel. Detta kan vara mycket praktiskt om man vet vad man gör. I den här kursen rekommenderar vi dock att ni inte använder det i er lab.- och projektkod. Det är bättre att ordentligt lära sig typer och typdeklarationer först, innan man börjar "sudda" bort dem från sina program. Om ni ändå känner att ni vill testa detta, skriv en (vanlig) kommentar direkt ovanför deklarationen för vilken datatyp det borde "bli".

Sidansvarig: Magnus Nielsen
Senast uppdaterad: 2023-02-16