Критерии диплома веб-разработчика

Мы составили критерии проверки дипломного проекта. За выполнение каждого критерия начисляются баллы. Чтобы сдать дипломную работу, нужно набрать не меньше 80-ти баллов.

Критерии имеют разный вес. Они разделены на блоки:

Если какой-либо из критериев блока «Работа принимается, если соблюдены критерии работоспособности» не выполнен — у вас есть возможность компенсировать это счет выполнения критериев из других блоков.

Бэкенд

Нумерация

Работа отклоняется от проверки

  • API не регистрирует пользователя по валидным данным.
  • Приложение не запускается с помощью команды npm run dev после установки всех необходимых зависимостей.
Нумерация

Работа принимается, если соблюдены критерии работоспособности

    • в проекте есть package.json;
    • .editorconfig;
    • .eslintrc, расширяющий конфигурацию airbnb-base, а также необходимые для работы линтера dev-зависимости;
    • .gitignore;
    • в .eslintrc добавлено исключение для _id. Директивы eslint-disable, eslint-disable-line и eslint-disable-next-line запрещены.
  • Нет ошибок линтера. При выполнении команды npx eslint . они должны отсутствовать. / 3.64
    • есть команда npm run start, которая запускает сервер на localhost:3000;
    • и npm run dev, которая запускает сервер на localhost:3000 с хот релоудом.
    • запрос на GET /users/me возвращает информацию о пользователе (email и имя);
    • PATCH /users/me — обновляет информацию о пользователе;
    • GET /movies все сохранённые пользователем фильмы;
    • POST /movies создаёт фильм с переданными в теле данными;
    • DELETE /movies/_id удаляет сохранённый фильм по _id;
    • POST /signup создаёт пользователя с переданными в теле данными;
    • POST /signin возвращает JWT, если в теле запроса переданы правильные почта и пароль.
    • Если вы сохраняете JWT в куках, роут /signout должен удалять JWT из куки.
  • Пользователь не может удалить сохранённую карточку из профиля другого пользователя. / 3.64
  • Все роуты, кроме /signin и /signup, защищены авторизацией. / 3.64
  • Роуты пользователей и роуты фильмов описаны в отдельных файлах. / 3.64
    • используются статус-коды ошибок: 400, 401, 403, 404, 409, 500;
    • если в запросе что-то не так, сервер возвращает статус ответа, который соответствует типу ошибки;
    • сообщение об ошибке соответсвует ее типу;
    • асинхронные обработчики завершены блоком catch;
    • API не возвращает стандартных ошибок базы данных или Node.js.
    • пароль хранится в виде хеша;
    • API не возвращает хеш пароля клиенту.
    • Запрос валидируется перед передачей контроллеру. Тело и, где необходимо, заголовки и параметры проверяются по соответствующим схемам. Если запрос не соответствует схеме, обработка не передаётся контроллеру, и клиент получает ошибку валидации.
    • Данные валидируются перед добавлением в базу.
  • В production-режиме адрес базы данных берётся из process.env. / 7.28
  • К серверу можно обратиться с помощью https по адресу домена, указанному в README.md. / 3.64
    • для продакшн сборки он хранится в .env файле — этот файл не добавляется в git;
    • в режиме разработки (при process.env.NODE_ENV !== 'production') код запускается и работает и без .env файла.
Нумерация

Хорошие практики

  • Все роуты подключены в файле index.js, который находится в папке routes. Оттуда единый роут подключается в файле app.js / 2.14
  • Асинхронные операции реализованы промисами или async/await. / 2.14
  • Валидация описана в отдельном модуле. / 2.14
    • запросы и ответы записываются в файл request.log;
    • ошибки записываются в файл error.log;
    • файлы логов не добавляются в репозиторий.
  • Ошибки обрабатываются централизованным обработчиком. / 2.14
  • Централизованный обработчик ошибок описан в отдельном модуле. / 2.14
    • Подходящий адрес:
      movies-explorer.nomoreparties.co/api,
      api.movies-explorer.nomoreparties.co.
    • Неподходящий адрес:
      server-movies-explorer.nomoreparties.co,
      movies-explorer.nomoreparties.co/sometext.
