Programmeerimisparadigmad: definitsioon, tüübid ja näited
Programmeerimisparadigmad on viis, kuidas programmeerimiskeeli ja nendes kirjutatud lähenemisi rühmitada vastavalt sellele, kuidas nad probleeme lahendavad ja kuidas programm konstruktsiooni korraldab. Paradigma ei ole keele range omadus — keel võib toetada mitut paradigmat korraga ning sageli kaotab piir selgete kategooriate vahel praktilises programmeerimises tähenduse.
Mis paradigmasid mõõdetakse?
Paradigma võib keskenduda eri aspektidele, näiteks:
- kuidas koodi täidetakse (järjestus, kontrollvood, kõrvalmõjud),
- kuidas kood on struktureeritud (suured üksused vs palju väikseid funktsioone/komponente),
- milliseid abstraktsioone kasutatakse (objektid, funktsioonid, reeglid, vood jm).
Mõned paradigmad on seotud kõrvaltõusudega või nende keelamisega, teised rõhutavad andmete ja loogika eraldamist. Sellepärast eristatakse laias laastus kahte suurklassi: imperatiivseid ja deklaratiivseid paradigmasid — kuigi paljud keeled on hübriidsed.
Imperatiivne programmeerimine
Imperatiivsetes programmides annavad programmeerijad arvutile järjestatud sammude jada, mis kirjeldab, milliseid samme täpselt tuleb sooritada, et saavutada soovitud tulemus. Imperatiivne stiil keskendub programmi seisundi muutmisele ja sammude järjekorrale. Tüüpiline omadus on muutujate kasutamine ning kõrvalmõjude (nt muutmine, sisend-väljund) olemasolu.
Lihtne näide illustratsiooniks (kontseptuaalne): "võta andmed, sorteeri need, prindi tulemus". Siin on rõhk sammude järjekorral ja nende täitmisel.
Struktureeritud ja protseduuriline programmeerimine
Struktureeritud programmeerimine rõhutab selge kontrollvoo kasutamist — tingimuslaused, tsüklid ja alamprogrammid — ning keelab hämarad hüpped nagu "mine tagasi samm 3 juurde" (s.t. goto-käsklused), mis raskendavad loetavust ja hooldatavust. Enamik kaasaegseid keeli toetavad struktureeritud konstruktsioone.
Protseduuriline programmeerimine on struktureeritud paradigmade alamtüüp, kus programm jaguneb selgelt eristatavateks protseduurideks või funktsioonideks (alamsüsteemideks). Protseduurid võimaldavad korduvkasutatavust ja selget ülesandejaotust.
Objektorienteeritud programmeerimine
Objektorienteeritud lähenemine modelleerib süsteemi objektide kaudu — need on kooditükid, millel on omad andmed ja käitumine (meetodid). OOP rõhutab kapseldamist, pärimist ja polümorfismi, mis aitab realiseerida realistlikumaid abstraktsioone ning hallata suurt ja keerukat koodi. Objektidele antakse sageli hulk käsklusi ja neil võib olla oma olek (muutujad).
Objektorienteeritud mõtteviisi leiab suurel hulgal keeltes, kuid seda kasutatakse eri viisidel (näiteks Smalltalk, Java, C++). OOP ei ole alati sobiv igale probleemile — mõnel juhul on funktsionaalne või komponendipõhine lähenemine selgem.
Deklaratiivne programmeerimine
Deklaratiivses programmeerimises ütleb programmeerija arvutile midakuidas seda samm-sammult teha. See võimaldab abstrakteerida kontrollvoogu ja jätta täitmise detailid kompilaatori või käituskeskkonna hooleks.
Funktsionaalne programmeerimine
Funktsionaalne paradigm rõhutab puhtaid funktsioone (funktsioonid ilma kõrvalmõjudeta), immutability't (muutumatu andmestruktuuride kasutamist) ja kõrgema järgu funktsioone. Selline lähenemine lihtsustab tegemist paralleelsuse ja testimisega, kuna puuduvad jagatud muutuvad olekud. Näited keeltest, mis funktsionaalset stiili toetavad või rõhutavad: Haskell, Erlang, Clojure, aga ka osaliselt Scala, F# ja Python.
Loogika- ja reeglipõhine programmeerimine
Loogikapõhises paradigmas kirjeldatakse fakte ja reegleid, mille põhjal tõlgendussüsteem vastab küsimustele või sünteesib lahendusi. Prolog on tüüpiline näide: programmeerija esitab teadmised ja forsseerib päringud, mitte ei defineeri täpset algoritmi, kuidas päring tulemuseni jõuab.
Sündmuspõhine ja reaktiivne programmeerimine
Sündmuspõhises paradigmas on kood organiseeritud sündmuste ja nendega seotud käitlejate ümber; fragmendid käivitatakse siis, kui vastavad sündmused aset leiavad (näiteks kasutajaliidese klikk, võrguandme saabumine). Reaktiivne programmeerimine laiendab seda ideed voogude ja ajaliselt muutuvate andmete käsitlemisele, võimaldades lihtsamalt modelleerida asünkroonset ja reaalajas käitumist.
Muud paradigmad ja eri kombinatsioonid
Lisaks ülalkirjeldatutele eksisteerib palju spetsiifilisemaid paradigmasid: deklaratiivsed andmepõhised lähenemised (nt SQL), andmevoo (dataflow) programmeerimine, aspektipõhine programmeerimine (AOP), komponentpõhine arendus, reaalajas süsteemide paradigma jm. Sageli kombineeritakse paradigmaid: näiteks võib keel olla samaaegselt objektorienteeritud ja funktsionaalne (nt Scala, JavaScript, Python), mis võimaldab valida sobivaim tehnika iga probleemi osa jaoks.
Ülevaade: kuidas valida paradigmat?
Paradigma valik sõltub mitmest tegurist:
- probleemi olemusest (aritmeetilised protseduurid, andmetöötlus, UI, distribuutsioon jne),
- hooldatavusest ja meeskonna oskustest,
- soovitavast paralleelsuse või asünkroonse käitumise mudelist,
- tööriistadest ning ökosüsteemist (raamistike, IDE-de ja teekide tugi).
Kombinatsioonid annavad paindlikkuse, kuid võivad tekitada ka arusaamatusi, kui projektis puudub selge stiilijuhend.
Probleemid paradigmadega
- Õppekõver: mõningad paradigmad (nt puhtalt funktsionaalne või loogikapõhine) võivad olla algajale programmeerijale keerukad.
- Jõudlus: deklaratiivse abstraktsiooni hinna võib olla vähem kontrolli madalama tasandi optimeerimisel.
- Paradiigmade segamine: kui projektis kasutatakse mitu paradigmat ilma selge juhiseta, võib see vähendada loetavust ja suurendada vigade riski.
- Võimalik sobimatus probleemiga: mõni paradigma ei pruugi sobida reaalajas süsteemi või madala latentsusega rakenduse nõuetega.
Ajalugu
Programmeerimisparadigmade areng on tihedalt seotud arvutite ja keelte ajaloo ning teaduslike ideedega.
Masinakood
Alguses kirjutati programme otseselt masinkoodina (binaarselt) või assamblee keeles, mis oli tugevalt imperatiivne ning seotud riistvara spetsiifikaga.
Protseduurilised keeled
1950.–1970. aastatel hakkasid levima protseduurilised keeled nagu Fortran ja C, mille eesmärgiks oli struktureerida koodi ja lihtsustada arvutuste ja algoritmide kirjeldamist. 1960.–1970. aastatel tõusis esile ka Dijkstra argument struktuurse programmeerimise kasuks.
Objektipõhine programmeerimine
Simula ja hiljem Smalltalk esitasid 1960.–1970. aastatel objektorienteeritud idee; 1980.–1990. aastatel said OOP-i laialdased populaarsuse tõus C++ ja Java kaudu, eriti suurte süsteemide modellimisel ja UI-arenduses.
Deklaratiivsed paradigmad
Funktsionaalne programmeerimine põhineb lambda-arvutuse ideedel (Church) ja sai praktilise väljundi Lispis, ML-is ja hiljem Haskellis. Loogikapõhine programmeerimine jõudis Prologis laiemasse kasutusse AI ja teadmiste esindamise valdkonnas. SQL on näide väga edukast deklaratiivsest keelest andmebaaside haldamiseks.
Kokkuvõte
Programmeerimisparadigmad annavad mõtteraamistiku, kuidas probleemi modelleerida ja lahendada. Parimat paradigmat ei ole — sobivus sõltub ülesandest, meeskonnast ja keskkonnast. Tänapäeva keeled ja tööriistad võimaldavad sageli kombineerida tugevaid külgi eri paradigmadest, andes arendajale laia valiku lähenemisviise.
Ülevaade
Programmeerimiskeeled on rühmitatud paradigmade järgi samamoodi nagu masinad võivad olla rühmitatud selle järgi, milleks neid kasutatakse.
Mõned keeled sobivad vaid ühte peamise paradigma alla, näiteks:
- Smalltalk (objektorienteeritud)
- Assamblee (imperatiivne, kuid mitte struktureeritud või objektorienteeritud)
- Haskell (funktsionaalne)
- Prolog (loogika)
Enamik keeli on aga rohkem kui ühes paradigmas. Mõned neist, mis paistavad silma selle poolest, et neil on rohkem kui üks, on järgmised:
- Scala (objektorienteeritud, funktsionaalne, paralleelne)
- Visual Basic (sündmusepõhine, objektorienteeritud)
- Common Lisp (protseduuriline, funktsionaalne, objektorienteeritud, meta)
- Skeem (funktsionaalne, protseduuriline, meta)
- Perl (funktsionaalne, protseduuriline, meta, objektorienteeritud, sündmuspõhine)
- Python (funktsionaalne, objektorienteeritud, protseduuriline)
- Ruby (funktsionaalne, objektorienteeritud, protseduuriline)
- Wolfram Language (funktsionaalne, protseduuriline, üldiselt deklaratiivne)
- Oz (loogiline, funktsionaalne, imperatiivne, objektorienteeritud)
- F# (funktsionaalne, imperatiivne, objektorienteeritud, meta)
Rohkem paradigmasid ei ole alati hea. Üks kord, kui vähem paradigmasid võib olla hea, on see, kui on olemas keel, mis on ainult funktsionaalne. Mõnikord teeb funktsioon ühes sellises keeles vähem tööd (näiteks läheb üle ainult need osad, mida ta tegelikult vajab), kui see oleks pidanud tegema, kui keel oleks ka protseduuriline.
Paljud programmeerimisparadigmad on tuntud nii nende asjade poolest, mida nad ei lase inimestel teha, kui ka nende poolest, mida nad lasevad inimestel teha. Üks kord, kus see kehtib, on funktsionaalsed keeled. Kui funktsionaalne keel on ainult või enamasti funktsionaalne, siis tavaliselt ei luba ta kõrvalmõjusid. Teine kord, kus see kehtib, on struktureeritud programmeerimine: see erineb tavalisest imperatiivsest keelest, sest see ei lase programmeerijatel kasutada "goto-avaldusi" (avaldused, mis ütlevad programmile, et ta peab minema varasemasse sammu). Selle ja muude põhjuste tõttu arvavad inimesed mõnikord, et uued paradigmad ei võimalda piisavalt asju. Mõnikord on aga okei, et arvuti ei lase inimestel asju teha: see võib aidata inimestel vältida probleeme oma koodiga ja lasta arvutil teha oletusi, et ta saaks koodi kiiremini käivitada või isegi kontrollida koodi probleemide suhtes enne koodi käivitamist!


