Programiranje

Desetljeća pogodaka i promašaja u razvoju programskih jezika

Oton Ribić nedjelja, 3. svibnja 2020. u 16:24

Zanimljivo je kako su programski jezici, razvijajući se tijekom dekada, utjecali na računala, trendove i ideje u informatičkoj zajednici, kako je ta zajednica formirala njih, a to nastavlja i danas

Nakon što smo se u prošlom tekstu pozabavili uzrocima koji su doveli do smišljanja same ideje programskih jezika, ovaj put ćemo u svojevrsnom indirektnom nastavku pozornost obratiti na neke konkretne trendove i ideje koji su otada naovamo igrali, ili još igraju, na ovoj neobičnoj pozornici. (Ako prethodni tekst niste još pročitali, sad je pravi trenutak za to, pa se onda vratite ovamo.)

Priča je šarenija nego što bi se to laički na prvi pogled pomislilo: radnja je isprepletena i kompleksna, programski jezici poput likova u drami imaju svoje urnebesne biografije, rodna stabla i misije, a svaki je k tome “rođen” u svoja karakteristična vremena, koja su mu dobrim dijelom upravljala životom.

Logično, cjelokupna priča o svakom liku, uopće i spominjanje svakoga od njih, bilo bi daleko preopsežno i za knjigu, a kamoli za časopis. No možemo se usredotočiti na ono zabavno, a marljivim znatiželjnicima prepustiti daljnje ronjenje po oceanu fakata.

Kamen temeljac

Premda je prvi pravi programski jezik Autocode nastao 1952. godine u Manchesteru, radilo se o akademskom projektu koji nije imao širi utjecaj – ostaje upamćen prema svojoj povijesnoj ulozi, ali ne i prema praktičnom korištenju. Taj drugi cilj, pak, dosegnuo je Fortran, koji je IBM predstavio dvije godine kasnije.

Kao što ste možda već zapamtili iz naše prošle epizode, u trenutku dolaska na scenu Fortran je za tadašnjih pionira programiranja konačno bio prilika više ne razmišljati o najsitnijim detaljima funkcioniranja računalnog hardvera, već su svoj zadani problem mogli riješiti na apstraktnijoj razini. U to doba velik i vizionarski korak naprijed, ali s današnjeg gledišta, taj pra-Fortran izgleda nevjerojatno grubo i nezgrapno. Znalo se reći: iz njega ipak posvuda izviru karakteristike strojnog jezika. Pa ipak, tadašnji programeri njime su se dobro snalazili, već su bila počela razmišljanja o sljedećoj generaciji jezika koji bi nudili veću apstrakciju, i time omogućili rješavanje težih, kompleksnijih problema (što se i dogodilo).

No nekoliko ključnih teoretičara već je tih, pedesetih godina počelo uočavati jedan mogući nadolazeći problem. Naime, tada se programiranju u tim ranim jezicima pristupalo kao prevedenom, odnosno pojednostavljenom, pisanju instrukcija strojnog kôda. One su bile lakše za pisanje, ali općenita logika nije im bila ništa jednostavnija. U tome nije ništa pogrešno samo za sebe, no upućivalo je na jednu drugu zavrzlamu: kako će se jezici rafinirati i postajati sve apstraktniji, tako će i programi postajati sve kompleksniji, a ako se oni nastave programirati kao malo ušminkana verzija strojnog kôda, brzo će se dosegnuti plafon, pri kojemu nitko više neće moći nakon tjedan dana shvatiti ni kôd koji je sâm napisao, a kamoli onaj koji je napisao netko drugi. Bilo je važno rastjerati taj crni oblak.

Struktura za sve!

Nastojanje da se taj problem riješi doveo je do jednog od najvažnijih koncepata u povijesti programskih jezika: strukturiranog programiranja. Iako je u njega uloženo dosta razmišljanja i iskustva, njegova rezultirajuća načela zavaravajuće su jednostavna. Naglasak je na korištenju što je više moguće upravljanja nad tokom programa pomoću uvjeta (if-then-else), ponavljanja (for i while) i odvajanja dijelova kôda u blokove i zasebne funkcije, ili dijelove koji rade zasebno (subrutine), a pritom maksimalno izbjegavati omraženu naredbu goto, dakle izravan skok iz kôda u proizvoljnu drugu točku u njemu. Odavde i ona izjava poznatog teoretičara Edsgera Dijkstre o štetnosti naredbe goto, a 1960-ih je i dokazano da se svaki dijagram toka može isprogramirati bez njezina korištenja.

