Programske paradigme so načini razvrščanja in opisovanja programskih jezikov glede na slog razmišljanja in način reševanja problemov, ki ga podpirajo. Paradigme se osredotočajo na to, kako so izraženi izračuni, kako so organizirane podatkovne strukture in kako se upravlja z izvajanjem programa. Jeziki lahko podpirajo več kot eno paradigmo in so zato pogosto opisani kot multi-paradigmatski.

Paradigme lahko obravnavajo različne vidike: način izvajanja kode (npr. prisotnost stranskih učinkov ali vrstni red izvedbe), način organizacije kode (npr. razbijanje v velike module ali več majhnih delov) ter način, kako so izraženi pogoji, podatki in odnosi (vrstni red, dele itd.).

V grobem delimo paradigme na dve veliki skupini: imperativne in deklarativne. Veliko jezikov podpira lastnosti obeh skupin.

Imperativno programiranje

V imperativnih programih programerji računalniku podajo natančen, urejen niz korakov, ki jih je treba izvedeti, da dosežemo želeni rezultat. Primer za risanje mačjega obraza bi bil niz navodil: "Tukaj nariši krog, tam nariši dva manjša kroga, na vrhu nariši dva trikotnika" itd. Imperativni programi pogosto vsebujejo spreminjajoče se stanje in lahko imajo veliko stranskih učinkov, kar pomeni, da izvedba ene operacije lahko vpliva na drugo preko skupnih podatkov ali zunanjih virov.

Obstajata dve glavni veji imperativnih paradigm, in jezik pogosto podpira obe:

  • Strukturirano - računalnik dobi navodila, ki so vedno v določenem vrstnem redu. Koraki, kot je "vrni se na korak 3" (znani kot stavki goto), niso dovoljeni.
    • Proceduralni - Program omogoča programerju, da seznam ukazov poimenuje, kar te ukaze spremeni v "postopek", ki ga lahko uporabi pozneje. Tudi večina strukturiranih jezikov je proceduralnih.
  • Objektno usmerjeno - ideje so računalniku razložene s predmeti, deli kode, ki imajo nabor ukazov, ki jih lahko dobijo, in nekaj informacij o njih. Tak pristop spodbuja enkapsulacijo, dedovanje in polimorfizem.

Imperativne paradigme so primerne, kadar želimo nadzor nad nizom korakov in nad spreminjanjem stanja (npr. sistemsko programiranje, visoko zmogljivi algoritmi, upravljanje z napravami). Slabosti so lahko težje preverljivo vedenje zaradi stranskih učinkov, težave pri vzporednem izvajanju in kompleksno upravljanje stanja v velikih projektih.

Deklarativno programiranje

V deklarativnih paradigmah programer računalniku pove kajkako naj to naredi. Namesto da navedemo postopek, izrazimo lastnosti želenega izhoda ali razmerja podatkov, upravljalnik jezika pa skrbi za izvedbo. Za risanje mačjega obraza bi na primer rekli: "Nariši obraz, nariši dve očesi, dve ušesi in usta".

Najbolj znane deklarativne paradigme so:

  • Funkcionalno - Večino dela opravijo funkcije brez stranskih učinkov. Funkcionalni jeziki poudarjajo nedejavnost (immutability) in kompozicijo funkcij, kar poenostavi dokazljivost in vzporedno programiranje.
  • Logika - Navedena so dejstva, nato pa se postavi eno ali več "vprašanj". Pogojna sklepanja in iskanje rešitev gredo preko notranjih mehanizmov uresničevanja pravil.
  • Dogodki - Deli kode so nastavljeni tako, da se zaženejo, ko se zgodijo določene stvari (na primer vklop računalnika). Ta pristop je pogost v uporabi grafičnih vmesnikov in asinhronih sistemih.

Deklarativni pristopi pogosto omogočajo krajše, berljivejše in lažje preverljive izraze problemov. Slabosti so lahko manjši nadzor nad izvedbo (kar lahko vpliva na zmogljivost) in včasih večja zahtevnost izražanja določenih vrst algoritemov.

Druge paradigme

