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

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

Ответ

Entity (Сущность) — это ядро бизнес-логики приложения, представляющее фундаментальные концепции предметной области. В моих Flutter-проектах, построенных по принципам Clean Architecture, Entity находятся в самом центре, не завися от фреймворков, UI или внешних сервисов.

Пример реализации Entity для приложения управления задачами:

// Value Object для идентификатора задачи
class TaskId {
  final String value;

  TaskId(this.value) {
    if (value.isEmpty) {
      throw ArgumentError('TaskId cannot be empty');
    }
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is TaskId &&
          runtimeType == other.runtimeType &&
          value == other.value;

  @override
  int get hashCode => value.hashCode;
}

// Value Object для статуса задачи
enum TaskStatus { todo, inProgress, done }

// Основная Entity - задача
class Task {
  final TaskId id;
  final String title;
  final String description;
  final TaskStatus status;
  final DateTime createdAt;
  final DateTime? completedAt;
  final List<String> tags;

  Task({
    required this.id,
    required this.title,
    required this.description,
    required this.status,
    required this.createdAt,
    this.completedAt,
    this.tags = const [],
  }) {
    // Бизнес-правила валидации
    if (title.isEmpty) {
      throw ArgumentError('Title cannot be empty');
    }

    if (completedAt != null && status != TaskStatus.done) {
      throw ArgumentError('Only completed tasks can have completion date');
    }
  }

  // Бизнес-методы (логика предметной области)
  Task markAsInProgress() {
    return Task(
      id: id,
      title: title,
      description: description,
      status: TaskStatus.inProgress,
      createdAt: createdAt,
      completedAt: completedAt,
      tags: tags,
    );
  }

  Task complete() {
    return Task(
      id: id,
      title: title,
      description: description,
      status: TaskStatus.done,
      createdAt: createdAt,
      completedAt: DateTime.now(),
      tags: tags,
    );
  }

  bool get isOverdue {
    final deadline = createdAt.add(const Duration(days: 7));
    return status != TaskStatus.done && DateTime.now().isAfter(deadline);
  }
}

Принципы работы с Entity в моих проектах:

  1. Независимость от фреймворка — Entity не импортируют flutter/dart:ui
  2. Богатая модель — содержат бизнес-правила и методы
  3. Иммутабельность — все поля final, методы возвращают новые экземпляры
  4. Value Objects — использование специализированных объектов для примитивов
  5. Легкая тестируемость — можно тестировать без Flutter-зависимостей

Преобразование между слоями:

// Из DTO в Entity
Task fromDto(TaskDto dto) {
  return Task(
    id: TaskId(dto.id),
    title: dto.title,
    description: dto.description,
    status: TaskStatus.values.firstWhere((e) => e.name == dto.status),
    createdAt: DateTime.parse(dto.createdAt),
    completedAt: dto.completedAt != null ? DateTime.parse(dto.completedAt!) : null,
    tags: dto.tags,
  );
}