← Назад к вопросам

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

1.3 Junior🔥 191 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

Зачем нужна архитектура

Представьте, что вы строите дом:

  • Без архитектуры — стены в случайных местах, окна не подходят к стене, провода везде
  • С архитектурой — план, каждая комната на своём месте, все провода в стене

То же самое с кодом.

Основные паттерны архитектуры

1. MVC (Model-View-Controller)

Класс шаблон для веб-приложений, разделяющий ответственность:

┌──────────────┐
│    USER      │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│   CONTROLLER │  (обрабатывает запрос)
│              │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│    MODEL     │  (бизнес логика, БД)
│              │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│     VIEW     │  (ответ пользователю)
│              │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│    USER      │
└──────────────┘

Пример на Express:

// routes.js (Controller)
router.get('/users/:id', userController.getUser);

// controllers/userController.js
exports.getUser = async (req, res) => {
  const user = await User.findById(req.params.id); // Model
  res.render('user', { user }); // View
};

// models/User.js
const userSchema = new Schema({ name: String, email: String });

2. Layered Architecture (Слойная архитектура)

Код организуется слоями, где каждый слой имеет чёткую ответственность:

┌─────────────────────────────────┐
│   Presentation Layer            │  (контроллеры, HTTP responses)
├─────────────────────────────────┤
│   Application/Business Layer    │  (use cases, бизнес логика)
├─────────────────────────────────┤
│   Domain/Service Layer          │  (доменные модели, интерфейсы)
├─────────────────────────────────┤
│   Data/Infrastructure Layer     │  (БД, внешние API, кеш)
└─────────────────────────────────┘

Правило: зависимости должны идти только вниз (сверху к низу).

// Presentation Layer
@Post('/users')
creatUser(@Body() createUserDto: CreateUserDto) {
  return this.userService.create(createUserDto); // вызов слоя ниже
}

// Application/Business Layer
@Injectable()
export class UserService {
  create(dto: CreateUserDto) {
    // бизнес-логика
    return this.userRepository.save(dto); // вызов слоя ниже
  }
}

// Data/Infrastructure Layer
@Injectable()
export class UserRepository {
  save(user: User) {
    return database.query('INSERT ...');
  }
}

3. DDD (Domain-Driven Design)

Фокус на доменной логике, а не на техническом стеке:

┌─────────────────────────────────┐
│   User Interface (HTTP API)     │
├─────────────────────────────────┤
│   Application Services          │  (команды, запросы)
│   (CreateUserCommand)           │
├─────────────────────────────────┤
│   Domain Models & Services      │  (User, UserService)
│   (Entities, Value Objects)     │
├─────────────────────────────────┤
│   Infrastructure                │  (Repository, Database)
└─────────────────────────────────┘

Структура папок:

src/
├── modules/
│   └── users/
│       ├── application/          (use cases)
│       ├── domain/               (entities, value objects)
│       ├── infrastructure/       (repository, database)
│       └── presentation/         (controllers)

4. Clean Architecture (Чистая архитектура)

Полная изоляция бизнес-логики от деталей реализации:

     ┌────────────────────────────────┐
     │   Enterprise Business Rules    │  (User, Product entities)
     ├────────────────────────────────┤
     │   Application Business Rules   │  (use cases, services)
     ├────────────────────────────────┤
     │   Interface Adapters           │  (controllers, presenters)
     ├────────────────────────────────┤
     │   Frameworks & Drivers         │  (web, DB, external APIs)
     └────────────────────────────────┘

Ключевой принцип: зависимости должны указывать в центр (внутрь).

Практический пример: простое приложение

// 1. DOMAIN LAYER - бизнес логика
class User {
  constructor(id, email, password) {
    this.id = id;
    this.email = email;
    this.password = password;
  }
  
  isPasswordValid(plainPassword) {
    return bcrypt.compareSync(plainPassword, this.password);
  }
}

// 2. SERVICE LAYER - бизнес сценарии
class UserService {
  constructor(userRepository) {
    this.userRepository = userRepository;
  }
  
  async register(email, password) {
    if (await this.userRepository.findByEmail(email)) {
      throw new Error('User already exists');
    }
    
    const hashedPassword = bcrypt.hashSync(password, 10);
    return this.userRepository.save(new User(uuid(), email, hashedPassword));
  }
  
  async login(email, password) {
    const user = await this.userRepository.findByEmail(email);
    if (!user || !user.isPasswordValid(password)) {
      throw new Error('Invalid credentials');
    }
    return user;
  }
}

// 3. INFRASTRUCTURE LAYER - работа с данными
class UserRepository {
  async findByEmail(email) {
    return database.query('SELECT * FROM users WHERE email = ?', [email]);
  }
  
  async save(user) {
    return database.query(
      'INSERT INTO users (id, email, password) VALUES (?, ?, ?)',
      [user.id, user.email, user.password]
    );
  }
}

// 4. PRESENTATION LAYER - обработка HTTP
router.post('/register', async (req, res) => {
  try {
    const user = await userService.register(req.body.email, req.body.password);
    res.json({ success: true, user });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

Выбор архитектуры

АрхитектураКогда использоватьСложность
MVCПростые приложенияНизкая
LayeredСредние CRUD приложенияСредняя
DDDСложная бизнес логикаВысокая
CleanБольшие масштабируемые системыОчень высокая

SOLID принципы в архитектуре

  • S — Single Responsibility — один класс, одна ответственность
  • O — Open/Closed — открыто для расширения, закрыто для модификации
  • L — Liskov Substitution — наследники заменяемы родителями
  • I — Interface Segregation — много маленьких интерфейсов лучше одного большого
  • D — Dependency Inversion — зависимости от абстракций, а не реализаций

Вывод

Хорошая архитектура:

  • Облегчает тестирование
  • Упрощает добавление новых фич
  • Делает код понятнее
  • Облегчает работу в команде
  • Снижает технический долг

Не усложняйте архитектуру без причины, но и не игнорируйте её полностью. Выбирайте архитектуру, соответствующую размеру и сложности проекта.

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