(toiminnot)

hwechtla-tl: Mitä on elegantti koodi?

Kierre.png

Mikä on WikiWiki?
nettipäiväkirja
koko wiki (etsi)
viime muutokset


(nettipäiväkirja 09.02.2016) Olen nähnyt viime aikoina useiden koodereiden kirjoittavan, että heidän mielestään hyvä koodi on eleganttia ja että he haluavat kirjoittaa eleganttia koodia. Olen jotenkin onnellinen, että tämä näkökulma on pinnalla, mutta täytyy silti sanoa, että elegantti on aika huonosti määritelty sana eikä oikeastaan ohjaa koodin kirjoittamista yhtään mihinkään. Elegantti tarkoittaa "näppärää, tyylikästä, hienoa". Miksi kukaan haluaisi kirjoittaa epäeleganttia koodia? Lähinnä sanan arvo on siinä, että se korostaa, että koodin ei pidä olla vain toimivaa vaan myös kaunista. Mutta eikö kauneus ole katsojan silmässä?

Olen kiistellyt paljon eri koodereiden kanssa siitä, mikä oikeastaan on kaunista. Koodin tyylikkyydessä on sama ongelma kuin käytöstavoissa. Yhden kulttuurin (vaikkapa brasilialaisen yläluokan) sisällä kasvaneen on vaikea nähdä, että hänen omaksumansa käytöstavat eivät ole kaikkien näkökulmasta hyvää käytöstä; samoin yhden koodauskulttuurin (vaikkapa Lisp-kulttuurin) sisällä kasvaneen on vaikea nähdä, että hänelle päivänkirkas koodi on jollekulle muulle esoteerista, epäkäytännöllistä tai rumaa. On tietysti taito sinänsä osata vaihtaa kulttuuriaan ja viestiä tavalla, joka tuntuu mukavalta vastaanottajista - oli sitten kyse koodista tai käytöksestä. Mutta käytöstavoissa on tietty kova ydin, joka on hyvää käytöstä lähes kulttuurista riippumatta: ole kiinnostunut, ole iloinen, näytä pitäväsi muista, kuuntele ja yritä ymmärtää, älä tuomitse. Ja haluaisin samaan tapaan puolustaa kantaa, että oikeasti on myös olemassa kulttuuririippumattomasti eleganttia koodia.

Kuten käytöstavoissa, ei koodissakaan voi jättää kaikkia kulttuurillisia näkökohtia ottamatta huomioon. Jos kirjoittaa Python-koodereille, ei yksinkertaisesti voi olettaa, että monimutkainen listakeräelmä avautuisi kaikille. Mutta kuten käytöstavoissa, pitää pyrkiä myös universaalisti tyylikkääseen koodiin - koodiin, joka on kaunista ja helppolukuista vastaanottajan kulttuurista riippumatta. Mitä tämä kulttuuririippumattomasti elegantti koodi oikein on? Minulla on eleganssille kolme tärkeää mittaria, joita olen valmis puolustamaan. Elegantti koodi on:

  1. oikein nimettyä,
  2. yksinkertaista ja
  3. lyhyttä.

Näistä mittareista viimeinen, lyhyys, on tärkein, vähiten ymmärretty ja sen suhteesta koodereiden tuottavuuteen on kaikkein eniten empiiristä todistusaineistoa. Koodi on sitä parempaa, mitä lyhyempää se on (kunhan ei murskaa täysin eleganssin kulttuuririippuvaisia odotuksia). Tämä on minulle tärkeä väite, jonka ilosanomaa yritän levittää. Palaan siihen tuonnempana. Tarkastellaan ensin, mitä nämä kaikki mittarit tarkoittavat.

Oikein nimetty koodi on sellaista, jossa jokainen muuttuja nimeää hyvin sen, mitä se sisältää, ja jokainen funktio/aliohjelma/metodi nimeää hyvin sen, mitä palauttaa tai aiheuttaa. Lisäksi oliometodologiassa jokainen luokka ja rajapinta nimeää asian, jota se edustaa kuvitteellisessa todellisuudessa, mutta tämä ei ole niin olennaista. Tämä ei ole puhtaasti mitattava asia, koska se riippuu muun muassa koodin lukijan tulkintakyvystä ja kulttuurista, mutta hyvä testi on se, että luettuaan funktion nimen ohjelmoijan pitäisi suunnilleen pystyä arvaamaan, mitä se ottaa syötteekseen, ja luettuaan funktion nimen ja sen syötteiden nimet ohjelmoijan pitäisi suunnilleen pystyä arvaamaan, mitä funktio tuottaa tuloksekseen milläkin syötteillä. Katso funktio ja elegantti nimeämismalli.

Yksinkertainen koodi on sellaista, jonka voi lukea helposti ja nopeasti alusta loppuun niin, että saa järkevän kuvan siitä, mitä kyseinen pätkä koodista tekee. Yksinkertaisuudelle on erilaisia mittareita, kuten syklomaattinen kompleksisuus, funktioiden pituus (hyvä maksimipituus funktiolle on 7 riviä), sekä esim. tilamuutosten, funktioiden, olioiden ja invarianttien riippuvuuksista muodostettujen dependenssiverkkojen konnektiivisuus ja syklien määrä ja koko. Näistä on jonkin verran tutkimustietoa, mutta hajanaisesti. Yksinkertainen koodi, melkein millä tahansa yllä olevista mitattuna, on nopeampaa lukea ja helpompaa muokata rikkomatta. Jos koodi on yksinkertaista, muuttujien ei tarvitse olla edes oikein nimettyjä. Jos muuttujan määrittelyn saa aina pari riviä ennen käyttö(j)ä, ei muuttujan nimen tarvitse olla kovin kuvaava.