Нумерация

Рекомендации

  • Для ошибок API созданы классы, расширяющие конструктор Error.
    / 0.71
  • Используется модуль Helmet для установки заголовков, связанных с безопасностью. / 0.71
    • адрес Mongo-сервера и секретный ключ для JWT в режиме разработки вынесены в отдельный конфигурационный файл;
    • сообщения ответов и ошибок (константы приложения) вынесены в отдельный файл с константами.
  • Настроен rate limiter: число запросов с одного IP в единицу времени ограничено. / 0.71
  • rate limiter сконфигурирован в отдельном файле и импортируется в app.js. / 0.71
  • Для имени базы данных используется bitfilmsdb / 0.71

Вёрстка и JSX

Нумерация

Работа отклоняется от проверки

  • Пул реквест не отправлен на проверку.
  • Одна или более секций отсутствуют.
  • Разметка не портирована в JSX.
  • Проект не соответствует сгенерированному под него макету.
Нумерация

Работа принимается, если соблюдены критерии работоспособности

  • Проект адаптирован под различные разрешения экрана. Горизонтальный скролл не возникает на разрешениях от 320 пикселей и больше. Нельзя скрывать полосу прокрутки свойством overflow: hidden. / 11.55
  • Все блоки из макета свёрстаны. Корректно работает навигация между страницами и ссылки на внешние ресурсы: ни одна ссылка не ведёт в пустоту или на якорь, внешние ссылки открываются в новой вкладке. На все страницы проекта можно попасть, а скрытые блоки можно отобразить. / 11.55
  • Именование классов по БЭМ. / 11.55
  • Отзывчивая вёрстка, которая корректно тянется на всех промежуточных разрешениях. / 11.55
  • В коде используется семантическая разметка: применяются семантические теги, выбор элементов при вёрстке корректен (параграф должен быть параграфом, список — списком); структура DOM-дерева состоит не только из контейнеров div. / 3.38
  • Для позиционирования элементов выбран верный подход, описанный корректным синтаксисом. Например, при абсолютном позиционировании элемента его родительскому блоку задано относительное позиционирование. / 3.38
  • Каркас макета реализован на Flex layout или Grid layout. / 3.38
  • Инфраструктурные файлы проекта созданы через CRA. / 3.38
  • Работа модальных окон настроена верно. / 3.38
    • разметка заключена в ( ), лишние пустые <div> для этого не используются, / 3.38
    • разметка вынесена в соответствующие ей компоненты. / 3.38
    • директория images/ с картинками, / 3.38
    • директория components/ с JS и CSS-файлами компонентов, / 3.38
    • директория fonts/ со шрифтами. / 3.38
Нумерация

Хорошие практики

  • Кнопки, инпуты и ссылки реализованы во всех состояниях, указанных в макете. / 2.14
  • В макете есть одинаковые элементы. Для их оформления должен быть переиспользован один компонент. / 2.14
  • Шрифты подключены через @font-face. / 2.14
  • Иконки экспортированы в формате SVG. / 2.14
  • Элементы формы должны выделяться, когда на них установлен фокус. Состояние фокуса, а также outline стилизованы в соответствии с макетом или на своё усмотрение. / 2.14
  • У формы должны быть заданы плейсхолдеры и валидированы обязательные поля. / 2.14
  • Reset.css запрещён. / 2.14
Нумерация

Рекомендации

  • Для каждого шрифта указаны альтернативные варианты из системных шрифтов. / 1.68
  • Для изображений задан атрибут alt с подходящим значением. / 1.67
  • Растровые и векторные изображения оптимизированы. / 1.67

React и JS

Нумерация

Работа отклоняется от проверки

  • Пул реквест не отправлен на проверку.
  • Не работает описанная в задании функциональность. API поиска/сохранения/удаления фильмов, авторизации/регистрации/редактирования профиля не работают, либо при обращении к ним возникают ошибки в консоли.
  • Сборка или запуск проекта выполняются с ошибками.
  • Фронтенд часть приложения не выложена на сервер;
