Programmering - workshop
Programmeringsspråk inneholder presise, utvetydige instruksjoner for hva en datamaskinen skal gjøre, samt hvordan maskinen skal reagere på ulike hendelser som måtte oppstå under kjøringen av programmet. Foto fra en workshop i programmering, 2017.
Av /TT/NTB.

Programmering er innen IT å beskrive en serie instruksjoner som må utføres for å oppnå et bestemt resultat. Instruksjonene må gis i et egnet språk som den eller de som skal utføre dem forstår. I dataprogrammer skrives instruksjonene i et programmeringsspråk som kan tolkes av datamaskinen. Instruksjonene, også kalt kildekoden, inneholder presise, utvetydige instruksjoner for hva datamaskinen skal gjøre, samt hvordan maskinen skal reagere på ulike hendelser som måtte oppstå under kjøringen av programmet.

Faktaboks

Uttale
programmˈering
Også kjent som

programutvikling, utvikling, koding

Fagfelt og ferdigheter

Programmering er et eget fagfelt med tilhørende utdannelsestilbud på universiteter og høgskoler verden over.

Selve ordet «programmering» er et vidt begrep som rommer alt fra å programmere et vaskeprogram på en vaskemaskin, til å skrive komplekse dataprogrammer for finansielle systemer eller kunstig intelligens. Når vi innstiller en vaskemaskin på 60 °C, velger forvask, ekstra skylling og sentrifugeringshastighet på 1400 omdreininger per minutt, programmerer vi vaskemaskinen til å utføre det vaskeprogrammet vi ønsker.

Å programmere en datamaskin er i prinsippet det samme: vi gir datamaskinen detaljerte instruksjoner for hvordan den skal utføre en konkret oppgave. Men jo større og mer kompleks oppgaven som skal utføres er, desto mer kreves det av både kunnskap og ferdigheter fra programmererens side. For å kunne kommunisere med datamaskinen må vi skrive instruksjonene i et språk som datamaskinen er konstruert til å forstå. Det krever at vi behersker et programmeringsspråk som er egnet for oppgaven. Videre må vi ha grundig innsikt i oppgaven som skal utføres og forstå problemet som skal løses, slik at vi er i stand til å beskrive løsningen i detalj, instruksjon for instruksjon. Er oppgaven stor, vil det være nødvendig å dele programmet inn i mindre deler, såkalte moduler, der hver modul løser sin del av oppgaven.

Som programmerer er det imidlertid ikke nok å kunne programmere. Skal dataprogrammet fungere etter hensikten, må vi vite hvordan det skal brukes og ikke minst hvem som skal bruke det.

Programmeringsspråk

Programmeringsspråket Python
Python er et programmeringsspråk beregnet på utvikling av verktøy og applikasjoner (dataprogram og apper).
Programmeringsspråket Python
Av /Shutterstock.

Datamaskinen forstår kun digital maskinkode, det vil si sekvenser av nuller og enere. I teorien lar det seg gjøre å programmere i maskinkode, men i praksis vil være umulig å holde oversikt over hva programmet gjør. Maskinkode er derfor ikke egnet til å lage reelle dataprogrammer.

Av denne grunn er det utviklet høynivå programmeringsspråk, som Java, C++, C#, Python og PHP. Disse ligger nærmere det menneskelige språk, og er dermed lettere å skrive instruksjoner i. Datamaskinen, som kun forstår maskinkode, kan imidlertid ikke utføre høynivå kildekode direkte. Kildekoden må først oversettes til maskinkode. Dette gjøres ved hjelp av et eget oversettelsesprogram, en såkalt kompilator. Først når kildekoden er kompilert (oversatt), kan datamaskinen utføre programmet.

Det finnes mange ulike programmeringsspråk. Den mest utbredte typen er de objektorienterte språkene som Java, C# og C++. Her er kildekoden organisert i logiske enheter, såkalte klasser og objekter, ikke ulikt slik vi oppfatter virkeligheten rundt oss.

Språkets oppbygging

