Читать книгу Full stack Developer - Группа авторов - Страница 8
Раздел II. Продукт и требования, единые для всех реализаций.
Глава 6. Домен TaskFlow: что строим
ОглавлениеTaskFlow – это сервис управления задачами. Если очень коротко: “таски, проекты, комментарии, поиск, роли”. Если чуть длиннее – это маленькая копия того, что люди используют каждый день: Trello/Jira/Asana, но в более компактном виде и с понятным доменом, удобным для обучения.
Мы будем мыслить продуктом: не «сделать таблицы», а «помочь людям работать».
6.1. Главная идея продукта
У пользователя есть рабочие пространства (Workspace). Внутри них – проекты (Project). В проектах – задачи (Task), у задач – комментарии (Comment) и метки (Label).
Плюс обязательные вещи, без которых любой сервис задач быстро превращается в грустный список:
– регистрация и логин,
– права доступа,
– поиск и фильтрация,
– понятные ошибки в API,
– нормальная пагинация,
– аудит действий (кто что сделал).
Опционально (но мы предусмотрим место в дизайне):
– прикрепления файлов,
– уведомления (email/webhook).
> Важно: мы строим учебный, но реалистичный продукт. Поэтому всё, что “потом разберёмся”, мы хотя бы обозначим контрактами и моделями.
6.2. Сущности и их смысл
Ниже – не “таблицы базы данных”, а язык предметной области. Это сильно упрощает жизнь, когда вы будете писать код на любом языке.
6.2.1. User
User – это человек, который входит в систему.
Минимальные поля (логические):
– id – уникальный идентификатор
– email – логин (уникальный)
– password_hash – пароль в виде хеша (никогда не хранить “как есть”)
– name – отображаемое имя
– created_at, updated_at
Что важно сразу:
– email – уникальный.
– пароль не возвращаем через API никогда.
– имя может быть пустым или заполняться позже.
Вопрос продукта: может ли быть один пользователь в нескольких workspace?
Да, иначе сервис слишком ограничен. Это типичная модель “команд”.
6.2.2. Workspace
Workspace – рабочее пространство (команда/организация/группа).
Поля:
– id
– name
– owner_user_id (логический владелец)
– created_at, updated_at
Связи:
– Workspace содержит проекты.
– Workspace содержит участников (membership).
Почему Workspace нужен:
– отделяем проекты разных команд,
– вводим роли и права,
– создаём границы для поиска/доступа.
6.2.3. Роли и права (owner/admin/member)
Роли в рамках workspace:
– owner – главный, может всё, включая удаление workspace и управление правами.
– admin – почти всё, но не «уничтожить мир» (например, не сменить owner).
– member – обычный участник, работает с задачами и проектами по правилам.
Мы должны ответить на вопросы:
– кто может создавать проекты?
– кто может удалять проекты?
– кто может приглашать/удалять участников?
Для учебного проекта фиксируем разумное:
– owner/admin: управление участниками и проектами
– member: CRUD задач и комментариев (в пределах workspace)
– удаление workspace – только owner
> Да, роли всегда вызывают споры. Это нормально. Суть не в идеале, а в ясных правилах.
6.2.4. Project
Project – контейнер задач внутри workspace.
Поля:
– id
– workspace_id
– name
– description (опционально)
– status (например: active/archived)
– created_at, updated_at
Зачем статус:
– “архивировать проект” проще, чем “удалить навсегда”.
– архив не должен мешать поиску по умолчанию (но должен быть доступен через фильтр).
6.2.5. Task
Task – основная единица работы.
Поля (ядро):
– id
– workspace_id (или через project, но удобно иметь прямую привязку)
– project_id
– title
– description (опционально)
– status (todo/in_progress/done/canceled – минимально)
– priority (low/medium/high – опционально)
– assignee_user_id (опционально)
– reporter_user_id (кто создал)
– due_date (опционально)
– created_at, updated_at
Связи:
– Task имеет много комментариев.
– Task имеет много меток (many-to-many).
Сразу оговорим поведение:
– задача всегда принадлежит проекту;
– пользователь должен иметь доступ к workspace проекта, чтобы видеть задачу;
– менять статус может member/admin/owner (если есть доступ).
6.2.6. Comment
Comment – обсуждение задачи.
Поля:
– id
– task_id
– author_user_id
– body
– created_at, updated_at
– опционально: edited_at
Смысл:
– комментарии – это история решений. Поэтому удаление комментариев лучше делать мягким (soft delete) или запрещать полностью. В учебном варианте можно разрешить удаление автору/админу, но в аудит всё равно писать.
6.2.7. Label
Label – метка (тег), используемый для фильтрации.
Поля:
– id
– workspace_id
– name
– color (опционально)
– created_at, updated_at
Почему label живёт в workspace, а не в проекте:
– часто метки общие для всех проектов (“bug”, “feature”, “urgent”).
– проще делать единообразные фильтры.
6.3. Ключевые фичи (и что именно подразумеваем)
6.3.1. Регистрация и логин
Минимальный сценарий:
– пользователь регистрируется по email+паролю
– получает токен (например, JWT или opaque token)
– использует токен для запросов
Важно:
– регистрацию надо защищать от спама и брутфорса (rate limiting – обсудим в главе 7)
– ошибки должны быть понятными, но не слишком разговорчивыми (не рассказывать злоумышленнику, существует ли email)
6.3.2. CRUD проектов и задач
CRUD = Create/Read/Update/Delete, но в реальном продукте:
– “Delete” часто заменяется на архивирование или soft delete
– “Update” – частичное (PATCH), чтобы не отправлять каждый раз всю модель
Для учебной системы мы оставим:
– проекты: создать/получить/обновить/архивировать
– задачи: создать/получить/обновить/удалить (или тоже архивировать – на ваш выбор, но важно быть последовательными)
6.3.3. Поиск, фильтры, сортировка
Это то, что отличает “список задач” от “рабочего инструмента”.
Примеры фильтров для задач:
– по статусу
– по исполнителю
– по метке
– по сроку (due_date)
– по проекту
– по тексту (title/description)
Сортировка:
– по created_at
– по updated_at
– по due_date
– по priority
Поиск:
– простейший: q как подстрока по title/description
– продвинутый: отдельный поисковый движок (не обязательно в первой версии)
Сразу договоримся: фильтры должны быть комбинируемыми, а не “или это, или то”. Это влияет на дизайн API.
6.3.4. Прикрепления файлов (опционально)
Мы можем не реализовать полноценное хранение, но должны понимать модель:
Вариант A (практичный): файлы хранятся в объектном хранилище (S3-подобном), а API хранит только метаданные.
Сущность Attachment (пока концептуально):
– id
– task_id
– uploader_user_id
– filename
– content_type
– size
– storage_key или url
– created_at
Почему это важно даже “опционально”:
– нужно заранее решить: файл лежит у нас или мы выдаём ссылку?
– нужно заранее решить: кто может скачать файл?
– нужно заранее решить: как удалять/истекать ссылки?
6.3.5. Уведомления (email/webhook)
Уведомления почти всегда начинаются с двух событий:
– “задача назначена на меня”
– “в задаче новый комментарий”
Каналы:
– email (человеку)
– webhook (внешней системе: Slack/Teams/что угодно)
Мы будем думать об уведомлениях как о событии:
– событие возникло (task_assigned/comment_added)
– его нужно доставить подписчикам
– доставка может быть не мгновенной
– доставка может повторяться при ошибках
Даже если мы не делаем брокер сообщений в первой версии, мы можем заложить модель и API “подписки на webhooks”.
6.4. Границы доступа и типовые сценарии
Чтобы не сделать “дырявую” систему, полезно проговорить простые правила:
1) Пользователь видит только те workspace, где он участник.
2) Пользователь видит только проекты внутри доступных workspace.
3) Задачи доступны только через доступ к workspace/проекту.
4) Метки – внутри workspace, не глобальные.
5) Комментарии видны только тем, кто видит задачу.
Если вы соблюдаете эти пять пунктов, вероятность “случайно отдать данные другой команды” резко падает.
6.5. Что можно установить для комфортной работы (независимо от языка)
Чтобы не страдать с окружением:
– Docker Desktop или альтернативы (для БД/Redis локально)
– PostgreSQL (обычно удобнее как основная БД)
– DBeaver (просмотр БД)
– HTTP-клиент: Postman / Insomnia / или curl (curl – как хлеб: простой, но питательный)
– Markdown редактор (чтобы вести заметки по контрактам)
6.6. Мини-итог главы
Мы зафиксировали домен и сущности, а главное – общий смысл продукта. Дальше нам нужно договориться, как система должна себя вести под нагрузкой, как мы защищаемся от повторов и ошибок, как ведём аудит.