Привет, Хабр! Недавно Skillbox начал тестировать формат кросскомандных дипломных проектов для студентов направления «Программирование». Сегодняшняя статья посвящена разбору первого подобного реализованного диплома по разработке соцсети, в котором приняли участие 8 студентов курсов «Java-разработчик», «Фреймворк Vut.js» и «Автоматизированное тестирование на Java». Как устроен этот формат обучения, и что вышло в результате трех месяцев кропотливой командной работы, расскажу я, Кирилл Кошаев, спикер профессии «Java-разработчик PRO», курса «Java-фреймворк Spring» и тимлид кросскомандного диплома.
Командный диплом
Однажды у нас появилась идея изменить формат дипломных проектов с одиночной работы на командную. Благодаря этому можно протестировать и прокачать не только hard skills студентов — знание языка программирования, фреймворков, но и soft skills — работу в команде, умение общаться, отстаивать свои идеи.
Мы решили дать студентам фреймворк, на базе которого они смогут работать в составе небольшой самоорганизующейся команды из разных курсов. Проект позволяет без критических последствий допускать ошибки, устранять их, развивать системное и проектное мышление, попробовать на практике некоторые элементы DevOps.
Проект социальной сети состоит из двух больших разделов: пользовательская часть и панель администратора. Первый включает следующие модули:
регистрация пользователей;
управление учетной записью;
управление личной страницей — профилем пользователя;
обмен сообщениями с помощью встроенного чата;
система оповещений о различных событиях.
Панель администратора представлена в виде дизайн-верстки. Мы подумали, если команда успеет сделать и этот модуль, то значит, она смогла решить “задачу со звездочкой”. На старте студенты получили API-документацию, дизайн-верстку фронтенда, исходные коды фронтенда и приступили к работе.
Почему социальная сеть?
Мы сделали такой выбор не случайно. С одной стороны, социальная сеть, как информационная система, имеет довольно широкую функциональность. Чтобы её реализовать, студентам приходится использовать много разных технологий и концепций, интегрировать их между собой для получения целостного продукта. Вот лишь несколько элементов:
механизмы создания и управления пользовательскими учетными записями;
поиск контента;
аутентификация и авторизация;
оптимизация вывода больших объемов контента;
система оповещений.
И всё это, включая работу с REST. Сейчас это стандарт для таких проектов.
Ну а с другой стороны (да, мы про нее не забыли), с точки зрения контента, социальная сеть — не самый сложный объект. Потому что пишут, постят и заполняют профили тут сами пользователи.
Наконец, проект социальной сети позволяет студентам попрактиковаться в разработке бизнес-логики приложения, научиться управлять данными без необходимости их генерировать. Если взять вместо социалки интернет-магазин — сразу возникает необходимость оперировать с такими понятиями, как «артикул товара», «чеки», «история транзакций». Вместо этого мы работаем с более понятными для студентов терминами: «пользователь», «комментарий», «пост», «личное сообщение». Всё это хорошо знакомо любому интернет-пользователю.
Работа над проектом
Во время создания социальной сети у студентов возникали проблемы, они искали решения, учились работать сообща, развивали soft и hard скиллы. Ниже я расскажу об организационных моментах работы над проектом на примере последней команды. Как я уже говорил в начале статьи, в ней приняли участие студенты сразу трех курсов: четверо — по Java-разработке, трое — по frontend-разработке на фреймворке Vue.js и один — по тестированию.
Коммуникации
Команда работает по модели Agile. Мы используем Scrum, процесс разработки ПО разделен на короткие интервалы — спринты. Не буду на этом останавливаться подробно, на Хабре об этом писали много раз.
Команда собирается на ежедневные короткие созвоны scrum-daily, в ходе которых каждый участник отвечает перед всеми на три вопроса:
Что он сделал для продвижения проекта с последнего scrum-daily?
Какие планы до следующего scrum-daily?
Есть ли сейчас какие-то проблемы в работе?
Такой способ коммуникаций помогал всем понимать, кто чем занят, и насколько близка или далека от завершения та или иная задача. Плюс ежедневные встречи сплачивают команду.
После спринта команда делает презентацию. На ней присутствуют наши преподаватели и эксперты, которые задают команде вопросы и оценивают проект. Всё это повторяется до финального спринта. На выполнение проекта у студентов есть 3 месяца: 6 спринтов по 2 недели каждый. В самом конце команда защищает дипломную работу, которая на этом этапе состоит из 15-20 тысяч строк кода. В течение всего пути команду сопровождает и поддерживает тимлид.
Сложности проекта
Сказать, что всё прошло без сучка и задоринки — значит, быть не до конца искренним. Конечно, сложности были. Вот основные:
Удаленка. Разработчики живут в разных регионах страны. А это, например, разные часовые пояса. Если расхождение во времени большое, работа команды усложняется;
Техническая неоднородность. На старте у одних разработчиков уже был опыт работы в «боевых» условиях, а другие — только заканчивали курс. Но это была не совсем проблема, больше возможность обмениваться опытом между студентами с разным набором скиллов. Сегодня ценится, если разработчик может не только создавать сложные структуры и бизнес-логику, но еще и объяснить, научить этому своих коллег по цеху.
Еще студенты столкнулись с теми же проблемами и вызовами, которые ожидают любую команду разработчиков на «боевых» проектах: соблюдение сроков, code review, рефакторинг кода и так далее.
Технический инструментарий
Список технологий и инструментов довольно широкий. Для контроля версий использовался Gitlab, для ведения задач — Kanban, Wiki — для ведения документации, плюс CI/CD для непрерывной доставки, интеграции и развертывания кода на боевом сервере команды.
У бэкенда есть свои нюансы. Студенты из направления Java-разработки использовали технологии Spring Security, Spring Data, Spring Web, Spring Actuator и другие. Для работы с уровнем данных сейчас обычно используется PostgreSQL, системы управления миграциями, такие как Liquibase. Фронтенд выстроен на основе фреймворка Vue.js. Тестирование кода происходит на всех уровнях, от модульного до системного, с использованием технологий Mockito, JUnit, TestNG и Selenium WebDriver.
В выборе технологий, команда никак не ограничена и может использовать всё, что посчитает нужным. Мы поощряем применение передовых технологий вроде Docker для автоматизации развертывания и управления приложениями в разрабатываемой студентами экосистеме. Приветствуем разные организационные подходы для эффективной и слаженной командной разработки.
Чтобы проиллюстрировать работу над проектом, я решил показать код некоторых элементов социальной сети. Напоминаю, что это работа начинающих программистов, поэтому прошу не судить слишком строго. Сам пример вполне конкретный, это задача по реализации поиска с использованием JPA Specification.
Чтобы использовать возможности спецификаций, нужно расширить репозиторий JpaSpecificationExecutor. По мере погружения в задачу команда приняла несколько решений, которые повлияли на конечный результат.
1. Создать класс Generics, который позволил бы формировать предикаты динамически и не зависеть от сущности, с которой идет работа.
2. Поиск в диапазоне дат, чтобы любое значение могло быть передано Null с фронта. Null-значения спецификации не обрабатывают, выбрасывается NullPointerExeption. Их обработка — это проблема для программиста. Использовали следующий метод:
Здесь за точку отсчета взята дата 01.01.1900, а конечной выбрана текущая, проблема Null решена. Да, можно было использовать другое решение с использованием greaterThanOrEqualTo(Expression<? extends Y> x, Y y) и lessThanOrEqualTo(Expression<? extends Y> x, Y y), но код с between выглядел более компактным, поэтому остановились на нем.
3. Поиск текста и поиск по имени и фамилии. Имя и фамилию можно вводить в любом порядке, например, пользователь может написать в поисковой строке так: «Александр (Шура) петров-сидоров:Васечкин». Вот как это удалось обработать: был реализован метод contains() из-за необходимости использовать join<X, Y>. Чтобы избежать дублирования кода, его пришлось переопределить.
Основной метод: private Specification<T> contains(Path<String> key, String value) {}
Дополнительный: private Specification<T> contains(Path<String> key, Predicate.BooleanOperator booleanOperator, String... values)
Последний метод и позволил сделать корректный поиск по строке.
Здесь приведены заключительные методы для реализации поиска по тексту и данным по имени и фамилии:
Эти методы использовались в проекте неоднократно, например, для поиска по городу или стране проживания, фильтрации ленты новостей.
Личные впечатления и советы новичкам
На сегодняшний день, я как тимлид довел до финала уже 5 групп (кроме последнего кросскомандного проекта 4 предыдущие дипломные команды состояли из студентов одного курса), а это без малого 2 года работы. За это время почти все команды в процессе реализации проектов предлагали интересные фичи и решения, например, оригинальные CI/CD пайплайны для автоматизации деплоя кода на боевой сервер.
В одной из групп я даже как-то наблюдал за созданием фреймворка для работы с уровнем данных, из которого после сдачи командного диплома студенты создали собственный проект и продолжили развивать его дальше. Разработчики часто улучшают уже готовый функционал, используют сложные технологии.
Например, механизм чатов изначально реализован по простейшему принципу периодической отправки запросов фронтендом в сторону бэкенда для обновления данных. Студенты переписали этот блок с использованием webhook-ов. Некоторые группы успели полностью сделать админку. Они поменяли дизайн фронтенда, добавили в него новые разделы и расширили функциональность существующих.
Вместо заключения несколько советов для новичков в командной разработке:
не бойтесь больших проектов и задач: с командой можно свернуть горы;
лучше делать маленькие по объему коммиты часто, чем большие редко;
если задача долго не двигается с места — не бойтесь попросить помощи у команды;
ничего не коммитьте в master за полчаса до выкатки, если только проект уже не лежит;
посвящайте проектной документации и рефакторингу хотя бы один день в неделю;
тестируйте свой код.
Также хочу поделиться отзывами студентов, которые работали над кросскомандным дипломом.
Олег Прохоров, закончил курс “Java-разработчик”, в проекте отвечал за создание слоев бизнес-логики: "В первую очередь, этот проект был полезен для меня пониманием того, что такое командная работа. Ведь это понадобится в будущем, уже при попадании в команду в коммерческой компании. Во время работы наиболее сложным моментом было отсутствие необходимых знаний. Но эта проблема решалась поиском в сети, работе со Stack Overflow, чтением книг и помощью руководителя”.
Павел Владысик также закрывал в проекте задачи по созданию бизнес-логики: “В моей работе крайне важным оказалось общение с опытным тимлидом, что дало возможность развиваться профессионально. Он давал очень дельные подсказки, говорил, какие аспекты изучить, какие из них будут часто встречаться в будущем”.
В проекте участвовали:
Кирилл Кошаев — тимлид дипломного проекта
Олег Прохоров — бэкенд-разработчик
Мария Алексеева — бэкенд-разработчик
Павел Владысик — бэкенд-разработчик
Максим Карачун — бэкенд-разработчик
Марк Налимов — фронтенд-разработчик
Владимир Барсуков — фронтенд-разработчик
Дмитрий Андреев — фронтенд-разработчик
Алексей Симаков — тестировщик