Et programmeringsspråk kan sammenlignes med det engelske språket ved at de består av et gitt antall definerte engelske ord, såkalte nøkkelord, i tillegg til spesielle symboler, tall og tegn. Men mens det engelske språket består av over 170 000 ulike ord, er antall nøkkelord i et høynivå programmeringsspråk sjeldent mer enn et tosifret antall.

Når vi programmerer må vi imidlertid navngi alle enheter som vi oppretter (variabler, konstanter, metoder og klasser) slik at de kan identifiseres. Her står vi fritt til selv å lage nye ord. Velger vi ord som beskriver hva enheten inneholder eller gjør, vil det være lettere for andre mennesker å lese kildekoden, og dermed forstå programmet.

Syntaks

I likhet med menneskelige språk må setningene vi skriver i et programmeringsspråk følge språkets «grammatikalske» regler. Reglene kalles for språkets syntaks. Skal kompilatoren kunne oversette kildekoden til maskinkode, må de syntaktiske reglene følges til punkt og prikke. Ingen feil tolereres! Først når alle syntaktiske feil er rettet, kan kompilatoren oversette programmet til maskinkode slik at datamaskinen kan utføre det.

Grunnleggende elementer i et programmeringsspråk

Programmering krever solide kunnskaper og ferdigheter i programmeringsspråket dataprogrammet skal skrives i. Skal programmereren lykkes, er det imidlertid ikke nok å kjenne til språkets syntaktiske regler. Vi må også forstå hvordan maskinen tolker instruksjonene vi skriver. Forstår vi det, vil vi kunne følge programkontrollen og derved sikre oss at datamaskinen utfører det vi ønsker at den skal gjøre.

Tilordningssetningen

Tilordningssetninger
Først opprettes tre lagerenheter x, y og z. Deretter tilordnes x verdien 10 og y verdien 5. I siste instruksjon blir verdiene som inngår i regnestykket på høyresiden av "=" hentet fra lagerenhetene x og y (10 og 5), og summen (15) blir så lagret i lagerenheten z.
Tilordningssetninger
Lisens: CC BY SA 3.0

Den såkalte tilordningssetningen er selve grunnsteinen i all databehandling. Den brukes til å lagre verdier, samt flytte verdier fra én lagerenhet til en annen. I mange programmeringsspråk er symbolet tilordning det samme som likhetstegnet (=) vi kjenner fra matematikken. Betydningen er imidlertid en annen. Instruksjonen

x = 2;

fører til at tallet 2 blir lagret i lagerenheten med navn x. Vi sier at x tilordnes verdien 2. Instruksjonen

z = 2 + 3;

fører til at lagerenheten med navn z tilordnes summen av verdiene på høyresiden av likhetstegnet, i dette tilfellet verdien 5. På høyresiden må det stå en konkret verdi, eller et uttrykk som, når maskinen har evaluert det, resulterer i en konkret verdi. På venstresiden må det stå en lagerenhet som er egnet til å lagre verdien på høyresiden. Datamaskinen utfører alltid høyresiden av tilordningssetningen først, for så å lagre verdien i lagerenheten på venstresiden.

Datatyper

Datatyper

I programmeringsspråket Java brukes vanligvis datatypen int for lagring av heltall, double for lagring av desimaltall og String for lagring av tekst. Figuren viser opprettelse av tre variabler, tall, vekt og setning, som får henholdsvis startverdiene 1, 1.2 og teksten «Hva er programmering?». Konstanten PI er en desimalkonstant som får verdien 3.14159.

Datatyper
Lisens: CC BY SA 3.0

Dataverdiene vi lagrer i en datamaskin kodes forskjellig og krever ulik plass, alt etter hvilken type verdier det er snakk om. Eksempelvis lagres heltall annerledes enn desimaltall og tekst. Når vi skal løse en programmeringsoppgave må vi først skaffe oss oversikt over hvilke dataverdier vi har behov for å lagre. Deretter oppretter vi lagerenheter som er egnet til å lagre verdiene, det vil si lagerenheter av tilhørende datatyper. Hvis vi ønsker at en lagerenhet skal kunne endre verdi i løpet av programmet, oppretter vi en såkalt variabel. Hvis ikke, kan vi opprette en konstant, der verdien vi lagrer vil forbli den samme gjennom hele programmet.

