Критерии оценки финального проекта — Методическое руководство

Урок 3 из 3

Критерии оценки финального проекта — Методическое руководство

Общая структура оценки

Раздел Вес Max баллов
Полнота и качество SRS 25% 25
Корректность диаграмм (UML + BPMN) 25% 25
Связность артефактов (Traceability) 20% 20
Качество тест-кейсов 15% 15
Защита и ответы на вопросы 15% 15
Итого 100% 100

1. Детальная матрица оценок для каждого артефакта

1.1. SRS-документ (25 баллов)

Критерий Max баллов 0 баллов 0.5 балла 1 балл
1.1. Введение (цель, область применения) 2 Отсутствует или «вода» Есть, но неполно Чётко описаны цель, область, границы
1.2. Глоссарий 2 Отсутствует < 10 терминов 10+ терминов с чёткими определениями
1.3. Пользователи и роли 2 Отсутствуют Роли есть, но без описания прав Таблица ролей с правами и описанием
1.4. FR: полнота (5+ требований) 4 < 3 FR 3–4 FR 5+ FR с уникальными ID
1.5. FR: Acceptance Criteria (минимум 3 на каждое) 4 Нет AC AC для части FR AC для каждого FR, минимум 3
1.6. NFR: полнота (3+ требования с метриками) 4 < 2 NFR 2 NFR с метриками 3+ NFR с измеримыми метриками
1.7. Data Dictionary 4 Отсутствует Неполный (нет типов/FK) Все сущности ERD, с типами, FK, ограничениями
1.8. Описание As-Is / To-Be 3 Отсутствует Есть, но поверхностно Подробно: проблема, цифры, ожидаемый эффект
Итого SRS 25

1.2. UML и BPMN диаграммы (25 баллов)

Критерий Max баллов 0 баллов 0.5 балла 1 балл
2.1. Use Case Diagram 5 Отсутствует или не по нотации Есть, но неполно (пропущены актёры/UC) Все актёры из SRS, все UC, отношения
2.2. Activity / BPMN Diagram 7 Отсутствует Есть, но линейная (нет gateway) Есть gateway, роли, ошибки, default flow
2.3. Sequence Diagram 7 Отсутствует Только Happy Path, нет alt Синхр/асинхр вызовы, alt для ошибок
2.4. Class Diagram 6 Отсутствует Неполный (нет атрибутов/методов) Полный: классы, атрибуты, связи, multiplicity
Итого диаграммы 25

1.3. Трассируемость (20 баллов)

Критерий Max баллов 0 баллов 0.5 балла 1 балл
3.1. FR → Use Case → API → Test 5 Нет связи Частично Полная таблица маппинга
3.2. ERD → Data Dictionary → OpenAPI 5 Нет связи Частично Все сущности мапятся на схемы
3.3. Нет orphan-артефактов 5 Есть orphan 1–2 orphan 0 orphan
3.4. Все ID уникальны, нет пропусков 5 Дубли/пропуски 1–2 ошибки Идеально
Итого трассируемость 20

1.4. Тест-кейсы (15 баллов)

Критерий Max баллов 0 баллов 0.5 балла 1 балл
4.1. Минимум 5 тест-кейсов 3 < 3 3–4 5+
4.2. Структура (Preconditions, Steps, Expected) 4 Нет структуры Неполная Полная структура у каждого
4.3. Покрытие (Happy + Error + Security) 4 1 тип 2 типа 3+ типа
4.4. Связь с FR 4 Нет связи Неявная Явная ссылка на FR-ID
Итого тест-кейсы 15

1.5. Защита (15 баллов)

Критерий Max баллов 0 баллов 0.5 балла 1 балл
5.1. Структура презентации 3 Хаотично Есть структура 10 слайдов по шаблону
5.2. Аргументированность решений 4 «Так сделал» Частично обосновал Каждое решение обосновано (почему так, а не иначе)
5.3. Ответы на вопросы 5 Не ответил Ответил, но неуверенно Чёткие, аргументированные ответы
5.4. Знание предметной области 3 Путается в терминах Знает, но с ошибками Свободно оперирует терминами
Итого защита 15