Skeptici su isticali kako taj pristup ne donosi mnogo, jer se sve te napredne metode upravljanja programom na kraju, u prevedenom strojnom kôdu, ipak svode na svojevrsni goto, zapravo strojnu instrukciju jump. Uz to, žalili su se na to da ovo načelo u određenim situacijama rezultira dužim kôdom nego ako se ono samo pragmatično zaobiđe (što je i istina).

Unatoč tome, a i unatoč opstanku grupice sličnih skeptika sve do danas, načela strukturiranog programiranja ne samo da su se pokazala korisnima, već su se nametnula kao de facto standard bilo kakvog ozbiljnog programiranja bilo čega i u bilo kojem jeziku, osim za neke rjeđe, vrlo specifične svrhe. U novije vrijeme, kad je programiranje daleko više timska aktivnost, važnost lako shvatljivog kôda još je samo izraženija.

Iako se radi o teoretskom načelu, dakle nečemu što bi trebalo biti nezavisno od programskog jezika koji se konkretno koristi, ipak je ono imalo i velik izravan utjecaj na jezike. Već počevši s Algolom potkraj 1950-ih počeli su sve više nuditi mogućnosti za strukturirano programiranje, a neki i namjerno izostavljati nesretni goto kako bi čak svjesno otežali “nestrukturirano” programiranje. Danas bilo koji novi jezik ne bi imao ni najmanje izglede uspjeti bez tih fundamentalnih mogućnosti.

Carstvo objekata

Kad smo na konceptu strukturiranog programiranja, priča bi mogla eksplodirati na čitav sijaset drugih koji su se otad pojavili, no zadržimo se na jednom od važnijih. Radi se o objektno orijentiranom programiranju koje je pokušalo riješiti sličan problem, počevši u slično doba.

Premisa je opet bila ista: dokle programi postaju sve veći a računala sve moćnija i jeftinija, postoji li način nekako ih pametno organizirati i time napraviti lakšima za pisanje, održavanje i sve ostalo? Mogu li se oni nekako modularizirati, podijeliti na lako kontrolirane zasebne elemente?

O tome se također razmišljalo već tih plodonosnih pedesetih godina, ali prvi konkretan pomak napravilo je nekoliko inženjera iz Norsk Regnesentrala, računskog centra Norveške, koji su razvili jezik nazvan Simula. Bio je baziran na Algolu (koji se opet pokazuje ključnim jezikom iz kojeg su krenule važne ideje), i uveo je paradigmu objekata.

U tom kontekstu, svaki je objekt svoja nezavisna komponenta programa, koja se sastoji od svog kôda, varijabli i ostalih uobičajenih stvari, a program predstavlja skup takvih objekata, od kojih svaki obavlja svoj dobro definiran zadatak. Svi objekti programa sami za sebe funkcioniraju nezavisno jedan od drugog, ali ih programer može povezivati, tj. oni mogu komunicirati tamo gdje je i koliko je to potrebno. Ako vam je opis maglovit, zamislite analogiju u kojoj za rješavanje određenog zadatka sastavljate tim ljudi, zapravo objekata, od kojih svaki ima svoju zadaću i ne petlja se u rad ostalih, ali je među mnogima od njih potrebna i jasna i pravodobna komunikacija kako bi sve funkcioniralo.

Ta se ideja u praksi pokazala vrlo moćnom i korisnom. No za razliku od strukturiranog programiranja, koje je postalo općeprihvaćen standard, objektno orijentiranom programiranju trebalo je više vremena da se ustoliči u programerskoj praksi, a nije se niti posvuda probilo. Velik udio danas popularnih jezika objektno je orijentiran, ali, primjerice, C je istaknuti izuzetak.

