Stilguide

Vår stilguide er i bunn og grunn et lite utvalg fra Google Java Style Guide med noen få tillegg.

Generelt

Koden må kompilere Koden må kjøre Ikke gjenta deg selv Modulær kode Selvdokumenterende kode Gjør det enkelt

Javadoc

Javadoc for alt som er public og protected Ikke kombiner javadoc og @Override Beskriv returverdi Beskriv sideeffekter Beskriv oppførsel ved null-argumenter Beskriv parametre med @param Beskriv exceptions med @throws Javadoc < 72 tegn

Kommentarer

Ikke undervis Java Unngå unødvendige kommentarer Korte kommentarer Korrekte kommentarer Kommentarer < 80 tegn

Formatering

Innrykk på 2 mellomrom Kodelinjer < 80/100 tegn Bruk mellomrom riktig

Navngivning

Selvbeskrivende navn Korte navn Presise navn Navn på klasser er UpperCamelCase Navn på metoder og variabler er lowerCamelCase Navn på konstanter er UPPER_SNAKE_CASE Navn på pakker er lowercase Kvalifisering med this Kvalifisering med klassenavn

Kodestil

Korte metoder Unngå magiske verdier Unngå statiske variabler Begrens skopet til variabler Bruk parenteser Ikke bruk == med flyttall Ikke bruk == med objekter Benytt hjelpevariabler Små klasser kan være uforanderlige Variabler har abstrakte typer

Innkapsling

Bruk strengeste tilgangsmodifikator Instansvariabler er private

Testing

TestFoo ligger i samme pakke som Foo Test public og protected metoder Test for likhet Test hjørnetilfeller