2. Шкала итоговых оценок

Процент Баллы Оценка Описание
90–100% 90–100 5 (Отлично) Все артефакты полные, связные, глубокие. Студент свободно отвечает на вопросы.
75–89% 75–89 4 (Хорошо) Есть мелкие недочёты (1–2 незаполненных поля, пропущенный переход на диаграмме). Студент отвечает на большинство вопросов.
60–74% 60–74 3 (Удовлетворительно) Существенные недочёты: пропущены разделы SRS, неполные диаграммы, нет трассируемости. Студент путается в ответах.
< 60% 0–59 2 (Неудовлетворительно) Работа не завершена, артефакты не связаны, грубые ошибки в нотациях. Требуется полная переработка.

3. Гайд для экзаменатора: 15 глубоких вопросов на защите

Цель раздела: Проверить, что студент не просто скопировал артефакты из интернета, а понимает каждое своё решение. Вопросы построены так, что ответ «не подумал(а)» = 0 баллов за защиту.

Блок 1: Базы данных и ER-моделирование (вопросы 1–4)

Вопрос 1. Почему выбрали UUID для PK, а не автоинкремент (SERIAL)?

Проверяет: Понимание trade-offs между surrogate key типами.

Ожидаемый ответ студента:

  • UUID не требует централизованной генерации (хорошо для распределённых систем)
  • UUID не раскрывает количество записей (безопасность: /api/users/1 → понятно, что первый пользователь)
  • Но UUID: больше размер индекса (16 байт vs 4 для INT), медленнее вставка
  • Компромисс: для Task Manager (внутренняя система, 120 пользователей) можно было взять SERIAL, но UUID даёт гибкость на будущее

Красный флаг: «Мне сказали так сделать» / «Не знаю».

Вопрос 2. Покажите на ERD, какие индексы вы создадите и почему?

Проверяет: Понимание физического моделирования данных.

Ожидаемый ответ студента:

  • assignee_id (FK) — INDEX — для JOIN по исполнителю
  • status — INDEX — для фильтрации по статусу (если селективность высокая)
  • deadline — INDEX — для поиска просроченных задач
  • (project_id, status) — COMPOSITE INDEX — для дашборда по проектам
  • Composite index (assignee_id, status) для дашборда загрузки сотрудника

Красный флаг: «Индексы не нужны, база маленькая» / Не может объяснить, зачем индекс на FK.

Вопрос 3. В SRS у вас есть статусная модель. Как вы защитите данные от перехода в невалидный статус на уровне БД?

Проверяет: Понимание CHECK constraints, enum-типов, триггеров.

Ожидаемый ответ студента:

  • CHECK (status IN ('To Do', 'In Progress', 'Testing', 'Done', 'Blocked')) — базовый уровень
  • Если переходы сложные (не все статусы разрешены) — нужна отдельная таблица allowed_transitions или триггер на UPDATE
  • В PostgreSQL можно создать тип CREATE TYPE task_status AS ENUM(...) — жёстче, чем CHECK
  • В коде — enum в приложении + валидация на уровне сервиса

Красный флаг: «Валидация только на фронтенде» / Не знает, что такое CHECK constraint.

Вопрос 4. У вас есть таблица User и Task. Какой SQL-запрос покажет загрузку сотрудника в процентах?

Проверяет: SQL, JOIN, GROUP BY, CASE WHEN, понимание бизнес-метрик.

Ожидаемый ответ студента:

SELECT 
  u.id,
  u.name,
  COUNT(t.id) AS total_tasks,
  COUNT(CASE WHEN t.status NOT IN ('Done', 'Cancelled') THEN 1 END) AS active_tasks,
  ROUND(COUNT(CASE WHEN t.status NOT IN ('Done', 'Cancelled') THEN 1 END) * 100.0 / 
    GREATEST(COUNT(t.id), 1), 1) AS load_percent
FROM "User" u
LEFT JOIN Task t ON u.id = t.assignee_id
GROUP BY u.id, u.name
ORDER BY load_percent DESC;