Нумерация

Работа принимается, если соблюдены критерии работоспособности

    • Общее:
      • Все ссылки и кнопки в проекте работают.
      • Правильно работают оба состояния шапки: если пользователь не залогинился, в шапке должны быть кнопки «Войти» и «Регистрация»; если пользователь залогинился, кнопки исчезают — и появляются кнопки «Фильмы», «Сохранённые фильмы» и «Аккаунт», в том числе и на главной странице.
      • При поиске текст запроса, найденные фильмы и состояние переключателя короткометражек сохраняются в хранилище. Если пользователь повторно переходит на страницу фильмов, то при монтировании компонента данные достаются из локального хранилища. Страница отображается в соответствии с загруженными из хранилища данными.
      • Все формы валидируются и на стороне клиента. Пользователь не может отправить запрос с невалидными данными.
    • Страницы «Регистрация» и «Авторизация»:
      • На странице «Регистрация» клик по кнопке «Зарегистрироваться» отправляет запрос на роут /signup, если данные введены корректно. Если запрос прошёл успешно, то автоматически производится вход и редирект на страницу /movies.
      • На странице «Авторизация» клик по кнопке «Войти» отправляет запрос на роут /signin, если данные введены корректно. Если запрос прошёл успешно, происходит редирект на страницу /movies.
      • Все формы валидируются и на стороне клиента.
    • Страница редактирование профиля:
      • На странице редактирования профиля клик по кнопке «Сохранить» отправляет запрос на роут /users/me, если данные введены корректно.
      • Пользователю отображается уведомление об успешном запросе к серверу при сохранении профиля.
      • Если на странице редактирования профиля введённая информация соответствует текущим данным пользователя, кнопка «Сохранить» заблокирована и нельзя отправить запрос сохранения.
    • Поиск фильмов:
      • Прелоадер крутится во время выполнения запроса фильмов.
      • Работа с фильтром настроена:
        • Поиск фильмов регистронезависимый.
        • Если запрос выполняется впервые, то работа с фильтром происходит после получения данных.
        • Если карточки уже были отображены на странице в блоке результатов, клик по чекбоксу «Короткометражки» приводит к повторной фильтрации результата.
      • После успешного сабмита формы поиска появляется блок с результатами.
      • Если ничего не найдено, выводится текст: «Ничего не найдено».
    • На странице всех фильмов в блоке результата отображается такое же количество карточек, как в макете. Нажатие на кнопку «Ещё» отображает следующий ряд с тем же числом карточек. При отображении всех карточек кнопка "Ещё" скрывается.
    • Карточки:
      • Карточка состоит из изображения, названия фильма и его длительности. Длительность фильма рассчитывается корректно и соответствует формату в макете. Клик по карточке ведёт на трейлер фильма.
      • Кнопка лайка имеет правильное состояние, в зависимости от того, добавлен ли фильм в сохранённые или нет.
      • При клике на иконку «Лайк» в блоке карточки выполняется запрос к /movies нашего API для установки или снятия лайка, в зависимости от текущего состояния.
    • На странице «Сохранённые фильмы»:
      • отображается форма поиска. Она позволяет искать фильмы по уже полученным данным о сохранённых фильмах.
      • Блок карточки содержит кнопку удаления, а не лайка.
      • При нажатии на кнопку удаления выполняется запрос на удаление фильма. После успешного запроса карточка удаляется со страницы.
    • Удалённые или добавленные карточки фильмов появляются только после перезагрузки страницы.
    • Если осталось отобразить меньше карточек фильмов, чем в полном ряду, то нажатие кнопки «Ещё» вызывает появление ошибок в консоли.
    • При удалении сохранённых карточек на соответствующей странице «Сохранённые фильмы» их по-прежнему можно найти через поиск. Поиск начинает корректно работать только после перезагрузки страницы.
    • Другие баги, которые возникают при работе с сервисом и требуют перезагрузки страницы или «ломают» пользовательский опыт.
    • Роуты /saved-movies, /movies, /profile защищёны HOC-компонентом ProtectedRoute. Роуты / , /signin, /signup не защищены. / 2
    • При попытке перейти на любой защищённый роут происходит редирект на /. / 3
    • Если пользователь был авторизован и закрыл вкладку, он может вернуться сразу на любую страницу приложения по URL-адресу, кроме страниц авторизации и регистрации. / 2
    • После успешного вызова обработчика onSignOut происходит редирект на /. / 2
    • Корректно используется хук useHistory. / 1
    • При попытке перейти на несуществующую страницу происходит редирект на страницу «404». Кнопка «Назад» работает корректно. / 2
    • Корректно используются компоненты <Switch />, <Route /> и <Redirect />. / 1
    • JWT-токен хранится в localStorage или в cookie; / 2
    • Jwt проверяется запросом к серверу, а не только в локальном хранилище. / 2
    • При выходе из аккаунта jwt удаляется. / 3
    • Хуки не используются внутри условных блоков или циклов. / 1
    • Хуки вызываются в основной функции компонента. / 1
    • При использовании классовых компонентов эффекты описаны внутри методов жизненного цикла компонента. / 1
    • Имена пользовательских хуков начинаются с use. / 2
    • В корневом компоненте App создана стейт-переменная, которая хранит данные пользователя. Она используется в качестве значения для провайдера контекста. / 1
    • В компонент App внедрён контекст через CurrentUserContext.Provider. / 1
    • Компоненты, в которых используются данные профиля, подписаны на контекст. / 1
    • Запросы можно осуществлять через Fetch API или XMLHttpRequest, сторонние библиотеки, такие как axios или jQuery), не применяются. / 1
    • Запросы к API вынесены в отдельные файлы: MainApi.js и MoviesApi.js. Цепочка обработки промисов завершается блоком. / 1
    • Первый обработчик then возвращает res.json. res проверяется на корректность. / 1
    • Цепочка обработки промисов завершается блоком catch. / 1
    • Не выполняются лишние запросы к бэкенду, например: запрос всех фильмов с сервиса beatfilm-movies производится только при первом поиске; все сохранённые фильмы не запрашиваются с сервера при каждом лайке или дизлайке; данные пользователя запрашиваются один раз при запуске приложения. / 2
    • имена переменных, функций и параметров написаны в camelCase;
    • имена переменных — существительные;
    • имена переменных, функций и компонентов соответствуют содержимому;
    • имена коллекций NodeList — существительные во множественном числе;
    • имя функции начинается с глагола и отражает то, что она делает;
    • для именования запрещены: транслит и неуместные сокращения.
