Читать книгу 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. Мини-итог главы

Мы зафиксировали домен и сущности, а главное – общий смысл продукта. Дальше нам нужно договориться, как система должна себя вести под нагрузкой, как мы защищаемся от повторов и ошибок, как ведём аудит.

Full stack Developer

Подняться наверх