Datastrukturer

Skal vi behandle store mengder data, er det lite hensiktsmessig å lagre dem som enkeltvariabler. Da er det mer effektivt å samle lagerenhetene i ulike former for strukturer, som tabeller, lister eller grafer. I en tabell, et såkalt array, er dataene lagret sekvensielt etter hverandre, der hver enkelt lagerenhet er gitt en indeks. Første element har indeks 0, mens siste element har indeks tabellens lengde minus en. Hva slags datastruktur vi bør velge, avhenger av hvilke operasjoner vi har behov for å utføre. En tabell er for eksempel veldig godt egnet for oppslag av verdier, men skal vi stadig sette inn eller fjerne elementer, kan det være hensiktsmessig å velge en dynamisk datastruktur, for eksempel en liste.

Eksempel:

Java-instruksjonen

int tall[] = new int[10];

oppretter et array med 10 lagerenheter, tall[0], tall[1], tall[2], ... , tall[9], som hver kan lagre et heltall.

Kontrollstrukturer

Iterasjon

Eksempel på en while-løkke som summerer de ti første tallene, skrevet i programmeringsspråket Java.

Iterasjon
Lisens: CC BY SA 3.0
Valgsetning
Eksempel på en valgsetning i programmeringsspråket Java.
Valgsetning
Lisens: CC BY SA 3.0

Skriver vi instruksjonene sekvensielt etter hverandre, vil datamaskinen utføre dem i den rekkefølge de står, og programmet vil oppføre seg likt hver gang det kjøres. Vil vi at programmet skal utføre forskjellige ting, avhengig av hendelser som skjer under kjøringen, kan vi legge inn logiske betingelser. En logisk betingelse er enten sann eller usann, og gir oss mulighet til å foreta valg. Hvis en betingelse er oppfylt, det vil si sann, gjør vi én ting, hvis ikke, lar vi være å gjøre det, eller gjør noe annet i stedet.

Ved hjelp av betingelsene kan vi endre rekkefølgen instruksjonene utføres i, og derved få mulighet til å styre programkontrollens vei gjennom koden. Lar vi sannhetsverdiene avhenge av input fra brukeren av programmet, for eksempel via mus, berøringsskjerm eller tastatur, vil brukeren kunne påvirke programutførelsen.

De logiske betingelsene gir opphav til to hovedtyper av kontrollstrukturer:

  • Valgsetninger: Valg av ett av flere alternativer, avhengig av hvilke betingelser som er oppfylt. Valgsetningene kalles ofte if-setninger, if-else-setninger eller switch-case-setninger.
  • Repetisjonssetninger/iterasjoner/løkker: Repetisjon av én eller flere instruksjoner så lenge en betingelse er sann, slik at de samme instruksjonene kan utføres mange ganger. Også her finnes det flere typer, som while -setninger, do-while-setninger og for -setninger.

Ved å kombinere valgsetninger og repetisjonssetninger på forskjellige måter kan vi lage ulike algoritmer.

Metoder

Metode
Metode som sorterer tallene i en tabell i stigende rekkefølge, skrevet i programmeringsspråket Java.
Metode
Lisens: CC BY SA 3.0

Det kreves gjerne mange instruksjoner for å utføre én enkelt oppgave. Er dette en oppgave som skal utføres flere ganger i løpet av programmet, vil det være hensiktsmessig å samle instruksjonene som en navngitt enhet. Vi kan samle instruksjonene i en metode (også kalt funksjon, subrutine eller prosedyre), og gi metoden et navn som beskriver hva instruksjonene utfører.

Definisjonen av metoden gir kun en beskrivelse av de instruksjonene som metoden kan utføre. For at de skal bli utført, må vi foreta et såkalt metodekall, der vi ved hjelp av metodens navn, «kaller» den. Metodekallet fører til at programkontrollen flyttes til metoden, og når metodens instruksjoner er utført, returnerer programkontrollen til kallstedet, det vil si til det stedet i programmet metodekallet sto. Hvis metoden trenger data den selv ikke har for å utføre sin oppgave, kan vi la metoden ha parametere. Disse er lokale variabler som mottar og lagrer verdiene som sendes med i kallet.

