% REST API architektúra

\section{REST API Architektúra}

\begin{frame}{Miért van szükség architektúrára?}
  \begin{block}{A probléma: "Spagetti kód"}
    Kezdő fejlesztők gyakran mindent egy helyre írnak:
    \begin{itemize}
      \item Adatbázis lekérdezések a route-okban
      \item Üzleti logika a controller-ekben
      \item Validáció szétszórva mindenhol
    \end{itemize}
    
    \textbf{Eredmény:} Áttekinthetetlen, nehezen karbantartható kód
  \end{block}
  
  \begin{exampleblock}{A megoldás: Rétegezett architektúra}
    Minden funkciónak megvan a saját helye és felelőssége.
  \end{exampleblock}
\end{frame}

\begin{frame}{5-rétegű architektúra}
  \begin{block}{Separation of Concerns - Felelősségek szétválasztása}
    \begin{itemize}
      \item \textbf{Karbantarthatóság} - Könnyebb módosítás, hibakeresés
      \item \textbf{Tesztelhetőség} - Rétegek külön tesztelhetők
      \item \textbf{Skálázhatóság (Scalability)} - Független fejlesztés és skálázás
      \item \textbf{Újrafelhasználhatóság} - Rétegek több helyen használhatók
    \end{itemize}
  \end{block}
  
  \begin{alertblock}{Alapelv}
    Minden réteg csak a saját felelősségével foglalkozik!
  \end{alertblock}
\end{frame}

\begin{frame}{Az 5 réteg}
  \begin{enumerate}
    \item \textbf{API Layer (Presentation Layer)}
    \begin{itemize}
      \item HTTP kérések fogadása
      \item Route-ok, Controller-ek
    \end{itemize}
    
    \item \textbf{Application Layer (Service Layer)}
    \begin{itemize}
      \item Üzleti logika koordinálása
      \item Service-ek
    \end{itemize}
    
    \item \textbf{Domain Layer (Business Logic)}
    \begin{itemize}
      \item Üzleti szabályok
      \item Model-ek, Entity-k
    \end{itemize}
  \end{enumerate}
\end{frame}

\begin{frame}{Az 5 réteg (folyt.)}
  \begin{enumerate}
    \setcounter{enumi}{3}
    \item \textbf{Infrastructure Layer}
    \begin{itemize}
      \item Adatbázis hozzáférés
      \item Repository-k, ORM
    \end{itemize}
    
    \item \textbf{Communication Layer}
    \begin{itemize}
      \item Adatok átalakítása
      \item DTO-k, Validáció
    \end{itemize}
  \end{enumerate}
\end{frame}

\begin{frame}[shrink=10]{Rétegek áttekintése - Diagram}
  \begin{center}
    \begin{tikzpicture}[node distance=0.3cm]
      \node[draw, rectangle, fill=blue!20, minimum width=9cm, minimum height=1cm, align=center] (api) {\textbf{API réteg (API Layer)}\\Útvonalak, Vezérlők (Routes, Controllers)};
      
      \node[draw, rectangle, fill=green!20, minimum width=9cm, minimum height=1cm, below=of api, align=center] (app) {\textbf{Alkalmazás réteg (Application Layer)}\\Szolgáltatások (Services)};
      
      \node[draw, rectangle, fill=yellow!20, minimum width=9cm, minimum height=1cm, below=of app, align=center] (domain) {\textbf{Tartomány réteg (Domain Layer)}\\Modellek, Entitások (Models, Entities)};
      
      \node[draw, rectangle, fill=red!20, minimum width=9cm, minimum height=1cm, below=of domain, align=center] (infra) {\textbf{Infrastruktúra réteg (Infrastructure Layer)}\\Tárolók, Adatbázis (Repository, DB)};
      
      \node[draw, rectangle, fill=purple!20, minimum width=9cm, minimum height=1cm, below=of infra, align=center] (comm) {\textbf{Kommunikációs réteg (Communication Layer)}\\Adatátviteli objektumok, Ellenőrzés (DTOs, Validation)};
      
      \draw[->, thick] (api.south) -- (app.north);
      \draw[->, thick] (app.south) -- (domain.north);
      \draw[->, thick] (domain.south) -- (infra.north);
      \draw[<->, thick] (api.east) -- ++(1,0) |- (comm.east);
    \end{tikzpicture}
  \end{center}
\end{frame}

\begin{frame}[fragile,shrink=15]{API Layer - Route és Controller}
  \begin{exampleblock}{Route példa}
    \tiny
    \begin{verbatim}
// routes/user.routes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/user.controller');

router.get('/', userController.getAllUsers);
router.get('/:id', userController.getUserById);
router.post('/', userController.createUser);

module.exports = router;
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{API Layer - Controller}
  \begin{exampleblock}{Controller példa}
    \tiny
    \begin{verbatim}
// controllers/user.controller.js
const userService = require('../services/user.service');