Dekade razvoja jezika donosile su i razne druge paradigme, od kojih su mnoge bile napuštene kao nepraktične, nedovoljno korisne, ili čak mrtvorođene. Postavilo se mnogo pitanja o tome što programski jezik treba prepustiti programeru, a za što se brinuti sam. Ovdje nikad nije bilo univerzalno dobrih odgovora te ih nema ni danas. Stoga su se pojavile razne varijante: jezici gdje je potrebno jasno deklarirati varijable, kao i one gdje nije, ili gdje se jezik brine oko čišćenja nepotrebno zauzete memorije (tzv. garbage collection), kao i one gdje se za to brine programer, i još mnoge druge. Na kraju, sve su to danas različiti alati, a od iskusnih inženjera očekuje se da znaju izabrati pravi za zadatak koji je pred njima.

Kućna revolucija

Veći dio spomenutog bio je rezultat odgovaranja na nova teoretska pitanja koja su se pojavljivala kako su jezici postajali sve apstraktniji i sofisticiraniji. No, cijelo su to vrijeme drugu stranu kormila držali tržište i hardver. Moglo bi se argumentirati da bi na razini ideala programski jezici morali biti potpuno lišeni tih “profanih” stvari i razvijani bez obzira na njih, ali naravno da se radi o preusko povezanom svijetu da bi to doista bilo moguće. Primjer koji je imao neosporno gigantski efekt na IT svijet je Basic, ili kako se katkad piše, BASIC, s obzirom na to da se radi o umjetnoj skraćenici.

Thomasu Kurtzu i Johnu Kemenyu, inženjerima sa sveučilišta Darthmouth u New Hampshireu, koji su 1964. smislili prvu verziju Basica, motivacija za to nije bio daljnji teoretski razvoj tog područja, već realna potreba da osnovno programiranje postane dostupno i ljudima izvan IT struke. Za to je bilo nužno smisliti jednostavan jezik više razine koji se brzo uči, ne opterećuje tehnikalijama, i shvatljiv je ljudima bez čvrste inženjerske podloge, bez obzira na to što taj pristup donosi neke druge neizbježne nedostatke.

Taj prvi Basic imao je ponešto uspjeha u profesionalnom i akademskom sektoru, i možda bi ostao na tome da se u IT svijetu nije dogodio jedan kataklizmički događaj posve odvojen od programskih jezika, a ipak s nevjerojatnim posljedicama za njih. Naime, britanska tvrtka Science of Cambridge (još se tada nije zvala ni Sinclair Research!) lansirala je na tržište računalo ZX80.

Pojavilo se u to vrijeme nekoliko sličnih računala, ali generalni je konsenzus da je upravo ZX80 pokrenuo zemljotres: radilo se o jednom od prvih potpuno samodostatnih računala s cijenom ispod čarobne granice od stotinu funti, ili korigirano za kurs, inflaciju, cijenu života i ostale faktore, oko 3.800 današnjih kuna.

Imao je samo jedan kilobajt (da, 1024 bajta) memorije, doduše proširive na 16 kB, kao pohranu podataka koristio audiokazete, bio notorno nepouzdan i sklon pregrijavanju, ali ništa ga od toga nije spriječilo da pokrene revoluciju kućnih, osobnih računala. Od tog trenutka lavina raznih kućnih računala samo se pojačavala. Basic se, ni kriv ni dužan, našao u situaciji biti jednim od rijetkih postojećih jezika koji su dovoljno jednostavni da bi privukli kućne entuzijaste, a opet i dovoljno nesofisticirani da stanu u vrlo, vrlo ograničen i skup ROM tih prvih računala.

Programiranje za svakoga

Basic je stoga u raznim varijantama bio osnovni jezik na cijeloj toj generaciji kućnih računala osamdesetih, od ZX80 preko ZX81 i Spectruma do Commodorea 64, CPC-a i dalje. Basic je bio na vrhu razvijenog svijeta, s nevjerojatno entuzijastičnom zajednicom koja je časopisima i raznim drugim metodama privlačila tisuće novih članova dnevno, uključivo naše prostore.

Usprkos fragmentaciji među raznim sličnim, ali u finim detaljima nekompatibilnim vrstama Basica, unatoč kritici struke da se radi o vrlo nezgrapno i loše osmišljenom jeziku koji previše toga vuče iz Fortrana, čak i usprkos tvrdnji ranije spomenutog Dijkstre da su programeri koji su prvo radili u Basicu previše mentalno masakrirani da bi poslije mogli propisno programirati, taj pokret kućnih računala i programiranja pred televizorom otvorio je horizont za bezbrojne nove ideje i primjene računala. Zacijelo će se dobar dio Bugova čitateljstva ovdje prepoznati.