Нумерация

Хорошие практики

  • Начальное состояние стейт-переменных содержит корректный тип данных. / 1
  • Для элементов списка используется уникальный ключ key, а не индекс массива. / 2
  • Запросы к API описаны внутри компонента App или в корневых компонентах страниц. / 2
  • Для внутренних ссылок в приложении используются компоненты из библиотеки react-router. / 2
  • Не происходит утечки памяти при навешивании обработчиков. Все обработчики, добавленные через addEventListener, удаляются при размонтировании компонента. / 2
    • пользователь получает сообщение в случае любой ошибки; / 4
    • поля формы заблокированы во время отправки запросов, и у пользователя нет возможности отправить новый запрос до завершения предыдущего. / 2
  • Фиксированные значения (константы) именуются заглавными буквами и вынесены в отдельный конфиг-файл. / 2
Нумерация

Рекомендации

  • Сторонние JavaScript-библиотеки не применяются. / 2
  • Используются семантически правильные блоки для компонентов. Не используются <div> или иные обертки для компонентов, которые состоят из одноуровневых блоков. / 1
    • нет беспорядка в коде;
    • нет лишнего кода: например, переменная объявлена, но не используется, или есть какая-то избыточная логика;
    • код форматирован одинаково, соблюдается иерархия отступов.