diff --git a/órai anyagok/common/webfejl.sty b/órai anyagok/common/webfejl.sty index 5ed8277..107df12 100644 --- a/órai anyagok/common/webfejl.sty +++ b/órai anyagok/common/webfejl.sty @@ -179,6 +179,7 @@ megtekintéséhez!},icon=Paperclip} } % Kisebb betűméret a slide-okhoz +\setbeamerfont{section in head/foot}{size=\tiny} \setbeamerfont{frametitle}{size=\normalsize} \setbeamerfont{framesubtitle}{size=\small} \setbeamerfont{block title}{size=\small} diff --git a/órai anyagok/extras/sections/00-bevezetes.tex b/órai anyagok/extras/sections/00-bevezetes.tex new file mode 100644 index 0000000..410bc46 --- /dev/null +++ b/órai anyagok/extras/sections/00-bevezetes.tex @@ -0,0 +1,92 @@ +\section{Bevezetés} + +\begin{frame}{Miről szól ez az anyag?} +\footnotesize +Ez egy \textbf{önállóan is végigkövethető, kiegészítő} tananyag a TypeScriptről. Nem feltételezi, hogy láttad a 2. hét TypeScript diáit -- a legelejétől indulunk, majd jóval mélyebbre megyünk, mint amit egy heti óra kerete engedne. + +\begin{itemize} +\item Ha még sosem láttál TypeScript kódot, nyugodtan kezdd itt +\item Ha a 2. héten már megismerted az alapokat, néhány dia ismétlés lesz -- utána viszont új anyag következik +\item A cél: hogy magabiztosan tudj TypeScript kódot olvasni és írni, ne csak felismerni +\end{itemize} + +\begin{alertblock}{Nem kötelező anyag} +Ez a diasor \emph{nem} számonkérendő tananyag -- annak szól, aki jobban meg szeretné érteni a TypeScript-et, mint amire a heti órák ideje engedne. +\end{alertblock} +\end{frame} + +\begin{frame}{Mi az a TypeScript, és miért érdemes használni?} +\footnotesize +A JavaScript \textbf{gyengén típusos} nyelv: egy változó bármikor bármilyen típusú értéket felvehet, és a legtöbb hiba csak futás közben derül ki. A \textbf{TypeScript} (Microsoft, 2012) a JavaScript egy kiterjesztése, ami \emph{statikus típusrendszert} ad hozzá -- a kód végül mindig sima JavaScript-té fordul le. + +\begin{itemize} +\item A típushibák nagy része már íráskor / fordításkor kiderül, nem futás közben, esetleg egy élő felhasználónál +\item Az IDE (VS Code, stb.) pontos kódkiegészítést, azonnali hibajelzést tud adni +\item A kód önmagát dokumentálja: egy függvény szignatúrájából látszik, mit vár és mit ad vissza +\item Nagyobb csapatban, nagyobb, hosszú távon karbantartott kódbázisban különösen megtérül +\end{itemize} + +\begin{block}{Fontos} +A TypeScript \emph{opcionális, fokozatosan bevezethető} réteg -- egy meglévő JavaScript projektbe fájlonként is átállhatunk rá. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Telepítés és a \texttt{tsconfig.json}} +\footnotesize +A TypeScript fordítót (\texttt{tsc}) npm csomagként telepítjük, majd egy konfigurációs fájlt hozunk létre, ami megmondja a fordítónak, hogyan viselkedjen. + +\begin{block}{Telepítés} +\begin{verbatim} +npm install -D typescript +npx tsc --init +\end{verbatim} +\end{block} + +\begin{block}{A \texttt{tsconfig.json} legfontosabb mezői} +\begin{itemize} +\item \texttt{target} -- milyen JavaScript verzióra fordítson (pl. \texttt{"ES2020"}) +\item \texttt{module} -- modulrendszer (\texttt{"commonjs"} vagy \texttt{"esnext"}) +\item \texttt{outDir} / \texttt{rootDir} -- hova kerüljön a lefordított kód, honnan olvasson forrást +\item \texttt{strict} -- bekapcsolja az összes szigorú típusellenőrzést (\emph{erősen ajánlott} \texttt{true}) +\end{itemize} +\end{block} +\end{frame} + +\begin{frame}[fragile]{Futtatás fejlesztés közben} +\footnotesize +A \texttt{.ts} fájlokat sem a böngésző, sem a Node.js nem futtatja közvetlenül -- előbb JavaScript-té kell fordítani. Fejlesztés közben ezt kényelmesebb eszközökkel oldjuk meg, mint kézzel fordítani minden mentés után. + +\begin{block}{Klasszikus fordítás} +\begin{verbatim} +npx tsc # egyszeri forditas +npx tsc --watch # automatikusan ujrafordit mentes utan +\end{verbatim} +\end{block} + +\begin{block}{Közvetlen futtatás (nincs külön fordítási lépés)} +\begin{verbatim} +npx tsx index.ts +\end{verbatim} +A \texttt{tsx} (és a régebbi \texttt{ts-node}) memóriában fordítja és rögtön futtatja is a kódot -- ez a legkényelmesebb fejlesztés közben. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Az első \texttt{.ts} fájl} +\footnotesize +Nézzük meg, hogyan néz ki egy egyszerű, típusozott TypeScript fájl -- ez lesz az alapja a következő diáknak, ahol részletesen végigvesszük az egyes típusokat. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +function add(a: number, b: number): number { + return a + b; +} + +const result = add(2, 3); +console.log(`Az eredmeny: ${result}`); + +// add('2', 3); -- ez forditasi hibat adna! +\end{lstlisting} + +\begin{block}{Amit érdemes megfigyelni} +A paraméterek és a visszatérési érték típusát kettősponttal adjuk meg. Ha rossz típusú értékkel próbálnánk hívni a függvényt, a fordító \emph{azonnal} hibát jelezne -- még mielőtt a kód lefutna. +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/01-alaptipusok.tex b/órai anyagok/extras/sections/01-alaptipusok.tex new file mode 100644 index 0000000..00428c9 --- /dev/null +++ b/órai anyagok/extras/sections/01-alaptipusok.tex @@ -0,0 +1,99 @@ +\section{Alaptípusok} + +\begin{frame}[fragile]{Primitív típusok} +\footnotesize +A TypeScript primitív típusai megegyeznek a JavaScript primitív értékeivel -- csak most a fordító is számon tartja, melyik változó melyik típusú. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +let name: string = 'Anna'; +let age: number = 25; +let isActive: boolean = true; +let id: bigint = 123n; +let nothing: null = null; +let notSet: undefined = undefined; +\end{lstlisting} + +\begin{itemize} +\item \texttt{string}, \texttt{number}, \texttt{boolean} -- a leggyakrabban használt három típus +\item \texttt{null} és \texttt{undefined} önálló típusként is léteznek, de gyakrabban más típusokkal együtt (pl. \texttt{string | null}) fordulnak elő +\item \texttt{bigint} és \texttt{symbol} ritkábban használt, speciális típusok +\end{itemize} +\end{frame} + +\begin{frame}[fragile]{Tömbök és tuple-ök} +\footnotesize +A tömböknél meg kell adni, milyen típusú elemeket tartalmaznak. A \textbf{tuple} egy speciális, rögzített hosszúságú és típussorrendű tömb. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +let names: string[] = ['Anna', 'Bela']; +let scores: Array = [10, 20, 30]; + +// Tuple: pontosan ket elem, elore rogzitett tipussal +let point: [number, number] = [3, 5]; +let entry: [string, number] = ['age', 25]; +\end{lstlisting} + +\begin{block}{Miért hasznos a tuple?} +Egy \texttt{[string, number]} tuple azonnal jelzi, hogy pontosan két elemet várunk, meghatározott sorrendben -- ellentétben egy sima \texttt{(string | number)[]} tömbbel, ami bármilyen hosszú és sorrendű keveréket engedne. +\end{block} +\end{frame} + +\begin{frame}[fragile]{\texttt{any}, \texttt{unknown} és \texttt{never}} +\footnotesize +Három speciális típus, amit érdemes megkülönböztetni -- könnyű összekeverni őket, de nagyon más a szerepük. + +\begin{itemize} +\item \textbf{\texttt{any}:} teljesen kikapcsolja a típusellenőrzést erre a változóra -- gyakorlatilag "visszatérünk sima JavaScript-hez". Kerülendő, csak végső esetben használjuk! +\item \textbf{\texttt{unknown}:} szintén "bármi lehet", de \emph{használat előtt} típusellenőrzést (narrowing) kényszerít ki -- ez a biztonságos alternatívája az \texttt{any}-nek +\item \textbf{\texttt{never}:} olyan érték típusa, ami \emph{sosem} fordulhat elő -- pl. egy függvény, ami mindig hibát dob, vagy egy végtelen ciklus visszatérési típusa +\end{itemize} + +\begin{alertblock}{Ökölszabály} +Ha típust nem tudsz vagy nem akarsz megadni, használj \texttt{unknown}-t \texttt{any} helyett -- így a fordító legalább kikényszeríti, hogy ellenőrizd az értéket, mielőtt használnád. +\end{alertblock} +\end{frame} + +\begin{frame}[fragile]{Type inference -- amikor nem kell kiírni a típust} +\footnotesize +A TypeScript sok esetben \emph{magától kikövetkezteti} (infer) a típust a kezdőértékből -- nem kell mindenhol explicit típust írnunk. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +let name = 'Anna'; // TypeScript tudja: ez string +let age = 25; // TypeScript tudja: ez number + +name = 42; // Hiba! nem lehet number-t string-nek adni +\end{lstlisting} + +\begin{block}{Mikor írjunk mégis explicit típust?} +Függvényparamétereknél szinte mindig érdemes (a fordító nem tudja kitalálni, mit fogunk hívni), de egyszerű, azonnal értékadott lokális változóknál nyugodtan hagyatkozhatunk az inferálásra. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Type alias -- saját név egy típusnak} +\footnotesize +A \texttt{type} kulcsszóval nevet adhatunk egy típusnak -- ez különösen hasznos, ha egy összetettebb típust (pl. union típust, amit a 4. fejezetben veszünk) többször is használunk. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +type UserId = number; +type Username = string; + +function getUser(id: UserId): Username { + return 'Anna'; +} +\end{lstlisting} + +Ez még nem sokkal több, mint egy elnevezés -- de amint a következő fejezetekben összetettebb típusokat (union, interfész) ismerünk meg, a \texttt{type} igazán hasznossá válik. +\end{frame} + +\begin{frame}{Összefoglalás -- Alaptípusok} +\footnotesize +\begin{block}{Alaptípusok} +\begin{itemize} +\item Primitívek: \texttt{string}, \texttt{number}, \texttt{boolean}, \texttt{null}, \texttt{undefined}, \texttt{bigint} +\item Tömbök: \texttt{string[]}; Tuple: rögzített hosszú/sorrendű tömb, pl. \texttt{[string, number]} +\item \texttt{any} (kerülendő) vs \texttt{unknown} (biztonságos) vs \texttt{never} (sosem előforduló érték) +\item Type inference: a fordító sokszor magától kitalálja a típust +\item \texttt{type} -- nevet adhatunk egy típusnak, újrafelhasználhatóvá téve azt +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/02-interface-type.tex b/órai anyagok/extras/sections/02-interface-type.tex new file mode 100644 index 0000000..90325ca --- /dev/null +++ b/órai anyagok/extras/sections/02-interface-type.tex @@ -0,0 +1,90 @@ +\section{Interface/Type} + +\begin{frame}[fragile]{Interfész alapok} +\footnotesize +Az \texttt{interface} egy objektum \emph{alakját} (mely mezők, milyen típussal) írja le. Ahol egy interfészt típusként megadunk, a fordító ellenőrzi, hogy az érték tényleg megfelel-e neki. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +interface User { + id: number; + name: string; + email: string; + nickname?: string; // opcionalis mezo + readonly createdAt: Date; // csak olvashato +} + +const user: User = { + id: 1, + name: 'Anna', + email: 'anna@example.com', + createdAt: new Date(), +}; +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]{Opcionális és csak olvasható mezők} +\footnotesize +Két apró, de nagyon hasznos jelölés van, amivel pontosabbá tehetjük az interfészünket: a \texttt{?} és a \texttt{readonly}. + +\begin{itemize} +\item \textbf{\texttt{mezo?: tipus}} -- a mező elhagyható, de ha megadjuk, a megjelölt típusúnak kell lennie +\item \textbf{\texttt{readonly mezo: tipus}} -- a mező az objektum létrehozása után nem módosítható +\end{itemize} + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +const user: User = { id: 1, name: 'Anna', + email: 'a@b.com', createdAt: new Date() }; + +user.createdAt = new Date(); // Hiba! readonly mezo +\end{lstlisting} + +\begin{block}{Miért hasznos?} +A \texttt{readonly} segít elkerülni azokat a hibákat, amikor véletlenül módosítunk egy olyan mezőt, aminek soha nem szabadna változnia (pl. egy azonosítót). +\end{block} +\end{frame} + +\begin{frame}[fragile]{Interfészek kiterjesztése} +\footnotesize +Egy interfész \texttt{extends}-szel örökölheti egy másik interfész mezőit -- így elkerülhetjük az ismétlődést hasonló, egymásra épülő alakoknál. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +interface Animal { + name: string; + age: number; +} + +interface Dog extends Animal { + breed: string; +} + +const myDog: Dog = { name: 'Buksi', age: 3, breed: 'labrador' }; +\end{lstlisting} + +A \texttt{Dog} interfész mindent örököl az \texttt{Animal}-tól, és hozzáad egy \texttt{breed} mezőt -- pontosan úgy, ahogy egy osztály is örökölhet egy másiktól. +\end{frame} + +\begin{frame}{\texttt{interface} vs \texttt{type} -- mikor melyiket?} +\footnotesize +A két eszköz sokban hasonlít, és a legtöbb egyszerű esetben szinte mindegy, melyiket választjuk -- de van néhány különbség, ami eldöntheti a választást. + +\begin{itemize} +\item \textbf{\texttt{interface}:} csak objektum alakok leírására való; több, azonos nevű interfész deklaráció automatikusan összeolvad (declaration merging); \texttt{extends}-szel bővíthető +\item \textbf{\texttt{type}:} bármilyen típust elnevezhet -- objektumot, uniót, primitívet is; nem olvad össze automatikusan, de intersection-nel (\texttt{\&}) kombinálható +\end{itemize} + +\begin{block}{Gyakorlati ökölszabály} +Objektum \emph{alakokhoz} (pl. egy adatmodell) válaszd az \texttt{interface}-t -- olvashatóbb hibaüzeneteket ad. Union típusokhoz (a következő fejezet) csak a \texttt{type} jöhet szóba. +\end{block} +\end{frame} + +\begin{frame}{Összefoglalás -- Interface és Type} +\footnotesize +\begin{block}{Interface és Type} +\begin{itemize} +\item \texttt{interface}: objektum alakjának leírása -- mezők, opcionális (\texttt{?}) és readonly mezők +\item \texttt{extends}: interfészek egymásra építése, kódismétlés elkerülése +\item \texttt{type}: bármilyen típusnak adhatunk nevet, nemcsak objektumoknak +\item Objektum alakoknál \texttt{interface}, union típusoknál \texttt{type} -- ökölszabályként +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/03-fuggvenyek.tex b/órai anyagok/extras/sections/03-fuggvenyek.tex new file mode 100644 index 0000000..e966c5a --- /dev/null +++ b/órai anyagok/extras/sections/03-fuggvenyek.tex @@ -0,0 +1,88 @@ +\section{Függvények} + +\begin{frame}[fragile]{Függvények típusozása} +\footnotesize +Egy TypeScript függvénynél mind a paraméterek, mind a visszatérési érték típusát megadhatjuk -- a visszatérési típust a fordító a legtöbbször ki is következteti, de explicit kiírva olvashatóbb, és véd az elgépelés ellen. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +function multiply(a: number, b: number): number { + return a * b; +} + +// Nincs visszatero ertek -> void +function logMessage(message: string): void { + console.log(message); +} +\end{lstlisting} + +\begin{block}{Miért érdemes kiírni a visszatérési típust?} +Ha véletlenül rossz típusú értéket adnánk vissza (pl. \texttt{string}-et \texttt{number} helyett), a fordító azonnal jelezné a hibát -- még mielőtt bárhol meghívnánk a függvényt. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Opcionális és alapértelmezett paraméterek} +\footnotesize +Nem minden paraméter kötelező -- a JavaScript-hez hasonlóan itt is megadhatunk alapértelmezett értéket, vagy jelölhetjük egy paramétert opcionálisként. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +function greet(name: string, greeting: string = 'Szia'): string { + return `${greeting}, ${name}!`; +} + +function createUser(name: string, nickname?: string) { + return { name, nickname: nickname ?? name }; +} + +greet('Anna'); // "Szia, Anna!" +greet('Anna', 'Hello'); // "Hello, Anna!" +\end{lstlisting} + +\begin{alertblock}{Fontos sorrend} +Az opcionális (\texttt{?}) és alapértelmezett paraméterek csak a kötelező paraméterek \emph{után} szerepelhetnek a paraméterlistában. +\end{alertblock} +\end{frame} + +\begin{frame}[fragile]{Függvénytípusok -- callback-ek típusozása} +\footnotesize +Amikor egy függvény egy másik függvényt vár paraméterként (pl. egy callback-et), magának a "függvény alaknak" is megadhatjuk a típusát. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +type MathOperation = (a: number, b: number) => number; + +function calculate(a: number, b: number, op: MathOperation): number { + return op(a, b); +} + +const sum: MathOperation = (a, b) => a + b; +calculate(2, 3, sum); // 5 +\end{lstlisting} + +Ez különösen hasznos Express.js-ben: egy route handler is pontosan egy ilyen "függvény alakú" típus (\texttt{(req, res) => void}). +\end{frame} + +\begin{frame}{Function overloads -- röviden} +\footnotesize +Néha egy függvény többféle paraméter-kombinációval is hívható, és a visszatérési típus a bemenettől függ. Erre valók a \textbf{overloads}: több szignatúra deklarálása egyetlen implementáció előtt. + +\begin{itemize} +\item Több "fejlécet" (szignatúrát) írunk le, majd egyetlen tényleges implementációt +\item A hívó fél oldaláról úgy tűnik, mintha több, különböző típusú változata lenne a függvénynek +\item Ritkán szükséges kezdőként -- inkább unió típusokkal (következő fejezet) old meg a legtöbb esetet +\end{itemize} + +\begin{block}{Gyakorlati tanács} +Ha csak most ismerkedsz a TypeScript-tel, nem kell aktívan használnod az overloads-ot -- elég felismerni, ha egy könyvtár dokumentációjában találkozol vele. +\end{block} +\end{frame} + +\begin{frame}{Összefoglalás -- Függvények} +\footnotesize +\begin{block}{Függvények TypeScript-ben} +\begin{itemize} +\item Paraméterek és visszatérési típus típusozása -- \texttt{void}, ha nincs visszatérő érték +\item Alapértelmezett érték (\texttt{= ...}) és opcionális paraméter (\texttt{?}), mindig a kötelezők után +\item Függvénytípusok: \texttt{(a: number, b: number) => number} -- callback-ek típusozásához +\item Overloads: több szignatúra egy implementációhoz -- ritkán szükséges kezdőként +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/04-union-intersection.tex b/órai anyagok/extras/sections/04-union-intersection.tex new file mode 100644 index 0000000..adb240d --- /dev/null +++ b/órai anyagok/extras/sections/04-union-intersection.tex @@ -0,0 +1,90 @@ +\section{Union/Intersection} + +\begin{frame}[fragile]{Union típusok -- "vagy ez, vagy az"} +\footnotesize +Egy \textbf{union} típus (\texttt{|} jellel) azt fejezi ki, hogy egy érték \emph{többféle} típus egyike lehet. Ez az egyik legtöbbet használt eszköz a valós TypeScript kódban. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +type Id = string | number; + +function printId(id: Id) { + console.log(`Az azonosito: ${id}`); +} + +printId(123); // OK +printId('abc-123'); // OK is +\end{lstlisting} + +\begin{block}{Gyakori példa} +\texttt{type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';} -- ilyenkor a fordító nem enged elgépelt, érvénytelen metódusnevet. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Type narrowing -- a típus leszűkítése} +\footnotesize +Ha egy változó union típusú, a fordító csak azokat a műveleteket engedi rajta, amik \emph{minden} lehetséges típusnál érvényesek -- amíg nem szűkítjük le (narrowing), melyik konkrét típusról van szó. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +function printId(id: string | number) { + if (typeof id === 'string') { + console.log(id.toUpperCase()); // itt mar biztos string + } else { + console.log(id.toFixed(2)); // itt mar biztos number + } +} +\end{lstlisting} + +\begin{itemize} +\item \texttt{typeof} -- primitív típusok megkülönböztetésére (\texttt{string}, \texttt{number}, stb.) +\item \texttt{instanceof} -- osztálypéldányok megkülönböztetésére +\item \texttt{in} -- egy adott mező meglétének ellenőrzésére egy objektumon +\end{itemize} +\end{frame} + +\begin{frame}[fragile]{Intersection típusok -- "ez is, az is"} +\footnotesize +Az \textbf{intersection} típus (\texttt{\&} jellel) ennek épp az ellentéte: egy érték \emph{egyszerre} feleljen meg több típusnak is -- a mezők összeadódnak. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +interface HasId { + id: number; +} +interface HasName { + name: string; +} + +type Entity = HasId & HasName; + +const user: Entity = { id: 1, name: 'Anna' }; +\end{lstlisting} + +Az \texttt{Entity} típusú értéknek \emph{mindkét} interfész mezőit tartalmaznia kell -- ez hasznos, ha kisebb, újrafelhasználható "építőelemekből" rakunk össze nagyobb típusokat. +\end{frame} + +\begin{frame}[fragile]{Literal típusok} +\footnotesize +A TypeScript-ben nemcsak \texttt{string} vagy \texttt{number} lehet egy típus, hanem egy \emph{konkrét érték} is -- ezt hívjuk literal típusnak. Union-nal kombinálva rendkívül kifejező, önmagát dokumentáló kódot kapunk. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +type Status = 'pending' | 'active' | 'closed'; + +function setStatus(status: Status) { + // csak a harom felsorolt string-et fogadja el +} + +setStatus('active'); // OK +setStatus('done'); // Hiba! nincs ilyen Status +\end{lstlisting} +\end{frame} + +\begin{frame}{Összefoglalás -- Union és Intersection} +\footnotesize +\begin{block}{Union és Intersection típusok} +\begin{itemize} +\item Union (\texttt{|}): "vagy ez, vagy az" -- egy érték többféle típus egyike lehet +\item Type narrowing: \texttt{typeof}/\texttt{instanceof}/\texttt{in} -- leszűkítjük, melyik konkrét típusról van szó +\item Intersection (\texttt{\&}): "ez is, az is" -- több típus mezői összeadódnak +\item Literal típusok: konkrét értékek típusként, gyakran union-nal kombinálva (pl. HTTP metódusok) +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/05-generics.tex b/órai anyagok/extras/sections/05-generics.tex new file mode 100644 index 0000000..0ab32d0 --- /dev/null +++ b/órai anyagok/extras/sections/05-generics.tex @@ -0,0 +1,89 @@ +\section{Generikusok} + +\begin{frame}[fragile]{A probléma, amit a generikák oldanak meg} +\footnotesize +Képzeljünk el egy függvényt, ami egy tömb első elemét adja vissza -- de szeretnénk, hogy \emph{bármilyen} típusú tömbre működjön, miközben megőrizzük a típusinformációt. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +function firstOfNumbers(arr: number[]): number { + return arr[0]; +} +function firstOfStrings(arr: string[]): string { + return arr[0]; +} +// ...es igy tovabb minden tipusra kulon fuggveny? +\end{lstlisting} + +\begin{alertblock}{A probléma} +\texttt{any}-jal megoldhatnánk, de akkor elveszítenénk a típusbiztonságot: a fordító többé nem tudná, mit ad vissza a függvény. +\end{alertblock} +\end{frame} + +\begin{frame}[fragile]{Generikus függvények} +\footnotesize +A \textbf{generikus típus} egy "típusparamétert" (jellemzően \texttt{T}) vezet be, amit a híváskor a konkrét típus tölt ki -- így egyetlen függvény működik bármilyen típusra, típusbiztonság elvesztése nélkül. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +function first(arr: T[]): T { + return arr[0]; +} + +const n = first([1, 2, 3]); // T = number +const s = first(['a', 'b', 'c']); // T = string +\end{lstlisting} + +A TypeScript minden híváskor kikövetkezteti, mi legyen \texttt{T} -- a visszatérési érték típusa mindig pontosan illeszkedik a bemenethez. +\end{frame} + +\begin{frame}[fragile]{Generikus interfészek} +\footnotesize +Nemcsak függvények, hanem interfészek (és típusok) is lehetnek generikusak -- ez az alapja például annak, ahogy a legtöbb adatbázis-eredmény vagy API válasz típus felépül. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +interface Box { + value: T; +} + +const numberBox: Box = { value: 42 }; +const stringBox: Box = { value: 'hello' }; + +interface ApiResponse { + data: T; + success: boolean; +} +\end{lstlisting} + +Egy \texttt{ApiResponse} pontosan jelzi, hogy a \texttt{data} mező egy \texttt{User} objektumot fog tartalmazni -- ezt fogjuk a későbbi heteken az Express válaszainknál is használni. +\end{frame} + +\begin{frame}[fragile]{Constraints -- a generikus típus korlátozása} +\footnotesize +Néha nem szeretnénk \emph{bármilyen} típust elfogadni -- csak olyanokat, amiknek van egy adott mezőjük vagy tulajdonságuk. Erre valók a \texttt{extends} kulcsszóval megadott \textbf{constraint}-ek. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +interface HasLength { + length: number; +} + +function logLength(item: T): T { + console.log(item.length); + return item; +} + +logLength('hello'); // OK - a string-nek van length-je +logLength([1, 2, 3]); // OK - a tombnek is +logLength(42); // Hiba! a number-nek nincs length-je +\end{lstlisting} +\end{frame} + +\begin{frame}{Összefoglalás -- Generikus típusok} +\footnotesize +\begin{block}{Generikus típusok} +\begin{itemize} +\item A generikák elkerülik a kódduplikációt anélkül, hogy fel kellene adnunk a típusbiztonságot +\item \texttt{function first(arr: T[]): T} -- a típusparamétert a hívás tölti ki +\item Interfészek/típusok is lehetnek generikusak, pl. \texttt{Box}, \texttt{ApiResponse} +\item \texttt{T extends ...} -- a generikus típus korlátozása egy adott "alakra" +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/06-utility-types.tex b/órai anyagok/extras/sections/06-utility-types.tex new file mode 100644 index 0000000..9ac5e66 --- /dev/null +++ b/órai anyagok/extras/sections/06-utility-types.tex @@ -0,0 +1,78 @@ +\section{Utility Types} + +\begin{frame}[fragile]{Miért kellenek a Utility Type-ok?} +\footnotesize +A TypeScript beépít néhány \textbf{beépített generikus segédtípust} (utility type), amikkel egy meglévő típusból egy \emph{módosított változatot} tudunk létrehozni -- anélkül, hogy a mezőket kézzel újra le kellene írnunk. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +interface User { + id: number; + name: string; + email: string; +} +\end{lstlisting} + +A következő diákon ebből az egy \texttt{User} interfészből építünk különböző, gyakran szükséges változatokat -- pl. "frissítéshez", "listázáshoz" vagy "létrehozáshoz". +\end{frame} + +\begin{frame}[fragile]{\texttt{Partial} és \texttt{Required}} +\footnotesize +\begin{lstlisting}[language=JavaScript,style=NodeJS] +type UserUpdate = Partial; +// { id?: number; name?: string; email?: string; } + +type UserStrict = Required; +// minden mezo kotelezo, meg ha eredetileg ? volt is +\end{lstlisting} + +\begin{itemize} +\item \textbf{\texttt{Partial}:} minden mezőt opcionálissá tesz -- tökéletes egy \texttt{PATCH} végpont bemenetéhez, ahol nem kötelező minden mezőt megadni +\item \textbf{\texttt{Required}:} minden mezőt kötelezővé tesz -- a \texttt{Partial} ellentéte +\end{itemize} +\end{frame} + +\begin{frame}[fragile]{\texttt{Pick} és \texttt{Omit}} +\footnotesize +Ez a két típus mezőket \emph{válogat ki}, vagy éppen \emph{hagy ki} egy meglévő típusból. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +type UserPreview = Pick; +// { id: number; name: string; } + +type UserWithoutEmail = Omit; +// { id: number; name: string; } +\end{lstlisting} + +\begin{block}{Gyakori felhasználás} +Egy adatbázisból visszakapott \texttt{User} rekordot gyakran \emph{nem} akarunk teljes egészében visszaküldeni az API válaszban (pl. egy jelszó-hash mezőt biztosan nem) -- a \texttt{Pick}/\texttt{Omit} pontosan erre való. +\end{block} +\end{frame} + +\begin{frame}[fragile]{\texttt{Record} és \texttt{Readonly}} +\footnotesize +\begin{lstlisting}[language=JavaScript,style=NodeJS] +type UsersById = Record; +// { [id: number]: User } - kulcs-ertek par tipusa + +type ImmutableUser = Readonly; +// minden mezo csak olvashato (readonly) +\end{lstlisting} + +\begin{itemize} +\item \textbf{\texttt{Record}:} egy objektum típusa, ahol a kulcsok \texttt{K}, az értékek \texttt{V} típusúak -- gyakori egy azonosító szerint indexelt "gyorsítótárnál" +\item \textbf{\texttt{Readonly}:} minden mezőt \texttt{readonly}-vá tesz -- hasznos, ha biztosítani akarjuk, hogy egy objektum ne módosuljon +\end{itemize} +\end{frame} + +\begin{frame}{Összefoglalás -- Utility Types} +\footnotesize +\begin{block}{Utility Types} +\begin{itemize} +\item \texttt{Partial} / \texttt{Required} -- mezők opcionálissá / kötelezővé tétele +\item \texttt{Pick} / \texttt{Omit} -- mezők kiválogatása / kihagyása +\item \texttt{Record} -- kulcs-érték típusú objektum +\item \texttt{Readonly} -- minden mező írásvédetté tétele +\item Mindegyik egy meglévő típusból épít egy \emph{módosított változatot} -- kódismétlés nélkül +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/07-enums-classes.tex b/órai anyagok/extras/sections/07-enums-classes.tex new file mode 100644 index 0000000..618d7a9 --- /dev/null +++ b/órai anyagok/extras/sections/07-enums-classes.tex @@ -0,0 +1,122 @@ +\section{Enum/Osztályok} + +\begin{frame}[fragile]{Enum alapok} +\footnotesize +Az \texttt{enum} (felsorolt típus) egy névvel ellátott, korlátozott értékkészletet definiál -- hasonló célt szolgál, mint a korábban látott string literal union, de saját névtérrel és futásidejű objektummal is jár. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +enum Role { + Admin, // 0 + Editor, // 1 + Viewer, // 2 +} + +enum Status { + Pending = 'pending', + Active = 'active', + Closed = 'closed', +} + +const myRole: Role = Role.Admin; +\end{lstlisting} + +Numerikus enumnál automatikusan 0-tól számozódnak az értékek; string enumnál mi adjuk meg a konkrét szöveges értéket -- ez utóbbi jobban olvasható naplókban, hibaüzenetekben. +\end{frame} + +\begin{frame}[fragile]{Osztályok TypeScript-ben} +\footnotesize +A TypeScript osztályai a JavaScript ES6 osztályaira épülnek, kiegészítve a mezők típusozásával. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +class Person { + name: string; + age: number; + + constructor(name: string, age: number) { + this.name = name; + this.age = age; + } + + greet(): string { + return `Szia, ${this.name} vagyok!`; + } +} + +const p = new Person('Anna', 25); +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]{Access modifierek} +\footnotesize +Az osztály mezőihez és metódusaihoz \textbf{láthatósági szinteket} rendelhetünk -- ez segít elrejteni az implementációs részleteket, és csak a szándékolt "publikus felületet" mutatni kifelé. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +class BankAccount { + private balance: number = 0; + public readonly owner: string; + + constructor(owner: string) { + this.owner = owner; + } + + public deposit(amount: number): void { + this.balance += amount; + } +} +\end{lstlisting} + +\begin{itemize} +\item \textbf{\texttt{public}} (alapértelmezett): bárhonnan elérhető +\item \textbf{\texttt{private}}: csak az osztályon belülről érhető el +\item \textbf{\texttt{protected}}: az osztályon és leszármazottjain belül érhető el +\end{itemize} +\end{frame} + +\begin{frame}[fragile]{Interfész implementálása osztállyal} +\footnotesize +Egy osztály az \texttt{implements} kulcsszóval kötelezettséget vállal arra, hogy megfelel egy adott interfésznek -- a fordító ellenőrzi, hogy tényleg minden szükséges mezőt/metódust megvalósít-e. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +interface Greetable { + greet(): string; +} + +class Person implements Greetable { + constructor(private name: string) {} + + greet(): string { + return `Szia, ${this.name} vagyok!`; + } +} +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]{Decorators -- rövid kitekintés} +\footnotesize +A \textbf{decorator} egy speciális jelölés (\texttt{@valami}), amit osztályok, mezők vagy metódusok elé írhatunk, és ami futásidejű viselkedést csatol hozzájuk -- kicsit hasonlóan ahhoz, ahogy Express-ben a middleware-ek "csomagolják be" a route handlereket. + +\begin{block}{Miért fontos ez most csak kitekintésként?} +A decorators ma még kísérleti funkció TypeScript-ben, de rendkívül elterjedt az ORM-ekben (pl. a későbbi heteken megismert TypeORM) -- ott \texttt{@Entity}, \texttt{@Column} jelölésekkel írjuk le az adatbázis-táblákat. +\end{block} + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +@Entity() +class User { + @Column() + name: string; +} +\end{lstlisting} +\end{frame} + +\begin{frame}{Összefoglalás -- Enum és Osztályok} +\footnotesize +\begin{block}{Enum és Osztályok} +\begin{itemize} +\item \texttt{enum}: névvel ellátott, korlátozott értékkészlet (numerikus vagy string alapú) +\item Osztályok: mezők típusozása, konstruktor, metódusok -- az ES6 osztályokra épül +\item Access modifierek: \texttt{public} / \texttt{private} / \texttt{protected} -- a láthatóság szabályozása +\item \texttt{implements}: egy osztály kötelezettséget vállal egy interfész megvalósítására +\item Decorators: \texttt{@valami} jelölések, amik későbbi heteken (TypeORM) kerülnek elő +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/extras/sections/08-osszefoglalas.tex b/órai anyagok/extras/sections/08-osszefoglalas.tex new file mode 100644 index 0000000..1caa7ee --- /dev/null +++ b/órai anyagok/extras/sections/08-osszefoglalas.tex @@ -0,0 +1,32 @@ +\section{Összefoglalás} + +\begin{frame}{Teljes összefoglalás} +\footnotesize +\begin{block}{Alapok} +Statikus típusrendszer JavaScript fölött; \texttt{tsc} fordít, \texttt{tsx}/\texttt{ts-node} közvetlenül futtat; \texttt{tsconfig.json} vezérli a fordítást (\texttt{strict} ajánlott). +\end{block} + +\begin{block}{Típusok} +Primitívek, tömbök, tuple-ök; \texttt{any} kerülendő, \texttt{unknown} biztonságos; \texttt{interface}/\texttt{type}; union (\texttt{|}) és intersection (\texttt{\&}); generikák (\texttt{}); utility types (\texttt{Partial}, \texttt{Pick}, stb.) +\end{block} + +\begin{block}{Osztályok} +Access modifierek (\texttt{public}/\texttt{private}/\texttt{protected}), \texttt{implements}, \texttt{enum}, decorators (kitekintés a TypeORM felé) +\end{block} +\end{frame} + +\begin{frame}{Hogyan tovább?} +\footnotesize +A legjobb módja a TypeScript elsajátításának a \emph{gyakorlás} -- az elmélet önmagában nem elég, próbáld ki a saját kódodban is. + +\begin{itemize} +\item Alakítsd át egy régebbi, sima JavaScript projektedet fokozatosan TypeScript-re, fájlonként haladva +\item Kapcsold be a \texttt{strict} módot a \texttt{tsconfig.json}-ban -- kezdetben tűnhet szigorúnak, de hosszabb távon ez fizetődik ki igazán +\item Olvasd a hivatalos dokumentációt: \texttt{typescriptlang.org/docs} -- naprakész, sok interaktív példával +\item A tárgy további heteiben (Express.js + TypeScript, majd TypeORM) a itt tanultak folyamatosan elő fognak kerülni +\end{itemize} + +\begin{alertblock}{Emlékeztető} +Ez az anyag kiegészítő, önálló tanulást szolgál -- nem számonkérendő, de a mélyebb megértés a féléves munkádat is megkönnyíti. +\end{alertblock} +\end{frame} diff --git a/órai anyagok/extras/typescript.pdf b/órai anyagok/extras/typescript.pdf new file mode 100644 index 0000000..2d7f04b Binary files /dev/null and b/órai anyagok/extras/typescript.pdf differ diff --git a/órai anyagok/extras/typescript.tex b/órai anyagok/extras/typescript.tex new file mode 100644 index 0000000..9781a90 --- /dev/null +++ b/órai anyagok/extras/typescript.tex @@ -0,0 +1,24 @@ +\documentclass[aspectratio=169]{beamer} +\usepackage{../common/webfejl} + +\title{TypeScript} +\subtitle{Kiegészítő tananyag -- a JavaScript alapoktól a haladó típusokig} + +\begin{document} + +\begin{frame} +\titlepage +\logoalul +\end{frame} + +\input{sections/00-bevezetes} +\input{sections/01-alaptipusok} +\input{sections/02-interface-type} +\input{sections/03-fuggvenyek} +\input{sections/04-union-intersection} +\input{sections/05-generics} +\input{sections/06-utility-types} +\input{sections/07-enums-classes} +\input{sections/08-osszefoglalas} + +\end{document} diff --git a/órai anyagok/week01/alapok.pdf b/órai anyagok/week01/alapok.pdf index 7fe1613..4c0c94d 100644 Binary files a/órai anyagok/week01/alapok.pdf and b/órai anyagok/week01/alapok.pdf differ diff --git a/órai anyagok/week01/sections/00-targybemutatas.tex b/órai anyagok/week01/sections/00-targybemutatas.tex index 76eb4d3..242f6fd 100644 --- a/órai anyagok/week01/sections/00-targybemutatas.tex +++ b/órai anyagok/week01/sections/00-targybemutatas.tex @@ -37,8 +37,8 @@ Az első hat hét az alapozásról szól: megismerjük a HTTP protokollt, felép \begin{block}{} \begin{tabular}{ll} \textbf{1. hét} & Alapok, Node.js, HTTPS, NPM package manager \\ -\textbf{2. hét} & REST API, architekturális felépítések, CQRS \\ -\textbf{3. hét} & Express.js, Routing, Postman, TypeScript \\ +\textbf{2. hét} & Express.js, Routing, Postman, TypeScript \\ +\textbf{3. hét} & REST API, architekturális felépítések, CQRS \\ \textbf{4. hét} & ORM, database connection, CRUD operations \\ \textbf{5. hét} & TypeORM, Aggregates, Repositories \\ \textbf{6. hét} & \textbf{ZH 1}: Database CRUD, ORM, CQRS + DTOs, Mappers \\ diff --git a/órai anyagok/week01/sections/04-kovetkezo-lepesek.tex b/órai anyagok/week01/sections/04-kovetkezo-lepesek.tex index a80094b..730c282 100644 --- a/órai anyagok/week01/sections/04-kovetkezo-lepesek.tex +++ b/órai anyagok/week01/sections/04-kovetkezo-lepesek.tex @@ -8,6 +8,6 @@ A mai órán megismertük a webes kommunikáció alapjait, elindítottunk egy No \item \textbf{Fejlesztői környezet telepítése} (Node.js, npm) -- ha még nincs telepítve, mindenképp pótold otthon \item \textbf{Git és verziókezelés alapjai} -- a kódunkat innentől mindig verziókezelve fogjuk fejleszteni \item \textbf{Első Express.js alkalmazás elkészítése} -- a jövő héten a beépített \texttt{http} modul helyett egy sokkal kényelmesebb keretrendszert használunk -\item \textbf{REST API alapok megismerése} (2. hét) -- ráépítünk a mai HTTP-s tudásra +\item \textbf{REST API alapok megismerése} (3. hét) -- miután megírtuk az első route-jainkat, rátérünk a tudatos tervezésükre is \end{enumerate} \end{frame} diff --git a/órai anyagok/week02/express.pdf b/órai anyagok/week02/express.pdf new file mode 100644 index 0000000..a6188fe Binary files /dev/null and b/órai anyagok/week02/express.pdf differ diff --git a/órai anyagok/week02/express.tex b/órai anyagok/week02/express.tex new file mode 100644 index 0000000..c15a9b8 --- /dev/null +++ b/órai anyagok/week02/express.tex @@ -0,0 +1,21 @@ +\documentclass[aspectratio=169]{beamer} +\usepackage{../common/webfejl} + +\title{Webtechnológia és webalkalmazás-fejlesztés} +\subtitle{2. hét -- Express.js, Routing, Postman, TypeScript} + +\begin{document} + +\begin{frame} +\titlepage +\logoalul +\end{frame} + +\input{sections/00-visszatekintes} +\input{sections/01-expressjs} +\input{sections/02-routing} +\input{sections/03-postman} +\input{sections/04-typescript} +\input{sections/05-kovetkezo-lepesek} + +\end{document} diff --git a/órai anyagok/week02/sections/00-visszatekintes.tex b/órai anyagok/week02/sections/00-visszatekintes.tex index 37a6fc6..44569f7 100644 --- a/órai anyagok/week02/sections/00-visszatekintes.tex +++ b/órai anyagok/week02/sections/00-visszatekintes.tex @@ -2,30 +2,31 @@ \begin{frame}{Miről volt szó múlt héten?} \footnotesize -Az első héten megismertük a webes kommunikáció alapköveit: a HTTP protokollt, a Node.js futtatókörnyezetet és az npm csomagkezelőt. Ezek nélkül nem tudnánk elindulni -- de önmagukban még nem elegendők egy jól használható backend rendszer megépítéséhez. +Az első héten megismertük a webes kommunikáció alapjait: a HTTP protokollt, a Node.js futtatókörnyezetet, és elindítottunk egy egyszerű szervert a beépített \texttt{http} modullal. Emellett megtanultuk, hogyan kezeljük npm-mel a projekt függőségeit. \begin{itemize} -\item \textbf{HTTP/HTTPS:} Request-Response modell, állapotmentes protokoll, metódusok (GET, POST, PUT, PATCH, DELETE), státuszkódok -\item \textbf{Node.js:} szerveroldali JavaScript futtatókörnyezet, beépített \texttt{http} modul egy egyszerű szerver elindítására -\item \textbf{npm:} csomagkezelés, \texttt{package.json}, függőségek +\item \textbf{HTTP:} Request-Response modell, metódusok (GET, POST, PUT, PATCH, DELETE), státuszkódok +\item \textbf{Node.js:} \texttt{http.createServer} -- egy függvény, ami minden kérést kiszolgál +\item \textbf{npm:} \texttt{package.json}, csomagok telepítése, \texttt{npm scripts} \end{itemize} \begin{block}{A hiányzó darab} -Múlt héten a \texttt{http.createServer}-rel csak egyetlen, mindent kiszolgáló függvényt írtunk. Éles alkalmazásoknál ez gyorsan kezelhetetlenné válik -- szükségünk van egy \emph{tervezési logikára}, ami megmondja, hogyan szervezzük az útvonalainkat, adatainkat és a kódunk rétegeit. +A nyers \texttt{http} modullal minden egyes útvonalat, minden HTTP metódust és a kérés törzsének feldolgozását is kézzel, \texttt{if-else} ágakkal kellene megírnunk. Ez pár végpontnál még kezelhető, de gyorsan átláthatatlanná válik. \end{block} \end{frame} \begin{frame}{Mi a célja a mai órának?} \footnotesize -A mai anyag három, egymásra épülő témát dolgoz fel: hogyan tervezzünk jól használható API-kat, hogyan szervezzük a backend kódunkat rétegekbe, és hogyan válasszuk szét az írási és olvasási műveleteket, ha a rendszerünk ezt megkívánja. +A mai órán egy valódi keretrendszert vezetünk be, amivel a múlt heti kézi munkát nagyrészt kiváltjuk, majd megtanuljuk, hogyan teszteljük és hogyan típusozzuk a kódunkat. \begin{itemize} -\item \textbf{REST API alapok} -- hogyan tervezzünk következetes, könnyen használható API-t -\item \textbf{Architekturális felépítések} -- hogyan szervezzük a backend kódunkat rétegekbe, hogy karbantartható maradjon -\item \textbf{CQRS} -- mikor éri meg szétválasztani az írási és olvasási műveleteket +\item \textbf{Express.js} -- a legelterjedtebb Node.js webes keretrendszer, ami elveszi a routing és a kérésfeldolgozás nagy részének terhét +\item \textbf{Routing} -- hogyan szervezzük az útvonalainkat, hogyan olvassuk ki a kérés adatait +\item \textbf{Postman} -- hogyan teszteljük a saját API-nkat anélkül, hogy frontendet kellene hozzá írnunk +\item \textbf{TypeScript} -- hogyan adjunk típusbiztonságot a JavaScript kódunkhoz \end{itemize} \begin{alertblock}{Fontos} -A mai témák még mindig \emph{tervezési} kérdések -- konkrét kódot Express.js-ben csak a jövő héttől írunk. Most a "miért így?" kérdésre keressük a választ, hogy a következő heti kód már értelmes döntéseken alapuljon. +Ma még mindig egyszerű, tárolás nélküli (memóriában tartott) példákkal dolgozunk -- az adatbázis-kapcsolat csak a 4. héten kerül képbe. Most a keretrendszerre és az eszközökre fókuszálunk. \end{alertblock} \end{frame} diff --git a/órai anyagok/week02/sections/01-expressjs.tex b/órai anyagok/week02/sections/01-expressjs.tex new file mode 100644 index 0000000..f1968f7 --- /dev/null +++ b/órai anyagok/week02/sections/01-expressjs.tex @@ -0,0 +1,95 @@ +\section{Express.js} + +\begin{frame}[fragile]{Miért nem elég a nyers \texttt{http} modul?} +\footnotesize +Emlékezzünk vissza az 1. héten írt szerverre: egyetlen callback-ben kellett eldöntenünk, milyen útvonalra és milyen metódussal érkezett a kérés. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +const server = http.createServer((req, res) => { + if (req.url === '/users' && req.method === 'GET') { + // ... + } else if (req.url === '/users' && req.method === 'POST') { + // ... + } else if (req.url.startsWith('/users/') && req.method === 'GET') { + // egy adott felhasznalo -- id kezzel kivagva az URL-bol + } // es igy tovabb... +}); +\end{lstlisting} + +\begin{alertblock}{A probléma} +Tíz-húsz végpontnál ez a lánc kezelhetetlenné válik: nincs beépített segítség a paraméterek kiolvasásához, a JSON törzs feldolgozásához, vagy az útvonalak csoportosításához. +\end{alertblock} +\end{frame} + +\begin{frame}{Mi az Express.js?} +\footnotesize +Az \textbf{Express.js} a legelterjedtebb Node.js webes keretrendszer (web framework): a nyers \texttt{http} modulra épül, és eltünteti a kézi \texttt{if-else} láncokat egy sokkal kényelmesebb, deklaratív routing API-val. + +\begin{itemize} +\item Egyszerű, minimalista -- nem kényszerít ránk egy előírt projektszerkezetet +\item Beépített segítség: útvonal-paraméterek, query stringek, JSON válaszok +\item Hatalmas ökoszisztéma: middleware-ek szinte minden problémára (autentikáció, naplózás, CORS, stb.) +\item Ez lesz a tárgy hátralévő részének elsődleges keretrendszere +\end{itemize} + +\begin{block}{Fontos} +Az Express \emph{nem} helyettesíti a Node.js-t -- ráépül. Amit az 1. héten a \texttt{http} modulról tanultunk (request/response ciklus), az Express alatt is pontosan úgy működik. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Az első Express alkalmazás} +\footnotesize +Néhány sorból már működő szerverünk van -- hasonlítsd össze az előző dia \texttt{if-else} láncával! + +\begin{block}{Telepítés} +\begin{verbatim} +npm install express +\end{verbatim} +\end{block} + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +const express = require('express'); +const app = express(); + +app.get('/', (req, res) => { + res.send('Hello, Express!'); +}); + +app.listen(3000, () => { + console.log('Szerver fut: http://localhost:3000'); +}); +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]{A middleware fogalma} +\footnotesize +Az Express legfontosabb koncepciója a \textbf{middleware}: egy függvény, ami a kérés és a válasz között fut le, és vagy továbbengedi a folyamatot (\texttt{next()}), vagy lezárja azt egy válasszal. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +app.use((req, res, next) => { + console.log(`${req.method} ${req.url}`); + next(); // tovabb a kovetkezo middleware-hez/route-hoz +}); + +app.use(express.json()); // JSON body-t olvaso middleware +\end{lstlisting} + +\begin{itemize} +\item A kérések egy "csövön" (pipeline) haladnak végig, middleware-eken keresztül +\item \texttt{express.json()} nélkül a \texttt{req.body} üres lenne POST/PUT kéréseknél +\item Naplózás, autentikáció, hibakezelés -- mind middleware-ként valósul meg +\end{itemize} +\end{frame} + +\begin{frame}{Összefoglalás -- Express.js} +\footnotesize +\begin{block}{Express.js alapok} +\begin{itemize} +\item Node.js-re épülő, minimalista webes keretrendszer +\item Kiváltja a kézi \texttt{if-else} útvonal-elágazásokat +\item \texttt{app.listen()} -- szerver indítása, ugyanaz mint a nyers \texttt{http}-nél +\item Middleware: \texttt{app.use()} -- a kérés-válasz "csövének" építőeleme +\item \texttt{express.json()} -- beépített middleware a JSON törzs feldolgozásához +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/week02/sections/02-routing.tex b/órai anyagok/week02/sections/02-routing.tex new file mode 100644 index 0000000..53a2d94 --- /dev/null +++ b/órai anyagok/week02/sections/02-routing.tex @@ -0,0 +1,125 @@ +\section{Routing} + +\begin{frame}[fragile]{HTTP metódusok Express-ben} +\footnotesize +Minden HTTP metódushoz külön Express függvény tartozik, ami pontosan a metódus nevét viseli -- ez sokkal olvashatóbb, mint egy \texttt{if (req.method === ...)} lánc. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +app.get('/users', (req, res) => { /* lista */ }); +app.post('/users', (req, res) => { /* letrehozas */ }); +app.get('/users/:id', (req, res) => { /* egy elem */ }); +app.put('/users/:id', (req, res) => { /* teljes frissites */ }); +app.patch('/users/:id', (req, res) => { /* reszleges frissites */ }); +app.delete('/users/:id', (req, res) => { /* torles */ }); +\end{lstlisting} + +\begin{block}{Emlékeztető} +Ez pontosan a 2. héten (a jövő héten, amikor visszatérünk rá) tárgyalt CRUD $\to$ HTTP metódus táblázatot követi -- nem véletlen az egyezés. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Route paraméterek és query stringek} +\footnotesize +Az útvonalban lévő \texttt{:id}-hez hasonló szegmenseket \textbf{route paramétereknek} hívjuk, a kérdőjel utáni \texttt{?key=value} részt pedig \textbf{query stringnek}. Express mindkettőt készen, feldolgozva adja át. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +// GET /users/123?includeOrders=true +app.get('/users/:id', (req, res) => { + const userId = req.params.id; // "123" + const includeOrders = req.query.includeOrders; // "true" + res.json({ id: userId, includeOrders }); +}); +\end{lstlisting} + +\begin{itemize} +\item \textbf{\texttt{req.params}:} az útvonal része, egy konkrét erőforrás azonosítására (\texttt{/users/:id}) +\item \textbf{\texttt{req.query}:} opcionális finomítás (lapozás, szűrés, rendezés) +\end{itemize} +\end{frame} + +\begin{frame}[fragile]{A kérés törzse: \texttt{req.body}} +\footnotesize +\texttt{POST}, \texttt{PUT} és \texttt{PATCH} kéréseknél az adat jellemzően a kérés törzsében (body) érkezik JSON formátumban -- ehhez szükséges az előző órán megismert \texttt{express.json()} middleware. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +app.use(express.json()); + +app.post('/users', (req, res) => { + const { name, email } = req.body; + const newUser = { id: Date.now(), name, email }; + users.push(newUser); + res.status(201).json(newUser); +}); +\end{lstlisting} + +\begin{block}{Emlékeztető az 1. hétről} +A \texttt{201 Created} a helyes státuszkód sikeres \texttt{POST} esetén -- ezt már az 1. héten megismertük. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Útvonalak szervezése: \texttt{express.Router()}} +\footnotesize +Ahogy nő az alkalmazás, egyetlen fájlban tartani az összes route-ot áttekinthetetlenné válik. Az \texttt{express.Router()} lehetővé teszi, hogy erőforrásonként külön fájlba szervezzük az útvonalakat. + +\begin{columns} +\begin{column}{0.48\textwidth} +\begin{block}{routes/users.js} +\begin{lstlisting}[language=JavaScript,style=NodeJS] +const router = express.Router(); + +router.get('/', listUsers); +router.post('/', createUser); + +module.exports = router; +\end{lstlisting} +\end{block} +\end{column} +\begin{column}{0.48\textwidth} +\begin{block}{app.js} +\begin{lstlisting}[language=JavaScript,style=NodeJS] +const usersRouter = + require('./routes/users'); + +app.use( + '/users', + usersRouter +); +\end{lstlisting} +\end{block} +\end{column} +\end{columns} +\end{frame} + +\begin{frame}[fragile]{Hibakezelés alapjai} +\footnotesize +Express két speciális esetet kezel middleware-ekkel: amikor egy útvonal nem létezik, és amikor egy route handler hibát dob. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +// 404 - ha semelyik route nem illeszkedett +app.use((req, res) => { + res.status(404).json({ error: 'Nem talalhato' }); +}); + +// hibakezelo middleware -- negy parameter jelzi Expressnek! +app.use((err, req, res, next) => { + console.error(err); + res.status(500).json({ error: 'Szerver hiba' }); +}); +\end{lstlisting} + +\begin{block}{Fontos} +A hibakezelő middleware-t \emph{a legvégén} kell regisztrálni, az összes route után -- Express a négy paraméter alapján ismeri fel. +\end{block} +\end{frame} + +\begin{frame}{Összefoglalás -- Routing} +\footnotesize +\begin{block}{Routing Express-ben} +\begin{itemize} +\item \texttt{app.get/post/put/patch/delete} -- metódusonként külön, olvasható route definíció +\item \texttt{req.params} -- útvonal paraméterek, \texttt{req.query} -- query string, \texttt{req.body} -- kérés törzse +\item \texttt{express.Router()} -- útvonalak szervezése külön fájlokba, erőforrásonként +\item 404 és hibakezelő middleware a route-ok végén +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/week02/sections/03-postman.tex b/órai anyagok/week02/sections/03-postman.tex new file mode 100644 index 0000000..c4fc5c1 --- /dev/null +++ b/órai anyagok/week02/sections/03-postman.tex @@ -0,0 +1,67 @@ +\section{Postman} + +\begin{frame}{Mi a Postman, és miért használjuk?} +\footnotesize +Eddig minden végpontunkat vagy böngészőből (csak GET-hez alkalmas), vagy egyáltalán nem próbáltuk ki. A \textbf{Postman} egy grafikus alkalmazás, amivel bármilyen HTTP kérést összeállíthatunk és elküldhetünk -- anélkül, hogy előbb frontendet kellene írnunk hozzá. + +\begin{itemize} +\item Bármilyen metódus (GET, POST, PUT, PATCH, DELETE) kipróbálható +\item Egyedi fejlécek (headers) és JSON törzs (body) is összeállítható +\item A választ (státuszkód, headerek, body) azonnal, formázva látjuk +\item Elmenthető, újra futtatható, csapattagokkal megosztható kéréssorozatok +\end{itemize} + +\begin{block}{Miért nem elég a böngésző?} +A böngésző címsorába írt URL mindig \texttt{GET} kérést küld -- \texttt{POST}, \texttt{PUT}, \texttt{DELETE} kéréshez, vagy egyedi fejlécekhez (pl. \texttt{Authorization}) külön eszköz kell. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Egy kérés összeállítása} +\footnotesize +Egy Postman-kérés pontosan azokból az elemekből áll, amiket az 1. héten a HTTP kérés felépítéseként már megismertünk: metódus, URL, fejlécek, törzs. + +\begin{block}{Amit beállítunk} +\begin{itemize} +\item \textbf{Metódus:} pl. \texttt{POST} +\item \textbf{URL:} \texttt{http://localhost:3000/users} +\item \textbf{Headers:} \texttt{Content-Type: application/json} +\item \textbf{Body (raw, JSON):} +\end{itemize} +\end{block} + +\begin{verbatim} +{ + "name": "Kis Anna", + "email": "anna@example.com" +} +\end{verbatim} + +Küldés után azonnal látjuk a választ: \texttt{201 Created} és a visszakapott, azonosítóval kiegészített felhasználó. +\end{frame} + +\begin{frame}{Collections és Environment változók} +\footnotesize +Ahogy egyre több végpontot tesztelünk, hasznos ezeket rendszerezni, és elkerülni, hogy mindig kézzel írjuk be az alap URL-t. + +\begin{itemize} +\item \textbf{Collection:} kérések egy mappába rendezett gyűjteménye -- pl. minden "Users" végpont egy collection-ben +\item \textbf{Environment:} névhez kötött változók (pl. \texttt{baseUrl}), amikkel a kéréseinkben \texttt{\{\{baseUrl\}\}/users} írható a teljes URL helyett +\item Így egyetlen változó átírásával válthatunk fejlesztői és éles környezet között +\end{itemize} + +\begin{block}{Gyakorlati tipp} +Fejlesztés közben minden újonnan megírt végpontot azonnal próbálj ki Postmanben -- ez sokkal gyorsabb visszajelzést ad, mint egy teljes frontend felület megvárása. +\end{block} +\end{frame} + +\begin{frame}{Összefoglalás -- Postman} +\footnotesize +\begin{block}{Postman} +\begin{itemize} +\item Grafikus eszköz tetszőleges HTTP kérés összeállítására és elküldésére +\item Kiválthatja a böngészőt olyan esetekben, amikor nem elég a sima GET +\item Kérés = metódus + URL + headers + body -- ugyanaz, mint amit HTTP-ből már tudunk +\item Collections: kérések rendszerezése; Environments: újrafelhasználható változók +\end{itemize} +\end{block} +\end{frame} diff --git a/órai anyagok/week02/sections/04-kovetkezo-lepesek.tex b/órai anyagok/week02/sections/04-kovetkezo-lepesek.tex deleted file mode 100644 index 4a1468f..0000000 --- a/órai anyagok/week02/sections/04-kovetkezo-lepesek.tex +++ /dev/null @@ -1,17 +0,0 @@ -\section{Következő lépések} - -\begin{frame}{Következő lépések} -\footnotesize -Ma megismertük, hogyan tervezzünk jól használható REST API-t, hogyan szervezzük a backend kódunkat rétegekbe, és mikor érdemes szétválasztani az írási és olvasási műveleteket. A jövő héten ezekre a tervezési elvekre már konkrét kódot építünk. - -\begin{enumerate} -\item \textbf{Express.js megismerése} -- a jövő heti keretrendszer, amivel az API/Controller réteget ténylegesen megírjuk -\item \textbf{Routing gyakorlása} -- a mai órán tervezett erőforrás-orientált URL-eket Express.js route handlerekként fogjuk implementálni -\item \textbf{Postman telepítése} -- API-k manuális teszteléséhez, hogy a saját végpontjainkat is ki tudjuk próbálni -\item \textbf{TypeScript alapok} -- a jövő héttől fokozatosan áttérünk típusos JavaScriptre -\end{enumerate} - -\begin{alertblock}{Javaslat} -Nézd át még egyszer a CRUD $\to$ HTTP metódus táblázatot -- a jövő héten ezt fogjuk közvetlenül route definíciókra fordítani. -\end{alertblock} -\end{frame} diff --git a/órai anyagok/week02/sections/04-typescript.tex b/órai anyagok/week02/sections/04-typescript.tex new file mode 100644 index 0000000..02945f5 --- /dev/null +++ b/órai anyagok/week02/sections/04-typescript.tex @@ -0,0 +1,75 @@ +\section{TypeScript} + +\begin{frame}{Miért TypeScript?} +\footnotesize +A JavaScript \textbf{gyengén típusos} nyelv: egy változó bármikor bármilyen típusú értéket felvehet, és a hibák jó része csak futás közben derül ki -- gyakran éppen egy éles felhasználónál. A \textbf{TypeScript} a JavaScript egy kiterjesztése, ami \emph{statikus típusokat} ad hozzá. + +\begin{itemize} +\item A típushibák nagy része már fordításkor (kódírás közben) kiderül, nem futás közben +\item Az IDE sokkal pontosabb kódkiegészítést és hibajelzést tud adni +\item Nagyobb csapatban, nagyobb kódbázisban különösen megtérül +\item A TypeScript kód JavaScript-té fordul le -- a böngésző/Node.js sosem futtat TS-t közvetlenül +\end{itemize} + +\begin{block}{Fontos} +A TypeScript \emph{opcionális} réteg a JavaScript fölött -- minden érvényes JavaScript kód (majdnem) érvényes TypeScript is, fokozatosan vezethető be egy meglévő projektbe. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Telepítés és futtatás} +\footnotesize +A TypeScript fájlok (\texttt{.ts} kiterjesztéssel) nem futtathatók közvetlenül Node.js-szel -- előbb JavaScript-té kell őket fordítani, vagy egy erre képes futtatót kell használnunk. + +\begin{block}{Fordítás \texttt{tsc}-vel} +\begin{verbatim} +npm install -D typescript +npx tsc --init # letrehozza a tsconfig.json-t +npx tsc # lefordit minden .ts fajlt .js-re +\end{verbatim} +\end{block} + +\begin{block}{Fejlesztés közben: \texttt{tsx}} +\begin{verbatim} +npx tsx index.ts +\end{verbatim} +A \texttt{tsx} fordítás nélkül, közvetlenül futtatja a TypeScript fájlt -- fejlesztés közben ez a kényelmesebb. +\end{block} +\end{frame} + +\begin{frame}[fragile]{Alaptípusok és egy egyszerű interfész} +\footnotesize +A típusokat a változó/paraméter neve után, kettősponttal adjuk meg. Több mező közös leírásához pedig egy \texttt{interface}-t érdemes definiálni. + +\begin{lstlisting}[language=JavaScript,style=NodeJS] +let name: string = 'Anna'; +let age: number = 25; +let isActive: boolean = true; +let tags: string[] = ['admin', 'user']; + +interface User { + id: number; + name: string; + email: string; +} + +function greet(user: User): string { + return `Hello, ${user.name}!`; +} +\end{lstlisting} +\end{frame} + +\begin{frame}{Összefoglalás -- TypeScript} +\footnotesize +\begin{block}{TypeScript alapok} +\begin{itemize} +\item A JavaScript statikus típusokkal kiegészített változata -- fordításkor szűri a típushibákat +\item \texttt{tsc} -- fordítás JavaScript-té; \texttt{tsx}/\texttt{ts-node} -- közvetlen futtatás fejlesztéskor +\item Alaptípusok: \texttt{string}, \texttt{number}, \texttt{boolean}, tömbök +\item \texttt{interface} -- több mezőből álló adatszerkezet típusának leírása +\end{itemize} +\end{block} + +\begin{alertblock}{Több is van!} +Ez csak az alapok -- a generikus típusokról, a \texttt{union}/\texttt{intersection} típusokról és más haladó fogalmakról egy \emph{külön, önállóan is végigkövethető} kiegészítő anyagban olvashatsz, ha mélyebben el szeretnél merülni. +\end{alertblock} +\end{frame} diff --git a/órai anyagok/week02/sections/05-kovetkezo-lepesek.tex b/órai anyagok/week02/sections/05-kovetkezo-lepesek.tex new file mode 100644 index 0000000..c05e18e --- /dev/null +++ b/órai anyagok/week02/sections/05-kovetkezo-lepesek.tex @@ -0,0 +1,16 @@ +\section{Következő lépések} + +\begin{frame}{Következő lépések} +\footnotesize +Ma megírtuk az első valódi Express.js alkalmazásunkat, megtanultuk, hogyan teszteljük Postmannel, és belekóstoltunk a TypeScriptbe. Eddig azonban inkább \emph{gyakorlati megérzés} alapján dolgoztunk -- a jövő héten ezt tudatos tervezéssé alakítjuk. + +\begin{enumerate} +\item \textbf{REST API tervezési elvek} -- visszatekintünk a ma írt útvonalainkra: jól neveztük-e el őket? +\item \textbf{Architekturális felépítések} -- hogyan válasszuk szét a route handlert (amit ma írtunk) az üzleti logikától +\item \textbf{CQRS} -- mikor éri meg külön kezelni az írási és olvasási műveleteket +\end{enumerate} + +\begin{alertblock}{Javaslat} +Nézd át még egyszer a ma írt route-jaidat -- a jövő héten pontosan ezekre a konkrét példákra fogunk tervezési elveket alkalmazni. +\end{alertblock} +\end{frame} diff --git a/órai anyagok/week02/api.pdf b/órai anyagok/week03/api.pdf similarity index 87% rename from órai anyagok/week02/api.pdf rename to órai anyagok/week03/api.pdf index f1f74ca..c782bdf 100644 Binary files a/órai anyagok/week02/api.pdf and b/órai anyagok/week03/api.pdf differ diff --git a/órai anyagok/week02/api.tex b/órai anyagok/week03/api.tex similarity index 85% rename from órai anyagok/week02/api.tex rename to órai anyagok/week03/api.tex index cf098fd..39b03ae 100644 --- a/órai anyagok/week02/api.tex +++ b/órai anyagok/week03/api.tex @@ -2,7 +2,7 @@ \usepackage{../common/webfejl} \title{Webtechnológia és webalkalmazás-fejlesztés} -\subtitle{2. hét -- REST API, Architekturális felépítések, CQRS} +\subtitle{3. hét -- REST API, Architekturális felépítések, CQRS} \begin{document} diff --git a/órai anyagok/week03/sections/00-visszatekintes.tex b/órai anyagok/week03/sections/00-visszatekintes.tex new file mode 100644 index 0000000..aa7e3ba --- /dev/null +++ b/órai anyagok/week03/sections/00-visszatekintes.tex @@ -0,0 +1,32 @@ +\section{Visszatekintés} + +\begin{frame}{Miről volt szó múlt héten?} +\footnotesize +Az első héten megismertük a webes kommunikáció alapköveit (HTTP, Node.js, npm), a másodikon pedig ezekre építve megírtuk az első valódi backend kódunkat: Express.js-szel útvonalakat (route-okat) hoztunk létre, Postmannel kipróbáltuk őket, és belekóstoltunk a TypeScriptbe is. + +\begin{itemize} +\item \textbf{Express.js:} \texttt{app.get/post/put/delete} route-ok, middleware-ek, \texttt{express.Router()} +\item \textbf{Routing:} \texttt{req.params}, \texttt{req.query}, \texttt{req.body} kezelése, JSON válaszok +\item \textbf{Postman:} kérések összeállítása és tesztelése kód írása nélkül +\item \textbf{TypeScript:} alaptípusok, egy egyszerű interfész, fordítás \texttt{tsc}-vel +\end{itemize} + +\begin{block}{A hiányzó darab} +Múlt héten \emph{gyakorlati megérzés} alapján neveztük el az útvonalainkat és szerveztük a kódunkat. Ez működött, de nem feltétlenül a legjobb, legkövetkezetesebb módon -- ma megnézzük, milyen \emph{tervezési elvek} állnak a jó API-k és a jó backend-architektúrák mögött. +\end{block} +\end{frame} + +\begin{frame}{Mi a célja a mai órának?} +\footnotesize +A mai anyag három, egymásra épülő témát dolgoz fel: hogyan tervezzünk jól használható API-kat, hogyan szervezzük a backend kódunkat rétegekbe, és hogyan válasszuk szét az írási és olvasási műveleteket, ha a rendszerünk ezt megkívánja. + +\begin{itemize} +\item \textbf{REST API alapok} -- hogyan tervezzünk következetes, könnyen használható API-t +\item \textbf{Architekturális felépítések} -- hogyan szervezzük a backend kódunkat rétegekbe, hogy karbantartható maradjon +\item \textbf{CQRS} -- mikor éri meg szétválasztani az írási és olvasási műveleteket +\end{itemize} + +\begin{alertblock}{Fontos} +A múlt héten megírt Express.js route-jaink jó kiindulópontok, de a mai órán \emph{visszamenőleg is} átgondoljuk őket: melyik URL-t neveznénk most másképp, hol hiányzik egy réteg, hol keverednek a felelősségek. A "miért így?" kérdésre keressük a választ, hogy a jövőben már tudatosan jól tervezett kódot írjunk. +\end{alertblock} +\end{frame} diff --git a/órai anyagok/week02/sections/01-rest-api.tex b/órai anyagok/week03/sections/01-rest-api.tex similarity index 100% rename from órai anyagok/week02/sections/01-rest-api.tex rename to órai anyagok/week03/sections/01-rest-api.tex diff --git a/órai anyagok/week02/sections/02-architektura.tex b/órai anyagok/week03/sections/02-architektura.tex similarity index 96% rename from órai anyagok/week02/sections/02-architektura.tex rename to órai anyagok/week03/sections/02-architektura.tex index d13e009..83f5925 100644 --- a/órai anyagok/week02/sections/02-architektura.tex +++ b/órai anyagok/week03/sections/02-architektura.tex @@ -18,7 +18,7 @@ A rétegzett felépítésnél a kódot vízszintes rétegekbe szervezzük, ahol \begin{block}{} \begin{itemize} -\item \textbf{API / Controller:} fogadja a HTTP kéréseket, validálja a bemenetet, meghívja az Application réteget, visszaadja a választ -- ezt Express.js-ben írjuk meg a jövő héten +\item \textbf{API / Controller:} fogadja a HTTP kéréseket, validálja a bemenetet, meghívja az Application réteget, visszaadja a választ -- ezt Express.js-ben már megírtuk a múlt héten \item \textbf{Application:} az egyes use case-eket (parancsokat/lekérdezéseket) orchesztrálja -- ide kerülnek majd a CQRS command/query handlerek \item \textbf{Domain:} a tiszta üzleti logika, entitások, aggregates -- semmilyen technikai függősége nincs, nem "tudja", hogy Express-ben vagy adatbázissal fut \end{itemize} @@ -52,7 +52,7 @@ Az MVC (Model-View-Controller) a rétegzett architektúra egyik legismertebb kon \end{itemize} \begin{block}{Backend kontextusban} -Amikor a jövő héten Express.js-ben "route handler"-t írunk, az gyakorlatilag az API/Controller réteg szerepét tölti be: fogadja a HTTP kérést, és delegálja a munkát az Application rétegnek. +Amikor a múlt héten Express.js-ben "route handler"-t írtunk, az gyakorlatilag az API/Controller réteg szerepét töltötte be: fogadja a HTTP kérést, és delegálja a munkát az Application rétegnek. \end{block} \end{frame} diff --git a/órai anyagok/week02/sections/03-cqrs.tex b/órai anyagok/week03/sections/03-cqrs.tex similarity index 100% rename from órai anyagok/week02/sections/03-cqrs.tex rename to órai anyagok/week03/sections/03-cqrs.tex diff --git a/órai anyagok/week03/sections/04-kovetkezo-lepesek.tex b/órai anyagok/week03/sections/04-kovetkezo-lepesek.tex new file mode 100644 index 0000000..81403d4 --- /dev/null +++ b/órai anyagok/week03/sections/04-kovetkezo-lepesek.tex @@ -0,0 +1,16 @@ +\section{Következő lépések} + +\begin{frame}{Következő lépések} +\footnotesize +Ma megismertük, hogyan tervezzünk jól használható REST API-t, hogyan szervezzük a backend kódunkat rétegekbe, és mikor érdemes szétválasztani az írási és olvasási műveleteket. Eddig azonban minden adatunk csak a memóriában élt -- a jövő héten ezen változtatunk. + +\begin{enumerate} +\item \textbf{ORM megismerése} -- egy eszköz, ami a Domain rétegünk objektumait az adatbázis tábláira képezi le, SQL írása nélkül +\item \textbf{Adatbázis-kapcsolat kiépítése} -- az Infrastructure réteg végre ténylegesen egy adatbázishoz kapcsolódik +\item \textbf{CRUD műveletek} -- a ma megtervezett \texttt{POST}/\texttt{GET}/\texttt{PUT}/\texttt{DELETE} végpontok mögé valódi, perzisztens adatkezelést építünk +\end{enumerate} + +\begin{alertblock}{Javaslat} +Gondold át még egyszer az öt rétegű architektúrát -- a jövő héten pontosan az Infrastructure réteget töltjük meg valódi tartalommal. +\end{alertblock} +\end{frame}