To je definitivno bio najmarkantniji trenutak u životu Basica te primjer kako su hardver i tržište jedan jezik digli u ionosferu, ali zanimljivo je da se nešto srodno dogodilo s Basicom desetak godina kasnije. Visual Basic u prvoj je polovici devedesetih bio dovoljno pristupačan, stabilan i jednostavan, a računala dovoljno moćna da je programiranje jednostavnih aplikacija za osnovne poslovne potrebe postalo široko dostupno. Ako je trgovina obuće trebala aplikaciju za preračunavanje raznih standarda veličina cipela, to više nije bio posao za IT eksperte (koji su i dalje složno bili protiv Basica, i ne bez razloga), već se time mogao pozabaviti netko manje vičan, možda iz same tvrtke, i uz malo eksperimentiranja riješiti problem.

Dobar dio njih koristi se i danas, ali treba pošteno reći i kako je današnja inkarnacija Basica, VB.NET, beskrajno sofisticiranija od onih prvih Basica, ali je u Microsoftovoj .NET inicijativi ipak izgubila popularnost u odnosu na rašireni C#, koji je imao prednost biti smišljen “od nule”.

Mreža svih mreža

Još jedan pokret koji je neizmjerno utjecao na programske jezike bio je, naslućujete, dolazak Interneta. Tu se nije radilo o toliko nagloj lavini, već o nečemu što se postupno pokazivalo sve važnijim kako je tržište počelo shvaćati kakve mogućnosti Internet pruža. (A onda ih precjenjivati, što je dovelo do notorne Dot-com katastrofe 2000. godine, no to je jedna druga priča.)

Pojam programa koji se izvršava na jednom računalu, ali ima sučelje na nekom drugom, možda tisućama kilometara daleko, nije bio ništa novo: o tome su razmišljali još sredinom 20. stoljeća u kontekstu distribuiranog rada na terminalima. No očito okrupnjavanje ideje Interneta kao švicarskog noža za sve i svašta stvorila je potrebu za jezicima koji su osmišljeni upravo za pisanje web-aplikacija, koje bi od web-preglednika kao interpretera pukih web-stranica napravile konkretnu i ozbiljnu platformu s daleko većim mogućnostima i interaktivnošću. Tako su sredinom devedesetih koncipirani PHP, JavaScript, ASP i kasnije njegov nasljednik ASP.NET, od kojih su svi i dalje živi i zdravi u praksi.

Otprilike u slično vrijeme tržište je slutilo kako će za samo nekoliko godina svime na svijetu upravljati programi, te je zbog toga nastala Java. Osmišljena je tako da se lako može upogoniti neovisno o platformi; tada se slutilo da će biti upogonjena posvuda, od auto-radija preko šivaćih strojeva do industrijskih robota i, naravno, računala. Zapravo se svijet nije baš toliko promijenio, ali zahvaljujući tome, kao i univerzalnosti i dobro smišljenim osnovama, Java je među najpopularnijim jezicima u upotrebi danas.

Slučajem ili namjerom?

Govoreći o tome kako su jezici evoluirali dijelom sami, a dijelom u reakciji na zbivanja u svijetu hardvera i biznisa, lako je previdjeti element puke slučajnosti. Djeluje komično da bi netko razvio nešto tako kompleksno kao što je programski jezik slučajno, ili barem ne razmišljajući predaleko unaprijed o tome, ali ima neobičnih primjera.

Čak su C, izuzetno moćan i prema mnogo čemu ključan jezik u povijesti IT-a, njegovi tvorci počeli stvarati kako bi usput riješili neke vlastite nevolje pri razvoju utility programa za operacijski sustav Unix, čiji im je razvoj zapravo bio primarni cilj. Ne samo da je C i danas među najraširenijim i najmoćnijim jezicima, već je i postavio na noge brojne standarde koji se danas vide posvuda – kako na području funkcioniranja, tako i prema sintaksi.

