Document:Coding Standard
| Coding Standard | |
|---|---|
| Datum | 07-04-2008 |
| Fase | Fase 5 |
| Versie | 1.5 |
| Status | Concept |
| Auteurs | Coding Standard Group |
| Goedgekeurd door | |
| Aangepast door | Chris van Schoonhoven |
Contents |
Naamgeving
Bij het benamen van een identifier is het belangrijk om het doel van het achterliggende object zo goed mogelijk te beschrijven. Wees niet bang om met lange namen te werken, en gebruik alleen afkortingen als er kan worden aangenomen dat de betekenis algemeen bekend is in het vakgebied. Gebruik geen underscores of andere leestekens om woorden te scheiden, maar begin elk nieuw woord met een hoofdletter. (Uitgezonderd constanten) Gebruik Engels als voertaal bij het naamgeven, omdat dit de minste beperkingen oplegt bij het vinden van geschikt personeel om je applicatie te ontwikkelen.
Klassen en interfaces
Klasse- en interfacenamen dienen te beginnen met een hoofdletter. De naam moet in zijn geheel een zelfstandig naamwoord zijn. Afkortingen in de samengestelde naam kunnen gewoon met hoofdletters worden geschreven.
Goed:public class DatabaseManager { ... }
public class GPSReceiver { ... }
public class DatabaseManaging { ... }
Variabelen
Namen van variabelen dienen te beginnen met een kleine letter. De naam moet in zijn geheel een zelfstandig naamwoord zijn, of het meervoud daarvan wanneer het om een array of collectie van een type gaat. Wanneer de naam met een afkorting begint, dient deze geheel in kleine letters te worden geschreven.
Veel programmeurs gebruiken een underscore of een andere tekencombinatie aan het begin van een variabele om aan te geven dat het om een klassenvariabele gaat. Hierdoor staan alle klassenvariabelen onder elkaar gegroepeerd in het intelli-sense menu van de IDE, wat door sommigen als prettig wordt ervaren. Helaas heeft deze gewoonte een negatieve invloed op de leesbaarheid en de eenduidigheid van de code voor mensen die dit niet gewend zijn. Er is dus ook besloten om dit niet toe te staan.
Goed:private int clientCount;
private SOAPConnection[] soapConnections;
private SOAPConnection[] sOAPConnections;
Constanten
Namen van constanten zijn net als variabelen zelfstandig naamwoorden, of het meervoud daarvan. Echter worden deze altijd met hoofdletters geschreven, waarbij woorden worden gescheiden met behulp van underscores.
Voorbeelden:private static final int MAXIMUM_CLIENTS = 255;
private static final Color DEFAULT_BUTTON_COLOR = Color.GRAY;
private static final int maximumClients = 255; { ... }
Methoden
Methodenamen dienen te beginnen met een kleine letter. De naam moet beginnen met een werkwoordsvorm in de tegenwoordige tijd aangezien methoden altijd iets ‘doen’ wanneer je ze aanroept.
Goed:private void initializeApplication(boolean showSplashscreen) { ... }
private boolean isActive() { ... }
private void initializingApplication(boolean showSplashscreen) { ... }
Bestandsnamen
De naam van een bestand dient hetzelfde te zijn als de naam van de klasse, dus een logische klasse naam is een logische bestandsnaam. Over het algemeen gaat dit in Java automatisch.
Goed:
- DrawingGraph.java
- EventHandler.java
Fout:
- my_groovy_class.java
- new_addon.java
- drawingGraph.java
- event_Handler.java
Bestandsextensies
Java bron code bestanden dragen de extensie .java en Java bytecode bestanden de extensie .class. Ook dit gaat in de meeste IDE’s automatisch.
Commentaar
Code op zichzelf is vaak moeilijk leesbaar en moeilijk te begrijpen, daarom is het belangrijk om commentaar te gebruiken. Vooral wanneer het over een grote hoeveelheid code gaat. Commentaar voegt extra informatie aan de code toe, waardoor de code voor mede ontwikkelaars eenvoudiger te begrijpen is. Commentaar mag alleen informatie bevatten die relevant is aan het lezen en begrijpen van het programma.
Informatie die aan de hand van de code duidelijk is dient niet dubbel gedocumenteerd te worden en daarom niet ook nog eens in het commentaar verwerkt te worden. Code wordt constant veranderd en aangepast waardoor bijbehorend commentaar out-of-date raakt. Daarom dient commentaar die out-of-date kan raken, vermeden te worden. Veel gebruik van commentaar kan de slechte kwaliteit van code weergeven, aangezien de code zelf dan niet duidelijk genoeg is. Overweeg of de code beter geprogrammeerd kan worden waardoor het makkelijker te begrijpen is.
Algemene richtlijnen waar men zich aan dient te houden m.b.t. commentaar zijn:
- Commentaar wordt in het Engels geschreven;
- Schrijf liever geen commentaar, dan commentaar dat als onnuttig aangemerkt kan worden;
- Inherit alleen commentaar indien dit van toepassing is op de gebruikte klassen;
- Let op hoofdletters en interpunctie;
- ‘Commented’ code is niet toegestaan, tenzij hier een goede reden voor is. Deze reden dient er dan ook bij geschreven te worden;
- De auteur van een klasse dient zowel zijn voor- als achternaam te vermelden, inclusief zijn email adres (bijv. @author Gert Laan <gert.laan@wosi.org>).
Javadoc commentaar
JavaDoc commentaar beschrijft Java klasses, interfaces, constructors, methodes en velden. Elk Javadoc commentaar staat tussen commentaar tekens /**...*/, met één stukje commentaar per klasse, interface of member. Dit commentaar moet boven de declaratie van een klasse neergezet worden. Hieronder een voorbeeld daarvan:
/** * Voorbeeld klasse bevat ... */ public class Example { ... }
Wanneer er informatie over een klasse, interface, variabele of methode gegeven moet worden die niet geschikt is voor documentatie, dan moet er direct na het declaratie blok, commentaar of enkele lijn commentaar gebruikt worden. Bijvoorbeeld details over de implementatie van een klasse moet vermeld worden in blok commentaar en niet in klasse Javadoc commentaar. Javadoc commentaar moet niet ‘in’ een methode of constructor definitie blok.
Hieronder de Javadoc block tags in de volgorde van hoe ze gebruikt moeten worden.
/**
* @param (alleen voor klassen, interfaces, methodes en constructors)
* @return (alleen voor methodes)
* @exception (@throws kan hiervoor ook gebruikt worden)
* @author (alleen voor klassen en interfaces)
* @version (alleen voor klassen and interfaces)
* @see
* @since
* @serial (@serialField of @serialData kan ook gebruikt worden)
* @deprecated
* @link
*/Voor meer informatie over Javadoc commentaar wordt er naar de Javadoc home page verwezen: http://java.sun.com/Javadoc/
Algemeen commentaar
Commentaar kan op vier manieren in het programma geïmplementeerd worden:
- Block
- Single-line
- Trailing
- End-of-line
Block commentaar
Blok commentaar wordt gebruikt om files, methodes, data structuren en algoritmes van informatie te voorzien. Blok commentaar kunnen ‘vóór’ elke file of methode gebruikt worden. Ze kunnen ook voor andere situaties gebruikt worden. Bijvoorbeeld ‘in’ een methode. Blok commentaar moeten gescheiden worden van de code door een enkele blanke regel.
Hieronder twee voorbeelden waar blok commentaar gebruikt wordt:
/** * Blok commentaar voor de methode. */ public void execute() { /** * Blok commentaar in de methode. */ }
Enkele lijn commentaar
Enkele lijn commentaar is bijna hetzelfde als blok commentaar. Wanneer het een kort stuk commentaar is dat op één enkele regel past, dient er enkele lijn commentaar gebruikt te worden. Dit enkele lijn commentaar dient ook opgevolgd te worden door één blanke regel.
Hieronder een voorbeeld van enkele lijn commentaar:
if (someCondition) { /* Enkele lijn afhandeling. */ }
Trailing commentaar
Naast enkele lijn commentaar kunnen er ook trailing commentaar gebruikt worden. Dit trailing commentaar wordt op dezelfde regel als de code neergezet. Worden er meer kort stukken commentaar gebruikt, dan dienen deze op dezelfde tab breedte geplaatst te worden.
Hieronder een voorbeeld van trailing commentaar:
if (someOtherCondition) { return true; /* True */ }
End-of-line commentaar
End-of-line commentaar kan worden gebruikt voor tijdelijke toelichting op de code. Ook kan end-of-line commentaar een hele regel, een deel van een regel of meerdere regels tijdelijk als commentaar gemaakt worden. End-of-line commentaar wat uit meerdere regels bestaat voor de beschrijving van een stuk code moet vermeden worden.
if (someOtherCondition) { // Condition is true. ... } else { return false; // Condition is false. } //if (condition) //{ // // Comment //} //else //{ // return false; //}
Interpunctie
Witregels
Witregels bevorderen de leesbaarheid van de code. Ze worden gebruikt om logische stukken code te groeperen. Er wordt onderscheid gemaakt tussen een enkele witregel en een dubbele witregel.
Dubbele witregels worden gebruikt:
- Tussen verschillende stukken code in een bestand
- Tussen de definities van interfaces en klassen
Enkele witregels worden gebruikt:
- Tussen methoden
- Tussen lokale variabelen in een methode en het eerste statement
- Voor een enkele lijn of blok commentaar
- Tussen logische delen in een methode om de leesbaarheid te vergroten
Spaties
Ook spaties zorgen voor een betere leesbaarheid van de code. Een spatie gebruik je:
- Tussen een keyword en een haakje (niet tussen een methode naam en het bijbehorende haakje!).
- Na iedere komma in een rij argumenten
- Tussen iedere operand en zijn binaire operator, behalve de punt. Verder worden spaties nooit gebruikt bij unaire operatoren (zoals ++ of --).
- Tussen de expressies in een for-statement.
- Na het gebruikt van typecasting.
while (true) { ... } a += c + d; a = (a + b) / (c * d); printSize(“Size is: ” + foo + “\n”);
Inspringing
Tabs
Als tab nemen we de lengte van standaard tabs of 4 spaties.
Lengte van een regel
Probeer de regels code niet langer dan 70 a 80 karakters te maken. Hiermee bevorder je het leesgemak en voorkom je problemen met bepaalde tools en terminals.
Afbreken van een regel
Wanneer je met een te lange regel code te maken krijgt dien je deze af te breken volgens de volgende regels:
- Afbreken na een komma
- Afbreken voor een operator
- De nieuwe regel dient te worden uitgelijnd met de daarbij behorende expressie van de vorige regel.
result = longName1 * (longName2 + longName3 – longName4) + 5 * longname6;
result = longName1 * (longName2 + longName3 - longName4) + 5 * longname6;
Condities en statements
If statements
Een if-else statement dient er volgt uit te zien. Gebruik alleen accolades als er meer dan één statement in het codeblok zit.if (condition) { ... } else if (condition) { ... } else { ... }
For Statements
De for-statements dienen volgens onderstaand voorbeeld geprogrammeerd te worden. Wanneer je te maken hebt met uitgebreide formules in het for-statement, probeer dan waar mogelijk de formules buiten het for-statement te gebruiken zodat het for-statement overzichtelijker wordt.for (initialization; condition; update) { ... }
While Statements
Het while-statement dient er al volgt uit te zien.while (condition) { ... }
Do-while Statements
Het do-while-statement wordt als volgt geprogrammeerd.do { ... } while (condition);
Switch Statements
Een switch-statement wordt als volgt geprogrammeerd. Wanneer je in een bepaalde case geen break-statement gebruikt moet je dit aangeven met het volgende stukje commentaar: /* falls through */ Dit plaats je op de plek waar je normaal gesproken het break-statement zou plaatsen. Iedere switch-statement moet ook een default-case hebben. Deze moet ook worden afgesloten met een break-statement.
switch (number) { case 1: ... /* falls through */ case 2: ... break; default: ... break; }
Try-catch Statements
Een try-catch statement moet op de volgende manier worden gebruikt:try { ... } catch (ExceptionClass exception) { ... }
try { ... } catch (ExceptionClass exception) { ... } finally { ... }
Object Georiënteerd Programmeren
Klassen en interfaces
Voorwaarden
Een klasse moet aan een aantal voorwaarden voldoen:
- Een correcte naamgeving (zie [#_Naming_conventions Naamgeving – Klassen en interfaces])
- Dezelfde naam hebben als z’n bestand
- Eén klasse/interface per bestand (m.b.t. overzichtelijkheid)
Commentaar
Elke klasse die gemaakt wordt moet vooraf beginnen met commentaar aan de hand van de Javadoc manier (zie [#_Commentaar Commentaar]). Aan de hand van deze commentaar kan er eenvoudig bepaald worden wie bijvoorbeeld de auteur is en wat de huidige versie is.
Voorbeeld
Bestandsnaam: DrawGraph.java/** * This class can draw a graph * * @author: P. Rogrammer * @version: 1.0 */ class DrawGraph { /** * DrawGraph constructor */ public DrawGraph() { } }
Constructors
Een Constructor dient altijd aanwezig te zijn. In het geval als er geen specifieke taken zijn voor een constructor laat deze dan leeg zoals bovenstaande voorbeeld.
Standaard heeft de Constructor een public toegankelijkheid maar dit kan in sommige gevallen ook private zijn door het gebruik van een design pattern zoals het singleton pattern
Methoden
Voor de naamgeving van een methode van een klasse zie: [#_Methoden Naamgeving - Methods]
Een klasse dient modulair opgebouwd te zijn zodat
- De code herbruikbaar (eventueel van buiten de klasse)
- Er geen dubbele code in een klasse komt (fout gevoelig)
- Een klasse overzichtelijk blijft voor onderhoudbaarheid
- De code leesbaar blijft
Let hierbij wel op dat er niet te veel ‘nutteloze’ methoden komen. Want dit kan de kans op fouten weer verhogen.
Voorbeeld:/** * This class can draw a graph * * @author: P. Rogrammer * @version: 1.0 */ Class DrawGraph { /** * DrawGraph Constructor */ public DrawGraph() { //Nothing to do } /** * Get the X as value of the graph * * @return integer */ public int getXAsValue() { return graphXValue; } /** * Set the X as value of the graph * * @param int graphXValue */ public void setXAsValue(int graphXValue) { this.graphXValue = graphXValue; }}
Variabelen benaderen
Om een variabele te benaderen dient er gebruik te worden gemaakt van zogenaamde getters en setters. Dit zijn methodes in de klasse die ervoor zorgen dat de variabelen kunnen worden bereikt. Er zijn uitzonderingen mogelijk in het geval van staticvariabelen.
Variabele voorzien van waardes
Om een waarde te zetten in een variabele moet er gebruik worden gemaakt van een ‘setter’. De variabele naam die wordt meegegeven als argument dient hetzelfde te heten als de klasse of methode z’n variabele. De variabele van de klasse of methode dient als postfix this. te hebben. Voor of na het zetten van een variabele kunnen er processen gestart worden. En vooraf, bijvoorbeeld een controle worden uitgevoerd op juistheid van informatie.
public void setVariabele(<type> <variabele>) { this.<variabele> = <variabele>; }
public void setVisitorName (string visitorName) { this.visitorName = visitorName; }
Variabele uitlezen
Om ervoor te zorgen dat de klasse de controle houdt over de variabelen dient een variabele uitgelezen te worden aan de hand van een ‘getter’.public <type> getVariabelengt() { return <variabele>; }
public string getVisitorName() { return visitorName; }
XML Coding standard
Witregels
In de XML bestanden wordt elke tag op een regel gezet. En de tag erna op de volgende regel, enz. Er zitten dus geen lege witregels tussen tags in.
Spaties
Spaties worden alleen gebruikt in de tags om attributen te scheiden en om het eerste attribuut van de tag. Als er geen attributen in de tag zitten dan zijn er ook geen spaties aanwezig.
Goed:<profile> <setting id=”setting_id” value=”value”/>
<settingid=”setting_id”/> <setting id=”setting_id” value = ”value”/>
Inspringing
Tabs
Als tab nemen we de lengte van 4 spaties. Dit is in vrijwel iedere ontwikkelomgeving in te stellen.
Geneste Elementen
Voor de leesbaarheid wordt elke regel, waar het geneste element X lagen diep ligt, vooraf gegaan aan een X aantal tabs. Dus als er 3 ‘lagen’ zijn dan worden er 3 tabs gebruikt voor het element wat wordt geplaatst.
Goed:<sports> (laag 0) <soccer> (laag 1) <soccerclub> (laag 2) <!-- ... --> (laag 3) </soccerclub> </soccer> </sports>
<sports> <soccer> <soccerclub> </soccerclub> </soccer> </sports>
Tag en attribuut namen
Hoe en welke tags en attributen gebruikt mogen worden moet zijn vastgelegd in een XSD of DTD. Hierin staat wat de elementen zijn van een XML document, waar zij voorkomen, wat de kenmerken zijn waaraan ze moeten voldoen, welke attributen zij kunnen bevatten, enzovoorts.
De naamgeving van de tags en attributen moeten zoals in veel gevallen betekenisvol zijn. Gebruik geen underscores of andere leestekens om woorden te scheiden, maar alles in kleine letters. Gebruik Engels als voertaal bij het naamgeven, omdat dit de minste beperkingen oplegt bij het vinden van geschikt personeel om je applicatie te ontwikkelen.
Goed:<profiles> <profile> <setting id=”setting_id” value=”value”/> </profile> </profiles>
<profiles> <singleProfile> <setting id=”setting_id” value=”value”/> <profileInfo> ... </profileInfo> </singleProfile> </profiles>
XML elementen sluiten
Met onderliggende lagen
Alle XML elementen met onderliggende lagen worden gesloten op dezelfde tab hoogte als dat het element geopend is. Logischerwijs moet de naam van het element wel gelijk zijn.
Zonder onderliggende lagen
Alle lege XML elementen die geen onderliggende lagen hebben worden in de openings element afgesloten. Voorafgaand aan de slash wordt geen spatie geplaatst.
Goed:<profiles> <profile> <setting id=”setting_id” value=”value”/> </profile> </profiles>
<profiles> <profile> <setting id=”setting_id” value=”value”></setting> </profile> </profiles>
Subversion
Subversion wordt gebruikt voor het versiebeheer van de applicatiecode in WOSI. Voor informatie betreffende de werking van SVN wordt doorverwezen naar de beschikbare literatuur.
Een standaard subversion repository toont drie magische mappen trunk, branches en tags. Trunk is de directory waar de main ontwikkeling plaatsvindt, de mappen branches en tags bevatten kopieën van de trunk, de kopieën in branches vind parallelle ontwikkeling plaats en in tags bevinden zich 'bevroren' kopieën.
Updaten
Zorg voordat er wijzigingen in de code gemaakt worden dat deze eerst d.m.v. updaten geactualiseerd wordt.
Comitten
Bij het committen van SVN gelden in principe dezelfde regels als voor commentaar en JavaDoc, voor zover deze toepasbaar zijn. Additionele richtlijnen:
- Commit zodra je een verandering of een bug fix werkend hebt.
- Geef in het commentaar veld precies aan wat je gewijzigd hebt.
- Controlleer altijd eerst of je aanpassingen werken, voordat je commit.
- Geef aan het nummer van het bijbehorende ticket aan (bijvoorbeeld #213) indien dit er is.
Voor meer informatie wordt doorverwezen naar:
http://www.iovene.com/5-svn-best-practices/
Controle
Kwaliteitscontroleur
De kwaliteitscontroleurs van de WOSI-projecten zijn de eindverantwoordelijken van de opgeleverde code. Deze personen dienen derhalve de code te controleren op naleving van de coding standard. Bij onvoldoende naleving moet de code worden aangepast om alsnog aan de standaard te voldoen voordat het wordt opgeleverd.
Eclipse code formatter
Als hulpmiddel bij het standaardiseren van code kan er gebruik worden gemaakt van een Eclipse code formatter instellingenbestand. In Eclipse kan dan met één druk op de knop, een heel project worden geformatteerd volgens de coding standard die in dit document is besproken. Let wel dat deze tool zich beperkt tot de regels met betrekking tot het uiterlijk van de code. Naamgeving, documentatie en andere onderdelen van de standaard zullen handmatig moeten worden nageleefd.