Ответ
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 в моих проектах:
- Независимость от фреймворка — Entity не импортируют flutter/dart:ui
- Богатая модель — содержат бизнес-правила и методы
- Иммутабельность — все поля
final, методы возвращают новые экземпляры - Value Objects — использование специализированных объектов для примитивов
- Легкая тестируемость — можно тестировать без 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,
);
}