Красный флаг: «Я не писал сложные запросы, это сделал бэкенд» / Не может объяснить LEFT JOIN vs INNER JOIN.

Блок 2: REST API и OpenAPI (вопросы 5–8)

Вопрос 5. Ваш API возвращает список задач на GET /tasks. Почему выбрали пагинацию через page/limit, а не cursor-based? В каком случае cursor-based лучше?

Проверяет: Понимание пагинации, её видов.

Ожидаемый ответ студента:

  • Offset/limit (page/limit): Просто, понятно, можно перейти на любую страницу. Проблема: при вставке данных пагинация «съезжает» (duplicate/skip). Хорошо для статических списков или UI с нумерацией страниц.
  • Cursor-based (keyset): Стабильная пагинация (не «съезжает»), быстрее на больших таблицах (WHERE id > last_seen). Проблема: нельзя перейти на страницу 3, только «дальше/назад». Хорошо для лент, бесконечного скролла.
  • Выбор: Для Task Manager (внутренняя система, статические задачи) page/limit ок. Для дашборда в реальном времени — лучше cursor-based.

Красный флаг: «Не знаю, что такое cursor-based пагинация» / «Пагинация не нужна, задач мало».

Вопрос 6. На защите вы показали PATCH /tasks/{id}/status. Почему PATCH, а не PUT? Почему не POST?

Проверяет: Понимание идемпотентности, разницы HTTP-методов.

Ожидаемый ответ студента:

  • PATCH — частичное обновление (меняем только status). PUT — полная замена ресурса (передали бы все поля). POST — создание (не подходит).
  • Идемпотентность: PATCH и POST — НЕ идемпотентны. PUT — идемпотентен. Если клиент повторно отправил PATCH — статус может измениться снова (если не реализована идемпотентность).
  • Безопасность: Если бы статус менялся на «Done» только один раз — нужно добавить Idempotency-Key или сделать проверку на сервере.

Красный флаг: «Всегда использую POST, потому что удобно» / Не слышал про идемпотентность.

Вопрос 7. В OpenAPI-спецификации вы указали security: Bearer JWT. Как будет обрабатываться запрос без токена? Какой статус-код?

Проверяет: Понимание аутентификации и статус-кодов.