Generelt
Koden må kompilere Koden din må kompilere uten feil. Hvis nødvendig, kommenter ut kode slik at det du leverer kompilerer.
Koden må kjøre Koden din må kjøre uten å krasje med en gang. Hvis koden din krasjer med en gang, har du tilgang til en feilmelding som hjelper deg å finne hva som er feil. Fiks feilen! Hvorvidt koden din er korrekt er egentlig et separat spørsmål; men så lenge koden krasjer med en gang er den hvertfall ikke korrekt.
Ikke gjenta deg selv Følg prinsippet om DRY (don't repeat yourself). Hvis du skrive den samme (eller nesten den samme) koden to eller flere ganger, bør du sannsynligvis endre noe slik at du kun trenger å skrive den én gang i stedet. Bruk hjelpemetoder i stedet.
Modulær kode Del opp koden din i pakker, klasser og metoder som representerer en logisk oppdeling av funksjonaliteten du trenger. Forsøk å begrense avhengighetene mellom de ulike klassene så mye som mulig.
Selvdokumenterende kode Alle klasser, metoder og variabler skal ha selvforklarende navn. Det er bedre med et selvforklarende navn som er langt enn et uforståelig navn som er kort. Dette er spesielt viktig for metoder, klasser, og feltvariabler.
Gjør det enkelt Følg prinsippet om KISS (keep it simple, stupid). Ikke ta hensyn til absolutt alle mulige fremtidige eventualiteter første gang du skriver en kodesnutt, men løs først og fremst problemet du har behov for å løse akkurat nå.
Javadoc
Javadoc for alt som er public og protected Alt som er public eller protected (klasser, metoder, konstruktører, feltvariabler) skal ha en javadoc-kommentar som beskriver hva det og hvordan det skal brukes. Javadoc-kommentarerer begynner med /** og avsluttes med */, og skrives like før definisjonen av klassen/metoden/variabelen. For eksempel:
  /**
   * Multiple lines of Javadoc text are written here,
   * wrapped before the 72 character mark.
   */
  public void methodName() {
    // ...
  }

Korte javadoc-kommentarer kan skrives på én linje

  /** An especially short bit of Javadoc. */
  public void methodName() {
    // ...
  }
Ikke kombiner javadoc og @Override Hvis en public metode er annotert med @Override, skal du likevel ikke skrive javadoc. La i stedet metoden implementeres i hehold til javadoc skrevet der metoden arves fra.
Beskriv returverdi En javadoc-kommentar for en metode skal beskrive hva metoden returnerer. Kan inkludere et eksempel på input og output.
Beskriv sideeffekter En javadoc-kommentar for en metode skal beskrive hvilke sideeffekter metoden har, og være tydelig på hvilket objekt som i så fall muteres. Bruk «this» for å referere til objektet metoden blir kalt på.
Beskriv oppførsel ved null-argumenter En javadoc-kommentar for en metode skal beskrive hva metoden gjør dersom et argument er null, og hva metoden gjør dersom argumentene på andre måter ikke er gyldige.
Beskriv parametre med @param Dersom javadoc går over flere linjer, beskriv hvert enkelt parameter med @param. I disse tilfellene, beskriv også returverdien med @return. For eksempel:
  /**
   * Multiplies two numbers.
   * 
   * @param a the first factor
   * @param b the second factor
   * @return the product of the two factors
   */
  public static int multiply(int a, int b) {
    return a * b;
  }
Beskriv kjente exceptions med @throws Beskriv excepitions du forutser kan oppstå, både deklarerte og ikke-deklarerte. For eksempel:
  /**
   * Divides two numbers. If the resulting number is not
   * an integer, the fractional part is discarded.
   * 
   * @param a the dividend
   * @param b the divisor
   * @return the quotient of the two numbers
   * @throws ArithmeticException if the divisor is zero
   */
  public static int divide(int a, int b) {
    return a / b;
  }
Javadoc < 72 tegn Ingen javadoc-linjer skal passere 72-tegn-grensen. Del heller opp kommentarer over flere linjer (unntak for lange internettadresser, som eventuelt kommer på en egen linje).
Kommentarer
Ikke undervis Java Ikke bruk kommentarer for å forklare hva Java gjør. Anta at den som leser koden din kan Java allerede. For eksempel, ikke skriv kommentarer som dette:
int foo = 42; // foo gets the value 42
Unngå unødvendige kommentarer Det er bedre med selvdokumenterende kode enn kommentarer. Benytt kommentarer kun dersom det ikke fremgår tydelig av metodenavn, javadocs og variabelnavn hva som skjer i metoden.
Korte kommentarer Hvis du trenger kommentarer i koden din for å gjøre den forståelig, hold kommentarene korte og konsise. For eksempel, ikke skriv lange kommentarer som dette:
// This is an array of ints holding the measured
// temperatures in the order they were registered.
int[] temps;

men skriv heller korte kommentarer som dette:

int[] temps; // in order of registration
Korrekte kommentarer Sørg for at kommentarer er oppdatert til en hver tid, og beskriver koden presist og korrekt. Det er verre med ukorrekte kommentarer enn ingen kommentarer i det hele tatt.
Kommentarer < 80 tegn Ingen kommentarlinjer skal passere 80-tegn-grensen. Del heller opp kommentarer over flere linjer (unntak for lange internettadresser, som eventuelt kommer på en egen linje).
Formatering
Innrykk på 2 mellomrom Benytt 2 mellomrom for å lage innrykk i koden din. Ikke bruk tab-symbolet. Konfigurer din editor til å bruke 2 mellomrom, og benytt din editor sin funksjonalitet for å automatisk rykke inn linjer hvis du ser at koden ikke er rykket inn skikkelig.

Konfigurering:

  • Gå til View -> Command Palette.
  • Skriv >Java: Open Java Formatter Settings with Preview.
    • Hvis du får spørsmål om å opprette en standard profil, svar ja.
  • Gå til indention -avsnittet og sett tab size til 2.
  • Gå til indention -avsnittet og påse at indention policy er satt til space.
  • Valgfritt: fjern merket for detect indentation from file content (du må fjerne dette merket for å endre innrykket i en fil med stegene under).

For å automatisk lage innrykk i filen du jobber med:

  • Gå til View -> Command Palette.

  • Skriv >Reindent Lines.

Konfigurering:

  • Velg Settings fra hovedmenyen og gå til Editor -> Code Style -> Java
  • Sett tab size og indent til 2, og continuation indent til 4
  • Påse at Use tab character ikke er merket

For å automatisk lage innrykk i filen du jobber med:

  • Velg Auto-indent lines fra Code -menyen.

Kodelinjer < 80/100 tegn Kodelinjer skal ideelt ikke passere grensen på 80 tegn per linje. Vi tillater likevel å bryte denne grensen av og til, men kun dersom det er maksimalt ett metodekall på linjen og det ikke umiddelbart lar seg gjøre å dele opp linjen med enkle grep. Ingen kodelinjer kan derimot være lengre enn 100 tegn. Unntaket er for lange internettadresser, i så fall lagres disse i en egen streng på en separat linje.

Hensikten med denne grensen: lettere å jobbe med split screen, lettere å lese, lettere å presentere koden med stor skrift (spesielt viktig for dine synshemmede kolleger), og lettere å skrive ut.

Bruk mellomrom riktig

Vi ser her på bruk av mellomrom som teknisk sett er frivillig, men hvor vi har retningslinjer som gjør koden vår penere å lese.

  • Aldri benytt to mellomrom etter hverandre.
  • I eksemplene under viser vi mellomrom som symbolet ·.
if/while/for
/do/switch
/try-catch

Bruk mellomrom for å omgi parentesene rundt testen. For eksempel:

if·(test)·statement;

eller

if·(test)
  statement;

eller

if·(test)·{
  // ...
}
metoder

Bruk mellomrom for å skille argumenter når du kaller metoder, men ikke ha mellomrom andre steder.

this.doFoo(42,·"bar");

Bruk mellomrom for å skille parametre i metodesignaturen, og benytt ett mellomrom for å skille parametrene fra krøllparentesen som begynner metodekroppen.

public void doFoo(int x,·String s)·{
  // ...
}
operatorer

Bruk mellomrom for å omslutte operator-symboler (+, -, *, /, ==, !=, <, <=, >, >= etc.) og tilordningssymboler (=, +=, : etc.).

int x·=·((-a·%·b)·*·Math.abs(2·–·c));
semikolon

Aldri ha mellomrom direkte før et semikolon. Dersom semikolon ikke avslutter linjen (for eksempel i en for-løkke), skal det alltid være mellomrom etter semikolon.

for (int i = 0;·i < 10;·i++) {
  // ...
}
Navngivning
Selvbeskrivende navn

Navn på klasser, metoder og variabler skal være selvbeskrivende. Ideelt sett bør navnet beskrive sin egen rolle såpass godt at det ikke er nødvendig å lese javdoc for å forstå hva metoden gjør eller hva variabelen inneholder.

Jo mer eksponert navnet er, jo viktigere er det at navnet er selvbeskrivende. Derfor er det for eksempel enda viktigere med selvbeskrivende navn for feltvariabler enn for lokale variabler.

Korte navn Navn på klasser, metoder og variabler skal være korte. Jo kortere navn, jo bedre; men det er likevel viktigst at navnet er selvbeskrivende. Hvis du må velge mellom et kort navn og et selvbeskrivende navn, velg det selvbeskrivende navnet.
Presise navn

Navn på klasser, metoder og variabler skal være presise. For eksempel er getValue et dårlig navn på en metode som returnerer og inkrementerer en verdi: getAndIncrementValue er bedre.

Hvis dennne regelen fører til at navnet på metoden din blir uhåndterlig langt, kan det være et tegn på at metoden har for mange hensikter, og burde vært delt opp i hjelpemetoder.

Navn på klasser er UpperCamelCase Navn på klasser og klasse-lignende ting som grensesnitt, enum, record, abstrakte klasser etc. skal begynne med stor bokstav, og ha en ny stor bokstav i stedet for mellomrom. Klassenavn skal normalt være substantiv (f. eks. Person, School, TetrisBoard), mens grensesnitt noen ganger kan være/begynne med adjektiv (f. eks. Runnable, ViewableModel, Controllable).
Navn på metoder og variabler er lowerCamelCase Navn på metoder og variabler skal begynne med liten bokstav, og ha en ny stor bokstav i stedet for mellomrom. Variabler er vanligvis substantiv (f. eks. board, familyName, items), mens metoder vanligvis begynner med et verb (f. eks. insert, getAge, removeFullRows). Unntak er for boolske (retur-)verdier, da kan navnet på variabelen eller metoden gjerne være et ja/nei -spørsmål (for eksempel isAlive eller hasContent).
Navn på konstanter er UPPER_SNAKE_CASE Navn på konstanter (uforanderlige feltvariabler som er static og final eller enum-objekter) skrives med store bokstaver og benytter underscore i stedet for mellomrom.
Navn på pakker er lowercase Navn på pakker er kun lowercase uten underscore, og begynner vanligvis med reversert domene til eier av koden; for eksempel no.uib.inf101.myapp.
Kvalifisering med this Når vi kaller på instansmetoder eller bruker instansvariabler som tilhører objektet vi kjører i konteksten av, kvalifiserer vi navnet på metoden eller variabelen ved å bruke «this.» før navnet på instansmetoden/instansvariabelen. Dette er nyttig for ferske programmerere for å bli vant til at this eksisterer, det tydeliggjør for leseren at variabelen/metoden er en instansvariabel/metode og vi unngår samtidig at lokale variabler skygger for instansvariabler uten at vi mener det.
Kvalifisering med klassenavn Når vi kaller på klassemetoder eller bruker klassevariabler/konstanter, kvalifiserer vi navnet på metoden eller variabelen ved å bruke «KlasseNavn.» før navnet på klassemetoden/klassevariabelen. Fordi klassenavn alltid begynne med stor bokstav (se over), kan vi på denne måten umiddelbart kjenne igjen at metoden/variabelen er statisk.
Kodestil
Korte metoder Hver enkelt metode skal være kort og konsis, og være lett å lese. Dersom metoden innebærer flere sub-steg, skal disse være utskilt som hjelpemetoder. Det er nesten aldri hensiktsmessig med mer enn 20 linjer kode per metode (unntak for svært oversiktlige switch-uttrykk).
Unngå magiske verdier En magisk verdi er en konkret verdi (for eksempel «15») som benyttes i koden uten å være angitt som en variabel med tilhørende selvbeskrivende navn. I stedet for å bruke magiske verdier kan du angi konstanter med selvbeskrivende navn og så benytte dem. For eksempel, ikke bruk den magiske verdien 15 slik som dette:
for (int r = 0; r < 15; r++) {
  // ..
}

men opprett en konstant med selvbeskrivende navn i stedet :

int rows = 15;
for (int r = 0; r < rows; r++) {
  // ..
}

Dersom denne samme verdien (15) brukes annet sted i koden også, skal kanskje de to verdien alltid være synkronisert. Da må de hentes fra samme sted; definer for eksempel verdien som en feltvariabel. Enten som en konstant klassevariabel, eller (ofte enda bedre) du kan bruke en instansvariabel slik at koden blir dynamisk og virker like bra for andre verdier enn 15 også.

Verdier vi ikke regner som magiske er -1, 0, 1, 2, "", og null.

Unngå statiske variabler Klassevariable/statiske variabler hører ikke hjemme i et godt strukturert, modulært og testbart program. I hvert fall utrolig sjeldent. I INF101 er det ikke lov å bruke statiske variabler for noen andre formål enn konstanter.
Begrens skopet til variabler Benytt det minste mulige skopet for en variabel. Ikke benytt feltvariabler hvis du klarer deg med en lokal variabel.
Bruk parenteser

Bruk paranteser når du skriver kombinerte uttrykk. Ikke anta at den som leser koden din har memorisert java sin presedenstabell.

Riktig:

isOk = (x == y) || (x == z)

Feil:

isOk = x == y || x == z
Ikke bruk == med flyttall Når man regner med flyttall kan det oppstå avrundingsfeil som gjør at sammenligning med == feiler. Benytt almostEqual i stedet:
public static boolean almostEqual(double a, double b) {
  return Math.abs(a - b) < 0.000000001;
}
Ikke bruk == med objekter For å sammenligne om to objekter a og b er like, ikke bruk a == b, men benytt Objects.equals(a, b) i stedet. Kun ved sammenligning mot null eller i sjeldne tilfeller hvor man faktisk ønsker å sammenligne referanser (og begrunner bruken godt med en kommentar) kan man benytte == for å sammenligne objekter.
Benytt hjelpevariabler Ved komplekse operasjoner og utregninger er det nyttig å mellomlagre delvise resultat i «hjelpevariabler.» Dette gjør koden lettere å lese, mer selvdokumenterende, og mye lettere å feilsøke med en debugger.
Små klasser kan være uforanderlige Hvis objekter i en klasse representerer en begrenset mengde data (inneholder ikke store samlinger/lister av noe) må du vurdere om klassen burde være uforanderlig.
Variabler har abstrakte typer

Når du skal velge variabeltype, velg en type som er så høyt oppe i typehierarkiet som mulig, men så lavt som nødvendig. Det er for eksempel bedre om en variabel har typen List<Foo> enn ArrayList<Foo> (såfremt du ikke er avhengig av en metode som finnes i ArrayList men ikke List).

Dette er spesielt relevant for parametre. Det er bedre å være avhengig av et grensesnitt enn å være avhengig av en klasse.
Innkapsling
Bruk strengeste tilgangsmodifikator Som utgangspunkt bør du alltid bruke strengeste mulige tilgangsmodifikator som tillater deg å gjennomføre det du skal.
Instansvariabler er private Alle instansvariabler skal være private. Hvis du trenger tilgang til dem utenfor klassen, bruk get og set-metoder.
Testing
TestFoo ligger i samme pakke som Foo Når man skriver JUnit-tester for en klasse Foo i pakken com.sample.myapp, skal klassen som tester Foo hete TestFoo og også ligge i pakken com.sample.myapp. Merk dog at testen skal ligge i test-mappen, ikke i main-mappen i maven-prosjektet.
Test public og protected metoder Skriv tester for alle metoder som er public eller protected. Tester for metoder som er pakke-privat er valgfritt. Ikke skriv tester for private metoder (tester skal teste funksjonalitet, ikke implementasjonsdetaljer)
Test for likhet Det er bedre å teste at en oppførsel gir et visst resultat enn å teste at det ikke gir et visst resultat (selv om det er ett riktig svar, kan det være mange gale svar).
Test hjørnetilfeller Skriv tester for de spesielle tilfellene. Skriv tester der du bruker veldig små verdier, veldig store verdier, nullverdier, ulovlige verdier og annen oppførsel som bare oppstår sjelden ved normal bruk.