Za Python, kojem stabilno raste popularnost i danas se čvrsto mota među pet najpopularnijih jezika na svijetu, njegov tvorac, Nizozemac Guido van Rossum niti ne skriva da je na njemu počeo raditi kako bi se imao čime baviti kod kuće u božićnom tjednu 1989. godine, kad je državni računalni institut u kojem je tada bio zaposlen bio na kolektivnom godišnjem odmoru.

Pa i PHP, jezik u kojem će desetljeće kasnije biti implementiran dobar dio Facebooka, a i cijelog weba, nastao je usput, kad je danski programer Rasmus Lerdorf počeo 1994. godine improvizirati nešto čime može postići osnovnu interakciju i logiku na svojim web-stranicama, i godinu dana kasnije to pokazao na Usenet grupama. Upravo zbog toga što PHP nije pozorno osmišljen, već je nastao kao rezultat improvizacija i razvoja “u letu” koje su dovele do nekih nelogičnosti, pokupio je, i dalje prima dosta kritike struke, ali bio je na pravom mjestu u pravo vrijeme, i to mu stoga ne smeta da i dalje bude izuzetno jak igrač na području web-aplikacija.

Dodir realnosti

Takve uspješne priče uvijek nose sa sobom zgodne anegdote, ali lako je s takvim zvijezdama na sceni previdjeti količinu okolne tame. Zapanjujuća većina svih programskih jezika u povijesti su prilično, ako ne i potpuno propali. To nije uvijek pošteno, jer su mnogi bili prava ideja u krivo vrijeme, ili krivo implementirana, ili nedovoljno predstavljena javnosti, ili, pak, za kojom nije bilo stvarne praktične potrebe. Ipak, nije trud oko svih tih tisuća programskih jezika uzalud, jer su mnogi utjecali na svoje nasljednike, prenoseći neke zanimljive ideje ili pokazujući što su greške koje treba izbjeći.

Uzevši u obzir kojom se brzinom razvija računalni hardver, laiku bi bilo logično pomisliti da se onaj “lakše” zamjenjivi dio, softver, mora mijenjati još brže. No u stvarnosti ni izdaleka nije tako. Razloga ima više – krenuvši od onog da učenje novog jezika uopće nije trivijalno, preko poslovnog pragmatizma koji ne želi rizik promjene nečeg što funkcionira, sve dok to nije doista nužno i želi isplatiti svoju investiciju, pa i toga što su dobro koncipirani jezici dovoljno fleksibilni i proširivi da mogu ići ukorak s vremenom, s novim potrebama i tehnologijama. C je primjer jezika koji je snažno prisutan i aktualan, iako nije nimalo mlad.

To, naravno, ne znači da za nove jezike nema mjesta, ili da ne treba barem pokušavati gurati nove trendove. Uostalom, svi veći IT giganti tu i tamo “poguraju” neki novi jezik: Go, Swift, Q#, i slični. Dijelom radi otvaranja novih mogućnosti i pojednostavljivanja postojećih, dijelom radi novih tehnologija koje se trebaju u potpunosti iskoristiti, pa dijelom i radi mogućih posve novih načela (tu posebno Q# igra na kartu kvantnih računala).

U svakom slučaju, to nije jedno od onih područja koja su imala šarolik početak, ali su do danas već utonula u pragmatičnu rutinu. Nema sumnje da će se za dekadu ili dvije opet moći napisati ovakav jedan tekst, s raznim čudesima koja nam se u međuvremenu spremaju.

Mobilne tehnologije, naročito smartfoni, nisu odmah iznjedrili svoje nove jezike. Neki od postojećih pokazali su se adekvatnima i proširivima za ono što treba, barem u početku
Mobilne tehnologije, naročito smartfoni, nisu odmah iznjedrili svoje nove jezike. Neki od postojećih pokazali su se adekvatnima i proširivima za ono što treba, barem u početku

 

Za razliku od većine jezika, Cobol koristi vrlo opširne naredbe, što se dugoročno pokazalo više nedostatkom za čitljivost, nego pomoći
Za razliku od većine jezika, Cobol koristi vrlo opširne naredbe, što se dugoročno pokazalo više nedostatkom za čitljivost, nego pomoći