Hvis man har brug for at udføre den samme type beregninger flere steder i et program, eller hvis en gruppe sætninger hører så meget sammen i forhold til sætningerne omkring dem, at man har et ønske om at "pakke dem ind", kan man med fordel oprette enfunktion (kaldes ogsåprocedure,(sub)rutine,metode). Funktionen kan modtage én til flere parametre som sine "input-data", og den kan tilsvarende returnere et resultat som "output-data". De steder i programmet, hvor beregningerne skal udføres, gennemfører man så etkald af funktionen med nogle aktuelle værdier som parametre, og en eventuelt returværdi fra funktionskaldet kan man så opfange og arbejde videre med. En fordel ved funktioner er, at variable, som kun oprettes af hensyn til beregningerne internt i funktion, kan erklæreslokalt i funktionen, så andre dele af programmet ikke kan manipulere, endsige se dem.
Den omfattende brug afGOTO-sætninger i implementeringen af forgreninger, løkker og funktionskald kunne meget nemt føre til uoverskueligspaghettikode. Især var det begrænsningerne ved funktionskald, der fremkaldte et behov for at kunne "indhegne" en gruppe sammenhørende sætninger i enblok, f.eks. med en parentetiskBEGIN ... END-struktur eller andre typer parenteser. Sådanne blokke anvendes både omkring de sætninger, der skal udføres i en forgrening og en iteration i en løkke, men de er især anvendelige til at erklære funktioner med parametre, returværdier og lokale variable. Sammen med de nye sprog med sådanne faciliteter opstodprogrammeringsparadigmetstruktureret programmering.
I de fleste sprog designet til struktureret programmering har man også muligheden for at erklære en funktion inde i "kroppen" af en anden funktion. På den måde kan en funktion ikke kun indeholde lokale variable, men også lokale funktioner. Der gælder nemlig som regel, at lokale variable eller funktioner i en funktion ikke kan "ses" udefra; man taler om, at deresscope kun er funktionen selv eller funktioner erklæret inde i funktionen. I sprog, hvor dette ikke gælder automatisk, er det op tilprogrammøren selv at udvise datadisciplin ved anvendelsen af variable. Udover at undgå anvendelsen afGOTO-sætninger er konsekvens omkring variables og funktionersscope nok det vigtigste middel til at undgåspaghettikode i struktureret programmering.
Struktureret programmering åbner også større muligheder for at arbejde medabstrakte datatyper, dvs. komplekse datastrukturer, der vha. reference-typer (pegere/pointere), post-typer og specielle funktioner er optimeret til at kunne udføre f.eks. indsættelse af elementer eller søgning efter elementer. Med de større muligheder blev der også større behov for at vurdere effektiviteten af et program, særligt med henblik på enalgoritmeskompleksitet. Hermed menes en vurdering af, i hvilket omfang beregningstiden i algoritmen vokser, når datamængden stiger. Hermed fik programmøren redskaber til at finde frem til den mest effektive algoritme for sit program.
I de første computere interagerede brugeren ved hjælp af en tekstbaseretkommandolinjegrænseflade til computerensstyresystem.[2] På en kommandolinie kalder man f.eks. programmet ved at skrive dets navn efterfulgt af eventuelle parametre som input. Når programmet har udført sin opgave, svarer den tilbage med eventuelt tekst-output og giver brugeren mulighed for at indtaste en ny kommando. Der er tale om en såkaldtlineær kommunikation mellem bruger og computer, hvor én af dem hele tiden venter på den anden.
Med fremkomsten af computere med engrafisk brugergrænseflade (GUI, fra eng.Graphical user interface) blev både input og output væsentligt mere komplekst. Brugeren kan ikke blot levere tekstinput flere forskellige steder på skærmen, men der kommunikeres også ved hjælp af forskellige enheder somtastatur,mus ogscanner, og der er ingen regler for, hvilken rækkefølge kommunikationen foregår. Computeren kører med fleretråde.
Dette satte skub i udviklingen afobjektorienteret programmering. I detteprogrammeringsparadigme arbejder man med begrebet etobjekt, som er defineret somen helhed med identitet, tilstand og adfærd.[3] Sådanne objekter kan eksempelvis være de enkelte komponenter, som et skærmbillede er opdelt i, eller de forskellige stykker hardware, som brugeren anvender. Men det kan også være genstande eller begreber fra it-systemetsproblemområde, den del af systemets omverden, som systemet skal afspejle. Det er opgaven forobjektorienteret analyse og design at finde frem til, hvilke objekter der skal medtages.
Desuden kan et objekt være en avanceret datastruktur til at manipulere en dynamisk samling af variable af samme datatype, optimeret til søgning eller sortering eller hurtig indsættelse og fjernelse af elementer.
I den objektorienterede programmering opdeles programkoden iklasser, der har hver sit velafgrænsede ansvarsområde i programmet. Et objekt er en forekomst (instans) af klassen. Et objekt kan altså opfattes som en variabel i programmet, og klassen er variabeltypen. Objektets tilstand beskrives vha.medlemsvariable, der som regel kun harscope i klassen. Objektets adfærd beskrives vha.metoder, funktioner med parametre, der kan kaldes udefra og som manipulerer med medlemsvariablene. Endelig sikres objektets identitet, ved at andre dele af programmet kun har dette objekt som variabel i form af enreference til objektet. To variable forskellige steder i programmet kan altså godt være ét og samme objekt, der interageres med.
Objektorienteret programmering har tre grundprincipper:
- Indkapsling
- Objektets tilstand er usynlig udefra, men dens adfærd bestemmes af engrænseflade af metoder, som omverdenen anvender (ved metodekald).
- Nedarvning
- Klassens definitioner af variable og metoder kan udvides til at definere en ny klasse. Man siger at ensubklasse arver fra en superklasse. Dermed er et objekt fra subklassen også en forekomst af superklassen.
- Polymorfi
- To subklasser med den samme superklasse, kan arve samme metode fra superklassen, men udviser forskellig adfærd, når metoden kaldes. De har hver sin implementering af metoden, og eventueltoverskriver de superklassens implementering af metoden.
Med disse principper har man gode muligheder for f.eks. at få en GUI til at udvise den ønskede adfærd. Hvis man vil have en bestemt komponent til at opføre sig anderledes, definerer man en ny klasse, der arver fra denne komponent, og giver den en ny implementering af metoderne.
De fleste muligheder for kodning istruktureret programmering er også overført til objektorienteret programmering. Dog er muligheden med at definere en funktion lokalt i en anden funktion ikke overført til en klasses metoder. Derimod kan man i en klasse definere en anden såkaldtindre klasse, som på mange måder kan anvendes, hvor man i struktureret programmering ville anvende lokale funktioner.
I et program med mange klasser kan det ofte være svært at afgøre, præcist hvilke ansvarsområder, man skal fordele til hvilke klasser. En hovedregel i denne problemstilling – som egentlig er en design-problematik – er, at man skal lade den klasse, som besidder den nødvendige information, løse opgaven. Det betyder, at hvis der f.eks. opstår en runtime-fejl i en klasse, og klassen har tilstrækkelig information til at håndtere fejlen, skal den selv håndtere den i stedet for at sende problemet videre til en anden klasse.
En anden hovedregel er, at man så vidt muligt skal ladeafhængighed mellem to klasser kun gå den ene vej, hvor "afhængighed" betyder, at koden i den ene klasse er afhængig af kendskab til den anden klasses grænseflade. Også i objektorienteret programmering kan man nemlig lavespaghetti-kode. Det kan f.eks. være fristende at definere et GUI-vindue, der udover at levere en brugergrænseflade også tager sig at at evaluere data, som brugeren taster ind, og gemme disse i en database. Dette kan måske være overskueligt, hvis der kun er få typer data i et system, men hvis der f.eks. er mange bindinger mellem data i en database, der kræver flere forskellige GUI-vinduer til brugerens indtastninger, kan der blive så mange afhængigheder mellem de enkelte klasser, at det besværliggør vedligeholdelse af koden. Der er løsningen at få lavet en hensigtsmæssig fordeling af ansvarsområderne ud på enkelte klasser.
En sådan opdeling er der f.eks. i den såkaldte 3-lags-model (eng.3-tier-model), også kaldet MVC (fra eng.Model-View-Control). I en sådan vil man fordele ansvarsområderne således:
- Model: Her definerer man klasser, der afspejler klasserne i genstandsområdet. Klasserne skal primært opbevare data og evaluere data, den modtager udefra. I størst muligt omfang skal klasserne opdeles hierarkisk, så afhængigheden kun går "nedad".
- View: Denne står for brugergrænsefladen, som skal levere data til de enkelte objekter i modellen. Klasser her skal have kendskab til én eller flere klasser i modellen. Den skal kun evaluere indtastede data i det omfang, de helt åbenlyst ikke kan være brugbare.
- Control: Denne skal styre forretningsgangen i programmet og have kendskab til både modellen og brugergrænsefladen. Desuden skal den hente data om modellen fra en database og levere dem til brugergrænsefladen, ligesom den skal gemme data om modellen i databasen.