Haiseeko koodi?
Kirjoittanut J-P Julkaistu 19.3.2009
Jokaiselle koodarille lienee tuttu termi spagettikoodi. Termillä viitataan koodareiden keskuudessa ohjelmakoodiin, joka on epäselvää, vaikeasti ymmärrettävää ja erityisen vaikeaa ylläpitää.
Spagettikoodia sisältävä järjestelmä voi toimia oikein, mutta muutosten tekeminen järjestelmään on kohtuuttoman työlästä ja jo ajatuskin koodiin koskemisesta saa hien valumaan koodarin otsalta. Usein spagettikoodi aiheuttaa myös epämääräisiä bugeja joiden alkuperäistä syytä kukaan ei oikeastaan tiedä. Itse väitän, että kaikki ohjelmointityötä tekevät ihmiset tuottavat spagettikoodia ainakin joskus. Milloin on liian kiire tehdä kerralla hyvää ohjelmakoodia, milloin vaatimukset muuttuvat ja aiheuttavat jatkuvia koodimuutoksia jne. tekosyitä on monia.
Kun koodisi on spagettia voidaan myös sanoa, että koodi haisee pahalle. Mistä on kyse kun puhutaan haisevasta koodista? Kent Beck ja Marting Fowler esittelivät termin Fowlerin kirjassa Refactoring, Improving the Design Of Existing Code.
Paha haju on merkki siitä, että ohjelmakoodissasi on mahdollisesti jotain vikaa ja siihen olisi syytä kiinnittää huomiota. Monet kokeneet ohjelmoijat tunnistavat huonoja koodirakenteita intuitiivisesti. Paha haju antaa intuitiolle ja sen aiheuttajille nimet niin, että muutkin kuin vain alansa huiput voivat löytää ohjelmakoodista ongelmallisia kohtia. Kuten useimmissa ongelmissa, ongelman myöntäminen on ensimmäinen askel parantumiseen. Ongelma on tunnistettava, jotta se se voidaan korjata.
Seuraavissa luvuissa olen lyhyesti kuvannut muutaman hajun, joita itse pidän tärkeinä tai yleisinä. Löytyykö omasta ohjelmakoodistasi tällasia elementtejä? Jos löytyy, niin suosittelen vakaasti tarkastelemaan omaa koodiasi kriittisesti ja refaktoroimaan sitä parempaan suuntaan.
Toistuva koodi ja toistuvat metodit
Mitä ohjelmointiin tulee, copy-paste -tekniikka on kaiken pahan alku ja juuri. Jos useissa metodeissa, luokissa tai koodilohkoissa tehdään toistuvasti samoja asioita voi koodin ylläpitäminen muodostua isoksi ongelmaksi. Ei riitä, että korjaamme virheen yhdessä paikassa, korjaus on kopiotava joka paikkaan missä on toistuvaa koodia.
Neuvoni onkin. Älä käytä copy-paste -tekniikkaa ohjelmoinnissa. Jos sinusta tuntuu siltä, että se on ainoa mahdollisuus edetä, pysähdy miettimään asiaa hetkeksi. Eikö varmasti ole mitään keinoa tehdä metodia, luokkaa tms. koodilohkoa, jota voitaisiin kutsua lohkon kopioinnin sijasta?
Jos uudelleenkäytettävän koodilohkon kirjoittaminen kopioinnin sijasta vaikuttaa hitaammalta tehtävältä muista, että koodia täytyy myös ylläpitää. Uudelleenkäytettävän koodilohkon kirjoittaminen on lähes aina hitaampaa kuin koodin kopiointi, mutta se säästää moninkertaisesti aikaa ohjelman ylläpito vaiheessa. Viiden minuutin lisätyö nyt voi säästää sinut tuntien lisätyöltä myöhemmin. Uusiokäyttöisten metodien ja luokkien käyttäminen on myös nopeampaa kuin vielä uusien kopioiden tekeminen.
Ylipitkät metodit
Hyvä metodi on lyhyt metodi. Ylipitkien metodien lukeminen ja niiden sisällön ja toiminnallisuuden hahmottaminen voi olla välillä hyvinkin haastavaa. Tietokoneelle pitkien metodien lukeminen ei ole ongelma. Ihmiselle se voi sitä olla. Käytännössä olen huomannut, että pitkien metodien välttäminen auttaa minua kirjoittamaan itse itseään selittävää ohjelmakoodia, jolloin tarve kuvata ohjelman toimintalogiikkaa koodikommentein vähenee. Kun jaamme pitkät metodit useammaksi pieneksi lisäämme koodilohkojen uudelleenkäytön mahdollisuuksia ja voimme kertoa jo metodin nimillä mitä koodimme tekee.
Mikä sitten on liian pitkä metodi? Parhainpana peukalosääntönä olen itse pitänyt ruudun mittaa. Tämä nyt tietysti riippuu paljon käyttämästäsi näytön resoluutiosta ja fonttikoosta, mutta antaa jonkinlaisen kuvan asiasta. Jos metodi on merkittävästi pidempi kuin mitä näytöltä voidaan kerralla lukea kannattaa harkita sen pilkkomista pienempiin osiin.
Onko olemassa liian lyhyitä metodeja? Ei. Itse pidän perusteltuna jopa yhden rivin metodeja, jos metodilla (ja sen nimeämisellä) voidaan selkeyttää koodin toimintaa ja lisätä uudelleen käyttöä.
Taikanumerot ja -merkkijonot
Taikanumerot ja -merkkijonot ovat hieno nimi asialle, joka ilmenee kaikille koodareille tutussa ominaisuudessa kovakoodauksessa. Taikanumeroilla- ja merkkijonoilla viitataan koodissa oleviin numeriisiin tai tekstuaalisiin arvoihin joiden merkitys ei käy selväksi. Mitä esimerkiksi tarkoittaa arvo 0 seuraavassa koodinpätkässä? Miksi käytämme arvoa 0 emmekkä esimerkiksi arvoa 12?
String columnName = getNameFor(0);
Taikanumerot ja -merkkijonot ovat alttiita kirjoitusvirheille ja hankaloittavat ohjelmakoodin ymmärtämistä merkittävästi. Taiat onkin syytä korvata vakiolla tai joissain tilanteissa enumeraatioilla. Tämä tekee ohjelmakoodista huomattavasti selkeämpää ja vähentää kirjoitusvirheiden mahdollisuuksia.
String columnName = getNameFor(OLETUS_VALINTA);
Ohjelmalogiikan kommentointi
Ohjelmalogiikan kommentointi on ehkä yksi niistä pahoista hajuista, joka selkeimmin jakaa mielipiteitä. Kommenttienhan pitäisi olla hyvä asia ja tässä minä nyt väitän, että kommentit haisevat pahalle. En kuitenkaan väitä, että kaikki kommentointi on pahasta. Kommentti väärässä paikassa tai metodin sisäistä toimintaa selittävä kommentointi ovat vahvoja indikaatiota siitä, että koodissa on jotain vialla.
private void process() { for(int i=0;i<nc;i++) { String s = getS(i); System.out.println((i+1)+") "+s); } }
Luokkien, muuttujien ja metodien nimet pitäisi valita siten, että koodi on ymmärrettävää ilman ylimääräisiä kommetteja. Rajapinnan kommentointi on hyvä ja välttämätön asia. Tämä tarkoittaa sitä, että Java-koodari kirjoittaa javadoc-kommentteja, joissa kerrotaan mitä metodi/luokka tekee. Sen sijaan metodin sisällä olevat kommentit joissa kerrotaan miten tuo asia tehdään, ovat vahva indikaatio siitä, että metodi pitäisi paloa pienempiin kokonaisuuksiin, muuttujat pitäisi nimetä uudelleen tai tehdä jotain muuta mikä auttaa ymmärtämään miten koodi tehtävänsä suorittaa. Koodin pitäisi siis olla itse itseään selittävää.
private void printColumnNames() { for(int columnIndex=0; columnIndex<numberOfColumns; columnIndex++) { String columnName = getColumnNameFor(columnIndex); int columnOrderNumber=columnIndex+1; System.out.println(columnOrderNumber+") "+ columnName); } }
Lisää pahoja hajuja sekä apua niiden vähentämiseen Comian kurssilta Suunnittelumallit ja refaktorointi.



