Что такое архитектура приложения?

«Что такое архитектура приложения?» — вопрос из категории Архитектура, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Архитектура приложения — это высокоуровневая структура системы, определяющая организацию компонентов, их взаимодействие и принципы принятия решений. В контексте Node.js это часто означает выбор подхода к структурированию кода и распределению ответственности.

Основные архитектурные стили для Node.js:

  1. Монолитная архитектура: Все компоненты (API, бизнес-логика, доступ к данным) тесно связаны и развертываются как единое целое. Это просто для старта, но сложно масштабировать и обновлять.

    // Типичная структура монолита в Express
    // routes/users.js
    const express = require('express');
    const router = express.Router();
    const db = require('../db'); // Прямой доступ к БД
    
    router.get('/:id', async (req, res) => {
      const user = await db.query('SELECT * FROM users WHERE id = $1', [req.params.id]); // Логика и данные смешаны
      res.json(user);
    });
    module.exports = router;
  2. Слоистая (Layered) архитектура: Четкое разделение на уровни (Controller, Service, Repository/Data Access). Это повышает тестируемость и поддерживаемость.

    // Controller (обработка HTTP)
    exports.getUser = async (req, res, next) => {
      try {
        const user = await userService.getById(req.params.id);
        res.json(user);
      } catch (err) {
        next(err);
      }
    };
    
    // Service (бизнес-логика)
    class UserService {
      constructor(userRepository) {
        this.userRepository = userRepository;
      }
      async getById(id) {
        const user = await this.userRepository.findById(id);
        if (!user) throw new Error('User not found');
        // Дополнительная бизнес-логика
        return user;
      }
    }
    
    // Repository (доступ к данным)
    class UserRepository {
      async findById(id) {
        return db.query('SELECT * FROM users WHERE id = $1', [id]);
      }
    }
  3. Микросервисная архитектура: Система разбита на небольшие, независимо развертываемые сервисы, каждый со своей зоной ответственности. Они общаются через легковесные протоколы (HTTP/REST, gRPC, сообщения). В Node.js для этого часто используют фреймворки типа NestJS или чистый Express/Fastify с шиной событий или брокером сообщений (RabbitMQ, Kafka).

  4. Event-Driven архитектура: Компоненты взаимодействуют через события, что идеально для приложений реального времени. Ядро Node.js с его Event Loop и модулем EventEmitter хорошо подходит для этого.

    const EventEmitter = require('events');
    class OrderService extends EventEmitter {
      placeOrder(orderData) {
        // Сохраняем заказ...
        this.emit('order.placed', { orderId: 123, ...orderData }); // Генерируем событие
      }
    }
    
    const orderService = new OrderService();
    
    // Другие сервисы подписываются на события
    orderService.on('order.placed', (order) => {
      // Сервис нотификаций отправляет email
      // Сервис склада резервирует товар
    });

Выбор архитектуры зависит от масштаба проекта, требований к масштабируемости, компетенций команды и необходимости независимого деплоя компонентов. В Node.js популярны гибридные подходы, например, слоистая архитектура внутри сервиса в микросервисной системе.