Lyhyt koodi on ihan oikeasti vain lyhyttä. Siinä on siis vähemmän merkkejä kuin pitkässä koodissa. Hyvä koodi on lyhyttä: jos vaikkapa säännöllisten lausekkeiden käyttö lyhentää koodia, niin se parantaa sitä. Säännöllisten lausekkeiden, kuten muidenkin näppärien apukeinojen, vaara on siinä, jos joku kehittäjä ei ymmärrä niitä. Mitä osaamattomampiin kehittäjiin haluat varautua, sitä huonompaa koodia joudut kirjoittamaan.

Lyhyt koodi on nopeampaa lukea, ihan fysiologisista syistä. Tämä koskee sekä rivien pituutta että määrää. On tutkimusnäyttöä siitä, että jos koodin toiminnan tajutakseen pitää lukea enemmän kuin yksi näytöllinen koodia, lukeminen hidastuu rankasti. Vielä enemmän on näyttöä siitä, että koodaajat tuottavat koodia samaa merkkitahtia riippumatta siitä, kuinka paljon koodi tekee. Tämä pätee kielten välillä ja kielten sisällä: mitä pidempi ohjelma on, sitä kauemmin sen tekeminen kestää. Niinpä koodaajien tuottavuus on sitä parempi, mitä lyhyemmin he koodinsa kirjoittavat ja pystyvät kirjoittamaan, ja jokainen suunnitteluperiaate, joka lisää koodin pituutta, on lähtökohtaisesti haitallinen.

Kun puhutaan koodin ylläpidosta, on tietysti tärkeintä, että koodin ymmärtää. Silti myös kirjoitettaessa korjauksia koodiin ymmärtämisen jälkeen koodaukseen kuluva aika riippuu uuden koodin määrästä. Mitä vähemmän koodia oli, sitä vähemmän sitä tarvitsee muuttaa. Lyhyys auttaa ymmärtämisessäkin, koska isomman osan koodia pystyy hahmottamaan kerralla, ja koska lyhyys kulkee käsi kädessä yksinkertaisuuden kanssa.

Koodin lyhyys on erityisen hyvä mittari, koska sille on alaraja. Tiettyä toiminnallisuutta ei voi saada aikaan mielivaltaisen lyhyellä koodilla (pituuden alarajaa kutsutaan lopputuloksen "Kolmogorov-kompleksisuudeksi"). Vastaavaa ylärajaa ei ole: koodia voi aina pidentää ilman, että sen toimintatapa muuttuu.

fooza: "Eikös noilla perusteilla Perlin onlinerien pitäisi olla ylläpidettävyyden huippua..."

atehwa: Lyhyt vastaus: onhan ne, jos jättää huomiotta muut kriteerit kuin lyhyyden. Eli siis yksinkertaisuuskriteerit ja kulttuurilliset kriteerit.

Jos ollaan siinä kulttuurissa, jonka jäsenet osaavat lukea Perlin onelinereita, niin äkkiseltään väittäisin, että ne ovat varsin ylläpidettäviä. Nehän ovat tyypillisesti jonkinlaisia tekstimuunnoksia, jotka lukevat vakiosyötettä ja tulostavat vakiotulosteeseen. Niiden sopimus on suhteellisen selkeä, testaaminen helppoa ja ne tekevät tyypillisesti sen verran yksinkertaisen asian, että niiden korvaaminen kokonaan toisella koodilla ei ole ylitsepääsemätön vaiva. Tekstimuunnos, joka on faktoroitu moneksi perättäiseksi, putkilla yhdistetyksi onelineriksi on ylläpidettävissä sekä päivittämällä näitä onelinereita (jos osaa Perliä) tai korvaamalla niitä yksi kerrallaan muulla koodilla (jos ei osaa).

Mielenkiintoista kyllä, vaikka Perlissä on kaikenlaisia oikoteitä ja koodinlyhennyskeinoja, oman kokemukseni mukaan jollain funktionaalisella kielellä kirjoitettu koodi on itse asiassa usein lyhyempää jos tarvitaan esim. tietorakenteita tai mitään muuta monimutkaisempaa. Jos taas ei tarvita, vastaava sed-oneliner on usein lyhyempi (ja aivan yhtä kryptinen muista kulttuureista tulleille). Se, että Perl-kielellä on korkeahko oppimiskynnys, tietysti vaikuttaa ylläpidettävyyteen siinä mielessä, että potentiaalisia ylläpitäjiä (siis Perl-osaajia) on vähemmän. Käytännössä mikään tutkimus ei kuitenkaan kartoita sitä, kuinka paljon tästä kielten suosittuudesta (ja sen vaikutuksesta potentiaalisten ylläpitäjien määrään) on kielen vika ja kuinka paljon historiallisten sattumien / markkinoinnin /muun.


kommentoi (viimeksi muutettu 14.06.2016 09:13)