Razvoj aplikacija za Linux u stilu Visual Basica Istaknuto
Iako su tijekom proteklih godina i desetljeća različite verzije Unixa i kasnije Linuxa dobro uhvatile korijene na računalima širom svijeta, stječe se dojam kako je uvijek nedostajao još onaj jedan mali koračić kako bi i među programerima Linux postao omiljen kao različite verzije Windowsa. Nešto pomoću čega bi i manje vješti programeri mogli razvijati različite vrste aplikacija bez potrebe za prevelikim poznavanjem različitih finesa operativnog sustava.
Nešto poput dobro poznatog Visual Basica u Windows svijetu. Vjerovali ili ne, takav alat već neko vrijeme dostupan je programerima (i to besplatno ako se izuzme mogućnost uplate donacije kao poticaja za budući razvoj), a "odaziva" se na ime Gambas.
Što je zapravo Gambas? Riječ je o razvojnom sustavu za pisanje različitih vrsta aplikacija koji se temelji na programskom jeziku BASIC, ali istovremeno sadrži brojne karakteristike modernih programskih jezika, kao na primjer, objektna proširenja jezika. U stvari, autori alata ističu kako je Gambas u velikoj mjeri inspiriran idejama preuzetim od programskog jezika Java, iako sama sintaksa jezika predstavlja dijalekt Basica. Prije detaljnijeg predstavljanja mogućnosti Gambasa spomenimo važnu činjenicu kako je alat konstantno u razvoju potpomognutom prilično brojnom internacionalnom ekipom programera, pa se može računati kako će biti dostupan u budućnosti. Ili drugim riječima, vjerojatnost da počnete razvijati vlastite aplikacije u alatu čije se buduće verzije više neće pojavljivati je trenutno prilično mala. A to je svakako vrlo bitno ako odlučite krenuti u nekakav ozbiljniji rad na vlastitom projektu.
Glavni dijelovi Gambasa
Gambas je sastavljen od nekoliko različitih dijelova koji prilikom razvoja i distribucije vlastite aplikacije djeluju kao skladna cjelina:
- grafički orijentirana razvojna okolina
- prevoditelj izvornog programskog koda
- interpreter prevedenog koda
- arhiver izvršnog oblika programskog koda
- posebni modul za izvođenje Gambas skripti
- brojnih dodatnih biblioteka za uključivanje u vlastite projekte
O grafičkoj razvojnoj okolini nećemo trošiti previše riječi. Sadrži sve uobičajene mogućnosti potrebne za brz i jednostavan razvoj vlastitih Gambas aplikacija, bez prevelikog kompliciranja s dodatnim mogućnostima kao što je to na primjer slučaj kod Eclipse. Ili drugim riječima, ako ste do sada već koristili neku od verzija Visual Basica u Windows okolini, i ovdje ćete se snalaziti kao riba u vodi. Bitno je spomenuti kako razvojna okolina uključuje automatsko predlaganje naredbi tijekom pisanja programa, što bitno pomaže i ubrzava pisanje programskog koda, te alate za pronalaženje i ispravljanje pogrešaka u kodu. Danas manje-više očekivane mogućnosti od moderne razvojne okoline. No ima tu još zanimljivijih pikanterija poput editora vlastitih ikona ili posebnog modula za upravljanje različitim vrstama podržanih baza podataka.
Modul za prevođenje izvornog koda u izvršni djeluje također na uobičajeni način za moderne razvoje alate. Prevođenje izvornog koda ne izvodi se "do kraja", to jest u oblik pogodan za izravno izvođenje na procesoru, nego u poseban oblik "međukoda", čije izvođenje nakon toga preuzima interpreterski dio Gambasa. Prema tvrdnjama autora prevođenje se odvija izuzetno brzo – više stotina tisuća naredbi u sekundi, ali se pri tome ne izvodi nikakva optimizacija. Za optimizaciju prilikom izvođenja aplikacije zadužen je interpreterski dio.
Interpreterski dio Gambasa izvodi međukod nastao prevođenjem izvornog Basic koda. Budući da se kod prevođenja koda, kao što smo već spomenuli, ne izvodi nikakva optimizacija, interpreterski dio odrađuje stvari poput učitavanja pojedinih klasa programskog koda tek kad su one zaista potrebne u programu, međusobno povezivanje klasa te druge slične stvari neophodne za brzo pokretanje i izvođenje aplikacije napisane u Gambasu. Interpreterski dio je za današnje pojmove relativno mali pa na 64 bitnim sustavima ima veličinu od oko 320 KB!
Arhiver je zadužen za pripremu izvršne verzije vlastite aplikacije za distribuciju na druga računala, što osim prevedenog programskog koda uključuje i različite dodatne biblioteke potrebne za normalno izvođenje aplikacije.
Premda je Gambas prije svega namijenjen za razvoj i distribuciju vlastitih aplikacija na Linux platformi, zanimljivo je da ga možete koristiti na sasvim drugačiji način – kao skriptno orijentirani jezik za izvođenje različitih sistemskih operacija u okviru operativnog sustava. U ovom slučaju Basic naredbe upisane u običnu tekstualnu datoteku izvodi poseban modul (scripter). Na taj način uz pomoć Gambasa možete izvoditi prilično složene administrativne operacije u operativnom sustavu, bez potrebe za poznavanjem naredbi operativnog sustava na razini dobrog administratora. Kako to izgleda najlakše je demonstrirati na primjeru iz prateće dokumentacije koji pokazuje korištenje memorije za različite aktivne procese.
Function GetUsedMemory() AS Integer
Dim sRes As String
Dim aRes As String[]
Dim cVal As New Collection
Dim sVal As String
Exec ["cat", "/proc/meminfo"] To sRes
For Each sVal In Split(sRes, "\n", "", True)
aRes = Split(sVal, " ", "", True)
cVal[Left$(aRes[0], -1)] = CInt(aRes[1])
Next
Return cVal!MemTotal - cVal!MemFree - cVal!Buffers - cVal!Cached + cVal!SwapTotal - cVal!SwapFree - cVal!SwapCached
End
Print Subst("Used memory: &1 Kb", GetUsedMemory())
Programski jezik i biblioteke
Ugrađeni dijalekt programskog jezika Basic sadrži sve standardne dijelove modernih programskih jezika kao što su podrška za različite oblike struktura za ponavljanje i uvjetno izvođenje dijelova programskog koda, obradu pogrešaka ili mogućnost pozivanja različitih funkcija iz vanjskih biblioteka, ali i različite mogućnosti u prilogođavanju vlastitih aplikacija za internacionalnu distribuciju (UTF-8 podrška, mogućnost prevođenja vlastite aplikacije i ostalo).
U Gambas je također ugrađena podrška za brojne paradigme objektno orijentiranog razvoja aplikacija kao što su mogućnost kreiranja, korištenja te nasljeđivanja klasa i objekata, odnosno njihovih svojstava, događaja i metoda i tako dalje.
Jedna od najzanimljivijih mogućnosti Gambasa odnosi se korištenje dodatnih komponenti potrebnih za pristup različitim dijelovima operativnog sustava (QT4 toolkit ili GTK+ toolkit), bazama podataka (MySQL, PostgreSQL, SQLite i ODBC), različitim protokolima korištenim na razini operativnog sustava (HTTP, FTP, SMTP) i slično. Takve komponente mogu biti pripremljene u programskim jezicima C ili C++ (priložen izvorni kod), ali i u samom Gambasu. Naravno za prvi tip komponenti morate biti malo iskusniji Linux programer (treba li vam onda uopće Gambas), dok druge predstavljaju standardne Gambas projekte, koji se po potrebi pozivaju iz novog Gambas projekta.
Evo i poslastice. Malo prije spomenuto je kako Gambas podržava rad s nekoliko različitih sustava za upravljanje bazama podataka. Obično se u različitim implementacijama drugih programskih jezika za pristup svakoj vrsti baze koriste posebne biblioteke karakteristične za tu verziju baze. Kod Gambasa je cijela stvar bitno pojednostavljena – za pristup svim vrstama baza koristi se jedinstvene API funkcije što znači da je prebacivanje između korištenja različitih baza podataka trivijalno u odnosu na neke druge razvojne alate.
Treba li mi to uopće?
Prije nego što navedeno nekoliko karakterističkih primjera programskog koda, da bi stekli uvid u to kako se određene stvari rješavaju u Gambasu, odgovorimo na najvažnije pitanje – treba li mi to uopće? Ako ostavimo po strani čisto intelektualnu znatiželju u upoznavanju novog razvojnog sustava, ili ideju o razvoju ozbiljnije aplikacije za Linux platformu (da ne zaboravimo spomenuti trenutno podržane platforme: Archlinux, Debian, Fedora, Mandriva, SuSE, Slackware, Ubuntu) za globalno tržište, autor teksta će spomenuti slučaj koji mu se već dva puta dogodio u programerskoj praksi.
U oba slučaja korisnik je zahtijevao izradu relativno jednostavnog programa, koji je trebao preko specijaliziranog korisničkog sučelja (moj dio posla) na standardnom desktop računalu upravljati posebno projektiranim hardverskim uređajem od strane samog korisnika. Naravno, rok za izradu je bio “jučer” (dakle čim prije), što znači da nije bilo vremena za upoznavanje nekih bitno različitih alata za razvoj od onih koje sam već poznavao. U budžetu projekta bila su planirana sredstva potrebna za razvoj i proizvodnju specijaliziranih hardverskih uređaja te nabavku većeg broja računala potrebnih za nadzor nad uređajima. Preostalo je još samo da se dogovorimo oko cijene izrade softvera na strani računala. I gdje je nastao glavni problem? Cijenu koju sam predložio za izradu softvera korisnik bi također prihvatio, ali sam onda spomenuo da za svako računalo (ako želimo sve raditi legalno), treba nabaviti odgovarajuću licencu Windowsa. I kad je korisnik pomnožio cijenu licence u jednom slučaju s 20, a u drugom sa najmanje 100, sve skupa je palo u vodu. Ni jedan od potencijalna dva korisnika nije želio potrošiti tolika dodatna sredstva za Windowse, koji bi bili korišteni isključivo zato da se na njima izvodi moja Windows aplikacija.
E da sam tada bar znao za Gambas te mogao predložiti razvoj aplikacije za neku od podržanih, besplatnih verzija Linuxa, jer se doista nije radilo o složenim zahtjevima! Ali sad bar znam rješenje za slijedeću takvu priliku, ako se pojavi. A možda nešto slično zatreba i vama!
Nekoliko karakterističnih primjera u Gambasu
1. Primjer koda koji vraća distribuciju Linuxa na kojem se izvodi program
Static Private Sub GetDistribution() As String
Dim cDist As Collection = ["lsb-release": "/etc/lsb-release", "vector": "/etc/vector-version", "slackware": "/etc/slackware-version", "debian": "/etc/debian_version",
"redhat": "/etc/redhat-release", "arch": "/etc/arch-release", "SuSE": "/etc/os-release", "gentoo": "/etc/gentoo-release", "conectiva": "/etc/conectiva-release",
"mandriva": "/etc/mandriva-release", "pardus": "/etc/pardus-release", "kanotix": "/etc/kanotix-release"]
Dim sPath As String
Dim sDistro As String
Dim cData As Collection
Dim iPos As Integer
For Each sPath In cDist
sDistro = cDist.Key
If Not Exist(sPath) Then Continue
If sDistro = "lsb-release" Then
cData = ReadLsbRelease(sPath)
sDistro = cData["DISTRIB_DESCRIPTION"]
If sDistro Then Return sDistro
Return cData["DISTRIB_ID"] & " " & cData["DISTRIB_RELEASE"]
Else
Return sDistro & " " & Trim(File.Load(sPath))
Endif
Next
If Exist("/etc/issue") Then
sDistro = File.Load("/etc/issue")
If sDistro Then
iPos = InStr(sDistro, "\\")
If iPos Then sDistro = Left(sDistro, iPos - 1)
Endif
Else
Exec ["uname", "-s"] To sDistro
Endif
Return Trim(sDistro)
End
2. Primjer dijela koda Gambas komponente za rukovanje tablicama u MySQL bazi podataka
' Gambas class file
Export
Create Static
Private $hMaintenance As _TableMaintenance
Property Read Maintenance As _TableMaintenance
Public Procedure Modify(Table As String, Optional Database As String = modMain.$Connection.Name, Optional Engine As String = modMain.$Connection.MySQL.Engine, Optional Charset As String = modMain.$Connection.MySQL.Charset)
modMain.$Query = "ALTER TABLE `" & Database & "`.`" & Table & "`"
modMain.$Query &= " ENGINE = " & Engine
modMain.$Query &= " CHARACTER SET = " & Charset
modMain.RunQuery(modMain.$Query)
End
Public Procedure ModifyColumn(Table As String, Action As String, Optional Symbol As String, Optional Definition As String, Optional Database As String = modMain.$Connection.Name)
Action = Upper(Action)
modMain.$Query = "ALTER TABLE `" & Database & "`.`" & Table & "` "
Select (Action)
Case "DROP"
modMain.$Query &= Action & " COLUMN `" & Symbol & "` "
Case "ADD", "MODIFY", "CHANGE", "ALTER"
modMain.$Query &= Action & " COLUMN `" & Symbol & "` " & Definition
Case "CHARACTER SET"
modMain.$Query &= "CONVERT TO CHARACTER SET " & Definition
Case "ENGINE"
modMain.$Query &= "ENGINE " & Definition
Default
Error.Raise("Invalid Action")
End Select
modMain.RunQuery(modMain.$Query)
End
Public Procedure Add(Table As String, Optional Engine As String = modMain.$Connection.MySQL.Engine, Optional Charset As String = modMain.$Connection.MySQL.Charset, Optional Database As String = modMain.$Connection.Name)
'Make the table statement
modMain.$Query = "CREATE TABLE `" & Database & "`.`" & Table & "` ("
modMain.$Query &= modMain.ArrayToString(modMain.$FieldDefinition, False)
If modMain.$PrimaryKey Then modMain.$Query &= modMain.$PrimaryKey
If modMain.$Index.Count Then modMain.$Query &= ", " & modMain.ArrayToString(modMain.$Index, False)
If modMain.$ForeignKey.Count Then modMain.$Query &= ", " & modMain.ArrayToString(modMain.$ForeignKey, False)
modMain.$Query &= ") ENGINE = " & Engine & " DEFAULT CHARSET = " & Charset
'Clears all the information from this table to be ready for the next one
modMain.$FieldDefinition.Clear()
modMain.$PrimaryKey = Null
modMain.$ForeignKey.Clear()
modMain.$Index.Clear()
'Runs the query
modMain.RunQuery(modMain.$Query)
End
3. Primjer dijela koda Gambas komponente za crtanje grafikona
Public Sub Draw()
Dim iClientHeight, iClientWidth As Integer
Dim iTitleHeight As Integer
Dim iStaticSpace As Integer
'Draw.Font.Size = 12 * (Chart.Width / 640)
_fProportionnal = IIf(Me.Width <= Me.Height, Me.Width / (Desktop.Height * 2 / 3), Me.Height / (Desktop.Height * 2 / 3))
If Not $bProportionnal Then _fProportionnal = 1.0
iStaticSpace = 5 * Me._fProportionnal
'Draw the Legend and get the graph caneva size
$oLegend.Draw($bLegendSeries)
'Draw The Title
iTitleHeight = iStaticSpace
If Not IsNull(Me.Title.Text) And Me.Title.Visible Then
'Draw.Font.Grade = 4
Draw.Font = $oTitle.Font
Draw.Font.Size = $oTitle.Font.Size * _fProportionnal
iTitleHeight = Draw.Font.Height * 2
Endif
iClientWidth = Me.Width - $oLegend._Width - 2 * iStaticSpace
iClientHeight = Me.Height - $oLegend._Height - 2 * iStaticSpace
Draw.FillColor = color.White
If $iBorder Then Draw.Rect(iStaticSpace, iStaticSpace, iClientWidth - iStaticSpace, iClientHeight - iStaticSpace)
'Draw.Font.Grade = 4
$oGraphStyle.Draw(iStaticSpace, iTitleHeight, iClientWidth, iClientHeight - iTitleHeight - iStaticSpace)
If Not IsNull(Me.Title.Text) And Me.Title.Visible Then
Draw.ForeGround = Color.Black
Draw.Font.Size = Me.Title.Font.Size * _fProportionnal
Draw.Text(Me.Title.Text, iStaticSpace, iStaticSpace, iClientWidth, iTitleHeight, Align.Center)
Endif
End
Nenad Crnko
Izvor: Vidi 245/246
Za ovaj i brojne druge korisne i zanimljive sadržaje potražite tiskano izdanje časopisa Vidi, dostupnog na svim kioscima.
Vezani članci
- Prezentirani rezultati projekta OOP4FUN na FOI-ju: cilj je bio osnaživanje srednjoškolskih nastavnika u podučavanju objektno orijentiranog programiranja
- Projekti i praksa: most između teorije i karijere
- Tech Lead Nikola Buhiniček iz agencije Productive o AI alatima za programere
- Zagrebački startup privukao 1,7 milijuna kuna ulaganja
- Online edukacija: Osnove programiranja u programskom jeziku Python