Ожидаемый ответ студента:

  • 401 Unauthorized — если токен отсутствует или невалидный (просрочен, неверная подпись)
  • 403 Forbidden — если токен валиден, но у пользователя нет прав на ресурс (роль не позволяет)
  • Middleware на Gateway или в каждом сервисе проверяет JWT, извлекает userId, role, проверяет права
  • OpenAPI: эндпоинты с security — требуют токен; /auth/* — без security (public)

Красный флаг: «403 — если не авторизован» (путает 401 и 403).

Вопрос 8. Вы описали модель Task с полем status (enum). Как в OpenAPI 3.0 правильно описать enum?

Проверяет: Знание OpenAPI, JSON Schema.

Ожидаемый ответ студента:

Task:
  type: object
  properties:
    status:
      type: string
      enum: [To Do, In Progress, Testing, Done, Blocked]
      description: "Текущий статус задачи"
    priority:
      type: string
      enum: [Low, Medium, High, Critical]
  • Можно добавить x-enum-varnames для маппинга на код
  • В OpenAPI 3.1 можно использовать oneOf с константами, но enum — стандарт

Красный флаг: «Не помню, как описать enum» / Использует type: integer для статуса.

Блок 3: Интеграции и брокеры сообщений (вопросы 9–11)

Вопрос 9. В SRS вы описали, что система отправляет уведомления. Какую архитектуру выбрали — синхронную или асинхронную? Почему?

Проверяет: Понимание интеграционных паттернов (модуль 07).

Ожидаемый ответ студента:

  • Асинхронную (RabbitMQ/Kafka). Причина: отправка email/Slack не должна блокировать создание задачи.
  • Task Service отправляет событие task.created в очередь.
  • Notification Service читает из очереди, отправляет email/Slack.
  • Если Notification Service упал — сообщение остаётся в очереди (At-least-once).
  • Если Slack API временно недоступен — retry + Circuit Breaker.

Красный флаг: «Синхронную — отправляем email сразу из Task Service» / Не знает, зачем нужен брокер сообщений.

Вопрос 10. Что будет, если Notification Service получил событие task.created дважды? Как это предотвратить?

Проверяет: Понимание идемпотентности и гарантий доставки.

Ожидаемый ответ студента:

  • At-least-once доставка → сообщение может прийти дважды.
  • Решение: идемпотентность обработчика.
    • Хранить processed_events (eventId, processed_at) в БД.
    • Перед отправкой — проверить, обработан ли eventId.
    • Если уже обработан — пропустить (ACK без отправки email).
  • Альтернатива: Idempotency-Key от продюсера (но в асинхронной схеме eventId — аналог).
  • eventId генерируется как UUID при создании события.

Красный флаг: «У нас такого не будет, Kafka гарантирует exactly-once» (миф!).

Вопрос 11. Если дашборд загрузки (NFR-001: время < 2 сек) грузится слишком долго из-за JOIN к Task + Comment + Notification — что будете делать?

Проверяет: Понимание нефункциональных требований и путей оптимизации.

Ожидаемый ответ студента:

  • Materialized View — денормализованная таблица для дашборда, обновляется раз в N минут
  • Redis Cache — кэшировать результат дашборда на 5 минут (данные не должны быть real-time)
  • Отдельная таблица статистики — считать загрузку при изменении статуса (триггером или событием) и писать в отдельную таблицу
  • CQRS — разделить write model (нормализованная) и read model (денормализованная для дашборда)

Красный флаг: «Оптимизация не нужна, база маленькая» / Не знает, что такое Materialized View.

Блок 4: Нефункциональные требования и архитектура (вопросы 12–15)

Вопрос 12. NFR-03: «Аутентификация через JWT, пароли — bcrypt». Почему bcrypt, а не MD5 или SHA?

Проверяет: Понимание безопасности хранения паролей.

Ожидаемый ответ студента:

  • MD5, SHA1 — хеши для контроля целостности, а не для хранения паролей. Они быстрые — 1 млн хешей в секунду на GPU, перебор всех паролей за минуты.
  • bcrypt — адаптивный хеш. Можно регулировать cost factor (скорость). Даже с cost=10 — ~10 хешей в секунду, перебор 8-символьного пароля — миллионы лет.
  • bcrypt автоматически добавляет соль (salt) — одинаковые пароли дают разные хеши.
  • Альтернативы: argon2 (современнее, победитель Password Hashing Competition), scrypt.

Красный флаг: «Хешируем пароли MD5, он быстрый» / «Пароли храним в открытом виде, у нас же своя система».

Вопрос 13. NFR-02: uptime 99.5%. Сколько минут простоя допустимо в месяц? Что будете делать, если БД упала?

Проверяет: Понимание SLA, доступности, disaster recovery.

Ожидаемый ответ студента:

  • 99.5% = допустимо ~3.5 часа простоя в месяц (43 200 минут × 0.5% = 216 минут).
  • При падении БД:
    1. Connection pool (HikariCP) — не дать приложению упасть сразу
    2. Retry с exponential backoff — БД может перезагрузиться
    3. Circuit Breaker — если БД не отвечает, отключать запросы, возвращать fallback
    4. Replica — переключиться на read replica (если чтение)
    5. Backup — последний бэкап, point-in-time recovery
  • Для внутренней системы (120 пользователей) 99.5% — приемлемо. Для production заказчика нужно 99.9%+.

Красный флаг: «99.5% — это много, хватит» / Не знает формулу расчёта допустимого времени простоя.

Вопрос 14. Как вы обеспечите, что дашборд загрузки видит только HR, а разработчик — только свои задачи?

Проверяет: Понимание ролевой модели, авторизации.

Ожидаемый ответ студента:

  • Роли: ADMIN, TEAM_LEAD, DEVELOPER, HR (enum в таблице User)
  • JWT содержит role при аутентификации
  • Middleware/Interceptor в Spring/.NET Core:
    • DEVELOPER → GET /api/v1/tasks — только свои задачи (WHERE assignee_id = :userId)
    • HR → GET /api/v1/dashboard — все данные
    • TEAM_LEAD → GET /api/v1/tasks — задачи своей команды
  • Row-Level Security (RLS) в PostgreSQL — можно добавить политики на уровне БД
  • В OpenAPI: указать x-roles для каждого эндпоинта

Красный флаг: «Все видят всё, у нас доверенная среда» / Не может объяснить разницу между аутентификацией и авторизацией.

Вопрос 15. В проектном брифе сказано: «Новая задача создаётся не более чем за 3 клика». Как вы проверите это требование на этапе проектирования? А в production?

Проверяет: Понимание проверяемости требований, Usability Testing.

Ожидаемый ответ студента:

  • На этапе проектирования:
    1. Посчитать клики в прототипе (Figma). Создание задачи: кнопка «+» (1) → заполнить поля (2) → сохранить (3) = 3 клика.
    2. Если прототип требует 5 кликов — перепроектировать.
  • В production:
    1. Usability Test: посадить 5 пользователей, замерить количество кликов. Среднее не более 3.
    2. Analytics: добавить фронтенд-событие clicks_to_create_task, собрать статистику.
    3. Если > 3 — оптимизировать UI.
  • Критерий приёмки: 95% задач создаются за ≤ 3 клика (P95).

Красный флаг: «3 клика — это слишком абстрактно, не проверяется» / Не может предложить способ проверки.

Дополнительные вопросы (для усиления)

Тема Вопрос Что проверяет
CI/CD Как будете выкатывать новую версию без простоя? Понимание деплоя (blue-green, canary, rollback)
Мониторинг Как узнаете, что система упала в 3 часа ночи? Понимание observability (логи, метрики, алерты, Grafana/Prometheus)
Безопасность Как защититься от SQL-инъекции в поле title? Prepared statements, ORM, параметризованные запросы
Тестирование Какие тесты должны быть в CI перед деплоем? Unit → Integration → E2E (пирамида тестирования)
Брокеры Что делать, если RabbitMQ/Kafka умер? Dead Letter Queue, health check, Circuit Breaker, fallback
Кэш Почему вы выбрали Redis, а не in-memory кэш? Redis — распределённый, persistence, TTL, не теряется при рестарте приложения
Масштабирование Как система поведёт себя при 5000 одновременных пользователей? Connection pool, load balancer, кэш, асинхронность

4. Процесс защиты

1. Презентация (7–10 минут)
   ├── Студент показывает 10 слайдов
   └── Экзаменатор слушает, записывает вопросы

2. Вопросы (10–15 минут)
   ├── Минимум 3 вопроса из разных блоков (БД, API, интеграции, NFR)
   ├── 1 вопрос по трассируемости («Покажите, как FR-001 связан с API?»)
   └── 1 вопрос по выбору технологии («Почему PostgreSQL, а не MongoDB?»)

3. Оценка
   ├── По матрице оценки
   └── Субъективная оценка: уверенность, глубина, аргументация

Инструкция экзаменатору

  1. Не принимайте ответы «по бумажке». Если студент читает с листа — прервите и задайте уточняющий вопрос.
  2. Провоцируйте каверзными вопросами. Хороший студент скажет: «В моём проекте это не учтено, но в реальной системе я бы сделал так...».
  3. Проверяйте трассируемость вживую: «Покажите на SRS, где описана эта сущность. Теперь найдите её в ERD. А в OpenAPI?».
  4. Если студент не знает — задайте наводящий вопрос. Оценка «2» — только если студент не может ответить даже с наводящими.
  5. Записывайте тайминг. Защита — не более 25 минут. Если студент не укладывается — оценка снижается.

📚 Материалы модуля

🖼️ Схема и инфографика

🎬 Видео-лекция

🎬 Разбор IT-проекта

📄 Дополнительные материалы (PDF)

📄TeamTask Hub System Blueprint
Скачать
Спросить ИИ