E-Dobavki — веб-сервис поиска пищевых добавок на Java и Spring Boot, написанный моими студентами

    Введение


    Так получилось, что последние почти два года я преподаю программирование в одной из IT школ Киева. Занялся я этим Just For Fun. Когда-то я вел блог по программированию, потом забросил. Но желание рассказывать полезные вещи заинтересованным людям никуда не делось.


    Мой основной язык — Java. Я писал на ней игры для мобильных, софт для радиосвязи, и различные веб-сервисы. И преподаю я именно Java.


    Здесь я хочу рассказать историю обучения последней своей группы. Как они прошли путь от начал обучения до написания работающего веб-сервиса. Полезного веб-сервиса по поиску пищевых добавок. Бесплатного, без рекламы, регистрации и СМС.


    Сам сервис вот — E-Dobavki.com.



    Проект является учебным, не содержит какой-либо рекламы. Как я понял из этой публикации, можно давать ссылки на такие проекты.


    Перед описанием самого проекта немного расскажупро процесс обучения группы, без этого картина будет неполной.


    9 месяцев обучения


    В школе, где я преподаю, курс Java разбит на 2 части. Суммарно курс занимает примерно 9 месяцев, со всеми перерывами (новогодние каникулы, время на написание промежуточных проектов).


    Первая часть знакомит студентов с базовыми понятиями ЯП. Переменные, методы, основы ООП и все эти штуки.


    Вторая же часть курса предусматривает, что студент уже более-менее понимает, как писать на Java, и ему можно дать "взрослый" стек технологий. Начинается все с SQL, дальше JDBC, Hibernate. Потом HTTP, сервлеты. Дальше Spring, немного про git и maven. И студенты пишут финальные проекты.


    Все обучение разбито на модули. Занятия я проводил два раза в неделю. Длительность одного занятия — два часа.


    Мой подход к обучению


    Я выпустил 5 групп. Вроде много как для двух лет, но я почти всегда вел 2 группы параллельно.


    Я пробовал разные подходы.


    Первый вариант — это одна пара выделяется на презентацию с теорией. Вторая же пара — чистая практика. Такой подход как-то работал, но эффективность была не очень, как по мне.


    Второй вариант, к которому я пришел и по которому работаю сейчас — это не выделять целую пару на теорию. Вместо этого я миксую короткие отрезки теории по 5-10 минут, и сразу закрепляю их практическими примерами. Такой подход работает лучше.


    Если хватает времени, я вызываю студентов на мое место, усаживаю за мой ноут, и они сами делают практические примеры. Это круто работает, но к сожалению занимает много времени.


    До конца доходят не все


    Открытием для меня стал факт, что не вся группа доходит до конца курса.


    По моим наблюдениям, лишь половина студентов пишет финальный проект. Большая часть отсеивается еще на первой части курса. А те, кто дошел до второй части, уже обычно не отваливаются.


    Уходят по разным причинам.


    Первое — это сложность. Что бы не говорили, а Java — это не самый простой язык. Для написания даже самой простой программы необходимо понять концепцию класса, метода. А чтобы понять, почему нужно писать public static void main(String[] arg) нужно понять еще несколько концепций.


    Сравните это с Турбо Паскалем, с которого начинали многие, в том числе и я:


    begin
        writeln("Первая программа");
    end.

    Решать эту проблему, насколько я знаю, школа будет введением дополнительного тестирования. Теперь на Java пойти учиться смогут не все. Пока это на стадии концепта, но шаг явно правильный.


    А вторая причина — это как на картинке ниже:



    Люди часто думают, что программирование — это когда печатают много текста, и получают за это много денег. Как копирайтер, только денег больше.


    Реальность же немного другая. Много рутинного кода, неочевидные баги, постоянный процесс обучения. Это интересно, но не всем.


    Такая статистика. Вначале меня это расстраивало, я думал, что может я что-то не так делаю. Сейчас я понимаю, что примерно такая же статистика на большинстве курсов. Сейчас я не парюсь над этим, а обучаю тех людей, кому это интересно.


    Идея сервиса


    Когда студенты прошли полный курс, пришло время написания финального проекта. Были разные идеи. Предлагали ToDo листы, проекты управления проектами, еще что-то.


    Я же хотел сделать что-то простое, но полезное. Мой критерий был простой — смогу ли я и мои друзья пользоваться этим. Под эти требования подошел веб-сервис поиска пищевых добавок.


    Идея проста. Покупая какой-то продукт в магазине, вы видите в составе какую-то E-шную добавку. По коду непонятно, насколько это опасно или нет (а есть и опасные добавки, запрещенные во многих странах).


    Вы открываете сайт, вбиваете название добавки (номер, одно из альтернативных названий), и получаете сводку по добавке:



    Похожие проекты есть. Можно также просто вбить добавку в Гугл, хотя он не всегда корректно показывает информацию.


    Но поскольку проект учебный, трудности выше не остановили нас :)


    Реализация


    Все писали на Java, исходный код проекта на Гитхабе.


    Нас было 7 человек, включая меня. Каждый делал пулл реквест, и я, либо же еще один человек из группы, принимал этот пулл реквест.


    Реализация проекта заняла примерно месяц — от озвучки идеи до того состояния, который вы видите сейчас.


    Парсинг добавок


    Первое, что сделал один из студентов, не считая базового создания обвязки вокруг БД (сущности, репозитории и т.д.) — это парсинг добавок из существующего информационного сайта.


    Это необходимо было для тестирования остальных моментов. Не нужен дополнительный код для наполнения БД. Быстро спарсив несколько добавок, можно было дальше тестировать UI, сортировку, фильтрацию.


    Spring Boot позволяет создать несколько профилей. Профиль — это файл с настройками.


    Для dev-окружения мы использовали профиль с локальной СУБД H2 и HTTP портом по умолчанию (8080). Таким образом, при каждом запуске приложения БД очищалась. Парсер в этом случае был той вещью, которая спасала нас.


    Поиск и фильтрация


    Важный момент — это поиск и фильтрация. Человек в магазине должен быстро тыкнуть код добавки, или какое-то из названий, и получить результат.


    Поэтому сущность Добавка имеет несколько полей. Это код добавки, альтернативные названия, описание. Поиск идет по Like по все полям одновременно. И если вы введете [123] либо [амарант], то получите одинаковый результат.


    Делали все это на основе спецификаций (Specification). Это часть Spring, которая позволяет описать базовые условия поиска (like по какому-то полю, например), а потом комбинировать эти условия (OR или AND).


    Написав десяток спецификаций, можно задавать сложные запросы вида "все опасные добавки-красители, у которых в описании есть слово [красный]".


    В плане работы с БД Spring мне кажется очень удобным. Особенно это проявляется в случае работы со сложными запросами. Я понимаю, что это дает свой оверхед, и вручную написанный и оптимизированный SQL запрос будет выполняться быстрее.


    Но также я придерживаюсь точки зрения, что не нужно заранее все оптимизировать. Первая версия должна запуститься, работать, и допускать возможность замены отдельных частей. А если пойдет нагрузка — вот эти отдельные части и нужно переписывать.


    Security


    Все просто. Есть пользователи с ролью ADMIN — они могут редактировать добавки, удалять, добавлять новые.


    И есть другие пользователи (зарегистрированные либо нет). Они могут только просматривать список добавок и искать нужные.


    Для разделения прав использован Spring Security. Данные пользователей хранятся в БД.


    Пользователи могут регистрироваться. Сейчас это ничего не дает. Если студенты продолжат развивать сервис, и вводить какие-то персонализированные функции, то регистрация пригодится.


    Адаптивность и Bootstrap


    Следующий момент — это адаптивность. В случае с нашим сервисом (по крайней мере так, как мы это видели) большинство пользователей будут с мобильными телефонами. И с мобилки нужно быстро посмотреть добавку.


    Чтобы не мучаться с CSS, взяли Bootstrap. Дешево, сердито, и выглядит прилично.


    Не могу назвать интерфейс идеальным. Главная страница еще более менее, а страница детального описания добавки узкая, на мобилках нужно шире ее сделать.


    Могу сказать только, что я старался по минимуму вмешиваться в работу. Это все же проект студентов. Ну и конечно же ребята смогут поправить потом такие моменты.


    Минутка SEO оптимизации


    Поскольку я уже больше двух лет плотно занимаюсь сайтами и всем, что связано с SEO, я не мог выпустить проект без хотя бы базовой SEO оптимизации.


    По факту, я сделал шаблонную геренацию Title и Description для каждой добавки. URL почти ЧПУ, хотя можно сделать и короче.


    Я добавил также счетчики посещаемости. Добавил сайт в Яндекс Вебмастер и Google Search Console, чтобы отслеживать предупреждения от поисковых систем.


    Это мало. Нужно еще добавить robots.txt и sitemap.xml для полной индексации. Но опять-таки, это проект студентов. Я им скажу, что нужно сделать, и если захотят — сделают.


    Нужно прицепить SSL сертификат. Подойдет и бесплатный Let's Encrypt. Я делал это для Spring Boot. Делается несложно, а доверие ПС повышается.


    Что дальше с проектом


    Дальше по факту выбор за ребятами. Изначальная идея проекта еще включала в себя БД продуктов с привязками к добавкам.


    Вводите "сникерс" и видите, какие в нем есть пищевые добавки.


    Еще на старте проекта я знал, что продуктов у нас не будет :) Поэтому начали мы только с добавок.


    Сейчас же можно прикрутить продукты, внедрить доп. плюшки. Если это будет обширная БД, пользователи найдутся.


    Развертывание


    Проект развертывался на VPS, Aruba Cloud. Это самый дешевый VPS, который мы смогли найти. Я пользуюсь этим провайдером уже больше года для своих проектов, и он приятно меня радует.


    Характеристики VPS: 1 GB RAM, 1 CPU (за частоту не знаю), 20 GB SSD. Для нашего проекта этого хватает с головой.


    Проект собирается обычным mvn clean package. Получается fat jar — исполняемый файл со всеми зависимостями.


    Чтобы немного автоматизировать все это, я написал пару баш скриптов.


    Первый скрипт удаляет старый jar файл, и собирает новый.


    Второй скрипт запускает собранный jar, передавая ему имя нужно профиля. В этом профиле содержатся сведения подключения к БД.


    БД — MySQL на этом же VPS.


    Итого перезапуск проекта включает в себя:


    • зайти на VPS по SSH
    • скачать последние правки git
    • запустить local-jar.sh
    • убить запущенное приложение
    • запустить launch-production.sh

    Занимает эта процедура три минуты. Мне это кажется разумным выбором для такого небольшого проекта.


    Сложности


    Основные сложности при создании проекта были организационного характера.


    Есть группа людей, которые вроде бы и умеют программировать, но не очень. Что-то знают, но применить толком еще не могут. И вот нужно, чтобы они сделали проект за месяц.


    Я выделил условного тимлида в этой группе. Он вел гугл док со списком задач, раздавал задачи, контролировал их принятие. Также он принимал пулл реквесты.


    Также я попросил студентов, чтобы каждый вечер они писали краткий отчет по сделанной работе по проекту. Не сделали ничего — ок, так и пишите "не сделал ничего". Это отличная практика, которая заставляет немного напрячься. Не все этому правилу следовали, к сожалению.


    Цель всей этой движухи была простая. Сформировать команду, пусть и на короткое время, будет работать вместе.


    Я хотел, чтобы у ребят было ощущение важности их работы. Понимать, что они не пишут сферический код в вакуме. А что они делают вместе проект, которым потом будут пользоваться люди.


    Первую неделю-две была раскачка. Вяло делались сущности, небольшие коммиты. Понемногу я все же их расшевелил, и работа пошла веселее. Общение в чате стало живей, студенты предлагали свои дополнения.


    Я считаю, что цель достигнута. Проект сделан, небольшой опыт работы в команде ребята получили. Есть видимый ощутимый результат, который можно показать друзьям, можно дальше развивать.


    Выводы


    Обучение — это интересно.


    После каждой пары я приходил эмоционально взбудораженным. Я стараюсь сделать каждую пару уникальной, и передать максимум знаний.


    Приятно, когда группа, которую я обучаю, доходит до финала. Особенно круто, когда ребята пишут "я устроился на работу, все норм, спасибо". Пусть это джуниор, пусть не самые большие деньги сначала. Но самое главное — они сделали шаг навстречу своим желаниям, и у них это получилось.


    Статья хоть и получилась довольно объемной, но все моменты конечно же раскрыть не получилось. Поэтому пишите в комментариях ваши вопросы.

    Поделиться публикацией

    Похожие публикации

    Комментарии 24

      +2

      Спасибо за рассказ.
      Какой возраст был у студентов?


      Если хватает времени, я вызываю студентов на мое место, усаживаю за мой ноут, и они сами делают практические примеры. Это круто работает, но к сожалению занимает много времени.

      По каким признакам вы определили, что это работает?


      Он вел гугл док со списком задач, раздавал задачи, контролировал их принятие.

      Можно гуглдок посмотреть?
      Ваш тимлид был по-совместительству главный тестер или задача тестирования тоже делегировалась?


      Понемногу я все же их расшевелил, и работа пошла веселее.

      Поделитесь, как расшевеливали?

        +1

        Пожалуйста!


        Возраст — от 18 (студенты в ВУЗе) до 45 примерно. Медианно где-то 25-30.


        Как определил — субъективно. Студент более собранный становится, задает больше вопросов. Остальные студенты внимательней смотрят, подсказывают товарищу. Ну как бы не препод что-то там пишет, а ваш коллега. Ну и такой эффект включается, что тебя могут вызвать самого что-то написать, волей-неволей больше вдумываешься.


        Гуглдок вот — https://docs.google.com/document/d/1Of9u0tJ6hrSde2LiJ9nyWBMbTXJIuzuKZizA204RBdA/edit


        Задачей тимлида была выдача заданий, приемка пулл реквестов. А при приеме пулл реквеста он проверял, что проект запускается и работает. Ну и каждый, кто делал фичу, проверял, что она работает. Так и писал в чат — "сделал пулл реквест. Запустил, работает". Конечно это не назвать полноценным тестированием, но более-менее работало.


        За расшевеливание:
        1) Ежедневные отчеты. Кажется фигней, но отлично мотивирует. Эту штуку я подглядел, когда сам проходил онлайн-курсы (не по программированию).
        2) Ежедневное общение в чате. Отвечал на все комменты, задавал вопросы. То есть, было ощущение, что проект живет, развивается, пишется.
        3) Когда видел, что от кого-то долго нет отчетов и сообщений, писал ему лично, спрашивал, все ли нормально, есть ли таски. Помогало — были моменты, что человек что-то сделал, но стеснялся залить на гитхаб, даже так :)
        4) Как только появилась первая версия проекта, почти без ничего — залил на VPS, и показал, что оно шевелится. Появилось ощущение не "пишем пет-проект в стол", а "делаем сервис для людей"

        –6
        Теперь понятно откуда берутся разработчики
        habr.com/ru/post/448410
        image
          0

          Не совсем понимаю, о чем вы.


          Если о счетчиках посещаемости — да, добавлен счетчик Яндекс.Метрики и счетчик Google Analytics. Добавлены, потому что интересно посмотреть, сколько людей пользуются сайтом, по каким ключевым словам приходят.

            –4
            Вот студенты привыкают смотреть и потом на сайтах этой шелухи килотонны и получаются.
              +2

              Ну счетчики добавил я сам. А по факту вы в любом случае, особенно в случае коммерции, будете с ними сталкиваться. Вот спросят у вас простой вопрос — "Сколько людей за месяц зашло на наш сайт? А на вот эту страничку?". Так что или будете свои писать, либо готовые возьмете, с аналитикой уже готовой.

                –6
                Если завальщики оценивают эффективность по кол-ву заходов / просмотров рекламы — тогда конечно. Простонужно понимать, что если берешь что-то с неконтролируемых источников, то последствия могут быть непредсказуемыми. Да и свою аналитику сделать — не проблема.
          0
          Нужно прицепить SSL сертификат. Подойдет и бесплатный Let's Encrypt. Я делал это для Spring Boot


          Вы делали это средствами самого спрингбута или же ставили nginx/apache перед ним? Если только спрингбутом, то расскажите, пожалуйста, подробней.
            +5

            Только средства Spring Boot.


            Если кратко, примерно так:


            1) Генерируется SSL сертификат, преобразуется в понятный Спрингу формат. Делал по этому туториалу — https://dzone.com/articles/spring-boot-secured-by-lets-encrypt
            2) Меняется server.port: 8443 на server.port: 443. Это дефолтный для HTTPS порт
            3) Теперь ваше приложение будет доступно по HTTPS, но недоступно по HTTP. Чтобы это исправить, добавляете редирект с HTTP на HTTPS:


            @Configuration
            @Profile("prod")
            public class RedirectHttpComponent {
                @Bean
                public ServletWebServerFactory servletContainer() {
                    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
                        @Override
                        protected void postProcessContext(Context context) {
                            SecurityConstraint securityConstraint = new SecurityConstraint();
                            securityConstraint.setUserConstraint("CONFIDENTIAL");
                            SecurityCollection collection = new SecurityCollection();
                            collection.addPattern("/*");
                            securityConstraint.addCollection(collection);
                            context.addConstraint(securityConstraint);
                        }
                    };
                    tomcat.addAdditionalTomcatConnectors(redirectConnector());
                    return tomcat;
                }
            
                private Connector redirectConnector() {
                    Connector connector = new Connector(
                            TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
                    connector.setScheme("http");
                    connector.setPort(80);
                    connector.setSecure(false);
                    connector.setRedirectPort(443);
                    return connector;
                }
            }

            Аннотация Profile("prod") указывает, что эта конфигурация применится лишь при запуске приложения в продакшн режиме.

            0

            Вы упоминали Bash скрипты в теме, можете ними поделиться, сам изучаю spring boot, будет интересно взглянуть на sh скрипты для собственного развития, спасибо

            0
            Автор, почему не рассматривали gitlab для ведения проекта и обучения ваших студентов зачаткам ci\cd?
            VPS есть, могли настроить полноценный пайплайн, как это сделано в многих современных компаниях.
            Куда полезнее, чем вручную лезть по ssh и собирать проект на прод-машине. Даже для учебного проекта это слишком. :)
              0

              Я ни разу не пользовался gitlab, только читал про эту штуку, хочу попробовать. Согласен, что это лучше, чем набор bash скриптов.


              Может и попробуем gitlab чуть позже.

                0
                В вашем случае скрипт будет практически такой же, как ваши башскрипты, просто оно будет выполняться не вручную человеком, а машиной.
                При пуше в мастер(мёрдже мердж реквеста) автоматически будет запускаться процесс сборки и деплоя.
                — mvn clean package
                — scp target/app.jar user@remote.host:/some/remote/directory
                — ssh user@remote.host «cd some/remote/directory && java -jar app.jar»

                Благо, в гитлабе базовая функция ci\cd бесплатна и попробовать её можно хоть сейчас. Удачи в этом вам и вашим студентам.
                  0

                  Спасибо! Если продолжим развивать проект — попробуем gitlab

                +1
                Я думаю, что для учебного проекта это как раз полезно, чтобы студент понимал, как это делать руками, и, что этот процесс можно автоматизировать.
                  0
                  Это полезно показать и объяснить, верно. Но не использовать на регулярной основе.
                  Проводите грань между полезно знать, понимать, как это делается и использование на регулярной основе.
                  Напомню, они в течении месяца писали проект и каждый раз, после каждого изменения нужно было проделывать эту операцию с заходом на сервак, когда есть простые и доступные средства автоматизации.
                  Можно половину проекта, чтобы студенты поняли, как это происходит, вручную деплоить, а вторую половину автоматизируя посредством ci.

                  В текущем варианте студент не знал, что процесс можно автоматизировать и опыта автоматизации он не получил, поэтому это не полезно.
                    0
                    они в течении месяца писали проект и каждый раз, после каждого изменения нужно было проделывать эту операцию с заходом на сервак

                    Значит эта операция не отнимала такое количество времени и сил, чтобы ее захотелось автоматизировать. Если бы это было долго/нудно/неинтересно, то CI/CD наколхозили бы на коленке.

                      0
                      Значит эта операция не отнимала такое количество времени и сил, чтобы ее захотелось автоматизировать. Если бы это было долго/нудно/неинтересно, то CI/CD наколхозили бы на коленке.

                      Они студенты, а не профессиональные разработчики. Они могут банально не знать о том, что подобное можно автоматизировать. Не знать инструментов. Не знать теории. Не знать, что то, что они придумали наколенночное решение и можно было куда проще.

                      А ещё им может быть лень и даже не думали о том, что что-то можно поменять. Зависит от ситуации. Им могли выдать инструкцию, что вот так и так нужно обновлять приложение и они даже не думали, что можно иначе, а просто действовали по инструкции. Привычка.
                      Если им после этого показать, что можно автоматизировать — они могли, откровенно, получить просветление о том, что оказывается можно ТАК.

                      Иными словами — нет, это совершенно не значит, что эта операция была настолько незначительной, что им не хотелось её автоматизировать.
                        0

                        Да, вы правы, операция отнимала и отнимает мало времени. Обновление проекта занимает меньше пяти минут.


                        За все время разработки проект обновлялся на VPS не больше пяти раз. Остальное время тестировалось локально все.

                  0
                  А откуда берётся информация о добавках? Видимо, о добавках с номерами больше 1000, информации там не было.
                  P.S. Зачем украили эмблему https://e-dostavka.by/? :)
                    0

                    Информацию о добавках сейчас берем из сайта http://dobavkam.net. Это первый сайт, который попался нам на глаза.


                    Вы правы за количество. На этом сайте далеко не все добавки, только трехзначные. По нормальному нужно парсить Википедию, там больше данных. Ну мы взяли первый попавшийся сайт, потому что было важно написать парсер на примере любого сайта.


                    За эмблему не совсем понял :) Вы про эмблему сайта или про favicon? Если favicon, то это стандартная иконка Spring.

                      0
                      Я про то, что url, иконка да и название похожи. Нет, я не обвиняю в плагиате, просто информирую, что вот так получилось.
                        0

                        А, ну бывает и такое:) Действительно глянул логотип — похожий.

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое