031.1 Lecke 1
Tanúsítvány: |
Web Development Essentials |
---|---|
Verzió: |
1.0 |
Témakör: |
031 Szoftverfejlesztés és webtechnológiák |
Fejezet: |
031.1 A szoftverfejlesztés alapjai |
Lecke: |
1/1 |
Bevezetés
A legelső számítógépek programozása kábelek aljzatokba dugásával történt. A számítástechnikusok hamarosan egy soha véget nem érő kutatásba kezdtek, hogy hogyan lehet a számítógépnek könnyen megmondani, mit tegyen. Ez a fejezet a programozás eszközeit mutatja be. Átveszi, hogy a szöveges utasítások—a programozási nyelvek—milyen kulcsfontosságú módon jelenítik meg azokat a feladatokat, amelyeket a programozó el akar érni, valamint azokat az eszközöket, amelyek a programot a számítógép által futtatható gépi kódnak (machine language) nevezett formába hozzák.
Note
|
Ebben a szövegben a program és az alkalmazás (application) kifejezéseket felcserélhetően használjuk. |
Forráskód
A programozók általában úgy fejlesztenek alkalmazást, hogy szöveges leírást (úgynevezett forráskódot (source code)) írnak a kívánt feladatról. A forráskód gondosan megválasztott programozási nyelven van megírva, amely emberek által is érthető, magas szintű absztrakcióban reprezentálja, mire is képes a számítógép. Olyan eszközöket is kifejlesztettek, amelyek lehetővé teszik, hogy a programozók és a nem-programozók vizuálisan is kifejezzék gondolataikat, de a programozás legfőbb módja továbbra is a forráskód írása.
Ahogy egy természetes nyelvben vannak főnevek, igék és szerkezetek az ötletek strukturált kifejezésére, a programozási nyelvekben a szavak és az írásjelek szimbolikusan ábrázolják, milyen műveletek hajtódnak majd végre a számítógépen.
Ilyen értelemben a forráskód nem sokban különbözik az olyan szövegektől, amelyekben a szerző a természetes nyelv jól bevált szabályait alkalmazza az olvasóval való kommunikációhoz. A forráskód esetében az “olvasó” a számítógép, így a szöveg nem tartalmazhat kétértelműségeket vagy következetlenségeket—még finoman sem.
Mint minden olyan szövegnek, amely bizonyos témákat alaposan megvitat, a forráskódnak is jól felépítettnek és logikusan szervezettnek kell lennie az összetett alkalmazások fejleszétsekor. A nagyon egyszerű programok és didaktikai példák tárolhatók egy egyszerű szöveges fájl néhány sorában, amely a program teljes forráskódját tartalmazza. A bonyolultabb programok több ezer fájlra, azokon belül is több ezer sorra oszthatók.
A professzionális alkalmazások forráskódját különböző mappákba kell rendezni, általában egy adott célhoz társítva. Például egy chat program két mappában osztható fel: az egyik tartalmazza az üzenetek hálózaton keresztüli továbbítását és fogadását kezelő kódfájlokat, a másik pedig az interfészt felépítő és a felhasználói interakciókra reagáló fájlokat. Valójában gyakori, hogy az alkalmazáson belül számos mappa és almappa van a forráskódfájloknak, aszerint, hogy milyen specifikus feladatokhoz vannak rendelve.
Ezenkívül a forráskód nincs mindig külön fájlokban elkülönítve, ha mindent egy nyelven írnak. Webes alkalmazások esetén például egy HTML-dokumentumban lehet beágyazva JavaScript kód, hogy extra funkcionalitást adjon a dokumentumnak.
Kódszerkesztők és az IDE
A forráskód írásának különféle módjai ijesztőek lehetnek, ezért sok fejlesztő kihasználja a program írását és tesztelését segítő eszközöket.
A forrásfájl csak egy egyszerű szöveges fájl — mint ilyen, bármely szövegszerkesztővel szerkeszthető, még a legegyszerűbbel is. A forráskód és az egyszerű szöveg megkülönböztetésének érdekében minden nyelv egy magától értetődő kiterjesztést használ: .c
a C nyelvhez, .py
a Pythonhoz, .js
a JavaScript-hez, stb. A célszerkesztők elég jól értik a népszerű nyelvek forráskódját ahhoz, hogy dőlt betűkkel, színekkel és behúzásokkal tegyék a kódot átláthatóbbá.
Nem minden fejlesztő választ általános célú szerkesztőt a forráskódok szerkesztéséhez. Az integrált fejlesztőkörnyezet (Integrated Development Environment - IDE) olyan szövegszerkesztőt kínál, amelyhez olyan eszközök tartoznak, amelyek segítenek a programozónak elkerülni a szintaktikai hibákat és a nyilvánvaló következetlenségeket. Ezeket a szerkesztőket különösen ajánljuk a kevésbé tapasztalt programozóknak, de tapasztalt programozók is használják őket.
A népszerű IDE-k, mint például a Visual Studio, az Eclipse, és az Xcode intelligensen figyelik a programozó gépelését, gyakran javasolnak szavakat (automatikus kiegészítés) és valós időben ellenőrzik a kódot. Az IDE-k akár automatikus hibakeresést és tesztelést is lehetővé tehetnek a problémák azonosítására, amennyiben megváltozik a forráskód.
Néhány tapasztaltabb programozó kevésbé intuitív szerkesztőket választ, mint például a Vim, amelyek nagyobb rugalmasságot kínálnak és nem szükséges hozzájuk további csomagok telepítése. Ezek a programozók általában külső, önálló eszközöket használnak, amikor olyan szolgáltatásokra van szükségük, amik az IDE-k esetén beépítettek.
Kódkarbantartás
Legyen szó akár IDE-ről, akár önálló eszközökről, mindenféleképpen fontos valamilyen verziókövető rendszer (version control system — VCS) használata. A forráskód folyamatosan fejlődik, mert előre nem látható hibákat kell kijavítani és fejlesztéseket kell beépíteni. Ennek az evolúciónak elkerülhetetlen következménye az, hogy nagy kódbázis esetén ezek a javítások és újítások megzavarhatják az alkalmazás más részeit. Az olyan verziókövető rendszerek, mint a Git, a Subversion, és a Mercurial rögzítik a kódon végrehajtott összes módosítást és azt is, hogy ki végezte azt, lehetővé téve a módosítások nyomonkövetését és a sikertelen módosításból történő helyreállítást.
Ezenkívül a verziókövető rendszerek lehetővé teszik, hogy a csapat minden fejlesztője úgy dolgozzon a forráskódfájlok másolatán, hogy zavarná más programozók munkáját. Miután a forráskód új verzió elkészültek és tesztelve lettek, az egy példányon végrehajtott javításokat vagy fejlesztéseket a csapat többi tagja is beépítheti.
Napjaink legnépszerűbb verziókövető rendszere a Git, amely lehetővé teszi, hogy a repository számos, egymástól független példányát különböző emberek tartsák karban és bárhogy megoszthassák változtatásaikat. Mindazonáltal akár decentralizáált, akár centralizált verziókövető rendszert használunk, a legtöbb csapat fenntart egy megbízható repositoryt, amelynek forráskódjaira támaszkodhat. Számos online szolgáltatás kínál tárhelyet forráskód-repositoryk számára. Ezek közül a legnépszerűbbek a GitHub és a GitLab, de a GNU projekt Savannah rendszere is említést érdemel.
Programozási nyelvek
Nagyszámú programozási nyelv létezik; minden évtizedben újabbak jelennek meg. Minden programozási nyelvnek megvannak a maga szabályai és meghatározott célokra ajánlott őket használni. Bár a nyelvek felületes különbségeket mutatnak szintaxisukban és a kulcsszavaikban, a nyelveket valójában az általuk képviselt mély fogalmi megközelítések különböztetik meg, amiket paradigmáknak nevezünk.
Paradigmák
A paradigmák határozzák meg azokat a premisszákat, amelyeken a programozási nyelv alapul, különösen a forráskód felépítését illetően.
A fejlesztő a nyelvi paradigmából indul ki, hogy megfogalmazza a gép által elvégzendő feladatokat. Ezeket a feladatokat viszont szimbolikusan fejezik ki a nyelv által kínált szavak és szintaktikai konstrukciók.
A programozási nyelv procedurális, ha a forráskódban megadott instrukciók sorrendben hajtódnak végre, mint egy film forgatókönyve. Ha a forráskód függvényekre vagy rutinokra van felosztva, a main rutin gondoskodik a függvények meghívásának sorrendiségéről.
Az alábbi kód egy procedurális nyelv bemutatása. C-ben íródott és geometriai alakzatok oldalát, területét és térfogatát reprezentáló változókat definiál. Az oldal
változó értéke a main()
függvényben van megadva, amely a program futtatásakor meghívott függvény. A terulet
és a terfogat
változókat a negyzet()
és a kocka()
szubrutinok számítják ki, amelyek a main függvény előtt vannak:
#include <stdio.h>
float oldal;
float terulet;
float terfogat;
void negyzet(){ terulet = oldal * oldal; }
void kocka(){ terfogat = terulet * oldal; }
int main(){
oldal = 2;
negyzet();
kocka();
printf("Térfogat: %f\n", terfogat);
return 0;
}
A main()
-ben meghatározott műveletek sorrendje határozza meg a programállapotok szekvenciáját, amelyet az oldal
, a terulet
, és a terfogat
változók jellemeznek. A példa befejeződik, miután megjeleníti a terfogat
értékét a printf
utasítással.
Másfelől az objektumorientált programozás (OOP) paradigmájának fő jellemzője a program állapotának független alállapotokra való szétválasztása. Ezek az alállapotok és a kapcsolódó műveletek az objektumok, amelyeket azért hívunk így, mert többé-kevésbé függetlenek a programon belül és mert meghatározott céljaik vannak.
A különböző paradigmák nem feltétlenül korlátozzák a program által elvégezhető feladat típusát. Az előző példakód átírható az OOP paradigma szernt a C++ nyelv használatával:
#include <iostream>
class Kocka {
float oldal;
public:
Kocka(float o){ oldal = o; }
float terfogat() { return oldal * oldal * oldal; }
};
int main(){
float oldal = 2;
Kocka kocka(oldal);
std::cout << "Térfogat: " << kocka.terfogat() << std::endl;
return 0;
}
A main()
függvény itt is jelen van, de most van egy új szó, a class
, amely bevezeti az objektum definícióját. A Kocka
nevű meghatározott osztály a saját változóit és szubrutinjait tartalmazza. Az OOP-ban egy változót attribútumnak, míg egy szubrutint metódusnak nevezünk.
A példában található összes C++ kód magyarázata túlmutat ezen lecke keretein. Számunkra az a fontos, hogy a Kocka
tartalmazza az oldal
attribútumot és két metódust. A terfogat()
metódus számolja ki a kocka térfogatát.
Lehetőségünk van ugyanabból az osztályból több független objektum létrehozására is és az osztályok más osztályokból is összeállíthatók.
Ne feledjük, hogy ugyanazokat a funkciókat máshogyan is meg lehet írni és a fejezetben szereplő példák túlzottan le vannak egyszerűsítve. A C és a C++ sokkal kifinomultabb képességekkel rendelkeznek, amelyek sokkal összetettebb és praktikusabb konstrukciókat tesznek lehetővé.
A legtöbb programozási nyelv nem ír elő szigorúan egy paradigmát, hanem lehetővé teszi a programozók számára, hogy az egyik vagy másik paradigma különböző aspektusait válasszák. A JavaScript például különböző paradigmák aspektusait tartalmazza. A programozó felbonthatja a programot olyan funkciókra, amelyek nem osztanak meg közös állapotot egymással:
function kocka(oldal){
return oldal*oldal*oldal;
}
console.log("Térfogat: " + kocka(2));
Bár ez a példa hasonló a procedurális programozáshoz, vegyük észre, hogy a függvény a futáshoz szükséges összes információ másolatát kapja meg és mindig ugyanazt az eredményt produkálja ugyanazon paraméter esetén, függetlenül a függvény hatókörén kívül bekövetkező változásoktól. Ezt a funkcionálisnak nevezett paradigmát erősen befolyásolja a matematikai formalizmus, ahol minden művelet önellátó.
Egy másik paradigma a dekleratív nyelveket foglalja magában, amelyek leírják aokat az állapotokat, amelyekben a rendszert szeretnénk látni. Egy dekleratív nyelv képes kitalálni, hogy hogy érjük el a megadott állapotokat. Az SQL-t, az adatbázisok lekérdezésének univerzális nyelvét néha dekleratív nyelvnek nevezik, de valójában egyedülálló helyet foglal el a programozási panteonban.
Nincs univerzális, bármilyen kontextusban használható paradigma. A nyelvválasztást korlátozhatja az is, hogy mely nyelveket támogatja az a platform vagy futtatási környezet, ahol a programot használni fogják.
Egy böngésző által használt webes alkalmazást például JavaScriptben kell megírni, amely a böngészők által általánosan támogatott nyelv. (Néhány más nyelv is használható, mivel ezek a nyelvek JavaScript-konvertálókat is biztosítanak.) Tehát a böngészőhöz—amit néha a webalkalmazás kliensoldalának vagy frontendjének is neveznek—a fejlesztőnek a JavaScriptben megengedett paradigmákat kell használnia. Az alkalmazás szerveroldala vagy backendje, amely a böngészőből érkező kéréseket kezeli, általában más nyelven van programozva; erre a célra a PHP a legnépszerűbb.
Paradigmától függetlenül minden nyelv rendelkezik előre elkészített könyvtárakkal (library), amelyeket be lehet építeni a kódba. A matematikai függvényeket --mint például a példakódban bemutatottakat—nem a semmiből kell implementálni, mivel a nyelv már készen áll a függvény használatára. A JavaScript például a Math
objektumot biztosítja benne a leggyakoribb matematikai műveletekkel.
Az ennél is speciálisabb függvények általában a nyelv gyártójától vagy külsős, független fejlesztőktől érhetők el. Ezek az extra erőforrás-könyvtárak lehetnek forráskód formában; azaz olyan extra fájlokban, amelyek beépíthetők abba a fájlba, ahol használni fogják őket. JavaScriptben a beágyazás az import from
segítségével történik:
import { OrbitControls } from 'modules/OrbitControls.js';
Az ilyen típusú importálást, ahol a beágyazott erőforrás egyben egy forráskódfájl is, leggyakrabban az interpreteres nyelvek esetén használják. A fordítós nyelvek többek között lehetővé teszik az előre lefordított funkciók beépítését a gépi nyelvbe, azaz a fordított könyvtárakba. A következő szekcióban az ilyen típusú nyelvek közötti különbségekről lesz szó.
Fordítók és interpreterek
Azt már tudjuk, hogy a forráskód egy program szimbolikus reprezentációja, amelyet a futtatáshoz le kell fordítani gépi nyelvre.
A fordítást nagyjából kétféleképpen végezhetjük el: a forráskódot előzetesen átalakítjuk a későbbi végrehajtás érdekében, vagy a kódot a végrehajtás pillanatában alakítjuk át. Az első esetben a nyelveket fordított nyelveknek (compiled), a második esetben pedig interpreteres nyelveknek (interpreted) nevezzük. Egyes interpreteres nyelvek opcióként biztosítják a fordítást, hogy a program gyorsabban elindulhasson.
Fordítós nyelvek esetén egyértelmű különbség van a program forráskódja és a számítógép által végrehajtásra kerülő program között. A lefordított program általában csak azon az operációs rendszeren és platformon működik, amelyre lefordították.
Interpreteres nyelvben magát a forráskódot tekintjük a programnak és a gépi nyelvre való konvertálás folyamata átlátható a programozó számára. Interpreteres nyelv esetén a forráskódot általában szkriptnek nevezik. Az interpreter a szkriptet annak a rendszernek a gépi nyelvére fordítja, amelyen fut.
Fordítás és fordítók
A C programozási nyelv az egyik legismertebb példa a fordítós nyelvekre. A C nyelv legnagyobb erőssége a rugalmassága és a teljesítménye. Mind a nagy teljesítményű szuperszámítógépek, mind az otthoni készülékekben található mikrokontrollerek programozhatók C nyelven. További népszerű példák a fordítós nyelvekre a C++ és a C# (C sharp). Ahogy a nevük is mutatja, ezeket a C nyelv inspirálta, de olyan funkciókat tartalmaznak, amelyek támogatják az objektumorientált paradigmát.
Ugyanaz a C vagy C++ program lefordítható különböző platformokra úgy, hogy a forráskódot alig vagy egyáltalán nem kell módosítani. Léteznek platformspecifikus fordítóprogramok, valamint platformok közötti fordítóprogramok, mint például a GCC (a GNU Compiler Collection rövidítése), amelyek számos különböző architektúrára képesek bináris programokat előállítani.
Note
|
Vannak olyan eszközök is, amelyek automatizálják a fordítási folyamatot. Ahelyett, hogy közvetlenül hívná meg a fordítóprogramot, a programozó létrehoz egy fájlt, amelyben megjelöli az automatikusan végrehajtandó különböző fordítási lépéseket. Az erre a célra használt hagyományos eszköz a |
A fordítási folyamat nem minden esetben generál bináris programot gépi nyelven. Vannak olyan fordítós nyelvek, amelyek általánosan bytecode-nak nevezett formátumú programot állítanak elő. A bytecode a szkriptekhez hasonlóan nem platformspecifikus, ezért szükség van egy interpreterre, ami lefordítja azt gépi nyelvre. Ebben az esetben az interpreter programot egyszerűen runtime-nak nevezik.
A Java nyelv ezt a megközelítést alkalmazza, így a Java nyelven írt programok különféle operációs rendszereken is használhatók. A nevétől függetlenül a Java nem kapcsolódik a JavaScripthez.
A bytecode közelebb áll a gépi nyelvhez, mint a forráskód, így a végrehajtása általában viszonylag gyorsabb. Mivel a bytecode végrehajtása során még mindig van egy konverziós folyamat, nehéz ugyanazt a teljesítményt elérni, mint ugyanannak a programnak egy gépi nyelvre lefordított változata esetén.
Interpretálás és interpreterek
Az olyan interpreteres nyelvek esetében, mint a JavaScript, a Python, és a PHP, a programot nem kell előre lefordítani, ami megkönnyíti a fejlesztést és a módosítást. A fordítás helyett a szkriptet egy másik program, az értelmező hajtja végre. Általában a nyelv interpreterét magáról a nyelvről nevezik el. A Python szkriptek interpretere a python
nevű program. A JavaScript interpretere leggyakrabban a böngésző, de a szkriptek lefuttathatók a node
program segítségével böngészőn kívül is. Mivel az interpreteres program minden egyes futáskor bináris utasítássá konvertálódik, általában lassabb, mint a fordítós nyelvi megfelelője.
Semmi nem akadályozza meg azt, hogy ugyanannak az alkalmazásnak különböző nyelveken megírt összetevői legyenek. Ha szükséges, ezek a komponensek egy kölcsönösen érthető alkalmazásprogramozási interfészen (Application Programming Interface - API) keresztül kommunikálhatnak egymással.
A Python nyelv például nagyon kifinomult adatbányászati és adattáblázási képességekkel rendelkezik. A fejlesztő kiválaszthatja a Pythont a program ezen részeinek megírására egy másik nyelvet, például a C++-t a nehezebb numerikus feldolgozásra. Ez a stratégia akkor is alkalmazható, ha nincs olyan API, amely közvetlen kommunikációt tesz lehetővé a két komponens között. A Python nyelven írt program például képes olyan formátumú fájlt generálni, amelyet egy C++-ben írt program használhat.
Bár szinte bármilyen program megírható bármilyen nyelven, a fejlesztőnek azt kell választania, amelyik a leginkább megfelel az alkalmazás céljainak. Ezáltal a már tesztelt és jól dokumentált komponensek újrafelhasználásából profitálhat.
Gyakorló feladatok
-
Milyen típusú programmal szerkeszthetjük a forráskódot?
-
Milyen típusú eszköz segítségével integrálhatjuk ugyanabba a kódbázisba a különböző fejlesztők munkáját?
Gondolkodtató feladatok
-
Tegyük fel, hogy egy 3D-s játékot akarunk írni, amit a böngészőben lehet játszani. A webes alkalmazásokat és játékokat JavaScriptben fejlesztik. Bár az összes grafikus függvényt meg lehet írni a semmiből, sokkal produktívabb, ha egy kész könyvtárat használunk erre a célra. Milyen, harmadik féltől származó könyvtárak nyújtanak segítséget 3D animációhoz JavaScriptben?
-
A PHP-n túl milyen nyelvek használhatók egy webes alkalmazás szerveroldalán?
Összefoglalás
Ez a lecke a szoftverfejlesztés legfontosabb fogalmait tárgyalja. A fejlesztőnek ismernie kell a fontosabb programozási nyelveket és azok megfelelő használatát. Ez a lecke a következő eljárásokat és fogalmakat veszi át:
-
Mi az a forráskód.
-
Forráskód-szerkesztők és kapcsolódó eszközök.
-
Procedurális, objektumorientált, funkcionális és dekleratív programozási paradigmák.
-
A fordítós és az értelmezős nyelvek jellemzői.
Válaszok a gyakorló feladatokra
-
Milyen típusú programmal szerkeszthetjük a forráskódot?
Elvileg bármely program, ami képes egyszerű szöveg szerkesztésére.
-
Milyen típusú eszköz segítségével integrálhatjuk ugyanabba a kódbázisba a különböző fejlesztők munkáját?
Egy forrás- vagy verziókezelő rendszer, mint például a Git.
Válaszok a gondolkodtató feladatokra
-
Tegyük fel, hogy egy 3D-s játékot akarunk írni, amit a böngészőben lehet játszani. A webes alkalmazásokat és játékokat JavaScriptben fejlesztik. Bár az összes grafikus függvényt meg lehet írni a semmiből, sokkal produktívabb, ha egy kész könyvtárat használunk erre a célra. Milyen, harmadik féltől származó könyvtárak nyújtanak segítséget 3D animációhoz JavaScriptben?
Számos JavaScripthez készült 3D grafikus könyvtár van, mint például a threejs és a BabylonJS.
-
A PHP-n túl milyen nyelvek használhatók egy webes alkalmazás szerveroldalán?
A szerveren használt HTTP-kiszolgáló alkalmazás által támogatott bármely nyelv. Néhány példa: Python, Ruby, Perl és maga a JavaScript.