Programkode har ikke alltid samme struktur som kjørende kode. Det kan være dynamisk kode som blir generert, malverksfiler som kompileres, konfigurasjon som hentes inn fra flere kilder som kan overstyres under kjøring.
CSS og Javascript er også programmeringsspråk og bør behandles således.
Kode kjører i forskjellige miljøer, enten det er på en web-server, i en virtuell maskin, en applikasjonsserver, i nettleseren eller instruksjoner som dynamisk bygges opp og sendes til eksekveringsmotorer som gjør en jobb og sender ferdig prosessert data tilbake. Det kan være preprosessorer som ved kompilering skriver om deler av programkoden.
Dette er noe å tenke på når man strukturerer opp prosjektet i kataloger og filer.
Forskjellige programmeringsspråk krever forskjellige strategier
Noe man kanskje ikke tenker så mye på mens man forsøker å konfigurere opp prosjektet til å kjøre Java-testene eller kompilere C-fila, er at en løsning ofte består av flere enn ett programmeringspråk. Om man utvikler web-løsninger er CSS og Javascript blitt en selvfølge. CSS og Javascript er programmeringsspråk og bør behandles således.
Javascript er et nesten like gammelt språk som Java, men det er først de siste årene at tradisjelle utviklere har fått øynene opp for hva som er mulig med Javascript. Desto mer man gjør i Javascript desto større er behovet for å teste funksjonaliteten. Det er fullt mulig å kjøre automatiserte enhetstester mot Javascript-kode, og det finnes verktøy for å detektere typiske feil og påpeke klassiske fallgruver. Det finnes også verktøy for å minifisere Javascript slik at filene blir mindre og legger mindre beslag på båndbredden til brukerne av systemet, og ikke minst like viktig er at det kan spare kostnader ved å senke krav til båndbredde fra systemet. Tilsvarende finnes det verktøy for CSS som minifiserer filene og som kan analysere filene og detektere ineffektive regler og duplikate regler som aldri inntreffer.
Retningslinjer
Mange programmeringsspråk har anbefalinger til hvordan programkode skal struktureres. Om systemet som skal lages hovedsaklig skal skrives i ett programmeringsspråk kan man følge dette språkets retningslinjer. I retningslinjene defineres gjerne hva en typisk fil skal inneholde, navngiving, indentering, kontrollkode, feilhåndtering, hvordan filene plasseres i en katalogstruktur og mye annet. Perl-prosjekter struktureres ofte etter CPAN sine retningslinjer, PHP-prosjekter struktureres ofte etter PEAR sine retningslinjer og Java har sine retningslinjer.
En by bygger seg ikke selv. Foto: Flickr/Science Museum London (CC)
Det har de siste årene blitt populært å bruke Maven som kontrollsystem for prosjekter, spesielt for Java-prosjekter, men kan også brukes til andre programmeringsspråk som PHP og Javascript. Man bruker gjerne Maven som en innpakking av prosjektet, til bygging av systemet, kjøre tester, pakketere og rulle ut nye versjoner. Det legger ingen føringer for hvordan man strukturerer innholdet av filer i prosjektet.
Det er ingen fasit når det kommer til struktur av prosjekter, men dersom man er flere som arbeider på samme prosjekt kan det være smart å bli enige om hvilke retningslinjer man skal følge.
Ikke all kode er programkode
Tester skal støtte oppunder løsningen og gi en god og stabil leveranse.
Den viktigste delen av løsningen er det kjørbare systemet, og det er dette som skal gi merverdi til bedriften. Dokumentasjon, tester, byggerammeverk og utviklingsmiljø er biprodukter; støttefunksjoner som skal bidra til å gi et godt og kjørende system.
Maven brukes, som nevnt ovenfor, gjerne til bygging av løsningen og til å kjøre opp web-server under utvikling, men Maven er ikke en del av det kjørbare systemet i leveransen.
Tester, som enhetstester og funksjonstester, er ikke programkode og trenger ikke behandles som det. Tester skal støtte oppunder løsningen og gi en god og stabil leveranse. Tester bør holdes utenfor katalogstrukturen til programkoden. Det kan være løsere retningslinjer til testene, for eksempel friere navngiving av tester, ingen maksimal linjelengde eller flatere katalogstruktur.
Testene dine er viktige fordet!
En god test er en verifikator om at en funksjon fungerer. En god test er presis på hva den tester og er lett å lese og forstå.
En god praksis er å navngi testene etter hva de tester. Et eksempel kan være en test som skal teste at en kunde som heter “Ola” har adresse “Drammensveien”, og denne testen kan da hete test_kunden_ola_har_adresse_drammensveien
, selv om dette ikke stemmer overens med for eksempel Java’s camelcase.
En testfunksjon skal teste en ting, og kun én ting. Du trenger ikke å teste at du har korrekt brukernavn og passord i konfigurasjonen for hver eneste test du skriver. Hvis navnet på testen indikerer at en brukers adresse skal kontrolleres så skal testen gjøre det, og lite annet. Samme testen kan gjerne teste forskjellig input dersom det virker hensiktsmessig. For eksempel kan en e-postadresse-validator kontrollere flere godkjente e-postadresser, men kanskje bør det være en egen testfunksjon for verdier som skal feile valideringen.
Samhandling med andre arkitekturprinsipper
Det er mulig å kombinere struktur på utviklingsmiljøet med andre arkitekturvalg. For enkle web-løsninger er trelagsarkitekturen MVC (model-view-controller) populær, hvor man skiller applikasjonslogikk fra datamodell og presentasjon, og man kan plasserer filer i en katalog navngitt etter laget hvor de hører hjemme.
Hvis prosjektet setter domenedrevet design høyt så kan det være smart å segmentere ut filene som utgjør domenemodellene i egne kataloger, for å holde domenet samlet uten for mye støy fra annen kode.
En felles hverdag
Det er smart å ha orden i prosjektet sitt. Kildekoden til prosjektet kan sees på som skrivebordet ditt; hvis det er vanskelig å finne det du leter etter så er ikke arbeidsmiljøet optimalt. I et prosjekt med mange utviklere betyr dette at alle deler “felles skrivebord”. Å sette retningslinjer som alle i prosjektgruppen enes om å følge kan bidra til en ryddigere hverdag for alle, men retningslinjene bør ikke blir detaljerende og vanskelige å følge. Alle skal føle seg komfortable med disse.
Det er en felles hverdag. En god struktur bidrar til raskere utvikling, enklere feilsøking, og etterhvert til bedre kode med færre feil.