Ülevaade erinevatest programmeerimisparadigmadest Peter Van Roy järgi
Probleemid paradigmadega
Mõnele programmeerimiskeeli uurivale inimesele ei meeldi, et programmeerimiskeelte rühmitamiseks kasutatakse paradigmasid, näiteks Harper ja Krishnamurthi. Need inimesed ütlevad, et paljusid programmeerimiskeeli ei saa lihtsalt paradigmadeks rühmitada, sest keeled laenavad asju ja ideid paljudest paradigmadest.
Ajalugu
Aja jooksul on loodud uusi paradigmasid ja inimesed on neid kas toona või tagantjärele vaadates esile toonud. Üks esimesi paradigmasid, mis tunnistati uueks programmeerimisviisiks, oli struktureeritud programmeerimine 1960ndatest aastatest. "Programmeerimisparadigma" idee pärineb aastast 1978, kui mitte varem, kui Robert W. Floyd kasutas seda õpetamisel. Sõna "paradigma" selles tähenduses, nagu Robert seda mõtles, kasutas esmakordselt Thomas Kuhn oma raamatus "The Structure of Scientific Revolutions" (1962).
Masinakood
Kõige madalama taseme (mis on kõige lähemal sellele, kuidas arvuti asjadest aru saab) ja vanim programmeerimisparadigma on masinkood, imperatiivne paradigma. Masinakoodi juhised on lihtsalt hulk numbreid teatud järjekorras. Assembleri keel on veidi vähem madala tasemega (ja veidi vähem vana). Assembleri keeles antakse arvutile juhised mnemonika (kergemini meeldejäävad nimed) ja mäluaadressidele (juhised, kuidas leida arvutis mingi informatsioon) võib anda nimed. Neid nimetatakse mõnikord esimese ja teise põlvkonna keelteks.
1960ndatel tehti assemblerikeeled paremaks, lisades uusi asju nagu raamatukogu COPY, makrosid ("erilise" koodi tükid, mis muudeti tavaliseks koodiks enne programmi käivitamist), jooksvaid protseduure (suundade kogumid, millele antakse nimi ja mis salvestatakse hilisemaks) ja muutujaid (elemendid, millele antakse nimi ja mis salvestatakse hilisemaks) väljastpoolt programmi. See võimaldas inimestel kasutada mõnda koodi rohkem kui ühes projektis ja ei pidanud muretsema riistvaraspetsiifiliste probleemidega (probleemid, mis esinevad ainult ühes kindlas arvutis) tänu käskudele (suundade nimed) nagu READ/WRITE/GET/PUT.
Assemblerit kasutati ja mõnikord kasutatakse ikka veel süsteemides, kus on oluline, et kood oleks kiire, ning seda kasutatakse palju ka manussüsteemides, sest see võimaldab kasutajal täpselt kontrollida, mida masin teeb.
Protseduurilised keeled
1960ndate lõpus hakkasid inimesed leiutama protseduurilisi keeli. Need kolmanda põlvkonna keeled (esimesed mõned neist, mida me nüüd nimetame kõrgetasemelisteks keelteks) olid seotud sõnadega, mida nad püüdsid lahendada. Näiteks,
- COmmon Business Oriented Language (COBOL) - kasutab selliseid sõnu nagu fail, move ja copy.
- FORmula TRANslation (FORTRAN) - kasutab matemaatilisi sõnu ja sümboleid ( kirjutamisel ja trükkimisel kasutatavad kujundid). See on välja töötatud peamiselt teaduse ja tehnika jaoks.
- ALGOrithmic Language (ALGOL) - tehtud algoritmide kirjutamiseks (sammude kogumid, mis ütlevad arvutile, mida teha). See kasutab matemaatilisi sõnu ja sümboleid, nagu FORTRAN.
- Programmeerimiskeel üks (PL/I) - pidi olema kasulik kõigile.
- Algaja üldotstarbeline sümboolne käsukood (BASIC) - tehtud selleks, et aidata algajatel programmeerida.
- C - programmeerimiskeel, mis on mõeldud paljude asjade tegemiseks. Dennis Ritchie töötas selle kallal 1969-1973 AT&T Bell Labsis.
Objektipõhine programmeerimine
Pärast seda, kui paljud inimesed olid hakanud kasutama protseduurilisi keeli, leiutati objektorienteeritud programmeerimiskeeled. Nendes keeltes pannakse andmed ja nende "meetodid" (viisid, kuidas andmetega manipuleerida) ühte "objekti". Mõned programmeerijad, näiteks Richard Stallman, ei nõustu sellega, et objektorienteeritud keeled on arvutile ideede selgitamiseks paremad kui protseduurilised keeled.
Kuna objektorienteeritud programmeerimine on paradigma, mitte keel, on inimesed teinud objektorienteeritud assemblerkeeled nagu HLA (High Level Assembly).
Deklaratiivsed paradigmad
Samal ajal tegid mõned inimesed deklaratiivseid programmeerimiskeeli. Üks keel, mis on hästi tuntud deklaratiivsuse poolest, on SQL (keel, millega saab lisada ja eemaldada asju tabelitest).
Seotud leheküljed
- Mõtteviis
- Tüübisüsteem
- Turingi täielikkus
Küsimused ja vastused
K: Mis on programmeerimisparadigma?
V: Programmeerimisparadigma on programmeerimiskeelte rühmitamine nende tööpõhimõtete järgi.
K: Millised on kaks peamist paradigmade rühma?
V: Kaks peamist paradigmade rühma on imperatiivsed ja deklaratiivsed.
K: Mille poolest erinevad imperatiivsed ja deklaratiivsed paradigmad?
V: Imperatiivsed paradigmad vaatavad seda, kuidas koodi käivitatakse, näiteks lubavad kõrvalmõjusid või peavad asju tegema teatud järjekorras, samas kui deklaratiivsed paradigmad vaatavad seda, kuidas kood on grupeeritud, näiteks koodi paigutamine ühte või kahte tükki (või hoopis paljudesse väikestesse tükkidesse).
K: Kas keel võib olla nii imperatiivne kui ka deklaratiivne paradigma?
V: Jah, keel võib olla samaaegselt nii imperatiivne kui ka deklaratiivne paradigma.
K: Kuidas programmeerimisparadigma keeled rühmitab?
V: Programmeerimisparadigmad rühmitavad keeli selle järgi, mida nad teevad. Nad vaatavad, kuidas koodi käivitatakse, kuidas see on rühmitatud ja millises järjekorras ja millistest osadest programm koosneb.
K: Kas peale imperatiivse ja deklaratiivse on olemas ka muud tüüpi programmeerimisparadigmad?
V: Jah, lisaks imperatiivsele ja deklaratiivsele on olemas ka muud tüüpi programmeerimisparadigmad. Näiteks mõned vaatavad seda, kuidas koodi käivitatakse (näiteks kõrvaltoimete lubamine), teised vaatavad seda, kuidas kood on rühmitatud (näiteks koodi paigutamine ühte või kahte ossa).
K: Kas iga keel kuulub ainult ühte tüüpi programmeerimisparadigma?
V: Ei, mitte iga keel ei kuulu ainult ühte tüüpi programmeerimisparadigmasse; mõned keeled võivad kuuluda rohkem kui ühte tüüpi paradigmasse.