Obstajajo paradigmatske tehnike, ki se lahko pojavijo znotraj imperativnih ali deklarativnih jezikov ali kot dopolnila k njima. Te vključujejo:

  • Reaktivno programiranje – osredotoča se na pretoke podatkov in propagacijo sprememb (uporablja se v odzivnih vmesnikih in upravljanju asinhronih dogodkov).
  • Programiranje s kontrakti – dodajanje formalnih pogojev (pre- in postpogoj) za funkcije in metode za večjo zanesljivost.
  • Metaprogramiranje – programi, ki generirajo ali spreminjajo druge programe ali same sebe (makri, refleksija).
  • Paralelno in vzporedno programiranje – paradigme in modeli za obvladovanje deljenja dela in sinhronizacije na več procesnih enotah.

Pregled in primeri

V praksi se paradigme pogosto prepletajo. Mnogi sodobni jeziki, kot so Python, JavaScript ali Scala, podpirajo imperativne, objektne in tudi funkcionalne stile. Izbira paradigme je odvisna od problema, ekipe, orodij in ne nazadnje tudi osebnih preferenc.

Primeri tipičnih uporab:

  • Imperativno/proceduralno: sistemska orodja, jedrne knjižnice, obdelava vhodno-izhodnih operacij.
  • Objektno usmerjeno: velike aplikacije z mnogimi tipi entitet in njihovimi interakcijami (uporablja se za organizacijo kode in modeliranje domen).
  • Funkcionalno: obdelava zalednih tokov podatkov, zaporedna obdelava kolekcij, varno vzporedno računanje.
  • Deklarativno/logično: poizvedbe v podatkovnih zbirkah, reševanje problemov preko pravil (npr. Prolog) in konfiguracijski jeziki.

Težave s paradigmami

Paradigme prinašajo koristi, a tudi izzive:

  • Mešanje paradigm lahko vodi v nejasen slog kode, če ni vzpostavljenih smernic.
  • Upravljanje stanja v imperativnih jezikih lahko oteži testiranje in vzporedno izvajanje.
  • Učinkovitost – nekateri deklarativni pristopi abstraktirajo nad izvedbo, kar lahko povzroči slabše zmogljivosti brez optimizacij prevajalnika ali runtime-a.
  • Navajenost programerjev – prehod iz ene paradigme v drugo (npr. od imperativnega k funkcionalnemu) zahteva drugačen način razmišljanja in učenja novih vzorcev.

Zgodovina

Strojna koda

Najzgodnejše programske forme so bile neposredne ukaze procesorju – strojna koda in kasneje asemblerski jeziki. Ti sta bila strogo imperativna: programer je natančno določal zaporedje ukazov in način, kako se uporabi strojno stanje (registri, pomnilnik).

Proceduralni jeziki

V šestdesetih in sedemdesetih so se pojavili proceduralni jeziki (npr. Fortran, Algol, C), ki so uvedli strukturiranje kode z zanki, pogojnimi stavki in postopki/funkcijami. To je olajšalo abstrakcijo in ponovno uporabo kode ter zmanjšalo uporabo neposrednega goto-programiranja.

Objektno usmerjeno programiranje

Objektno programiranje se je razvilo kot način modeliranja kompleksnih sistemov z uporabo predmetov (objektov), ki vsebujejo stanje in vedenje. Jeziki, kot so Simula in pozneje Smalltalk, C++, Java, so popularizirali ta pristop, ki poudarja enkapsulacijo, dedovanje in polimorfizem.

Deklarativne paradigme

Hkrati so se razvijale deklarativne paradigme: funkcionalni jeziki (Lisp, ML, Haskell) so raziskovali uporabo funkcij kot temeljnih gradnikov z minimom stranskih učinkov, logični jeziki (Prolog) so uveljavili način izražanja problemov z dejstvi in pravili. V novejšem času so se deklarativni pristopi razširili tudi v podatkovne baze (SQL), konfiguracijske jezike in reaktivne sisteme.

Sorodne strani

  • Primerjava programskih jezikov
  • Vzorci programske zasnove
  • Paralelizem in vzporedno programiranje

Reference

Za poglobljeno branje priporočam literaturo o jezikih in paradigmah: uvodi v programiranje, znanstveni članki o jeziku specifikacijah in knjige, ki primerjajo sloge programiranja ter zgodovinske preglede razvoja jezikov.

Druge spletne strani

  • Spletne učilnice in vodiči za posamezne paradigme (funkcionalno, objektno, deklarativno)
  • Dokumentacija za popularne jezike, ki podpirajo več paradigm