Ofte vil metodens oppgave være å beregne en konkret verdi. I så fall lar vi metoden ha en returverdi som, etter at metoden er utført, blir plassert på kallstedet, det vil si det stedet i koden der kallet på metoden står.

Definering av metoder er viktig for oppbygningen av et dataprogram. Ved hjelp av dem får vi mulighet til å utføre de samme instruksjonene om og om igjen, når og hvor vi måtte ønske det.

Klasser og objekter

En av de mest utbredte typene programmeringsspråk er de objektorienterte programmeringsspråkene. Her er data og metoder samlet i logiske enheter, såkalte objekter, ikke ulikt slik vi oppfatter verden rundt oss.

Hvis vi for eksempel skal lage et dataprogram for et bibliotek, vil det være naturlig å samle data knyttet til hver enkelt bok i separate objekter. Hvert Bok-objekt kan for eksempel inneholde informasjon som bokens tittel, forfatter, sjanger, antall sider, isbn-kode og så videre. I tillegg trenger objektet metoder som gjør operasjoner på dataene, slik at vi kan nyttiggjøre oss av dem, som å lese, endre og slette dem.

Når vi skal opprette objekter må vi først bestemme hvordan objektene skal se ut. Vi må bestemme hvilke data som skal lagres og hvilke operasjoner som skal kunne gjøres på dataene. Dette gjør vi ved å definere en klasse der vi bestemmer objektets oppbygning.

Klassen Bok vil således beskrive hvilke data som skal lagres for hver bok og definere metoder for hvordan bok-dataene skal kunne brukes. Når vi først har opprettet klassen Bok, kan vi lage så mange Bok-objekter vi bare vil.

Biblioteker og rammeverk

Styrken ved objektorienterte språk er at de legger til rette for gjenbruk av kode. Er en klasse først definert, kan den brukes om og om igjen i nye programmer.

I programutviklingsverktøyene for de ulike programmeringsspråkene følger det gjerne med såkalte klassebiblioteker som inneholder ferdige klasser som programmererne kan benytte seg av. Klassene fra bibliotekene kan enten brukes som de er, eller videreutvikles til nye klasser.

I tillegg til standardbibliotekene er det også utviklet en mengde spesialbiblioteker, såkalte rammeverk, som inneholder programvare for ulike fagfelt og spesialoppgaver.

Det at programmerere kan bygge videre på andres kode, har bidratt til en voldsom utvikling innen datateknologi.

Programvarearkitektur

Mange av dataprogrammene vi bruker i det daglig er svært store. Eksempelvis inneholder tekstbehandlingsprogrammet Word mange hundre tusen instruksjoner. Skal vi programmere programmer av denne størrelsesorden, sier det seg selv at vi må dele det opp på en fornuftig måte.

En velkjent problemløsningsteknikk er å dele et stort problem inn i mindre delproblemer, for så å løse hver del for seg. På samme måte kan vi dele programmet inn i flere moduler (delprogrammer) som hver tar seg av sin deloppgave.

Det er for eksempel vanlig å la brukergrensesnittet, som tar seg av kommunikasjonen med brukeren av programmet, utgjøre en modul, databasen, som sørger for nødvendig lagring av dataene, utgjøre en annen, mens programlogikken, som behandler dataene, utgjør en tredje.

Ikke sjeldent er de forskjellige modulene programmert i ulike programmeringsspråk, alt etter hvilket språk som er best egnet til å løse deloppgaven. Hvis så er tilfelle, vil kommunikasjonen mellom modulene foregå via ulike applikasjonsgrensesnitt (API), der reglene for hvordan kommunikasjonen mellom dem skal foregå, er fastsatt.

Utviklingsmetodikk

