Ohjelmistokehityksen periaatteet ovat joukko erityisiä sääntöjä ja suosituksia, joita insinöörien tulisi noudattaa ohjelman toteutuksen aikana, jos he haluavat kirjoittaa kaunista, selkeää ja ylläpidettävää koodia. Ei ole olemassa taikasauvaa, joka voisi muuttaa muuttujien, luokkien ja funktioiden sekamelskaa täydelliseksi koodiksi, mutta on olemassa muutamia vinkkejä ja vihjeitä, jotka voivat auttaa insinööriä määrittämään, tekeekö hän oikein.
Katsotaanpa näitä perussuosituksia. Osa alla olevista periaatteista on Python-kohtaisia, mutta suurin osa ei.
Mittele kahdesti ja leikkaa kerran
Se on mielestäni kaikkein tärkein periaate. Jos opit tästä postauksesta vain yhden periaatteen, sen pitäisi olla tämä. Me, kehittäjät/arkkitehdit/johtajat ihmiset kamppailemme huomion puutteen, typerien virheiden ja painovirheiden, henkilökohtaisten ongelmien, huonon mielialan ja kylmän kahvin kanssa. Mikään näistä ei ole merkityksellistä – ongelma on ratkaistava. Minulle insinöörinä tämä periaate tarkoittaa oikean ratkaisun valitsemista ongelmaan, oikean lähestymistavan valitsemista ongelmaan, oikeiden työkalujen valitsemista ongelman ratkaisemiseen, luottamusta rakennettuun ratkaisuun. Valinta tarkoittaa tässä yhteydessä harkintaa, tarvittavien resurssien löytämistä, oikean tiimin kokoamista, suunnittelun miettimistä, lähestymistavan miettimistä, tehtävien asettamista, tuloksen valvomista ja vastuun kantamista siitä. Tämä on ”suunnittelua sellaisenaan”. Luulen, etten itse ole valmis kuvaamaan sitä oikeilla sanoilla.
Don’t Repeat Yourself (DRY)
Se on melko yksinkertainen mutta erittäin hyödyllinen periaate, joka sanoo, että saman asian toistaminen eri paikoissa on huono idea. Ensinnäkin se liittyy koodin jatkotuen ja muokkaamisen tarpeellisuuteen. Jos jokin koodinpätkä toistetaan useassa paikassa ohjelman sisällä, on suuri todennäköisyys kahteen katastrofaaliseen tilanteeseen:
- Tehdessäsi pieniäkin muutoksia lähdekoodiin joudut muuttamaan samaa koodia useassa paikassa. Se vaatii ylimääräistä aikaa, vaivaa ja huomiota(usein se ei ole helppoa).
- Ensimmäinen kohta seuraa toista. Sinä tai joku muu kehittäjä tiimistäsi saattaa vahingossa jättää yhden muutoksen tekemättä(se voi tapahtua yksinkertaisesti yhdistämällä haaroja vcs:ssä) ja kohdata myöhemmin sovelluksessa esiintyviä virheitä. Nämä bugit voivat olla sinulle turhauttavia, koska olet kuullut, että kyseinen bugi on jo korjattu.
Tältä osin on olemassa suositus – jos jokin koodi esiintyy listauksessa useammin kuin kaksi kertaa, se tulisi sijoittaa erilliseen tapaan. Tämä on yleinen suositus. Itse asiassa kannattaa miettiä erillisen metodin luomista, vaikka toistoon törmäisi toisenkin kerran.
Occamin partaveitsi
Se on hyvin yleinen ajatus, joka on tullut ohjelmointiin filosofiasta. Periaate sai nimensä englantilaiselta munkilta William of Oakhamilta. Tämä periaate sanoo: ”Entiteettejä ei saa monistaa ilman tarvetta”. Insinööritieteissä tämä periaate tulkitaan seuraavasti: tarpeettomia entiteettejä ei ole syytä luoda ilman välttämättömyyttä. On siis aina hyvä miettiä ensin, mitä hyötyä toisen menetelmän/luokan/työkalun/prosessin jne. lisäämisestä on. Loppujen lopuksi, jos lisäät toisen menetelmän/luokan/työkalun/prosessin jne. ja et saa mitään muuta hyötyä kuin lisääntyneen monimutkaisuuden, mitä järkeä siinä on?
Keep It Simple Stupid (KISS)
Tämä periaate on hyvin samankaltainen kuin edellä mainittu periaate, mutta sillä on hieman erilainen merkitys. Tämä periaate sanoo, että koodin on oltava mahdollisimman yksinkertaista ilman monimutkaisia rakenteita, muuten se vaikeuttaa koodin virheenkorjausta ja ylläpitoa. Lisäksi toisen ohjelmoijan on vaikeampi ymmärtää koodin logiikkaa, mikä puolestaan vaatii myös ylimääräistä aikaa ja vaivaa. Siksi kannattaa aina pyrkiä käyttämään yksinkertaisia konstruktioita, jotka ratkaisevat ongelman mahdollisimman hyvin ilman lukuisia haaroja, syvää sisäkkäisyyttä ja liian ylikuormitettuja luokkarakenteita. Tekemällä näin helpotat itsesi ja kollegojesi elämää, sillä monimutkaisuus synnyttää virheitä. Muista, mitä Peter Hintiens sanoi: ”Yksinkertaisuus on aina parempi kuin toiminnallisuus.”
You Aren’t Gonna Need It (YAGNI)
Ongelma, josta monet ohjelmoijat kärsivät. Halu toteuttaa kerralla kaikki tarvittava (ja joskus jopa tarpeeton) toiminnallisuus heti projektin alussa. Eli kun kehittäjä lisää kaikki mahdolliset metodit luokkaan heti alusta alkaen ja toteuttaa ne, eikä välttämättä edes käytä niitä koskaan tulevaisuudessa. Tämän suosituksen mukaan kannattaa siis ensin toteuttaa vain se, mitä tarvitaan, ja myöhemmin tarvittaessa laajentaa toiminnallisuutta. Näin säästät vaivaa, aikaa ja hermoja sellaisen koodin debuggaamiseen, jota ei oikeasti tarvita.
Suuri suunnittelu etukäteen
Ennen kuin ryhdyt kehittämään toiminnallisuutta, mieti ensin sovellusarkkitehtuuri ja suunnittele koko järjestelmä riittävän pieniin yksityiskohtiin asti ja siirry vasta sen jälkeen toteutukseen ennalta laaditun suunnitelman mukaisesti. Periaatteella on olemassaolonsa oikeus, mutta viime aikoina sitä kohtaan on esitetty aika paljon kritiikkiä. Se liittyy ennen kaikkea suunnitelman vanhentumiseen suunnittelun ja työstämisen aikana. Tässä yhteydessä on tarpeen tehdä vielä myöhempiä muutoksia. Mutta sillä on myös kiistattomia etuja, oikeassa suunnittelussa on mahdollista vähentää huomattavasti virheiden korjaamisesta ja korjaamisesta aiheutuvia kustannuksia. Lisäksi tällaiset tietojärjestelmät ovat pääsääntöisesti lakonisempia ja arkkitehtonisesti oikeampia.
Vältä ennenaikaista optimointia
”Ennenaikainen optimointi on kaiken pahan (tai ainakin suurimman osan siitä) alku ja juuri ohjelmoinnissa.” – Donald Knuth
Optimointi on erittäin oikea ja tarpeellinen prosessi, jolla voidaan nopeuttaa ohjelmaa sekä vähentää järjestelmäresurssien käyttöä. Mutta kaikella on oma aikansa. Jos optimointi tehdään kehityksen alkuvaiheessa, siitä voi olla enemmän haittaa kuin hyötyä. Ensinnäkin se liittyy siihen, että optimoidun koodin kehittäminen vaatii enemmän aikaa ja vaivaa kehittämiseen ja tukeen. Tällöin joudutaan melko usein tarkistamaan aluksi valitun kehitystavan oikeellisuus. Siksi on aluksi kannattavampaa käyttää yksinkertaista mutta ei kaikkein optimaalisinta lähestymistapaa. Ja myöhemmin, kun arvioidaan, kuinka paljon tämä lähestymistapa hidastaa sovelluksen työtä, siirrytään nopeampaan tai vähemmän resursseja vaativaan algoritmiin. Lisäksi niin kauan kuin aluksi toteutetaan optimaalisin algoritmi, vaatimukset voivat muuttua ja koodi menee roskiin. Aikaa ei siis kannata tuhlata ennenaikaiseen optimointiin.
Principle Of Least Astonishment
Tämä periaate tarkoittaa, että koodisi tulisi olla intuitiivista ja itsestään selvää, eikä se saisi yllättää toista kehittäjää koodia tarkistettaessa. Jos esimerkiksi metodin nimi on ”keksien tekeminen”, mutta tuloksena saadaan perunoita, koodi on huono (ilmeisesti). Lisäksi pitäisi yrittää välttää sivuvaikutuksia ja dokumentoida ne, jos niitä ei voi välttää.
S.O.L.I.D.
”SOLID” on itse asiassa joukko oliopohjaisia suunnitteluperiaatteita. Jokainen kirjain ”SOLIDissa” edustaa yhtä näistä periaatteista, jotka ovat:
- Yksittäinen vastuu tarkoittaa, että jokaisella moduulilla tai luokalla tulisi olla vastuu vain yhdestä osasta ohjelmiston tarjoamaa toiminnallisuutta, ja tämän vastuun tulisi olla kokonaan luokan kapseloima;
- Avoin-suljettu tarkoittaa, että ohjelmiston kokonaisuuksien (luokkien, moduulien, funktioiden jne.) pitäisi olla avoimia laajennuksille, mutta suljettuja muutoksille;
- Liskovin substituutio sanoo, että perittävän luokan pitäisi täydentää, ei korvata, perusluokan käyttäytymistä;
- Rajapintojen erottelu sanoo, että yhtään asiakasta ei pitäisi pakottaa riippuvaiseksi metodeista, joita se ei käytä;
- Riippuvuuden käänteistäminen sanoo, että ohjelmoijan pitäisi työskennellä rajapintatasolla eikä toteutustiedostotasolla.
Kun näitä periaatteita sovelletaan yhdessä, ne auttavat kehittäjää luomaan koodia, jota on helppo ylläpitää ja laajentaa ajan mittaan.
Demeterin laki
Tämän periaatteen perusidea on jakaa vastuualueet luokkien kesken ja kapseloida logiikka luokkaan, metodiin tai rakenteeseen. Tästä periaatteesta voidaan erottaa useita suosituksia:
- Luokkien tai entiteettien tulisi olla riippumattomia
- Tulee pyrkiä vähentämään eri luokkien välisten yhteyksien määrää (ns. coupling).
- Kytkettyjen luokkien tulee olla yhdessä moduulissa/paketissa/hakemistossa (tunnetaan myös nimellä koheesio).
Näiden periaatteiden noudattaminen tekee sovelluksesta joustavamman, ymmärrettävämmän ja helpommin ylläpidettävän.
Johtopäätös
Kehittäjäkollegat, olkaamme insinöörejä! Ajatelkaamme suunnittelua ja rakentakaamme vankkoja ja hyvin toteutettuja järjestelmiä sen sijaan, että kasvatamme orgaanisia hirviöitä. Luetellut periaatteet korreloivat vahvasti keskenään ja liittyvät olennaisesti toisiinsa. En tietenkään luonut niitä, mutta pieni muistutus ei haittaa, ainakaan minun muistini ei varmasti ole täydellinen.
Suositeltavat kirjat
- Clean Code by Robert C. Martin
- Clean Architecture by Robert C. Martin