Проект представляет собой систему онлайн-тестирования для проверки знаний учащихся в рамках дистанционного обучения. Система должна обеспечивать возможность гибкого подхода к составлению тестовых заданий и проверке работ, с тем чтобы разные образовательные организации, преподаватели, организаторы учебных курсов и т.д. могли адаптировать составление и проверку тестов под своё видение учебного процесса.
Ниже представлена контекстная диаграмма системы в нотации модели C4:
Диаграмма контекста показывает систему "в общем", фокусируясь не на конкретных деталях, а на акторах, задействованных в процессе - какие классы пользователей взаимодействуют с системой, с какими внешними сервисами общается сама система. По мере развития проекта диаграмма может меняться и дополняться.
Внутренняя структура системы на уровне компонентов отображена на диаграмме контейнеров:
Создание данного проекта преследует две цели:
- учебная - научиться строить архитектуру веб-приложения, написанного на C# с использованием принципов чистой архитектуры и предметно-ориентированного проектирования (DDD);
- демонстрационная - показать свои навыки в проектировании и разработке;
Система тестирования задумана и будет реализовываться именно как система для проверки знаний в онлайн-режиме. Сложные подходы к проверке работ, такие как деление на первичные и тестовые баллы (как в ЕГЭ) реализовывать не планируется. Также за рамками проекта остаются всевозможные статистические опросы, а также тесты со сложными системами метрик, например, психологическое тестирование.
Дерево функций системы представлено на рисунке ниже:
Узлы, помеченные оранжевым, подлежат уточнению. По мере развития проекта перечень функций, включённых в границы проекта, может дополняться и корректироваться.
Класс пользователей | Описание |
---|---|
Преподаватель | Сотрудник организации, непосредственно осуществляющий обучение и проверку знаний учащихся. Преподаватели составляют тесты, проводят экзамены, проверяют работы, выставляют оценки. Также преподаватель может выступать в качестве куратора учебной группы и иметь доступ к отчётам об успеваемости. |
Администратор | Сотрудник организации, осуществляющий контрольные функции. Администраторы управляют учётными записями пользователей, они отвечают за предоставление доступа к системе, блокировку пользователей, создание учебных групп. В особых случаях администратор может вмешиваться в процедуру проведения экзаменов и составления тестов. |
Учащийся (студент) | Пользователь, чьи знания подлежат проверке посредством тестирования в системе AlphaTest. Учащиеся объединены в учебные группы, в которых они сдают тесты на оценку. |
Для различных категорий пользователей определены следующие варианты использования:
Действующее лицо | Вариант использования |
---|---|
Преподаватель | |
Составление тестов | |
Просмотр списка тестов | |
Создание теста | |
Изменение названия или темы теста | |
Просмотр меню настроек теста | |
Изменение порядка прохождения вопросов теста | |
Настройка возможности повторно отправлять ответы на вопросы | |
Задание лимита времени на тест | |
Изменение числа попыток сдачи теста | |
Выбор политики оценивания ответов в тесте | |
Задание проходного балла для сдачи теста | |
Отправка заявки на публикацию теста | |
Просмотр списка вопросов в тесте | |
Добавление вопроса в тест | |
Удаление вопроса из теста | |
Изменение порядка вопросов в тесте | |
Просмотр информации о вопросе в тесте | |
Редактирование вопроса | |
Отправка теста в архив | |
Создание новой редакции теста | |
Настройка способа проверки работ | |
Настройка распределения баллов за вопросы | |
Управление доступом к тесту | |
Добавление другого преподавателя в список составителей | |
Исключение другого преподавателя из списка составителей | |
Передача теста другому преподавателю | |
Проведение экзаменов | |
Создание (назначение) экзамена | |
Перенос сроков экзамена | |
Отмена экзамена | |
Проверка работ учащихся | |
Просмотр списка непроверенных работ | |
Просмотр списка непроверенных ответов в сданном тесте | |
Проверка работы экзаменатором | |
Ручная оценка ответа на вопрос | |
Администратор | |
Управление учётными записями | |
Регистрация новой учётной записи | |
Массовый импорт сведений об учащихся | |
Назначение ролей доступа для пользователей | |
Блокировка учётной записи | |
Повторная генерация временного пароля | |
Передача теста другому автору | |
Передача полномочий экзаменатора | |
Работа с учебными группами | |
Создание учебной группы | |
Добавление учащихся в группу | |
Исключение учащихся из группы | |
Назначение преподавателя куратором группы | |
Расформирование учебной группы | |
Редактирование учебной группы | |
Обработка заявок | |
Обработка заявки на публикацию теста | |
Рассмотрение заявки на публикацию теста | |
Учащийся | |
Просмотр списка новых экзаменов | |
Просмотр информации о тесте | |
Начало тестирования | |
Просмотр списка вопросов в тесте | |
Просмотр информации о вопросе | |
Переход между вопросами | |
Отправка ответа на вопрос | |
Отзыв отправленноо ответа на вопрос | |
Досрочное завершение тестирования | |
Просмотр списка результатов тестирования | |
Просмотр детальной информации об индивидуальных результатах тестирования | |
Все пользователи | |
Смена пароля | |
Автоматические операции | |
Автоматическая проверка работ | |
Блокировка учётной записи пользователя по истечении срока действия временного пароля |
Подробное описание вариантов использования здесь
Создание прямой зависимости от какой-либо библиотеки или технологии противоречит принципам чистой архитектуры; ядро системы, где сосредоточена бизнес-логика, должно быть замкнуто само на себя. Но в том, что касается учёта пользователей я решил сэкономить время и не писать никакой переходной связующей логики, чтобы отделить класс пользователя в терминах бизнес-логики от класса IdentityUser, поэтому ядро системы зависит от ASP.NET Core Identity, которая просачивается также в слой приложения (обработку вариантов использования). Это (может быть) некрасиво с точки зрения управления зависимостями в проекте, но отказ от готовых сервисов, предоставляемых Identity, привёл бы к необходимости писать всё то же самое руками и потратить на это много времени.
Для доступа к данным при обработке вариантов использования EF Core используется напрямую. Это сделано с целью обойтись без использвоания паттерна "Репозиторий" и не писать репозиторий поверх ORM. Из-за этого 2 слоя системы (слой инфраструктуры и слой приложения) зависят от EF Core. Такая мысль появилась после просмотра вот этого доклада. Я с автором не согласен и многие его доводы кажутся мне притянутыми за уши (если не сказать манипулятивными). Но многие разработчики, как я понял, разделяют эту точку зрения в том или ином виде, поэтому я решил интереса ради обойтись без репозиториев.
Для устранения возможных сложностей и ошибок, возникающих при использовании DateTime.Now, во всех местах, где необходимо текущее время, используется DateTime.UtcNow. В то же время, пользователи, вводящие дату и время (например, при составлении расписания экзаменов) вводят местное время; также любая информация, содержащая дату и время и идущая из системы посредством Web API должна содержать дату и время, приведённые к нужному часовому поясу. Как эта задача решается:
- Создан класс TimeResolver, который осуществляет перевод времени из UTC в местное;
- При развёртывании системы мы исходим из допущения, что пользователи системы находятся в одном часовом поясе и при развёртывании мы задаём таймзону в переменной окружения ALPHATEST__TIMEZONE; содержимое переменной преобразуется в TimeZoneInfo при запуске системы при помощи метода TimeZoneInfo.FromSerializedString и сохраняется в классе TimeResolver.
Переменная | Назначение |
---|---|
ALPHATEST__MIGRATOR_LOGIN | Логин для авторизации приложения в SQL Server; на стороне SQL Server нужны права db_owner для применения миграций. Рабочий логин для повседневной работы приложения с четко прописанными правами доступа пока не создан. |
ALPHATEST__MIGRATOR_PASSWORD | Пароль для авторизации приложения в SQL Server |
ALPHATEST__SERVER | URL сервера базы данных |
ALPHATEST__NOTIFICATION_EMAIL | Почта, с которой система будет отправлять уведомления |
ALPHATEST__NOTIFICATION_NICKNAME | От чьего имени будут отправляться уведомления |
ALPHATEST__SMTP_SERVER | Адрес SMTP-сервера |
ALPHATEST__SMTP_PORT | Порт SMTP-сервера |
ALPHATEST__SMTP_USERNAME | Имя пользователя для авторизации на SMTP-сервере |
ALPHATEST__SMTP_PASSWORD | Пароль для авторизации на SMTP-сервере |
ALPHATEST__TIMEZONE | Временная зона, в которой работает система. Должна иметь вид строки, из которой можно получить значение с помщью метода TimeZoneInfo.FromSerializedString |
ALPHATEST__TOKEN_KEY | Секретный ключ, используемый для генерации JWT |