Programmering går ud på at udvikle computerprogrammer (software) til elektronisk databehandling på en computer ved hjælp af et programmeringssprog. Formålet med et program er overordnet at modtage nogle input-data, udføre en opgave på disse (f.eks. beregninger, udskrivning, kommunikation med database) og som resultat tilbagelevere nogle output-data.  Programmeringsprocessen Udviklingen af et program er en proces bestående af det at skrive kildekode, testning, fejlretning (også kaldet aflusning, eng. debugging) og vedligeholdelse af kildekoden. Programmet skrives som regel som ren tekst i et programmeringssprog, som har en defineret syntaks for koden. Hvis der er tale om et compileret sprog, oversættes (compileres) kildekoden først til maskinkode eller et anden mere maskinnær kode. I denne compilering opdages også eventuelle syntaksfejl. Den oversatte maskinkode kan derefter køres af computeren. Hvis der er tale om et fortolket sprog, kører fortolkeren programmet direkte fra kildekoden, og først undervejs i kørselen opdages eventuelle syntaksfejl. Programmeringen er en del af hele systemudviklingsprocessen, og forudsætningen for at programmere er, at der først er gennemført en analyse af, hvilke krav systemet skal opfylde over for brugerne. Dette er beskrevet i en kravspecifikation. Herefter designes systemet, og programmeringen gennemføres. Der er en løbende debat om hvorvidt kodning af programmer er en kunst, et håndværk eller en ingeniør disciplin. Generelt anses god programmering for at en afmålt anvendelse af alle tre, hvor målet er at producere en effektiv software-løsning som kan videreudvikles. Disciplinen afviger fra mange andre tekniske professioner, da programmører, generelt set, ikke behøver licens eller bevis på en standardiseret (eller offentligt reguleret) certifikation for at kalde sig selv "programmører" eller endda "softwareingeniør".  Variable og konstanter En dataværdi placeres ofte i en eller flere variable (pladsholder). En variabel er kendetegnet ved et alfanumerisk variabelnavn og en bestemt datatype, men dens konkrete værdi kan skifte undervejs i programmet. Har man brug for en pladsholder, der ikke må skifte værdi, har de fleste sprog mulighed for at definere en konstant.  Forgreninger Forgreninger er noget af det mest basale i et program, fordi grundlaget for computerberegninger netop er forgreninger, hvor der overalt evalueres på, om noget er sandt eller falsk. For at en algoritme ikke blot er en lineær sekvens af beregninger, men kan variere beregningerne afhængig af de givne data, er man nødt til at vurdere på, hvorvidt en betingelse er opfyldt eller ej. Enhver forgrening indledes derfor med en betingelse. Forgreninger kan også være indlejrede i hinanden (eng. nested), så man kan gå tre eller flere veje det givne sted i algoritmen. I de ældste programmeringssprog implementerede man forgreninger ved hjælp af etiketter (eng. labels) ved bestemte sætninger eller linienumre kombineret med GOTO-sætninger, der fortalte, hvor i programmet man skulle gå hen. GOTO-sætninger kunne dog nemt medføre fejl i programmets flow, fordi der til enhver "gren" i en forgrening skulle være en GOTO-sætning både for at starte på grenen og for at afslutte den. I dag har man andre metoder til at vise, at en gruppe sætninger hører sammen i en "gren". Som regel bruger man nøgleord som IF ... THEN ... ELSE ... for at implementere en forgrening, eller SWITCH ..., SELECT ... el.lign. ved en bredere forgrening.  Løkker Hvis en gruppe sætninger skal udføres flere gange, indfører man en løkke i programmet. Også her skal der anvendes en betingelse, der skal evalueres hver gang en iteration i løkken indledes eller afsluttes. Et meget vigtigt element i programmeringen af en løkke er at sikre sig, at gruppen af sætninger i løkken ændrer på data på en sådan måde, at betingelsen på et tidspunkt får programmet til at hoppe væk fra løkken. Hvis ikke, går programmet ind i en uendelig løkke med fatale følger for dets gennemførelse. Også løkker blev i de ældste programmeringssprog implementeret vha. GOTO-sætninger, og ligesom i en forgrening kunne det være komplekst at placere GOTO-sætninger rigtigt i programmet. I dag er løkker implementeret med nøgleord som f.eks. WHILE ... DO ... , REPEAT ... UNTIL ... eller FOR ... NEXT ... .  Funktionskald 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 en funktion (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å et kald 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æres lokalt i funktionen, så andre dele af programmet ikke kan manipulere, endsige se dem. Funktionskald var svære at gennemføre, da man kun havde GOTO-sætninger til rådighed. Det kunne lade sig gøre med lidt datadisciplin, for alle variable, også de lokale i funktionen, kunne i princippet anvendes overalt (globalt). I det mindste skulle både parametrene og returværdierne (grænsefladen mellem det kaldende sted i programmet og funktionen), anvendes både inden for og uden for funktionens gruppe af sætninger. Endelig skulle der være en variabel, der viste, hvilken etiket programmet skulle returnere til, når funktionen var færdig. Endnu mere komplekst blev det, hvis man skulle lave en såkaldt rekursion, hvor en funktion internt i sine beregninger kalder sig selv. Da hver funktionskald skulle kunne finde tilbage til det kaldende sted i programmet, var man nødt til programmeringsmæssigt at lave en begrænsning for, hvor mange rekursive kald der kunne være inden i hinanden.  Struktureret programmering Den omfattende brug af GOTO-sætninger i implementeringen af forgreninger, løkker og funktionskald kunne meget nemt føre til uoverskuelig spaghettikode. Især var det begrænsningerne ved funktionskald, der fremkaldte et behov for at kunne "indhegne" en gruppe sammenhørende sætninger i en blok, f.eks. med en parentetisk BEGIN ... 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 opstod programmeringsparadigmet struktureret 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 deres scope kun er funktionen selv eller funktioner erklæret inde i funktionen. I sprog, hvor dette ikke gælder automatisk, er det op til programmøren selv at udvise datadisciplin ved anvendelsen af variable. Udover at undgå anvendelsen af GOTO-sætninger er konsekvens omkring variables og funktioners scope nok det vigtigste middel til at undgå spaghettikode i struktureret programmering.  Kompleksitet Struktureret programmering åbner også større muligheder for at arbejde med abstrakte 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å en algoritmes kompleksitet. 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.  Objektorienteret programmering I de første computere interagerede brugeren ved hjælp af en tekstbaseret kommandolinjegrænseflade til computerens styresystem. 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åkaldt lineær kommunikation mellem bruger og computer, hvor én af dem hele tiden venter på den anden. Med fremkomsten af computere med en grafisk 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 som tastatur, mus og scanner, og der er ingen regler for, hvilken rækkefølge kommunikationen foregår. Computeren kører med flere tråde. Dette satte skub i udviklingen af objektorienteret programmering. I dette programmeringsparadigme arbejder man med begrebet et objekt, som er defineret som en helhed med identitet, tilstand og adfærd. 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-systemets problemområde, den del af systemets omverden, som systemet skal afspejle. Det er opgaven for objektorienteret 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.