LEKCE 12 / 15

Architektura & Design Patterns

Clean Architecture, SOLID, Repository pattern, Domain-Driven Design základy a jak navrhovat škálovatelné aplikace.

Clean Architecture — vrstvy

Každá vrstva závisí jen na vrstvách níže. Byznys logika nezávisí na frameworku, DB ani UI.

// Vrstvy (od centra ven):
// 1. Entities — core byznys objekty a pravidla
// 2. Use Cases — aplikační logika (co aplikace dělá)
// 3. Interface Adapters — controllers, presenters, gateways
// 4. Frameworks & Drivers — Express, React, Prisma, DB

// Dependency rule: závislosti VŽDY směrem dovnitř

// src/domain/entities/Product.ts (žádné závislosti!)
export class Product {
  constructor(
    public readonly id: number,
    public readonly nazev: string,
    private _cena: number,
  ) {}

  get cena() { return this._cena; }

  applyDiscount(pct: number): void {
    if (pct < 0 || pct > 100) throw new Error('Invalid discount');
    this._cena = this._cena * (1 - pct / 100);
  }
}

// src/application/usecases/CreateProduct.ts
export class CreateProductUseCase {
  constructor(private repo: IProductRepository) {} // interface!

  async execute(dto: CreateProductDto): Promise<Product> {
    const exists = await this.repo.findBySlug(dto.slug);
    if (exists) throw new Error('Slug already taken');
    const product = new Product(0, dto.nazev, dto.cena);
    return this.repo.save(product);
  }
}

// src/infrastructure/ProductRepository.ts (Prisma implementace)
export class PrismaProductRepository implements IProductRepository {
  async save(product: Product) {
    return prisma.product.create({ data: { ...product } });
  }
}

SOLID principy v praxi

Repository & Service patterns

// Repository — abstrakce nad datovou vrstvou
interface IUserRepository {
  findById(id: number): Promise<User | null>;
  findByEmail(email: string): Promise<User | null>;
  save(user: User): Promise<User>;
  delete(id: number): Promise<void>;
}

// Service — orchestrace use cases
class AuthService {
  constructor(
    private users: IUserRepository,    // abstrakce!
    private tokens: ITokenService,
    private email: IEmailService,
  ) {}

  async login(email: string, password: string) {
    const user = await this.users.findByEmail(email);
    if (!user || !await bcrypt.compare(password, user.password))
      throw new UnauthorizedError();
    return this.tokens.sign({ userId: user.id });
  }
}
LEKCE 13 / 15

DevOps & Infrastructure

Docker, Docker Compose, Kubernetes základy, monitoring s Sentry a Datadog, logging a alerting.

Docker produkční best practices

# Multi-stage Dockerfile — malý produkční image
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN npm run build

FROM node:20-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
# Bezpečnost: spustit jako non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=deps    --chown=appuser:appgroup /app/node_modules ./node_modules
EXPOSE 4000
CMD ["node", "dist/server.js"]

# docker-compose.prod.yml
version: '3.8'
services:
  app:
    build: .
    ports: ["4000:4000"]
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      db: { condition: service_healthy }
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    volumes: [db_data:/var/lib/postgresql/data]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      retries: 5

  nginx:
    image: nginx:alpine
    ports: ["80:80", "443:443"]
    volumes: [./nginx.conf:/etc/nginx/nginx.conf]

volumes: { db_data: }

Monitoring — Sentry + structured logging

// Sentry — error tracking
import * as Sentry from '@sentry/node';
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1, // 10% transakcí
});
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.errorHandler()); // musí být za routes

// Structured logging (pino)
import pino from 'pino';
const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  formatters: { level: (label) => ({ level: label }) },
});

// Log jako JSON pro log aggregátory (Datadog, Loki)
logger.info({ userId: 42, action: 'login', ip: req.ip }, 'User logged in');
logger.error({ err, orderId: order.id }, 'Order creation failed');

// Health check endpoint
app.get('/health', async (req, res) => {
  const dbOk = await checkDb();
  const status = dbOk ? 200 : 503;
  res.status(status).json({
    status: dbOk ? 'ok' : 'degraded',
    uptime: process.uptime(),
    timestamp: new Date().toISOString(),
  });
});
LEKCE 14 / 15

Mikroservisy &
Distribuované systémy

Kdy přejít na mikroservisy, API Gateway, message queues, event-driven architektura a distribuované transakce.

Monolith vs Mikroservisy

Začněte s monolitem. Přejděte na mikroservisy jen když máte konkrétní problém, který monolith nevyřeší.

Message Queue — async komunikace

// RabbitMQ / BullMQ pro asynchronní úlohy
import Queue from 'bull';

// Producer — přidat úlohu do fronty
const emailQueue = new Queue('emails', { redis: process.env.REDIS_URL });

await emailQueue.add('welcome', {
  to:      user.email,
  subject: 'Vítejte v aplikaci',
  userId:  user.id,
}, {
  attempts: 3,          // 3 pokusy při selhání
  backoff:  { type: 'exponential', delay: 2000 },
});

// Consumer — zpracovat úlohy
emailQueue.process('welcome', async (job) => {
  const { to, subject, userId } = job.data;
  await sendEmail({ to, subject, template: 'welcome', userId });
  await updateUserEmailSent(userId);
});

// Event-driven architektura
// Services komunikují přes events, ne přímými HTTP voláními
// OrderService → publish('order.created', order)
// EmailService → subscribe('order.created') → pošle potvrzení
// InventoryService → subscribe('order.created') → sníží sklad

// Výhoda: loose coupling, service neví o ostatních
LEKCE 15 / 15

Závěr &
Certifikát

Dokončili jste kompletní profi kurz. Certifikát, skill tree, odznaky a doporučené next steps pro vaši kariéru.

📊 Skill Tree — co jste se naučili

React Hooks95%
State Management90%
Next.js App Router88%
Node.js & Express85%
Prisma & PostgreSQL85%
Testování80%
WebSockets80%
Pokročilý TypeScript78%
Bezpečnost82%
Performance75%
Architektura70%
DevOps & Docker68%

🏅 Sbírka odznaků

🎓 Certifikát

CERTIFICATE OF COMPLETION
Tímto potvrzujeme, že
Vaše jméno
úspěšně absolvoval/a kurz
Profi webový vývoj — React, Next.js, Node.js, TypeScript, Bezpečnost & Architektura
React 18 Next.js App Router TypeScript Advanced Node.js & Express Prisma & PostgreSQL Testing (Vitest/Playwright) WebSockets Security (OWASP) Performance Clean Architecture Docker & DevOps Mikroservisy

🗺️ Co dál — senior level

☸️

Kubernetes

Orchestrace kontejnerů pro velké produkční systémy.

DevOps
🦀

Rust nebo Go

Druhý jazyk pro performance-critical services nebo CLI nástroje.

Backend
🤖

AI/LLM integrace

OpenAI API, Vercel AI SDK, RAG systémy, vlastní AI features.

AI
📐

System Design

Návrh distribuovaných systémů, CAP theorem, eventual consistency.

Architektura
🎯

Open Source

Přispívejte do projektů — nejlepší způsob jak se dostat na radar.

Kariéra
📝

Tech blog

Pište o tom, co se učíte. Buduje reputaci a ukotvuje znalosti.

Kariéra
🚀

Jste senior-ready.

Kurz pokrývá technologie, které pracují v produkci u Airbnb, Vercel, Shopify a tisíců startupů. Teď záleží jen na praxi — stavte věci, open-source přispívejte, pište o tom.