På samme måte som en husbygger stiller krav til hvilke funksjoner huset skal ivareta, vil en oppdragsgiver til et dataprogram stille krav til hva programmet skal utføre. Kravene er gjerne nedfelt i en kravspesifikasjon, som er utarbeidet i samarbeid mellom oppdragsgiveren og den eller de som skal programmere programmet. Hvor detaljert kravspesifikasjonen er, og hvordan programutviklerne forholder seg til den, vil avhenge av hva slags utviklingsmetodikk som er valgt. Vi kan skille mellom to hovedtyper:

  1. I sekvensiell utviklingsmetodikk (fossefallsmetoden) planlegges programmet i detalj før programmeringen, kalt implementasjonen, finner sted.
  2. I iterativ utviklingsmetodikk, ofte kalt smidige utviklingsmetoder, programmeres programmet i iterasjoner, det vil si leveranse for leveranse. Allerede fra første iterasjon vil man da ha et kjørbart program som kan testes. Deretter videreutvikles programmet, leveranse for leveranse, til det er ferdig.

Oppdragsgiveren til et program er ikke nødvendigvis den samme som sluttbrukeren av det. Selv om programmet innfrir kravene som er nedfelt i kravspesifikasjonen, er det ikke sikkert at det blir en suksess. Skal programmet fungere etter hensikten, må det også tilfredsstille sluttbrukerens behov og forventninger. Innen smidig utvikling er det derfor ikke uvanlig å la representanter for sluttbrukerne bidra med tilbakemeldinger og innspill under utviklingen av programmet.

Testing

I et digitalisert samfunn, der vi alle i økende grad er avhengig av ulike typer dataprogrammer, er det avgjørende at de fungerer som de skal. Enkelte feil skaper først og fremst irritasjon hos brukeren av programmet, men oppstår det for eksempel feil i et styringssystem til et tog eller fly, kan det få fatale konsekvenser, ja i verste fall med tap av liv. Å teste programvaren grundig før den tas i bruk, er følgelig helt avgjørende. For å sikre objektive vurderinger, brukes det ofte uavhengige testere som ikke selv har deltatt i utviklingen av programmet. Dette fratar imidlertid ikke programmereren ansvaret for kodens kvalitet.

På samme måte som vi har lett for å gjøre skrivefeil når vi skriver vanlig tekst, er det ikke til å unngå at vi gjør programmeringsfeil når vi programmerer. De syntaktiske feilene hjelper kompilatoren oss med. Verre er det med de logiske feilene. Oppdages ikke de i tide, vil ikke programmet fungere som det skal, noe som igjen kan få alvorlige konsekvenser. Ideelt sett bør programmereren teste koden fortløpende, det vil si for hver metode som programmeres bør det programmeres en tilhørende enhetstest (unit-test) som sjekker at metoden utfører det den skal. Enhetstestene utgjør grunnlaget for automatisk testing, som igjen gjør det mulig å effektivisere og øke omfanget av testingen. Etter hvert som dataprogrammene øker i kompleksitet og størrelse, øker også behovet for automatisert testing som en integrert del av utviklingsprosessen.

Testing av programvare, software testing, er et eget fagfelt som tar for seg hvordan testingen kan integreres gjennom hele programvarens livssyklus, fra planleggingsfasen, der vi sikrer oss at fundamentet programmet skal bygges på ikke inneholder feil og mangler, gjennom implementasjonsfasen, frem til ferdig produkt. Målet er å forebygge feil, og ikke minst luke dem ut så tidlig som mulig i utviklingsprosessen. Hvis en feil først har forplantet seg inn i koden, vil det koste det mangedobbelte å fjerne den i forhold til hva det ville kostet å luke den ut i en tidligere fase. Å starte testing tidlig i utviklingsprosessen er derfor en meget kostnadseffektiv teststrategi.

Les mer i Store norske leksikon

Kommentarer

Kommentarer til artikkelen blir synlig for alle. Ikke skriv inn sensitive opplysninger, for eksempel helseopplysninger. Fagansvarlig eller redaktør svarer når de kan. Det kan ta tid før du får svar.

Du må være logget inn for å kommentere.

eller registrer deg