Использование балльно-рейтинговых систем является важным инструментом оценки эффективности деятельности в различных областях, в том числе в образовании. Балльно-рейтинговая система позволяет оценить качество работы учебных заведений, преподавателей и студентов, а также обеспечивает стимулирование участников образовательного процесса к улучшению своих результатов. Балльно-рейтинговая система может помочь в развитии конкурентной среды между учебными заведениями и способствовать улучшению качества образования в целом, так как создание прозрачной системы оценки результатов обучения ведет к повышению мотивации студентов и учебных заведений для достижения лучших результатов. Отмечаем, что разработка балльно-рейтинговой системы для университета требует тщательного анализа и выбора критериев, которые будут использоваться для оценки. Критерии должны быть объективными и учитывать различные аспекты деятельности университета, такие как академические достижения, инновационные исследования, социальная ответственность и др. Кроме того, при разработке балльно-рейтинговой системы для вуза необходимо учитывать индивидуальные особенности учебного заведения, такие как направления подготовки обучающихся, задачи, структура и т.д. [1]. Только в этом случае система будет действительно эффективной и позволит оценить качество деятельности университета в целом [2].
Цель разработки – создание балльно-рейтинговой системы для университета, обеспечивающей объективную оценку успеваемости студентов и эффективности учебного процесса. Указанная цель предполагает решение следующих задач:
1) разработать архитектуру программного комплекса (ПК), реализующего балльно-рейтинговую систему и ее функционал, учитывая потребности университета и стандарты образования;
2) создать систему авторизации и доступа к балльно-рейтинговой системе с учетом безопасности и конфиденциальности персональных данных;
3) реализовать механизмы сбора и анализа данных об успеваемости студентов;
4) обеспечить интерфейсы для управления ПК балльно-рейтинговой системы администраторами и использования его студентами и преподавателями;
5) обеспечить масштабируемость и поддержку балльно-рейтинговой системы на протяжении всего времени ее использования.
Выбор инструментов для разработки ПО БРС
Для разработки ПО БРС рассматривались современные языки программирования, фреймворки, библиотеки и инструменты для фронтенда, бэкенда и работы с базами данных [3]. Были выбраны:
1) React – для создания интерфейса пользователя и фронтенд-части системы;
2) Koajs – для создания бэкенд-части системы и обработки запросов;
3) Mysql – для хранения и управления данными системы;
4) Prisma ORM – для упрощения работы с базой данных и уменьшения количества необходимого кода.
Инструменты были выбраны исходя из того, что создаваемый программный код БРС должен обеспечивать надлежащую производительность, удобство использования, масштабируемость и надежность [4].
1. Производительность. React позволяет создавать быстрые и отзывчивые пользовательские интерфейсы благодаря использованию виртуального DOM и оптимизации рендеринга. Koajs обеспечивает быстрое и эффективное обслуживание запросов благодаря использованию асинхронных функций и генераторов. Mysql – реляционная база данных, имеет оптимизированный движок и обеспечивает быстрое выполнение запросов. Prisma ORM позволяет быстро и эффективно работать с базой данных благодаря использованию генерации кода и оптимизации запросов.
2. Удобство использования. React использует компонентный подход, делающий код более читаемым и поддерживаемым. Koajs использует цепочку обработчиков, что делает код более читаемым и удобным для отладки. Mysql имеет простой интерфейс для работы с БД и широкие возможности по настройке безопасности и защите от несанкционированного доступа. Prisma ORM генерирует необходимый код автоматически, что позволяет сократить количество необходимого кода и упрощает работу с базой данных.
3. Масштабируемость. React позволяет легко добавлять новые компоненты и управлять состоянием приложения. Koajs позволяет легко масштабировать API, обрабатывать запросы в режиме реального времени. Mysql позволяет легко добавлять новые таблицы и поля в базу данных и обрабатывать большой объем данных. Prisma ORM позволяет легко масштабировать работу с базой данных и генерировать необходимый код автоматически.
4. Надежность. React использует строгую типизацию, что позволяет выявлять ошибки на ранней стадии разработки. Koajs использует механизмы обработки ошибок, что позволяет быстро и эффективно реагировать на возникающие проблемы. Mysql имеет высокую степень надежности и защиты от сбоев и потери данных. Prisma ORM обеспечивает высокую степень надежности при работе с базой данных и упрощает процесс обновления и изменения данных.
Процесс разработки
Наиболее очевидная задача, которую необходимо выполнить при создании веб-ресурса – построение структуры базы данных. Структурирование данных является одним из важных аспектов проектирования БД, имеет важное значение для обеспечения эффективного хранения и обработки информации. Одним из ключевых инструментов для достижения этой цели являются нормальные формы, которые определяют, каким образом данные должны быть структурированы и организованы в базе данных. Нормальные формы являются формальными правилами, которые определяют, какие типы зависимостей должны существовать между атрибутами таблицы, чтобы база данных была эффективной, надежной и безопасной. Созданная структура, соответствующая первым 3 нормальным формам, представлена на рис. 1.
Рис. 1. ER диаграмма базы данных
Следующий этап – построение структуры и разработка серверной логики для эффективной и масштабируемой работы. Оптимальная, грамотно разработанная структура проекта облегчает сопровождение, упрощает сопровождения и добавление новых функций. Также упрощает отладку и тестирование проекта в целом, так как все файлы и функции имеют четко определенные места в структуре проекта. Желаемой масштабируемости и эффективности удалось добиться путем использования контроллеров и роутинговой структуры. Контроллеры представляют собой модули, отвечающие за обработку запросов, обращения к базе данных и формирование ответов. Роутинговая структура определяет, какие запросы должны быть переданы на обработку соответствующим контроллерам. Вместе они обеспечивают правильную организацию кода, что позволяет создавать сложные серверные приложения, которые могут легко масштабироваться и поддерживаться в долгосрочной перспективе. Были написаны промежуточные обработчики (middleware), которые позволили создать разделение прав на запросы, определяя, какие запросы могут быть обработаны только авторизованными пользователями, а какие являются общедоступными. Пример обработчика, фильтрующего запросы от пользователей, не имеющих соответствующей роли:
import jwt from ‘jsonwebtoken’;
import { Context, Next } from ‘koa’;
import { UserRoles } from ‘../types/requestTypes’;
export default (roles: (keyof typeof UserRoles)[]) => {
return async (ctx: Context, next: Next) => {
try {if (ctx.request.user === undefined) {
return ctx.throw(401, “Token was not provided”);
}
if (roles.includes(ctx.request.user.role) === false) {
return ctx.throw(403, “Forbidden”); }
return next(); } catch(e: any) {ctx.throw(e.status, e.message); }}}
Для использования обработчика остается указывать при роутинге, какие роли допускаются для обработки запросов сервером. Пример нескольких роутов с ограничением доступа:
const router = new Router();
// users page routes
router.put(“/createUser”, roleFilter([UserRoles.ADMIN]), adminController.createUser);
router.post(“/changeUserSettings/:id”, roleFilter([UserRoles.ADMIN]), adminController.changeUserSettings);
router.delete(“/removeUser/:id”, roleFilter([UserRoles.ADMIN]), adminController.removeUser);
// group page routes
router.get(“/group/search”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), groupController.getGroupsBySearch);
router.get(“/group/getUserGroup”, groupController.getUserGroup);
router.put(“/group/create”, roleFilter([UserRoles.ADMIN]), groupController.createGroup)
router.get(“/group/:id”, groupController.getGroupById);
router.post(“/group/:id/addStudentToGroup”, roleFilter([UserRoles.HEADMAN, UserRoles.ADMIN, UserRoles.HEADMAN]), groupController.addStudentToGroup);
router.post(“/group/:id/removeStudentFromGroup”, roleFilter([UserRoles.HEADMAN, UserRoles.ADMIN, UserRoles.HEADMAN]), groupController.removeStudentFromGroup);
router.post(“/group/:id/change”, roleFilter([UserRoles.ADMIN]), groupController.changeGroupSettings);
router.delete(“/group/:id/remove”, roleFilter([UserRoles.ADMIN]), groupController.removeGroup);
// subject page routes
router.get(“/subject/search”, subjectController.getSubjectBySearch)
router.put(“/subject/create”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), subjectController.createSubject)
router.get(“/subject/:id”, subjectController.getSubjectById)
router.post(“/subject/:id/addGroupToSubject”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), subjectController.addGroupToSubject)
router.post(“/subject/:id/removeGroupFromSubject”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), subjectController.removeGroupFromSubject)
router.post(“/subject/:id/change”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), subjectController.changeSubjectSettings)
router.delete(“/subject/:id/remove”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), subjectController.removeSubject)
// table page routes
router.put(“/table/create”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), tableController.createTable)
router.get(“/table/getNames”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), tableController.getTableNames)
router.get(“/table/getStudentNames”, tableController.getStudentTableNames)
router.get(“/table/:id”, tableController.getTableById)
router.put(“/table/:id/setMark”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), tableController.setMark)
router.put(“/table/:id/addColumn”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), tableController.addColumn)
router.post(“/table/:id/changeColumn”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), tableController.changeColumnName)
router.delete(“/table/:id/remove”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), tableController.removeTable)
router.delete(“/table/:id/removeColumn”, roleFilter([UserRoles.ADMIN, UserRoles.TEACHER]), tableController.removeColumn) export default router.routes();
Для эффективной работы БРС на клиентской стороне веб-приложения необходим фронтенд, обеспечивающий взаимодействие пользователя с серверной частью приложения. Фронтенд состоит из HTML, CSS и JavaScript-кода и отвечает за отображение данных и обработку действий пользователя, а также за отправку запросов на сервер и обработку полученных от него ответов. В нашем случае для взаимодействия с сервером в клиентской части проекта используем библиотеку React и фреймворк Redux Toolkit (RTK). RTK предоставляет удобные инструменты для написания асинхронных запросов к серверу, таких как thunk-функции и срезы (slices) состояния. Комбинация React и RTK позволяет создавать удобный и масштабируемый интерфейс для взаимодействия с сервером, удобный пользовательский интерфейс и обеспечить более эффективную работу с сервером. Полный исходный программный код, разработанной БРС, размещен в открытом доступе на платформе GitHub [5]. Ниже приведен код сервиса, обеспечивающего коммуникацию с сервером для получения и редактирования данных о дисциплинах:
import { appApi } from “../store/reducers/appApi”;
import { ISubjectAddGroupRequest, ISubjectAddGroupResponse, ISubjectCreateRequest, ISubjectCreateResponse, ISubjectGetRequest, ISubjectGetResponse, ISubjectGetSearchRequest, ISubjectGetSearchResponse, ISubjectRemoveRequest, ISubjectRemoveResponse, ISubjectRemoveGroupRequest, ISubjectRemoveGroupResponse, ISubjectSettingsChangeRequest, ISubjectSettingsChangeResponse } from “../types/api”;
export const subjectService = appApi.injectEndpoints({
endpoints: bulider => ({
getSubject: bulider.query<ISubjectGetResponse, ISubjectGetRequest>({
query: ({ id }) => `subject/${ id }`,
providesTags: [‘Subject’] }),
getSubjectSearch: bulider.query<ISubjectGetSearchResponse,ISubjectGetSearchRequest>({
query: (credentials) => ({url: “subject/search”,
method:”GET”, params:credentials}), providesTags: [‘Subjects’] }),
addGroupToSubject: bulider.mutation<ISubjectAddGroupResponse, ISubjectAddGroupRequest>({
query: ({ id, groupId }) => ({url: `subject/${ id }/addGroupToSubject`,
method: “POST”, body: {id: groupId } }),
invalidatesTags: [‘Subjects’, ‘Subject’, ‘Groups’] }),
removeGroupFromSubject: bulider.mutation<ISubjectRemoveGroupResponse, ISubjectRemoveGroupRequest>({
query: ({ id, groupId }) => ({
url: `subject/${ id }/removeGroupFromSubject`,
method: “POST”,
body: { id: groupId } }),
invalidatesTags: [‘Subject’] }),
createSubject: bulider.mutation<ISubjectCreateResponse, ISubjectCreateRequest>({
query: (credentials) => ({url: “subject/create”,
method: “PUT”,
body: credentials
}), invalidatesTags: [‘Subjects’] }),
changeSubjectSettings: bulider.mutation<ISubjectSettingsChangeResponse, ISubjectSettingsChangeRequest>({
query: ({ initialId, ...credentials }) => ({
url: `subject/${ initialId }/change`,
method: “POST”,
body: credentials }),
invalidatesTags: [‘Subject’] }),
removeSubject: bulider.mutation<ISubjectRemoveResponse, ISubjectRemoveRequest>({
query: ({ id }) => ({url: `subject/${ id }/remove`,
method: «DELETE»}),
invalidatesTags: [‘Subjects’]})})})
Рис. 2. Интерфейс страницы «Дисциплины»
Взаимодействие с пользователем через удобный и интуитивно понятный интерфейс – один из ключевых элементов создания успешного веб-приложения [6]. Разработка приложения включает в себя не только правильную организацию и представление данных, но также и эстетически приятный и легко понятный пользовательский интерфейс. Фрагмент разработанного интерфейса представлен на рис. 2.
Заключение
Для создания эффективного и масштабируемого веб-приложения БРС необходимо проектировать его с учетом построения правильной структуры базы данных, заканчивая созданием удобного пользовательского интерфейса. Важно учитывать принципы организации кода, использовать подходящие технологии для каждого этапа разработки. Коммуникация с базой данных должна происходить через надежный ORM-фреймворк, например такой, как Prisma, а структура проекта сервера должна быть оптимизирована для обеспечения удобства сопровождения и масштабирования. Правильно организованная роутинговая структура и промежуточные обработчики помогут создать разделение прав на запросы и обеспечить безопасность приложения. И, наконец, использование современных технологий, таких как React для клиентской части, позволит создать удобный пользовательский интерфейс и обеспечить более эффективную работу с сервером. Полный исходный программный код, разработанной БРС, размещен в открытом доступе на платформе GitHub.