exports.getAllUsers = async (req, res) => {
  try {
    const users = await userService.getAllUsers();
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

exports.getUserById = async (req, res) => {
  try {
    const user = await userService.getUserById(req.params.id);
    if (!user) return res.status(404).json({ error: 'Not found' });
    res.json(user);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Application Layer - Service}
  \begin{exampleblock}{Service példa}
    \tiny
    \begin{verbatim}
// services/user.service.js
const userRepository = require('../repositories/user.repository');

exports.getAllUsers = async () => {
  return await userRepository.findAll();
};

exports.getUserById = async (id) => {
  return await userRepository.findById(id);
};

exports.createUser = async (userData) => {
  // Üzleti logika validálás
  if (!userData.email || !userData.name) {
    throw new Error('Email and name are required');
  }
  return await userRepository.create(userData);
};
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Domain Layer - Model/Entity}
  \begin{exampleblock}{User Model}
    \tiny
    \begin{verbatim}
// models/user.model.js
class User {
  constructor(id, name, email, createdAt) {
    this.id = id;
    this.name = name;
    this.email = email;
    this.createdAt = createdAt || new Date();
  }

  // Üzleti logika metódusok
  isActive() {
    return this.active === true;
  }

  hasRole(role) {
    return this.roles.includes(role);
  }
}

module.exports = User;
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Infrastructure Layer - Repository}
  \begin{exampleblock}{Repository példa}
    \tiny
    \begin{verbatim}
// repositories/user.repository.js
const db = require('../config/database');

exports.findAll = async () => {
  return await db.query('SELECT * FROM users');
};

exports.findById = async (id) => {
  const result = await db.query('SELECT * FROM users WHERE id = ?', [id]);
  return result[0];
};

exports.create = async (userData) => {
  const result = await db.query(
    'INSERT INTO users (name, email) VALUES (?, ?)',
    [userData.name, userData.email]
  );
  return { id: result.insertId, ...userData };
};
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{Communication Layer - DTO}
  \begin{exampleblock}{Data Transfer Object}
    \tiny
    \begin{verbatim}
// dtos/user.dto.js
class UserDTO {
  constructor(user) {
    this.id = user.id;
    this.name = user.name;
    this.email = user.email;
    // Érzékeny mezők nem kerülnek át (pl. password)
  }
}

class CreateUserDTO {
  constructor(data) {
    this.name = data.name;
    this.email = data.email;
    this.password = data.password;
  }

  validate() {
    if (!this.email || !this.name || !this.password) {
      throw new Error('All fields required');
    }
  }
}
    \end{verbatim}
  \end{exampleblock}
\end{frame}

\begin{frame}{Projekt struktúra - Mappa felépítés}
  \begin{block}{Az 5-rétegű architektúra a mappákban}
    \small
    \begin{itemize}
      \item \textbf{\texttt{src/}} - Forráskód gyökér
      \item \quad \texttt{routes/} - \textcolor{blue}{API réteg}: útvonalak definiálása
      \item \quad \texttt{controllers/} - \textcolor{blue}{API réteg}: HTTP kérések kezelése
      \item \quad \texttt{services/} - \textcolor{green}{Alkalmazás réteg}: üzleti logika
      \item \quad \texttt{models/} - \textcolor{orange}{Tartomány réteg}: adatmodellek
      \item \quad \texttt{repositories/} - \textcolor{red}{Infrastruktúra réteg}: DB műveletek
      \item \quad \texttt{dtos/} - \textcolor{purple}{Kommunikáció réteg}: adatátviteli objektumok
      \item \quad \texttt{middlewares/} - Köztes réteg (autentikáció, naplózás)
      \item \quad \texttt{config/} - Konfigurációs fájlok
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}{Projekt struktúra - Függőségek}
  \begin{block}{Kommunikáció a rétegek között}
    \begin{itemize}
      \item \textbf{Routes} $\rightarrow$ Controllers (útvonal hívja a vezérlőt)
      \item \textbf{Controllers} $\rightarrow$ Services (vezérlő hívja a szolgáltatást)
      \item \textbf{Services} $\rightarrow$ Models + Repositories (szolgáltatás használja az adatréteget)
      \item \textbf{Repositories} $\rightarrow$ Database (tároló eléri az adatbázist)
      \item \textbf{DTOs} $\leftrightarrow$ Minden réteg (minden réteg használhat DTO-kat)
    \end{itemize}
  \end{block}
  
  \begin{alertblock}{Fontos szabály}
    A belső rétegek NEM függhetnek a külső rétegektől! A függőségek mindig befelé mutatnak.
  \end{alertblock}
\end{frame}

\begin{frame}{Clean Architecture}
  \begin{block}{Dependency Rule}
    Belső rétegek nem függhetnek külső rétegektől. A függőségek mindig befelé mutatnak.
  \end{block}
  
  \begin{exampleblock}{Előnyök}
    \begin{itemize}
      \item Független a framework-től
      \item Tesztelhető
      \item Független az UI-tól
      \item Független az adatbázistól
      \item Független külső szolgáltatásoktól
    \end{itemize}
  \end{exampleblock}
\end{frame}

\begin{frame}{Összefoglalás - Architektúra}
  \begin{itemize}
    \item 5-rétegű architektúra a clean code érdekében
    \item API Layer (API réteg): Route-ok és Controller-ek (útvonalak, vezérlők)
    \item Application Layer (Alkalmazás réteg): Service-ek (szolgáltatások - üzleti logika)
    \item Domain Layer (Tartomány réteg): Model-ek és Entity-k (modellek, entitások)
    \item Infrastructure Layer (Infrastruktúra réteg): Repository-k és DB (tárolók, adatbázis)
    \item Communication Layer (Kommunikációs réteg): DTO-k és validáció (adatátvitel, ellenőrzés)
  \end{itemize}
\end{frame}
