Namngivning i koden - Lunds Tekniska Högskola

Namngivning i koden
Möjliga konflikter och lösningar
Djupstudie inom coachning av
programvaruteam, våren 2003
Adrian Ulander
Sammanfattning
Ett problem som brukar finnas i projekt är namngivningar i koden. Olika
gruppmedlemmar ser olika på hur man “bör” namnge sina klasser, metoder och
variabler. Jag har givit mig in i denna djungel av tips och “regler” för att försöka
hitta en röd tråd som kan vara dels årets projekt till nytta, men framförallt
kommande.
Förutom att jag har att sökt information och underlag till studien från andra
projekt har jag använt den kod som har skrivits under projekten i PVG-kursen
Frågorna jag ställde mig var; Hur har årets deltagare valt att göra när de har
namngivit delar i koden? Har det uppstått några problem till följd av detta? Vilka
åtgärder fick göras? Det finns många intressanta frågor som kan ställas, varav jag
hoppas att jag har fått med de flesta.
Jag har bland annat tittat på de coding standards som finns inom Java Code
Conventions och hur man bör använda dem i namngivningssyften. Ward
Cunningham har skrivit ett flertal artiklar1 som berör namngivning inom
programmering, bland annat “System of Names” som tar upp några viktiga tips
angående namngivning. På Berkeley har Ben Liblit skrivit en intressant artikel om
the kognitiva aspekterna av namngivning.
1
inom wiki-wiki-web, en “uppfinning” där alla kan gå in och ändra i webbsidorna, medför att det
finns många medförfattare
Sida 2 av 10
Innehållsförteckning
Innehållsförteckning.....................................................................................................................................3
Inledning.........................................................................................................................................................4
Bakgrund........................................................................................................................................................4
Grundläggande kodkonventioner i Java...................................................................................................5
Vanliga problem vid namngivning.............................................................................................................5
Kort tid vid namngivning...........................................................................................................................5
Långa namn.................................................................................................................................................6
Korta namn..................................................................................................................................................6
Konsekvens.................................................................................................................................................7
Förvillande namn........................................................................................................................................7
Förkortningar..............................................................................................................................................7
Slutsats.............................................................................................................................................................9
Vidare läsning................................................................................................................................................9
Referenslista.................................................................................................................................................10
Sida 3 av 10
Inledning
Innan jag påbörjade arbetet trodde jag att det skulle vara ganska lätt att hitta regler för
hur man bör namnge sin kod. Det visade sig dock ganska snabbt att det är svårt att
göra en helt objektiv bedömning av vad som är bra och dåligt. Det finns väldigt
många olika tankar för hur man ska göra, allt ifrån de som tycker att man bör skriva
koden så enkel att man kan använda sig av enbart enbokstavsvariabler till de som vill
ha en ”kod” i namnen som beskiver vad de gör och varifrån de kommer. Jag har
därmed fått göra en egen bedömning av de regler som jag tycker passar bäst in i vår
problemdomän.
Jag har valt att koncentrera mig på vad man bör tänka på och vilka effekter
namngivning i koden har, med tyngdpunkten på Java. I vissa fall har jag även antagit
att man använder sig av XP-metodiken. Namngivningskonventionerna skiljer sig
något åt mellan olika programspråk, bland annat handlar det om hur man avgränsar
ord, men det ingår även annat. Trots detta kommer de tips som jag kommer att ge att
vara användbara de flesta programspråk.
Jag har även valt att jämföra namnbruket inom de olika projekten i kursen
ProgramVaruuveckling i Grupp (PVG)2 våren 2003. Kursen ges vid Lunds Tekniska
Högskola till andraårsstudenter som går datateknikprogrammet. Kursen har som mål
att lära ut XP-metodiken, som fortsättningskurs finns Coachning av
Programvaruteam3, den här rapporten är skriven som en djupstudie inom den senare
kursen. Projekten hade samma uppgift att lösa och bör därför ha haft liknande klasser.
Bakgrund
Programkod har ett eget språk som, naturligtvis, har vissa likheter med vårt språk.
Men det finns vissa skillnader; bland annat kan man inte använda sig av lika målande
beskrivningar av saker i programkod som man kan i vanlig text eftersom man då får
alldeles för långa och otympliga namn. Men det är även viktigt att man inte går för
långt åt andra hållet, variabler med namn som: x, anInt är tyvärr inte helt ovanliga,
men för läsbarheten av programkoden kan de vara ödesdigra.
Samma problem uppkommer dessvärre nästan varje gång, till stor del ligger det i
att programmeraren inte är uppmärksam nog samt att den har för bråttom. Bästa tipset
i sådana fall är att ta det lugnt och göra gemensamma kodgenomgångar.
2
3
EDA260, www.cs.lth.se/Education/LTH/EDA260/
Coachning av programvaruteam, www.cs.lth.se/Education/LTH/Coach/
Sida 4 av 10
Grundläggande kodkonventioner i Java
Inom Java finns det ett gediget dokument som beskriver hur koden bör se ut4, bland
annat beskrivs där hur man bör placera sina hakparanteser med mera. Det finns även
ett kort avsnitt om konventioner för namngivning. Det som tas upp är hur namnen bör
vara utformade. Konventionerna är som följer5:
Paketnamn: Prefixet ska vara en av de toppdomäner som finns enligt ISO standard.
De resterande delarna i paketnamnet kan till exempel vara avdelningsnamn,
projektnamn eller inloggningsnamn för den/de som har gjort paketet.
Exempel: se.lth.cs.jlist
Klassnamn: Namnet ska vara ett eller flera substantiv där den första bokstaven i
varje ord ska vara stor. Man bör undvika förkortningar, förutsatt att förkortningen
inte är mer använd än den längre formen (till exempel HTML). Klassnamnet
avslutas naturligtvis med .java.
Exempel: Turtle.java
Interface: Namnges med adjektiv eller substantiv. Adjektiv är användbart till
exempel om man vill beskriva beteendet på interfacet. Formatering av bokstäver
sker på samma sätt som med klasser.
Exempel: Serializable.java, Collection.java
Metoder: Metoder bör vara ett eller flera verb där den första bokstaven är liten och
den första bokstaven i de efterföljande orden stora. Det finns även exempel på fall
då det är passar med substantiv eller adjektiv istället. Substantiv där man beskriver
vad man får ut från metoden och adjektiv där man beskriver beteendet.
Exempel: moveTurtle(), top(), empty()
Variabler: Skrivs på samma sätt som metoder, dock med substantiv istället för
verb. Variabler med endast en bokstav bör undvikas, kan dock användas i
temporära sammanhang som uppräknare med mera.
Exempel: String turtleColor
Konstanter: Enbart stora bokstäver med ’_’ som avgränsare.
Exempel: int TURTLE_WIDTH
Vanliga problem vid namngivning
När man skriver ny kod finns det några problem som man ställs inför varje gång. Jag
tar här upp några av dem samt ger exempel från projektens kod.
Kort tid vid namngivning
Ett ofta uppkommande problem verkar vara att man vet vad metoden kommer att
göra, man vet vilka data som kommer att behandlas men det är svårt att sätta ett ord
på det. En metod som skapar alla objekt (paneler med mera i ett grafiskt
användargränssnitt) som kommer att användas heter i ett fall makeObjects()6. Det
är namn som visserligen speglar vad som händer i metoden men metodnamnet är
samtidigt lätt att misstolka som något man måste använda när man vill skapa objekt.
setUp() hade i mina ögon varit ett bättre namn.
Problem som ovan uppkommer gärna i samband med tidspress, tiden som läggs på
namngivning är försvinnande liten. Från att man kommer på att man kanske bör ha en
4
5
6
Java Code Conventions, www.java.sun.com/docs/codeconv/
Listan är fritt översatt från java.sun.com/docs/codeconv/html/CodeConventions.doc8.html#367
PVG2003, grupp cs0307, GUI.java
Sida 5 av 10
metod där alla objekt skapas till att man börjar skriva den är runt fem till tio
sekunder7. Namnet rotar sig snabbt och nästa gång man går över koden känns namnet
självklart. Särskilt om det är samma personer som skapade koden som går igenom
den.
Om man har regelbundna så kallade ”stand up-meetings” där man berättar vilka
nya metoder och variabler man har skapat samt vad de gör/står för, kan gruppen
gemensamt komma överens om eventuella nya namn. Det är positivt om man tidigt
gemensamt kan ändra namnet till bättre mer anpassade namn. Det bidrar dessutom till
att man sprider kunskap om koden i gruppen.
Om man tränar sig i att åstadkomma bra och informativa namn kommer det till slut
bli något som sker automatiskt. Det blir därmed inte något problem att man lägger lite
tid på namngivningen eftersom man intuitivt väljer bra namn.
Långa namn
Det finns en avvägning man måste göra mellan långa beskrivande namn och kortare
mer lätthanterliga namn. Det gäller dock inte samma principer för klassnamn som det
gör för variabelnamn.
Det finns flera fördelar med att ha väl beskrivande klassnamn. Till exempel blir det
mycket enklare för oinsatta att förstå strukturen och användningen av de olika
klasserna. Ett av kursens absolut längsta klassnamn är ContestantByStart
NumberAndCompetitionClassComparator8, detta är dock ett exempel på ett
väl långt klassnamn. Det hade förmodligen gått lika bra att beskriva vilken typ av
lopp eller sortering som komparatorn är avsedd att användas till.
Ett annat problem som långa namn medför är att de inte får plats på raden, särskilt
om man är långt inne i ”if-while-for”-kombinationer (nästlade satser).
Korta namn
Det finns tillfällen då man tillåts använda mycket korta namn (läs: enbokstavsnamn) i
koden. Det är när man ska göra en loop och behöver ett index (rekommenderade
bokstäver är; i, j och k), förutsättningen är att man använder indexet enbart i sin
loop, måste man använda den även utanför finns risken att man snabbt glömmer bort
vad den egentligen är.
Om iterationsindexet har en högre mening, till exempel om det betyder olika typer
av motorcyklar bör man däremot välja ett beskrivande namn för det. I ett exemplet
skulle mcType eller MCType (beroende på hur man vill förkorta motorcykel).
Ett bra tips från wiki-wiki-web är att man kan välja sina temporära
enbokstavsvariabler namn som; xx, jj och så vidare9. På sådant sätt är det enkelt att
göra en så kallad ”search-and-replace” då man upptäckter att ett bättre namn behövs.
Risken finns naturligtvis att man är för lat för att upptäcka det.
Det är lätt att välja namn som x, test eller temp när man testar ny kod. Tyvärr är
risken ganska stor att man ”glömmer” att ändra dem till bättre namn då man har fått
rätt på koden. Slutsatsen är att man bör välja vettiga namn redan från början, då
minskar risken att man glömmer kvar dåliga namn till noll.
Exempel på korta namn finns det massvis av i projekten, men framförallt används
de som index i loopar och är därför motiverade.
7
8
9
enligt muntlig undersökning i projektgruppen samt bland bekanta
PVG2003, grupp cs0301,
ContestantByStartNumberAndCompetitionClassComparator.java
www.c2.com/cgi/wiki?SystemOfNames – jgsack
Sida 6 av 10
Konsekvens
Om man har en klass som heter till exempel ContestantList bör man kunna anta att
den uppför sig som en lista. Om det inte är en lista bör den ha ett annat namn. Är det
en lista bör dess metoder för att lägga till och ta ut element vara namngivna och ge
samma resultat som för en generell lista.
Är det en lista för deltagare är det förmodligen bara deltagare som man kommer att
lägga in i listan (kommer man att lägga in annat ska den ha ett annat namn), alltså är
det inte nödvändigt att kalla metoden för att lägga in saker i listan för
addContestant, add bör kunna fungera lika bra.
På samma sätt bör man inte använda olika ord för samma sak. Kallas något som
används för att ta saker ur en lista fetch i en klass ska det inte heta retrive i
någon annan, förutsatt att interfacet är lika.
Förvillande namn
Ward Cunningham skriver att ”människor gör ofta antagningar baserat enbart på
objektnamnen”, det visar hur viktigt det är att klassnamnen verkligen speglar klassens
innehåll och användningsområde.
Ett exempel från wiki-wiki-web är metoden runTests() som fanns i tidiga
JUnit-paket10. Det är lätt att tro att metoden användes för att köra test, men i själva
verket är det en metod som ger antalet körda test. Känslan förstärks av att det i en
klass finns en metod för antalet testfall, countTestCases(). Författaren som tar
upp exemplet ger flera exempel på bättre namn, ett är testsRunCount()11 (jag
hade föredragit countTestsRun() för att vara konsekvent med den tidigare
nämnda metoden).
I senare versioner har man bytt ut namnet mot det mer passande runCount(),
tyvärr har man fortfarande kvar namnet för antalet testfall och man har därmed inte en
konsekvent namngivning.
Från projekten finns det exempel på när detta misslyckas, jämför klassnamnen
Time och RealTime12. Båda klasserna återfinns i samma projekt, den första
hanterar tider (beräknar skillnad mellan två tider med mera) och den andra används
för att få aktuell tid. Namnet RealTime får åtminstone mig att tänka på
realtidstillämpningar, man skulle dessutom kunna tro att RealTime är en superklass
till Time men så är ju absolut inte fallet. I en annan grupps projekt (två grupper
faktiskt) finns klassen TimeStamp13, den klassen klarar samma saker som Time och
RealTime tillsammans, namnet ger dessutom något klarare information av vad den
ska användas till.
Förkortningar
I Javas code conventions nämns att man bör undvika förkortningar förutsatt att
förkortningen inte är mer använd än det förkortade namnet. Problemet med
förkortningar är att de i vissa fall kan vara högst personliga. Till exempel skulle
förkortningen FTR inte uppenbart vara en förkortning för FinishTimeRegistrator.
Ett följdproblem som förkortningar kan ge är problem med uttal. Krångliga
bokstavskombinationer blir omöjliga att uttala på ett bra sätt, de blir därmed svåra att
diskutera. Att ha egenpåhittade förkortningar talar dessutom emot att ha beskrivande
lättförståeliga namn.
Det här är viktigare att tänka på att undvika förkortningar när man namnger klasser
10
11
12
13
JUnit 2.1, www.sourceforge.net/projects/junit/, TestResult.java
www.c2.com/cgi/wiki?SystemOfNames – Dave Whipp
PVG2003, grupp cs0301, Time.java respektive Realtime.java
PVG2003, grupp cs0302 och cs0304, TimeStamp.java
Sida 7 av 10
och metoder än när man namnger variabler. Att använda nbrOfContestants
istället för numberOfContestants är nästan att rekommendera. Däremot är
nbrOfCont förmodligen att ta det hela lite för långt.
Sida 8 av 10
Slutsats
Jag skrev tidigare att jag trodde att det skulle vara lätt att hitta en standard för hur man
ska namnge. Jag trodde även att det skulle vara lätt att hitta fel och brister i projektens
kod. Det har däremot visat sig att kodkvaliteten, åtminstone vad det gäller namnen, är
ganska bra.
Fortfarande finns det många tips och idéer som man kan ta till sig. Inte minst när
det gäller Ward Cunninghams ord om klassnamn. Många av felen är lätta att rätta till,
såvida det gäller variabel och metodnamn. Har man misslyckats med ett klassnamn är
risken större att det hänger kvar, särskilt om man använder sig av CVS. Detta
eftersom det är, förvisso inte svårt, men omständligt att byta namn i ett CVS-system.
Efter det här arbetet kommer jag att ta med mig mer uppmärksamhet in i
kommande projekt rörande namngivning. Många av de saker jag har tagit upp har mer
eller mindre redan varit kända. Men jag har framförallt fått upp ögonen för vikten av
att man gemensamt kommer överens om en ”namngivningspolicy” samt vikten av
träning.
Jag kommer nog dessutom att vara mer uppmärksam och dessutom genomföra
förändringar då jag ser dåliga namn. Redan i slutet av projektet har jag upptäckt att
jag mer ofta har lagt märke till och påpekat dåliga namn.
Som coach av ett XP-team kan det tänkvärt att komma ihåg vikten av att hålla
koden i bra skick. Att ha det som en kontinuerlig rutin att diskutera de namn som man
har valt och kommer att välja kan man minska antalet kostsamma missförstånd.
Vidare läsning
Jag rekommenderar starkt den litteratur som finns i referenslistan. Framförallt anser
jag att Ottingers artikel ger många klara tips och idéer. På olika wiki-wiki-webs14
hittar man bra diskussioner om namngivning där man kan få mycket inspiration, men
det som framförallt kommer fram där är att det finns många olika uppfattningar.
Det som Ward Cunningham (med flera) har skrivit ger en bra överblick, man får
även många exempel på bra och dåliga namn. Det är även därifrån jag har hittat
många av mina exempel.
Ben Liblits artikel är mer åt det teoretiska hållet och tar främst upp hur och varför
programmerare väljer sina namn så som de gör (eller borde göra). Han hittar bland
annat en koppling mellan vår grammatik och grammatiken för program.
14
Ward Cunninghams är tveklöst den jag har haft mest nytta av, www.c2.com
Sida 9 av 10
Referenslista
Cunningham med flera, System of Names, www.c2.com/cgi/wiki?SystemOfNames
Cunningham med flera, System Metaphor, www.c2.com/cgi/wiki?SystemMetaphor
Fowler, Refactoring: Improving the Design of Existing Code, Addison-Wesley, 2000
Jeffries, Anderson, Hendrickson, Extreme Programming Installed, Addison-Wesley,
2001
Liblit, Speaking in Code: Cognetive Perspectives on the Role of Naming in Computer
Programs, www.cs.berkeley.edu/~liblit/naming/naming.pdf, 2001
Ottinger, Rules for Variable and Class Naming,
www.objectmonitor.com/resources/articles/naming.htm
Java Code Conventions, www.java.sun.com/docs/codeconv/
Sida 10 av 10