В предыдущей статье мы рассказали об идеях лежащих в основе наше Клуба инновационных решений, также известного как Социальная сеть для поиска инновационных решений, также известного как INnovationNETwork.
В этой статьей мы расскажем о программной реализации нашего Клуба, а точнее о программной реализации его функционального прототипа, включая: зачем нам понадобился прототип, что у него под капотом, на чем он работает, какие программные средства и компоненты мы используем для его разработки, какие средства мы используем для организации совместной работы.
Функциональный прототип Клуба
Такие проекты как Клуб начинаются с абсолютно голой идеи, которая по мере проработки обрастает такими гипотетическими деталями, как гипотетические задачи, пользователи и требования. Нельзя сказать что прорабатывая идеи Клуба мы не представляли себе кто является его потенциальными пользователями. Но, отсутствие непосредственного контакта с ними позволяет их причислить лишь к гипотетическим пользователям, а отталкиваясь от их гипотетических потребностей, получить лишь гипотетические задачи и требования.
Опираясь на эти гипотетические детали, зафиксированные в виде концепции, мы решили посмотреть (и другим показать) как это будет работать в живую, и начали работу над прототипом Клуба. Проскочив на полном ходу макетирование, фокус группы, мозговые штурмы и организационно-деловые игры, мы решили сделать функциональный прототип, который позволил бы нам и нашим экспертам оценить в работе Клуб и лежащие в его основе идеи.
![Веб-интерфейс Клуба, страница тематической группы "инновационная пасека" с задачами и решениями от Винни Пуха и его друзей Веб-интерфейс Клуба, страница тематической группы "инновационная пасека" с задачами и решениями от Винни Пуха и его друзей](https://habrastorage.org/getpro/habr/upload_files/fd5/63a/984/fd563a984186cb701fa1a38469ddd6ba.png)
Более того, предполагалось несколько последовательных этапов, состоящих из изучения прототипа различными группами экспертов, обсуждения и устранения их замечаний нами как разработчиками. На данный момент мы уже прошли часть этого пути и морально готовимся представить прототип Клуба хабровчанам.
Функциональное эволюционное прототипирование
В нашем понимании, функциональный прототип - это простейшая частичная реализация полноценного (прототипируемого) программного продукта, позволяющая оценить его функционал в процессе работы с ним, что требует программной реализации ключевых функций полноценного продукта, и, как следствие, использование полноценной программной платформы, компонент и средств разработки.
Основным минусом такого прототипирования безусловно является его стоимость, которая может приближаться к стоимости разработки минимально жизнеспособный продукта (MVP, Minimum Viable Product). А основным плюсом является опыт использования и программные наработки на раннем этапе работы над программным продуктом.
Прототипирование с получением и последующим использованием программных наработок называется эволюционным и довольно тесно граничит с итеративными Agile методиками разработки программного обеспечения. Более того, рискуя вызвать бурную дискуссию (возможно, это моя цель), скажу, что эта грань условна и определяется моментом перехода от последней версии прототипа к первой пилотной или полноценной (рабочей) версии продукта.
Под капотом у прототипа
Поднимая капот прототипа Клуба мы увидим, что это монолитное веб-приложение для платформы Java (на днях переехали на OpenJDK 17), написанное на языке Java, по большей части. Точнее бэкенд написан на Java довольно разбавленной аннотацией Spring, JPA (Java Persistence API), Hibernate, JAXB (Java Architecture for XML Binding оно же Jakarta XML Binding), Project Lombok, а фронтенд базируется на JSP (Java Server Pages) с использованием Bootstrap (модифицированные стили собираются с помощью SASS), jQuery и других JavaScript библиотек.
Скорее всего монолитная архитектура является временным решением. Она позволяет сэкономить время на проектировании отдельных веб-сервисов и реализации программных интерфейсов для взаимодействия сервисов. Отмечу, что в прототипе реализована своя подсистема регистрации событий, включая действия пользователей, отладочную информацию и информацию о производительности различных функций. Такая информация позволит нам определить узкие места и выбрать функционал, который может быть выделен в отдельные сервисы с целью повышения производительности.
![Java-класс базовой сущности задачи и решения, обратите внимание что и задачи и решения хранятся в одной таблице базы данных. Также, обратите внимание на использование аннотации JPA, JAXB и Lombok Java-класс базовой сущности задачи и решения, обратите внимание что и задачи и решения хранятся в одной таблице базы данных. Также, обратите внимание на использование аннотации JPA, JAXB и Lombok](https://habrastorage.org/getpro/habr/upload_files/e37/e88/fe9/e37e88fe9f50df8793408d6fc7db029d.png)
В наших проектах мы стараемся избежать использования дополнительных файлов, и в этом нам помогает самая разнообразная аннотация. Например, аннотация JPA и Hibernate говорит как работать с базой данных, какие значения могут принимать поля и т.д. Аннотация JAXB используется для выборочного импорта и экспорта данных в XML файлы, в частности для импорта данных при инициализации Клуба и его базы данных. Аннотация Lombok облегчает код и жизнь программиста избавляя от геттеров, сеттеров (речь не про породу собак), конструкторов по умолчанию и некоторых других рутинных элементов.
Однако, Lombok в сочетании с Javadoc и некоторыми другими инструментами может потребовать дополнительного времени на изучение и настройку. В частности, для генерирования документации с помощью Javadoc нужны исходные коды с геттерами, сеттерами и другими элементами генерируемыми Lombok. Таким образом, в POM файле (если вы используете Apache Maven) нужно сказать куда сохранять исходные файлы сгенерированные Lombok и откуда их брать для последующей генерации документации Javadoc.
![JSP-шаблон страницы используемой для работы с задачей или решением, обратите внимание на проверку прав доступа пользователя. JSP-шаблон страницы используемой для работы с задачей или решением, обратите внимание на проверку прав доступа пользователя.](https://habrastorage.org/getpro/habr/upload_files/cb7/cab/bc2/cb7cabbc257b57657f0da53c66d49a23.png)
Мы стараемся выполнять подобную проверку как в шаблонах страниц, так и в соответствующих им контроллерах. Например, пользователь может вносить изменения в задачу или решение только при наличие определенной роли в определенной тематической группе (hasPermission('GROUP:'+#activity.group.id,'manager')) или если он является автором данной задачи или решения (#activity.user.name == authentication.name).
Между Java-классами сущностей и JSP-шаблонами страниц лежат:
классы репозиториев, зачастую называемые DAO (Data Access Object) и реализующие базовый функции работы с данными и базой данных;
классы сервисов - реализация прикладных функций;
классы фильтров и контроллеров - обработка запросов пользователей и подготовка данных для шаблонов страниц.
Кроме этого, есть Java-классы конфигурации Spring (конфигурирование веб-приложения), вспомогательные классы, JavaScript, SCSS (диалект языка SASS (Syntactically Awesome Style Sheets), облегчающий работу с CSS стилями), CSS (вот собственно говоря и они), SQL, Docker файлы и многое другое. Но, обо всем по порядку, или не совсем по порядку.
![Класс репозитория для задач и решений, обратите внимание на использование CriteriaQuery вместо SQL запросов Класс репозитория для задач и решений, обратите внимание на использование CriteriaQuery вместо SQL запросов](https://habrastorage.org/getpro/habr/upload_files/7aa/4c9/750/7aa4c9750460f8b543e4a7c7dc513eec.png)
На наш взгляд CriteriaQuery удобней и безопасней традиционных SQL запросов. В идеале нужно использовать JPA Metamodel, чтобы уйти от указания имен полей сущностей в виде текста.
![Класс сервиса для задач и решений, обратите внимание на небольшой объем кода Класс сервиса для задач и решений, обратите внимание на небольшой объем кода](https://habrastorage.org/getpro/habr/upload_files/b12/0f1/1d6/b120f11d649be24c7a6cb1adcd0ca898.png)
В нашем случае смысловая нагрузка на сервисы значительно различается. Некоторые из них содержать большой объем прикладной логики (например, сервис транзакций баллов вознаграждения между пользователями), другие являются фактически прослойкой между контроллерами и репозиториями (сервис отвечающий задач и решений). Во втором случае, основной объем прикладной логики реализуется в соответствующих контроллерах.
Безусловно, при переходе от прототипа к полноценному продукту практически вся прикладная логика должна перекочевать в сервисы, обеспечивая тем самым возможность работы с ней различных контроллеров веб-интерфейса и программных интерфейсов.
![Класс контроллера страницы задачи или решения, обратите внимания на проверку прав доступа Класс контроллера страницы задачи или решения, обратите внимания на проверку прав доступа](https://habrastorage.org/getpro/habr/upload_files/313/6af/425/3136af4257122a255642f6b010645d64.png)
Как уже упоминалось раньше проверка прав доступа осуществляется на двух уровнях, на уровне шаблона страницы и на уровне класса контроллера. В первом случае это позволяет избежать генерации лишних HTML элементов (кнопки с действиями и т.д.). Во втором случае это предотвращает возможность выполнения тех или иных действий пользователем без необходимых для этого прав доступа.
Это довольно важный момент, так как для выполнения HTTP запроса не нужен веб-браузер с открытой страницей с кнопкой для выполнения соответствующего действия и вызова запроса. Для этого могут быть использованы такие средства как CURL и WGET, позволяющие сформировать и отправить любой GET или POST запрос.
Однако, существует защита от так называемых XSRF/CSRF (Cross-Site Request Forgery) атак, предотвращающая возможность выполнения HTTP запросов посредством использования сторонних страниц или средств. Суть этой защиты сводится в генерации уникального токена при открытии определенной страницы (например, страница задачи или решения) для определенного пользователя, и последующего его использования для проверки того, что запрос (запрос на архивирование задачи или решения) отправлен с данной страницы в рамках сессии данного пользователя.
Двигатель и карбюратор
В качестве двигателя или сервера приложений используется простой и надежный Apache Tomcat. Для простоты развертывания он встраивается в исполняемый JAR (Java ARchive) файл веб-приложения. Таким образом, для развертывания Клуба на сервере достаточно развернуть базу данных и запустить данный исполняемый файл.
В качестве карбюратора, обеспечивающего подачу и обработку данных или сервера баз данных, используется также всем известный PosgreSQL. Следуя нашей любви держать все яйца в одной корзине, мы постарались избежать лишних файлов. Для инициализации базы данных используется один единственный скрипт создающий пользователей и базу данных, добавляющий необходимые расширения (в том числе, для шифрования пароля и другой критичной информации) и определяющий дополнительные параметры необходимые для работы базы данных. Таблицы и связи добавляются в базу данных средствами Spring и Hibernate следуя JPA аннотации в классах сущностей.
Несмотря на это, иногда приходится забираться с гаечным ключом внутрь базы данных. Для этого используется pgAdmin, позволяющий выполнять практически необходимые действия без использования командной строки.
![Веб-интерфейс pgAdmin с общей информацией по работе сервера базы данных Веб-интерфейс pgAdmin с общей информацией по работе сервера базы данных](https://habrastorage.org/getpro/habr/upload_files/f9a/0a5/07f/f9a0a507f7256c26a5469e826e0da5e1.png)
Когда требуется получить полную картину таблиц и связей базы данных мы используем pgModeler, позволяющий как создать базу данных по существующей ERD (Entity Relationship Diagram) диаграмме - прямой инжиниринг, так и построить ERD диаграмму по существующей базе данных - обратный инжиниринг.
![Интерфейс pgModeler c ERD диаграммой базы данных Клуба Интерфейс pgModeler c ERD диаграммой базы данных Клуба](https://habrastorage.org/getpro/habr/upload_files/a81/b47/d37/a81b47d377736d8b5b34e581ec270506.png)
Иногда для работы с базами данных, а точнее для работы с SQL запросами и данными мы используем Beekeeper Studio, позволяющий быстро и удобно искать интересующие записи.
![Интерфейс Beekeeper Studio с данными по задачам и решениям от Винни Пуха и его друзей Интерфейс Beekeeper Studio с данными по задачам и решениям от Винни Пуха и его друзей](https://habrastorage.org/getpro/habr/upload_files/647/0f5/74d/6470f574da230db427618081c2c92676.png)
В гараже прототипа
Подозреваю что все уже насмотрелись на фрагменты кода в окне среды разработки, обещаю что впереди всего один такой скриншот. Как уже догадались в качестве интегрированной среды разработки мы используем Apache NetBeans. Нельзя сказать что среди бесплатных и открытых это лучшая или худшая среда. Есть много разработчиков, которые предпочтут Eclipse или IntelliJ IDEA (бесплатная версия) и есть разработчики, которые скажут что Vim или Emacs это наше все. Но, исторически сложилось что для Java проектов мы используем NetBeans (задолго до того как он встал под флаг Apache), привыкли к его особенностям, умеем лечить некоторые болячки и вполне счастливы.
Однако, для управления зависимости и сборкой Java проектов мы используем Apache Maven, использование которого практически полностью (если не считать удобства отладки) устраняет зависимость от среды разработки (большой и сложный проект можно собрать в одну команду из консоли). Подобно средам разработки, не могу сказать что Maven лучше или хуже Gradle. Возможно, Gradle лучше подходит для больших проектов, но и Maven вполне хорошо себя показывает со своими модульными проектами, возможность выполнения ANT команд и многими другими вкусными плюшками.
![POM файл Maven определяющий зависимости (требуемые программные библиотеки и компоненты) и параметры сборки программного обеспечения POM файл Maven определяющий зависимости (требуемые программные библиотеки и компоненты) и параметры сборки программного обеспечения](https://habrastorage.org/getpro/habr/upload_files/4f8/507/ed9/4f8507ed937b08f95c80e5b17aa60657.png)
Обратите внимание на использование плагина lombok-maven-plugin для указания куда именно требуется нужно сохранять сгенерированные исходные коды для последующей генерации документации Javadoc. Благодаря использованию таких доклетов как UMLDoclet документацию можно разбавить автоматически построенными UML диаграммами.
![Сгенерированная документация Javadoc, фрагмент UML классов сущностей базы данных Клуба Сгенерированная документация Javadoc, фрагмент UML классов сущностей базы данных Клуба](https://habrastorage.org/getpro/habr/upload_files/657/238/d04/657238d0464f9e57448dd9cf5721f8ce.png)
Шасси и кузов
Наконец мы добрались до того как мы упаковываем и развертываем прототип Клуба. Для этого мы используем хорошо всем известный Docker и его контейнеры. Первый вариант развертывания предназначен для разработки и отладки и включает в себя контейнер с PostgreSQL сервером и базой данных и контейнер с pgAdmin (забыл сказать что это веб-приложение). В этом случае, запуск веб-приложения выполняется средствами NetBeans, что довольно сильно облегчает отладку.
Второй вариант предназначен для развертывания на сервере и кроме вышеупомянутых контейнеров включает в себя контейнер веб-приложения Клуба (напомню что мы используем встроенный Tomcat). Кроме всего прочего, в этом случае указываются SSL ключи для работы с веб-приложением Клуба посредством протокола HTTPS.
![Файл docker-compose собирающий и связывающий контейнеры вместе Файл docker-compose собирающий и связывающий контейнеры вместе](https://habrastorage.org/getpro/habr/upload_files/fc5/47d/756/fc547d7562732ddaef8ed7b5fdffad3c.png)
Стоит отметить, что как для серверов, так и для рабочих станций мы используем операционные системы семейства Linux. В частности, для сервера Клуба мы используем операционную систему Ubuntu Server, ждем советов по импортозамещению и переходу на отечественный Linux:)
Приборная панель
Анализ данных Клуба представляет собой отдельную и большую тему для дискуссии. На этапе прототипирования мы не стали изобретать велосипед и использовали хорошо знакомый нам CytoScape для визуализации и анализа сетевых данных и Orange для того что называют дата майнингом (иногда еще говорят глубинный анализ данных). Единственное что нам пришлось сделать - это реализовать экспорт сетевых и числовых данных из Клуба в соответствующих форматах.
![Интерфейс CytoScape с графическим представлением взаимосвязей между группами, пользователями, задачами, решениями, технологиями и ресурсами (естественно, подготовленными Винни Пухом и его друзьями) Интерфейс CytoScape с графическим представлением взаимосвязей между группами, пользователями, задачами, решениями, технологиями и ресурсами (естественно, подготовленными Винни Пухом и его друзьями)](https://habrastorage.org/getpro/habr/upload_files/1f3/f06/4ae/1f3f064aed1b21e3bcf01e2ed1906665.png)
![Интерфейс Orange с алгоритмом построения дерева решений по характеристикам и показателям пользователей Клуба Интерфейс Orange с алгоритмом построения дерева решений по характеристикам и показателям пользователей Клуба](https://habrastorage.org/getpro/habr/upload_files/f6c/933/291/f6c933291a7c43f3e05a1ac2faf51b4a.png)
Кроме этого, не стоит пренебрегать средствами работы с электронными таблицами, следуя модным тенденциям мы используем LibreOffice и его Calc, со всеми его преимуществами и недостатками.
![Интерфейс LibreOffice Calc с данными по пользователям Клуба, а именно по Винни Пуху и его друзьям Интерфейс LibreOffice Calc с данными по пользователям Клуба, а именно по Винни Пуху и его друзьям](https://habrastorage.org/getpro/habr/upload_files/631/58f/99a/63158f99aad538e1b4cb3c0cd3f544f6.png)
Не стоит искать глубокого смысла в представленных здесь цифрах и диаграммах, это всего лишь иллюстрации программных средств анализа данных.
В курилке прототипа
Естественно, наша команда разработчиков Клуба не обходится без средств командной разработки. В первую очередь это корпоративный мессенджер RocketChat развернутый на нашем сервере, и позволяющий нам обсуждать новые функции и старых тараканов и общаться с нашими уважаемыми экспертами. Кроме всего прочего, RocketChat дружит с программным обеспечением для аудио и видео-конференций JitsiMeet.
![Веб-интерфейс RocketChat с обсуждением тараканов Клуба Веб-интерфейс RocketChat с обсуждением тараканов Клуба](https://habrastorage.org/getpro/habr/upload_files/061/af7/a56/061af7a56bb6ac2687b59191888c7544.png)
И конечно мы не могли обойтись без командной работы над исходными кодами. Для этого в дополнение к RocketChat и JitsiMeet развернуто программное обеспечение для управления версиями исходных кодов Gitea.
![Веб-интерфейс Gitea с исходными кодами Клуба Веб-интерфейс Gitea с исходными кодами Клуба](https://habrastorage.org/getpro/habr/upload_files/692/ce9/24c/692ce924ca27c7dd81cece1e167648b7.png)
Вместо заключения
В этой статье мы рассказали что из себя представляет и на чем работает функциональный прототип Клуба инновационных решений. Безусловно, некоторые аспекты его программной реализации (или реализации подобных решений) заслуживают отдельного детального обсуждения.
Если есть вопросы по реализации прототипа Клуба, будем рады на них ответить в комментариях или в отдельной статье.
В следующей статьей мы предложим самостоятельно попробовать наш Клуб, сформулируем задачи (надеемся что вместе с вами), расскажем как публиковать решения для задач, как оценивать и обсуждать решения и что делать с вознаграждением.
Если у вас есть веселые задачи, которые вы хотели бы попробовать решить с помощью нашего Клуба, ждем их в комментариях. Желательно для каждой задачи выделить: название, краткое описание и критерии для оценки предлагаемых решений. Иначе, будем решать задачи по пчеловодству от Винни Пуха и его друзей.
Надеемся что обратная связь и обсуждение помогут нам быстрее перейти от прототипа к продукту, понять кому он может быть полезен, как он должен выглядеть, какие функции в нём лишние, и каких функций в нём не хватает.