Java`s kodkonventioner och arbete i grupp

Java's kodkonventioner och arbete i grupp
Anders Hagsten
Lunds tekniska högskola
[email protected]
2005-02-13
Sammanfattning
Denna djupstudie handlar om faktorerna som ger tydlig och lättläst
kod och hur namngivningen påverkar detta. Med utgångspunkt från Java's
kodkonventioner behandlas vanligt förekommande namngivningsproblem
som till exempel för långa eller intetsägande namn. Konventionernas funktion i att lösa problem när man arbetar i grupp studeras även närmare.
Innehåll
1 Inledning
3
2 Konventioner
3
2.1
Syftet med konventioner . . . . . . . . . . . . . . . . . . . . . . .
3
2.2
Kort om Javas kodkonventioner . . . . . . . . . . . . . . . . . . .
3
3 Ofta förekommande namngivningsproblem
4
3.1
Magiska nummer . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2
Långa namn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
5
3.3
Korta namn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
3.4
Förkortningar . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
3.5
Intetsägande namn . . . . . . . . . . . . . . . . . . . . . . . . . .
6
3.6
Vilseledande klassnamn
3.7
Felstavade namn
. . . . . . . . . . . . . . . . . . . . . . .
6
. . . . . . . . . . . . . . . . . . . . . . . . . . .
7
4 Utvecklingsplattformen Eclipse
7
5 Projekterfarenheter
7
5.1
Allmänt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
5.2
De vanligaste problemen . . . . . . . . . . . . . . . . . . . . . . .
8
6 Slutsatser
8
7 Vidare undersökningar
8
2
1
Inledning
Namngivning är något som alltför ofta ställer till förtret. Det många glömmer
bort är att när man namnger något medför detta också förväntningar på funktionen hos detta. När man arbetar själv fungerar det bra att döpa saker efter
eget tyckte men när man arbetar i grupp måste mer eftertanke nnas. Detta på
grund av att alla i gruppen inte pratar samma språk.
Precis som i matematiken kan man i kod skriva en sak på era olika sätt men
med samma resultat. Här kommer kodkonventioner in i bilden för att avgöra
vilket sätt som är bäst. I denna rapport tar jag upp syftet med konventioner
och vanliga problem som uppstår när man arbetar i grupp. Jag har valt att utgå
från Java's kodkonventioner då detta är mitt primära språk.
2
Konventioner
2.1
Syftet med konventioner
Fördelarna med att ha konventioner för namngivning, formatering och hur man
skriver den faktiska koden är många. Det som kan vara lätt att glömma, när man
programmerar, är att någon i framtiden faktiskt ska underhålla koden genom
att till exempel lägga till ny funktionalitet. Har den som skrivit koden då valt
att följa givna konventioner underlättas underhållsarbetet. Det är helt enkelt
lättare att sätta sig in i koden då den följer en vedertagen standard. För företag
är detta extremt viktigt då 80% av livstidskostnaden för mjukvaran utgörs av
underhållsarbete. Vidare är det så att anställda tenderar att byta jobb ibland
eller företaget omorganiseras. Det gör att personen som skrev koden från början
inte alltid nns tillgänglig för att förklara den. Faktum är att det mycket sällan
är personen som skrev programmet som underhåller det.
2.2
Kort om Javas kodkonventioner
Företaget bakom Java, Sun Microsystems, tillhandahåller på sin hemsida Javas
kodkonventioner [1]. Detta dokument specicerar allt från metodernas längd till
hur man bör namnge sina variabler. Nedan presenteras de viktigare poängerna
i dokumentet:
• Formatering:
Undvik rader längre än 80 tecken. Detta för att många
program har svårt att hantera längre rader. Ett exempel på detta är pro-
AT Xsom denna text formaterats av. Vidare anges att metoder
grammet L
E
ej bör vara över 150 rader och hela Java-ler ej bör överstiga 2000 rader.
• Klassnamn:
Klassnamn ska alltid vara ett, eller en kombination, av sub-
stantiv. Samtliga substantiv i klassens namn ska ha stor bokstav.
Exempel:
ResultGenerator.java
• Gränssnitt:
Gränssnitt ska, precis som klassnamn, vara en kombination
av substantiv samt börja med stor bokstav. Javas kodkonventioner ger
inga riktlinjer om hur de bör namnges men om man tittar i Javas API
ser man att de ofta namges med adjektiv eller substantiv. Adjektiv har
fördelen att de ger en indikation på beteendet hos gränssnittet.
Exempel:
Observer.java, Adjustable.java
3
• Metodnamn:
Metodnamn ska innehålla verb för att tala om vad man
gör och gärna kombineras med substantiv eller adjektiv för att tydliggöra
metodens eekt på objektet. Första bokstaven i metodnamnet ska alltid
vara gemen och efterföljande inre ord ska börja med en versal.
Exempel:
printCompetitionData(), isEmpty(), getDriver()
• Variabler:
Variabelnamn skrivs på samma sätt som metodnamn. Pro-
grammerare som skolats i andra programspråk bör vara medvetna om att
variabelnamn som börjar med _ och $ ej, enligt konvention, bör användas men ändå tillåts. Variabelnamn bör vara korta men ändå meningsfulla och indikera användningsområdet. Korta namn som exempelvis i
bör undvikas utom när de används tillfälligt inuti en metod som räknare
eller dylikt.
Exempel:
int startNumber, ArrayList startTimes
• Konstanter:
Konstanter skrivs med versaler och om konstantens namn
består av era ord separeras dessa med _.
Exempel:
3
static final int MAX_SIZE = 4
Ofta förekommande namngivningsproblem
När man studerar kodexempel nns det fall som är ofta förekommande. Dessa
fall kommer vi titta närmare på här.
3.1
Magiska nummer
Magiska nummer [3] är tal som bara dyker upp från ingenstans och används i
koden. Siror som 1, -1, 0 och 2 anses inte vara magiska då användandet
av dessa är vida spritt. Exempel:
class Physics {
}
/**
* This method calculates the length contraction of an object.
* @param v - the velocity of the object.
* @param l - the length of the object.
* @return The length as experienced by the observer.
*/
public double lengthContraction(double v, double l) {
double ratio = (v * v) / (299792458 * 299792458);
double obsL = l * Math.sqrt(1- ratio);
return obsL;
}
Exemplet ovan är väldigt enkelt men visar ändå på hur otydligt det blir med
magiska nummer. Det fungerar felfritt men det blir svårt att läsa. När programmet sedan ska underhållas kommer det med största sannolikhet ställa till
problem för de som ska göra det. Tilldela istället en konstant detta värde och
skriv på följande sätt:
4
class Physics {
/* Speed of light in vacuum (m/s) */
public static final int SPEED_OF_LIGHT = 299792458;
}
/**
* This method calculates the length contraction of an object.
* @param v - the velocity of the object.
* @param l - the length of the object.
* @return The length as experienced by the observer.
*/
public double lengthContraction(double v, double l) {
double ratio = (v * v) / (SPEED_OF_LIGHT * SPEED_OF_LIGHT);
double obsL = l * Math.sqrt(1 - ratio);
return obsL;
}
Detta är mycket tydligare, mer lättanvänt och om man, mot förmodan, skulle
vilja ändra ljusets hastighet i vakuum behöver man bara göra det på ett ställe.
3.2
Långa namn
Långa namn är en eekt av att man vill vara övertydlig i metoden, klassens eller
variabelns funktion. Fördelarna med detta är att man eventuellt inte behöver
läsa dokumentationen utan det inses direkt vad den gör. Nackdelarna är dock
era, exempelvis får eventuellt inte anropen plats på .java-lens rader om man
ska följa kodkonventionerna på max 80 tecken på en rad. Vidare blir de arbetsamma att skriva om man skriver i en lättare editor utan komplettering och
därmed ökas risken för slarvfel. Ytterligare ett problem är att långa beskrivande
namn begränsar möjligheterna att lägga till ny funktionalitet utan att döpa om
klassen och därför medför extra arbete.
Ett exempel på långt namn är
ResultGeneratorSortedResultWithPlaceNumbers
som jag lånat från projektet jag just nu coachar. Detta är ett exempel på övertydlig namngivning som resulterar i långa namn. Mycket av det som inkluderas
i namnet borde stå i dokumentationen för klassen. Detta problem påtalades och
klassens namn ändrades till
ResultGeneratorByRank som ger samma intryck
men på ett tydligare sätt.
3.3
Korta namn
Korta namn såsom i, j och c bör, enligt Java's kodkonventioner, endast användas som temporära variabler inne i metoder. I t.ex forloopar är det närmast
konvention att man döper första loop-variabeln till i och sen om det nns en
inre loop döper den till j och så vidare. Problemet är att programmerare har
lätt att döpa sina variabler till temp eller liknande när de testar fram nya
lösningar för att sedan glömma ändra dem till förklarande namn.
Exempel:
public String giggleLoop(int nbrGiggles) {
String temp = "";
5
for (int i = 0; i<nbrGiggles; i++) {
temp += "giggle";
}
return temp;
}
Ovan är ett exempel på hur det ofta ser ut. Programmeraren har förstått att
han behöver en sträng att bearbeta men inte brytt sig om att ändra det när
metoden sedan färdigställts. Nedan visas resultatet efter namnbyte.
public String giggleLoop(int nbrGiggles) {
String giggleSequence = "";
for (int i = 0; i<nbrGiggles; i++) {
giggleSequence += "giggle ";
}
return giggleSequence;
}
Trots att detta exempel är väldigt trivialt ser man redan här att det blir mer
lättläst. Detta kan härledas till att namnet temp används ofta och i olika sammanhang vilket gör det svårt att förstå betydelsen i varje fall utan att verkligen
kontrollera.
3.4
Förkortningar
Förkortningar bör inte användas om inte förkortningen är mer använd än or-
getURL() med
getUniversalResourceLocator(). I vissa, dock ofta förekommande, fall är det
det och det därmed blir tydligare med dem. Jämför till exempel
mer frågan om att nna ett gemensamt språk än att använda förkortningar eller
ej. I vårt projekt fanns en variabel som höll reda på startnumret för en förare.
Denna variabel hade till en början inte mindre än tre namn: nbr, startnum-
1 get- och set-
ber och startNbr. Dessa hade den erhållit från handskrivna
metoder. Detta upptäcktes emellertid snart och ändrades till startNumber. Det
hela berodde på att programmerare med olika stil skrivit metoderna för att
hämta och sätta variabeln.
3.5
Intetsägande namn
I vårt projekt skrev vi en datastruktur för de tävlande för att sedan kunna bearbeta dem på olika sätt, t.ex sortera och visa alla som inte kom i mål. Problemet
var att denna namngavs till DataStructure. Detta namn talar bara om vad vi
redan vet, nämligen att det är en datastruktur. Det talar inte om på något sätt
hur klassen kan användas och gav ingen indikation på vilken sorts information
man ck ut. Klassens namn byttes senare ut mot DriverList som säger mycket
mer om form och funktion.
3.6
Vilseledande klassnamn
Det första som möter programmeraren när han ska använda en klass är klassnamnet. Klassnamnet ger ett initialt tips till programmeraren om hur den kan
1 Eclipse
kan automatgenerera så kallade getters och setters utifrån ett variabelnamn.
6
användas. Det är därför viktigt att namngivandet inte är vilseledande, t.ex om
vi hade döpt DriverList ovan till DriverTable ger det ett helt annat intryck om
klassens funktion för programmeraren.
3.7
Felstavade namn
När man programmerar skriver man oftast på engelska och då detta inte är vårt
modersmål kan ibland mindre problem uppstå på grund av detta. De esta är
dock medvetna om sina begränsningar när det gäller stavning på det engelska
språket och väljer därför att hellre hitta en synonym än att riskera att stava fel.
Något konkret exempel från vårt projekt lyckades jag inte nna så jag har konstruerat ett:
competitionType
och
raceType.
Detta är typiskt en omskrivning
som sker om man är osäker på stavning. De betyder, i princip, samma sak men
kräver olika ansträngning att stava. Det största problemet med felstavade namn
är att kompileringsfelen blir väldigt svåra att hitta i koden. Vi tenderar att inte
upptäcka stavfel om vi inte letar efter dem [4].
4
Utvecklingsplattformen Eclipse
De projekt som vi genomför använder sig av Eclipse som utvecklingsverktyg.
Eclipse är bra då layoutdelarna från Java's kodkonventioner i stort sett är implementerade i textformateringen som det använder sig av. Vid skapande av
klasser får man en varning av programmet om man använder sig av liten bokstav och det formaterar koden med hjälp av några enkla knapptryckningar.
Några missar nns ändå där, exempelvis när man namnger metoder får man
ingen varning om dessa skulle ha stor bokstav och detsamma gäller för variabelnamn. Stödet för namnbyte är exemplariskt, med refektoriseringsverktyget
kan man byta till exempel ett metodnamn och samtidigt döpa om alla anrop
till denna, något som kan ta lång tid i en vanlig text-editor så som Emacs.
5
5.1
Projekterfarenheter
Allmänt
I början av ett projekt är det bra att fastställa vilka konventioner som skall
råda. I vårt projekt bestämde vi under första mötet att Java's kodkonventioner
skulle gälla samt att alla skulle fräscha upp minnet genom att läsa dessa. Detta
gav oss en slags lagstiftning inom projektet. Under projektets gång kunde vi
sedan lösa många dispyter med hjälp av dessa, till exempel hur man skriver
if-satser eller vilket som är det bästa namnet på en klass. Att ha en lag att
hänvisa till gjorde vår styrande roll enklare. En annan eekt som märktes av
var att deltagarna, allt eftersom projektet fortlöpte, blev mycket mer medvetna
om namngivningens betydelse. Detta beror med stor säkerhet på att de aldrig
tidigare behövt arbeta med ett program under så lång tid och under ständiga
förändringar i kravspecikationen.
7
5.2
De vanligaste problemen
Under vårt projekt uppstod merparten av de problem som nns beskrivna i kapitel 3 men vissa var mer frekventa, exempelvis korta och långa namn. Problemet
med korta namn uppstod i början av projektet då arbetssättet och stressfaktorn var helt ny för deltagarna. Detta var första gången de skrev kod som inte
bara skulle fungera utan även vara läsbar. Jag tog upp problemet med de korta namnen under ett planeringsmöte och ck bra respons från deltagarna, de
hade också märkt att det ställde till problem. Eekten blev att det gick från
en extrem till en annan och vi ck väldigt långa namn som talade om exakt
var och hur det namngivna användes. De långa namnen var bra att ha under
utvecklingsfasen men när projektet började röra sig mot sitt slut fann vi att
deras roll var utspelad och namnen refaktoriserades till kortare versioner.
6
Slutsatser
Namngivning utan konvention fungerar så länge man arbetar i små grupper på
mjukvara som inte skall underhållas men så fort utvecklingen sker i större grupp
blir namngivningen kritisk. Dåliga namn för med sig kostsamma misstag som
kunde sparat både tid och pengar om några extra minuter lagts på namngivning.
Det har visat sig smidigt att tidigt i ett projekt välja en konvention som skall
gälla då det ger en lagstiftning åt projektet. Dispyter kan lösas snabbare när
man har en lag att hänvisa till istället för att dras in i ändlösa diskussioner.
Slutligen bör sägas att Java's kodkonventioner inte har lösningen på alla
namngivningsproblem utan det måste nnas en dialog inom projektgruppen.
7
Vidare undersökningar
För den som vill utforska namngivning och dess inverkan vid projektarbete ges
här ett par förslag för vidare undersökningar:
• Hur man får alla deltagare att följa konventionen
När man arbetar i större grupper är det ofelbart så att någon har en egen
konvention som denne anser är bättre. Hur styr man gruppen så att alla
följer samma konvention?
• Genomför ett projekt utan kodkonventioner
Undersök vilka konsekvenser ett projekt utan kodkonvention ger. Detta
kan vara svårt att göra under rådande kursformer då den endast är åtta
veckor lång men ändå väldigt intressant.
• Vilka roller har verktygen i hur väl kodkonventioner åtlyds
Eclipse, som används vid våra projekt, innehåller verktyg som xar till
de mindre delarna av Java's kodkonventioner, exempelvis 80 tecken på en
rad och stor bokstav på klassnamnet. Vad händer om exempelvis Emacs
istället används och hur väl kommer konventionerna att åtföljas?
• Skriv antipatterns för namngivning
Roedy Green tar i sin text How to Write Unmaintainable Code upp
en rad av vad man kan kalla antipatterns och då bland annat vad gäller
8
namngivning. Green är dock inte så tydlig i sitt framställande av dessa.
Använd Greens text för att nna tydligare antipatterns som kan vara till
nytta för andra som går kursen.
9
Referenser
[1] Scott Hommel.
Java Code Conventions
http://java.sun.com/docs/codeconv/CodeConventions.pdf
[2] Cunningham med era.
System of Names
http://www.c2.com/cgi/wiki?SystemOfNames
[3] Edward Parrish.
Document and Organize Java Code
http://www.edparrish.com/cs12/04f/codedoc.php#ovw
[4] Roedy Green
How to Write Unmaintainable Code
http://mindprod.com/unmain.html
10