<properties>
<zk.version>8.0.3.1</zk.version> </properties>
<repositories> <repository> <id>zk repository</id>
<url>#"896985.files/image006.jpg">
Рисунок 3.3 - Пример макета пользовательского интерфейса
4. РЕАЛИЗАЦИЯ
4.1 Особенности реализации
Этот этап также известен как фаза программирования. Реализация дизайна
программного обеспечения начинается с точки зрения написания программного кода
на подходящем языке программирования и эффективного развертывания исполняемых
программ без ошибок. Цель этапа реализации состоит в том, чтобы перевести
дизайн системы в код на заданном языке программирования. Для данного проекта
целью этого этапа является наилучшая реализация конструкции. Фаза кодирования
влияет как на тестирование, так и на поддержание. Хорошо написанный код снижает
затраты на тестирование и техническое обслуживание. Поскольку стоимость
тестирования и обслуживания программного обеспечения намного выше, чем
стоимость кодирования, целью кодирования должно быть сокращение усилий по
тестированию и обслуживанию. Следовательно, во время кодирования основное
внимание следует уделять разработке программ, которые легко писать. На этапе
кодирования следует стремиться к простоте и ясности. Так как данный проект
имеет слоистую архитектуру то, ниже подробнее рассказано о разработке каждого
слоя программного продукта.
4.1.1 Разработка структуры базы данных
Как было сказано ранее, в качестве СУБД было принято решение использовать
MYSQL. В базе данных мы будем хранить всю информацию необходимую для
обеспечения работы сервисного центра.
Таблица USERS хранит информацию о пользователях системы, содержит
следующие поля:
- ID INT(11) - идентификационный номер;
- NAME VARCHAR(45) - имя пользователя;
- SECOND_NAME VARCHAR(45) - отчество;
- FAMILY_NAME VARCHAR(45) - фамилия;
- EMAIL VARCHAR(45) - электронная почта;
- PASSWORD - пароль для доступа к системе хранится в зашифрованном виде;
Каждый пользователь имеет определенный набор прав в системе, полный
список прав храниться в таблице RIGHTS:
- ID INT(11) - идентификационный номер;
- TYPE VARCHAR(45) - тип ресурса в системе;
- таблицы USERS и RIGHTS имеют связь многие ко многим.
Каждое отделение имеет определенный адрес, который потом учитывается при
найме работников, местонахождении заказов, а также для других бизнес процессов.
Таблица PLACE имеет четыре поля:
- ID INT(11) - идентификационный номер;
- ADDRESS VARCHAR(255) - полный адрес отделения сервисного центра.
Следующие два поля используются для визуального отображения отделения на
карте:
- LAT DOUBLE - координата широты (latitude);
- LNG DOUBLE - координата долготы (longitude).
Таблица REQUEST используется для хранения информации о заказах, имеет
четыре поля:
- ID INT(11) - идентификационный номер;
- DATE DATE - дата создания заказа;
- DESCRIPTION VARCHAR(45) - описание заказа;
- CLIENT_ID INT(11) - ссылка на клиента сделавшего заказ.
Каждый заказ меняет статусы в зависимости от того на каком этапе
продвижения он находится. Все статусы хранятся в специальной таблице
- STATUS:
- ID INT(11) - идентификационный номер;
- STATUS VARCHAR(255) - название статуса;
Таблицы REQUEST и STATUS имеют связь многие ко многим. Связующей таблицей
является таблица STATUS_HISTORY. В данной таблице хранится:
- DATE DATE - дата добавления статуса к заказу;
- STATUS_ID INT(11) - ссылка на статус;
- REQUEST _ID INT(11) - ссылка на заказ.
В таблице DEFECT хранятся неисправности техники, имеет лишь два поля:
- ID INT(11) - идентификационный номер;
- NAME VARCHAR(45) - название неисправности.
Так как каждый заказ может иметь несколько неисправностей, причем одна и
та же неисправность может быть у разных заказов, то таблица DEFECT связана
отношением многие ко многим с таблицей REQUEST.
Сведения о клиенте находятся в таблице CLIENT:
- ID INT(11) - идентификационный номер;
- NAME VARCHAR(45) - имя пользователя;
- SECOND_NAME VARCHAR(45) - отчество;
- FAMILY_NAME VARCHAR(45) - фамилия;
- ADDRESS VARCHAR(45) - адрес проживания ( используется при доставке
заказа на дом);
- PHONE VARCHAR(45) - номер телефона для связи.
В процессе ремонта заказ передвигается от сотрудника к сотруднику и
возникает потребность хранить информацию о том, у какого сотрудника в данный
момент находится заказ. Для этого таблица REQUEST и USERS связаны отношением
многие ко многим с помощью таблицы REQUEST_USERS:
- ID INT(11) - идентификационный номер;
- DATE DATE - дата;
- REQUEST _ID INT(11) - ссылка на заказ;
- USER_ID INT(11) - ссылка на пользователя системы.
Описанная выше база данных может быть легко расширена (Приложение 1).
Листинг создания базы данных (Приложение 2).
.1.2 Разработка слоя взаимодействия с базой данных
Так как все данные приложения хранятся в базе данных, то необходимо
настроить взаимодействие СУБД и разрабатываемой системой. Язык Java является
объектно-ориентированным языком программирования, поэтому все данные в нем
должны представляться в виде объектов. Фреймворк Hibernate предоставляет
возможность объектно реляционного отображения данных. В базе данных на данный
момент находится двенадцать сущностей. Все эти сущности необходимы для работы с
пользователем, поэтому необходимо создать для каждой сущности объект который
отображал бы структуру сущности в базе данных. В структуре объекта необходимо
указать только те атрибуты из базы данных которые необходимы для работы
приложения, таким образом, сокращается требуемый приложению объем оперативной
памяти.
Для того чтобы использовать выбранную реализацию JPA фреймворк Hibernate
необходимо прописать зависимость в файле pom.xml и заново импортировать все
библиотеки. Maven автоматически подтянет все указанные библиотеки.
Для работы с данным фреймворком необходимо указать адрес, по которому
расположена база данных, название схемы, имя пользователя и пароль в базе
данных.
Над созданным классом сущности необходимо указать две аннотации @Entity и
@Table в атрибутах последней необходимо указать название сущности в базе
данных. Вместо аннотаций также допустимо использовать XML конфигурацию. Над
каждым полем класса указывается аннотация @Column, в атрибутах которой
указывается название атрибута сущности в базе данных, а также дополнительные
параметры. В качестве атрибута Java класса также может быть подмножество других
сущностей. Подмножества сущностей в Java классе представляют собой коллекцию
данных Set. Использование данного способа хранения обусловлено тем, что при
таком хранении данных отсутствует дублирование объектов. В Java классе над
полем такого подмножества прописывается аннотация @OneToMany, в атрибутах
данной аннотации указывается способ извлечения данных. Существует два способа
EAGER и LAZY. Использование второго способа более предпочтительно, так как по сравнению
с EAGER данные извлекаются из базы данных только во время вызова get метода
данного атрибута, при использовании EAGER извлекаются сразу все данные из
сущности соответствующей данному Java объекту. Согласно спецификации в Java
классе отражающем сущность в базе данных, необходимо создать не приватный
конструктор без аргументов.
Для операций над сущностями используется специальный интерфейс JPA
EntityManager. Данный интерфейс позволяет производить основные операции над
сущностями такие как, добавление, изменение, поиск, удаление и блокировка для
изменения от других потоков. EntityManager определяет только один сеанс
взаимодействия с базой данных. Внутри себя EntityManager содержит интерфейс
EntityTransaction который позволяет создавать транзакции, применять изменения в
базе данных и откатывать эти изменения обратно. Использование транзакций
позволяет проводить безопасные изменения в базе данны. Конкретная реализация
EntityManager определяется классом EntityManagerFactory - это фабрика
соединений, поддерживает соединение с базой данных, всю конфигурацию и кэш для
работы с базой данных основная задача EntityManagerFactory создавать объекты
интерфейса EntityManager.
Процесс добавления объекта в базу данных заключается в создании
конкретного экземпляра класса, заполнения его атрибутов данными, валидации
данных на правильность заполнения. После этого с помощью интерфейса
EntityManager и его методов persist и merge.
На рисунке 4.1 представлена общая схема взаимодействия DataAccess слоя с
базой данных с использованием связки JPA и Hibernate.
Рисунок 4.1 - Общая схема взаимодействия DataAccess слоя с базой данных
В данном проекте на данный момент создано 12 классов отражающих сущности
в базе данных. Для каждой сущности в слое работы с базой данных создан
специальный класс, отвечающий за операции вставки, удаления, обновления и
поиска данных.
В качестве паттерна использования конкретного DataAccess сервиса
применятся Singleton. Это позволяет использовать один экземпляр класса в работе
всего приложения. Достигается этот использованием Фреймворка Spring и его
возможности управления внедрения зависимостей Dependency Injection (DI). В
фреймворке Spring существует несколько способов управления внедрением
зависимостей: XML конфигурация, аннотации, использование специальных
интерфейсов фреймворка Spring для конфигурирования зависимостей с помощью Java
кода. В данном проекте используются первые два способа. В XML конфигурации
указывается конкретная реализация интерфейса EntityManagerFactory и
JpaTransactionManager. Разработанные нами сервисы DataAccess слоя
конфигурируются только при помощи аннотаций. Аннотация @Repository показывает,
что данный класс функционирует как репозиторий, что требует наличия прозрачной
трансляции исключений. В независимости от используемой технологии в слое
доступа данных слой сервиса будет иметь дело с общей иерархией исключений
Spring (DataAccessException). Над методами классов непосредственно
осуществляющих работу с базой данных стоит аннотация @Transactional перед
выполнением данного метода Spring открывает транзакцию, а после выполнения
метода транзакция коммитится, а при выбрасывании RuntimeException происходит
откат транзакции.
.1.3 Разработка слоя бизнес сервисов
В данном проекте имеется большая бизнес логика, для того что бы как то
отделить бизнес процессы от технических сервисов системы, вся логика связанная
с бизнес процессами вынесена в отдельный слой называемый Business Service(BS).
При разработке данного слоя активно используется фреймворк Spring и его возможность управления
внедрением зависимостей.
В данном проекте, как уже было описано выше, для каждой сущности
имеющейся в базе данных имеется отображающий ее объект в Java коде. По аналогии с объектами
называемыми моделями, были созданы сервисы, позволяющие осуществлять работу с
базой данных.
В проекте на данный момент создано 6 сервисов.ClientService отвечает за все операции, проводимые
с клиентами: добавить нового клиента, найти клиента по фамилии, изменить данные
клиента. Каждый сервис содержит в себе операции, проводимые с моделями. Такими
операциями как создание заказа, изменение заказа, удаление.
Например, при создании нового заказа часть полей для вставки в базу
данных заполняется автоматически именно в слое бизнес сервиса. Статус заказа,
место его регистрации и фактического нахождения, а так же ответственный
работник устанавливаются автоматически за счет повторного использования
сервисов. Такой подход позволяет использовать отдельные бизнес процессы
повторно.
Объекты в приложении имеют зависимости друг от друга. Хотя платформа Java
обеспечивает множество функциональных возможностей разработки приложений, ей не
хватает средств для организации базовых строительных блоков в единое целое,
оставляя эту задачу архитекторам и разработчикам. Для решения данной проблемы
можно использовать шаблоны проектирования, такие как Factory, Abstract Factory,
Builder, Decorator и Service Locator для составления различных классов и
экземпляров объектов, составляющих приложение, эти шаблоны содержат: лучшие
практики с указанием имени, с описанием что делает шаблон, где его применять,
проблемы, с которыми он обращается, и так далее. Шаблоны - это формализованные
лучшие практики, которые можно реализовать в своем приложении. Компонент Spring
Framework Inversion of Control (IoC) решает эту проблему, предоставляя
формализованные средства компоновки разрозненных компонентов в полностью
работающее приложение, готовое к использованию. Spring Framework кодирует
формализованные шаблоны проектирования как объекты первого класса, которые
можно интегрировать в свои собственные приложения.
Управление зависимостями и внедрение зависимостей - это разные вещи.
Чтобы получить эти приятные функции Spring в нашем приложении необходимо
собрать все необходимые библиотеки (файлы jar) и получить их на пути к классам
во время выполнения и, возможно, во время компиляции. Эти зависимости не
являются импортированными виртуальными компонентами, а физическими ресурсами в
файловой системе. Процесс управления зависимостями включает в себя размещение
этих ресурсов, их хранение и добавление их в пути к классам. Зависимости могут
быть прямыми (например, мое приложение зависит от Spring во время выполнения)
или косвенным (например, мое приложение зависит от commons-dbcp, который
зависит от общего пула). Косвенные зависимости также известны как
«транзитивные», и именно эти зависимости сложнее идентифицировать и управлять.
В каждый бизнес сервис с помощью Фреймворка Spring внедряется зависимость от сервиса, отвечающего за
взаимодействие с базой данных. С помощью данной зависимости бизнес сервисы
работают с данными находящимися в базе данных.
.1.4 Разработка слоя пользовательского интерфейса
По требованию заказчика сайт должен иметь две страницы: страница
авторизации, и главная страница на которой будет отображаться панель навигации
и все необходимые элементы для работы с сайтом. Такая структура сайта
обеспечивает наиболее удобное использование сервиса пользователем.
Благодаря Фреймворку ZK пользовательский интерфейс разрабатывается
достаточно быстро.
Так как к приложению имеется доступ из сети интернет, то необходимо
продумать безопасное использование приложения пользователями. Доступ
пользователей к системе осуществляется с помощью авторизации и аутентификации.
«Аутентификация» - это процесс установления принципала, это означает, что
пользователь, устройство или какая-либо другая система может выполнять действие
в приложении. «Авторизация» относится к процессу принятия решения о том,
разрешено ли участнику совершать действия в вашем приложении. В разделе проектирование
для этих целей было принято решение использовать Spring Security.Security
обеспечивает комплексное решение для обеспечения безопасности для
корпоративного программного обеспечения на базе Java EE приложения.Особое
внимание уделяется поддержке проектов, созданных с использованием Spring
Framework, который является ведущим решением Java EE для разработки
корпоративного программного обеспечения.
Большинство причин для привлечения Spring Security к проекту является
обнаружение функций безопасности спецификации сервлетов Java EE или
спецификации EJB так как не хватает глубины, необходимой для типичных сценариев
корпоративных приложений. Несмотря на упоминание этих стандартов, важно
признать, что они не переносимы на уровне WAR или EAR. Поэтому, если работа приложения
переключается на разные серверные среды, обычно требуется большая работа по
перенастройке безопасности вашего приложения в новую целевую среду.
Использование Spring Security позволяет преодолеть эти проблемы, а также
приносит вам десятки других полезных настраиваемых функций
безопасности.Security имеет архитектуру, которая предназначена для разделения
аутентификации от авторизации и имеет стратегии и точки расширения для обоих.
По левому краю страницы располагается навигационная панель содержащая
главный пункт меню «Заказы» когда пользователь заходит на сайт фокус на данной
странице установлен по умолчанию. Далее следует пункт меню «Справочники» с
подпунктами «места», «Статусы», «Клиенты», «Неисправности». На рисунке 4.2
изображено меню сайта.
Рисунок 4.2- Меню сайта
Во вкладке заказы расположен список с новыми заказами в системе.
При нажатии на вкладку «Справочники» разворачивается список с категориями
справочников.
Вкладка «Места» содержит списочное представление существующих мастерских
и приемных пунктов у данного сервисного центра.
В пункте меню «Статусы» списком представлены статусы присваиваемые
заказам во время выполнения бизнес процессов.
Справочник популярных неисправностей техники находится в пункте меню
«Неисправности».
Для удобства разработки меню сайта было принято решение использовать
сразу два шаблона взаимодействия клиента и сервера MVVM и MVC. Шаблон MVVM
используется для заполнения компонента данными, а шаблон MVC для управления
поведением компонентов меню.
При нажатии на нижнюю кнопку меню сайта сворачивается в левую сторону.
Механизм сворачивания осуществляется путем смены CSS стиля в Java коде.
Для создания данного компонента сайта необходимо создать файл с
расширением.zul, в нем при помощи специального языка описать, как должен
выглядеть компонент. Также для форматирования отображения компонента на
странице необходимо прописать CSS стили компонента.
В листинге 4.1 представлен исходный код файла sidebar.zul.
<div
id="sidebar" sclass="sidebar" apply="uiController.SidebarComposer">
//Устанавливаем контроллер для всех элементов находящихся внутри тега div <navbar id="navbar"
sclass="nav-list" orient="vertical"> // Объявляем компонент navbar <navitem
label="Заказы"
iconSclass="z-icon-home" selected="true" //Пункт меню onClick="@command('showRequests')"// Команда которую
выполнит ZK на событие клик мышью <nav label="Справочники"
iconSclass="z-icon-list"> // Раздел <navitem label="Места"
iconSclass="z-icon-angle-double-right" //Подпункты
onClick="@command('showPlaces')"/> <navitem label="Статусы"
iconSclass="z-icon-angle-double-right"
onClick="@command('showStatus')" /> <navitem label="Клиенты"
iconSclass="z-icon-angle-double-right"
onClick="@command('showClients')" /> <navitem label="Неисправности"
iconSclass="z-icon-angle-double-right"
onClick="@command('showDefects')" /> </nav>
</navbar> <div sclass="sidebar-collapse"> // <a
id="toggler" iconSclass="z-icon-angle-double-left"/> </div> </div>
|
Листинг 4.1 - Исходный код файла sidebar.zul
Для создания меню у фреймворка ZK имеется специальный тег «navbar», при
помощи данного тега можно легко и быстро создать меню для сайта. У данного
компонента можно настроить способ отображения указав в атрибуте «orien»
значение «vertical» или «horizontal». У каждого компонента предоставляемого
фреймворком ZK можно указать CSS стиль отображения. Тег «navitem» объявляет
пункт меню, внутри него необходимо указать название пункта которое будет
отображаться пользователю в атрибуте «label». Есть два основных способа задания
значения для строковых констант на сайте. Первый способ заключаются в вынесении
всех значенией в специальный файл с расширением.properties, в данном файле
объявляются константы и их значение. Значение атрибута «label» устанавливают
следующим образом: «${labels.*}», где вместо звездочки указывается константа,
значение которой необходимо для отображения пользователь. Данный подход
используется для создания сайтов с возможностью смен языка интерфейса, также
данный подход позволяет использовать одну константу в разных частях интерфейса.
Второй способ заключается в указании значения атрибута «label» напрямую,
прописывая в кавычках, что вывести пользователю. Так как сайт не
предусматривает смену языка интерфейса пользователя, то при разработке
используется второй способ. Для пункта меню заказы указано значение атрибута
selected="true", так как это главная страница сайта, и при открытии
страницы сайта пользователю должна отображаться именно эта страница. Для
обработки событий на форме необходим механизм, связывающий команды
пользователей и обработки этих событий на сервере.
Команда - это действие для манипулирования свойством ViewModel. Каждая
команда обозначает метод, который View может выполнять в ViewModel. Эти
действия также позволяют пользователям взаимодействовать с View. Например,
ViewModel предоставляет 2 команды: «сохранить» и «удалить». Это означает, что
пользователи могут выполнять только эти 2 действия в представлении с помощью
ViewModel.
Поскольку ViewModel действует как контроллер, существует возможность
связать событие компонента пользовательского интерфейса с командой, указав имя
команды, которое аналогично зарегистрировать в слушателе событий. Несколько
событий могут связываться с одной и той же командой. Когда пользователь
взаимодействует с компонентом (например, нажатием кнопки), компонент запускает
событие, механизм привязки данных запускает выполнение команды. Команда реализовывается
как метод ViewModel. Поскольку ViewModel является обычным Java объектом, чтобы
механизм привязки данных идентифицировал, какой метод представляет собой
команду, необходимо аннотировать метод с помощью ZK при помощи аннотации
@Command. Данные методы управляют свойством ViewModel, например удалением
элемента.
Команда - это действие для манипулирования свойством ViewModel. Каждая
команда обеспечивает действие, которое вид может выполнять в ViewModel.
Необязательный элемент аннотации - это имя строки для имени команды, и это имя
ссылается на ZUL с привязкой к событиям. Если он не указан, имя метода
устанавливается как имя команды по умолчанию.
Команда ViewModel - это как обработчик событий, к каждому событию
привязана команда на сервере. Связывание между событиями и командой -
называется «привязкой Event-Command». Прежде чем установить это обязательство,
мы должны объявить команду с ее именем в ViewModel. Имена команд в ViewModel не
должны дублироваться или это приведет к исключению во время выполнения.
Пункт меню заказы содержит информацию обо всех заказах на ремонт в
системе. Пользователь на данной странице может просматривать заказы, добавлять
и изменять их. Для отображения данных списочным способом фреймворк ZK
предоставляет готовый компонент «listbox», поддерживающий постраничное
представление данных пользователю, разделение данных на столбцы и строки.
Перемещение по списку можно осуществлять при помощи управляющих клавиш.
Рисунок 4.3 - Интерфейс пункта меню заказы
Для создания данного компонента нужно по аналогии с компонентом меню
требуется создать файл с расширением.zul и прописать необходимые теги и их
атрибуты.
Связывание данных на сервере и браузере клиента подобно буферу. Он
автоматически создает объект посредник. Перед сохранением в ViewModel все
входные данные сохраняются на объект посредник. Таким образом, мы можем хранить
данные от сохранения в ViewModel до подтверждения пользователем. Предполагая,
что пользователь заполняет форму в веб-приложении, пользовательские данные
ввода непосредственно сохраняются в свойствах ViewModel, целевого объекта.
Затем пользователь может отменить действие заполнения перед отправкой формы,
поэтому данные, хранящиеся в ViewModel, устарели. Это может вызвать проблемы, если
мы обработаем устаревшие данные дальше, поэтому входные данные сначала хранятся
в объекте посреднике, прежде чем перейти к реальному целевому объекту после
подтверждения пользователя. Связывание форм обеспечивает хранение в объекте
посреднике информации, не подтвержденной пользователем. Связывание формы
позволяет сохранить целевой объект в ViewModel без изменений до выполнения
команды для подтверждения. Перед сохранением свойств ViewModel (целевого
объекта) с помощью команды мы можем сохранить ввод в объекте посреднике. Когда
команда выполняется (например, кнопка нажата), входные данные действительно
сохраняются в свойствах ViewModel. Фреймворк позволяет легко достичь данного
эффекта, просто написав выражение ZK bind, поскольку оно снижает нагрузку разработчика
на очистку неправильных данных вручную или реализацию самого буфера.
Ниже представлен рисунок, на котором изображен поток данных между ZUL,
объектом посредником и целевым объектом:
Рисунок 4.4 - Поток данных между ZUL, объектом посредником и целевым
объектом
В листинге 4.2 представлен пример связывания данных в компоненте
«listbox» для отображения списка заказов пользователю.
<listbox
model="@bind(vm.placeListModel)"
selectedItem="@bind(vm.selectedPlace)" style="margin-top:10px"
mold="paging" pageSize="10"
onDoubleClick="@command('viewPlace')"> <listhead>
<listheader width="10%" label="№"/> <listheader
width="80%" label="Адрес"/>
</listhead> <template name="model"> <listitem>
<listcell label="@bind(each.id)"></listcell>
<listcell label="@bind(each.address)"></listcell> </listitem> </template>
</listbox>
|
Листинг 4.2 - Листинг файла place-list.zul
В первой строке листинга 4.2 объявляется компонент listbox, в атрибутах
указывается из какого объекта в ViewModel необходимо брать данные для
заполнения списка и в какой объект, находящийся во ViewModel необходимо
устанавливать выбранный пользователем объект из списка. Далее тегами listhead и
listheader устанавливается заголовки столбцов списка. В теге listcell устанавливаются,
какие конкретные поля объекта должны отображаться пользователю.
Вверху каждой страницы расположен компонент позволяющий производить
операции создания, удаления, поиска данных, а также кнопка позволяющая
производить обновление данных на странице.
При нажатии на кнопку добавления данных на странице заказы всплывает
форма создания заказа, изображенная на рисунке 4.3.
Рисунок 4.3 - Форма создания нового заказа
Для создания заказа необходимо выбрать клиента или создать нового,
добавить описание заказа, добавить неисправности. Только после этого можно
создать новый заказ. При нажатии на кнопку выбрать клиента всплывает новое окно
выбора клиента, на котором можно создать нового клиента. После того как нажата
кнопка создать все данные заносятся в базу данных.
Подтверждение ввода пользователем является незаменимой функцией
веб-приложения. Валидатор ZK помогает выполнить эту задачу. Валидатор является
элементом многократного использования, который выполняет проверку и сохраняет
сообщения проверки в списке сообщений проверки. Когда он применяется, он
вызывается перед сохранением данных в целевой привязке (ViewModel или
промежуточный объект). Если проверка не выполнена, свойства ViewModel (или
промежуточного объекта) не будут изменены.обеспечивает стандартный механизм
хранения и отображения сообщений проверки. После выполнения проверки валидатор
может сохранить сообщение проверки в списке сообщений подтверждения.
5. ТЕСТИРОВАНИЕ
.1 Обоснование методики тестирования
Тестирование программного обеспечения - это расследование, проводимое с
целью предоставления заинтересованным сторонам информации о качестве
тестируемого продукта или услуги. Тестирование программного обеспечения также
может обеспечить объективное независимое представление программного
обеспечения, позволяющее бизнесу оценить и понять риски реализации программного
обеспечения. Методы тестирования включают в себя процесс выполнения программы
или приложения с целью поиска ошибок программного обеспечения (ошибок или
других дефектов) и проверки того, что программный продукт подходит для
использования.
Поскольку количество возможных тестов для даже простых программных
компонентов практически бесконечно, все тестирование программного обеспечения
использует некоторую стратегию для выбора тестов, которые возможны для
доступного времени и ресурсов. В результате тестирование программного обеспечения
обычно (но не исключительно) пытается выполнить программу или приложение с
целью поиска ошибок программного обеспечения (ошибок или других дефектов).
Работа по тестированию - это итеративный процесс, когда фиксируется одна
ошибка, она может освещать другие, более глубокие ошибки или даже создавать
новые. Тестирование программного обеспечения может обеспечить объективную,
независимую информацию о качестве программного обеспечения и риск его отказа
пользователям или спонсорам.
Тестирование программного обеспечения может проводиться, как только
исполняемое программное обеспечение (даже если оно частично завершено)
существует. Общий подход к разработке программного обеспечения часто
определяет, когда и как проводится тестирование. Например, в поэтапном процессе
большинство тестов происходит после того, как требования к системе были
определены, а затем реализованы в тестируемых программах. Напротив, под Agile подход, требования, программирование
и тестирование часто выполняются одновременно.
Под методиками подразумевается создание плана, как реализовать идею, а
техника - метод или способ выполнения задачи. Таким образом, методики
тестирования создают набор входов для данного программного обеспечения, которое
обеспечит набор ожидаемых результатов. Идея состоит в том, чтобы система
работала достаточно хорошо, и она может быть выпущена с минимальными проблемами
для конечного пользователя.
Статические методы испытаний обеспечивают отличный способ улучшить
качество и производительность разработки программного обеспечения. Он включает
обзоры и дает обзор того, как они проводятся. Основная задача статического
тестирования - улучшить качество программных продуктов, помогая инженерам
распознавать и исправлять собственные дефекты на ранней стадии процесса
разработки программного обеспечения.
При тестировании данного программного продукта применяются методики
системного тестирования. Тестирование системы - это метод тестирования черного
ящика, выполненный для оценки всей системы соответствия системы заданным
требованиям. При тестировании системы функциональность системы тестируется с
точки зрения сквозной перспективы. Системное тестирование обычно выполняется
командой, которая не зависит от команды разработчиков, чтобы измерить качество
системы непредвзято. Он включает как функциональное, так и не функциональное
тестирование.
5.2 Результаты тестирования
Тестирование разрабатываемого приложения проводится путем тестирования
функций сайта, таких как добавление клиента, добавление заказа, просмотр
заказа, изменение заказа.
При тестировании были проверены все функциональные элементы сайта. В
результате тестирования все функции сайта выполняются согласно предъявленным
требованиям.
В качестве требований к функциональному тестированию взяты данные
диаграммы вариантов использования (см. приложение 4). Оценка соответствия
функциональности программы к заявленным требованиям представлена в таблице 5.1.
Таблица 5.1 - Параметры оценки соответствия функциональности программы
Функция программы
|
Реализация
|
Вывод сообщения при ошибке
|
Регистрация/ авторизация
|
Реализовано при входе
пользователя на сайт.
|
В случае ввода ошибочных
данных выводится сообщение «Неверный ввод логина и/или пароля»
|
Просмотр списков данных
|
Выбор в пункте меню
соответствующего списка данных
|
В случае отсутствия записей
в списке выводится сообщение «Список пуст»
|
Не все поля заполнены в
формах создания
|
Создание нового
пользователя, заказа, клиента или любой другой записи
|
В случае заполнения не всех
обязательных полей выводится ошибка над каждым полем.
|
При не возможности
подключения к БД
|
Отправкой запроса к базе
данных
|
В случае невозможности
подключения к БД ошибка «Невозможно подключиться к БД»
|
ЗАКЛЮЧЕНИЕ
На данный момент в системе разработана база данных отражающая основную
логику хранения данных. Организована связь между приложением и БД. Разработаны
и протестированы основные запросы на получение данных. Также осуществляется
взаимодействие по протоколу HTTP между клиентом сервером. Ведется разработка
бизнес логики и клиентской части приложения.
Разработана функциональность, которая позволяет использовать данную
информационную систему реальным пользователям.
В дальнейшем функциональность данной системы будет увеличена, за счет
появления новых требований заказчика. К данным требованиям относятся:
Автоматический расчет стоимости заказа.
Склад запасных частей.
Интеграция разработанной системы с основным сайтом сервисного центра.
Увеличение ролевой модели взаимодействия с сайтом.
Возможность печатать штрих коды для заказов.
Возможность подключения сканера штрих кодов.
Прикрепление фотографий, сделанных с помощью веб камеры, к заказу.
Панель администрирования сайта.
Все вышеперечисленные требования будут реализованы в последующих версиях
программы.
На данный момент разработка первой версии программы закончена.
СПИСОК ИСПОЛЬЗУЕМОЙ ЛИТЕРАТУРЫ
1. Ремонт
онлайн [Электронный
ресурс]: офиц. сайт. - Режим доступа: <https://remonline.ru/>
Приложение 2
Листинг Класса Status
Entity
@Table(name = "CLIENT")class Client implements
Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)Integer
id;
@Column(name = "NAME", nullable = false)String
name;
//TODO: Опечатка
@Column(name = "MIDLE_NAME", nullable = false)String
midleName;
@Column(name = "SURNAME", nullable = false)String
surname;
@Column(name = "ADDRESS", nullable = false)String
address;
@Column(name = "PHONE", unique = true, nullable =
false)String phone;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "client")Set<Request>
requests = new HashSet<Request>();Integer getId() {id;
}void setId(Integer id) {.id = id;
}String getName() {name;
}void setName(String name) {.name = name;
}String getMidleName() {midleName;
}void setMidleName(String midleName) {.midleName = midleName;
}String getSurname() {surname;
}void setSurname(String surname) {.surname = surname;
}String getAddress() {address;
}void setAddress(String address) {.address = address;
}String getPhone() {phone;
}void setPhone(String phone) {.phone = phone;
}Set<Request> getRequests() {requests;
}void setRequests(Set<Request> requests) {.requests =
requests;
}
}
Листинг класса StatusDao
@Repositoryclass ClientDao {
@PersistenceContextEntityManager entityManager;
@TransactionalList<Client> getAll() {query = entityManager.createQuery("select
c from Client as c");<Client> result = query.getResultList();result;
}
@Transactional( propagation = Propagation.REQUIRES_NEW)Client
insertClient(Client client) {.persist(client);.merge(client);client;
}
@Transactional(readOnly = true)Client findClientByName(String
clientName) throws UsernameNotFoundException {client;{query =
entityManager.createQuery("select c from Client as c where c.name
=:clientName")
.setParameter("clientName", clientName);= (Client)
query.getSingleResult();(client != null) {.initialize(client);
}
} catch (Exception e) {null;
}client;
}
}
Листинг интерфейса ClientServiceinterface ClientService
{<Client> getAllClient();saveClient(Client
client);findByClientName(String name);
}
Листинг класса ClientServiceImpl
@Service("clientService")
public class ClientServiceImpl implements ClientService {
@AutowiredclientDao;
@OverrideList<Client> getAllClient()
{clientDao.getAll();
}
@OverrideClient saveClient(Client client)
{findByClientName(client.getName()) == null ? clientDao.insertClient(client):
null;
}
@OverrideClient findByClientName(String name)
{clientDao.findClientByName(name);
}
}
Листинг класса ClientListVM
@VariableResolver(DelegatingVariableResolver.class)class
ClientListVM {Window window;
@WireVariableclientService;ListModel<Client>
clientListModel;Client selectedClient;String keyWord;static final String
CREATE_CLIENT = "sc/create-client.zul";static final String CLIENT =
"CLIENT";
@Init(superclass = true)void
init(@ContextParam(ContextType.COMPONENT) Window window) {.window = window;();
}
@Commandvoid addClient() {wind = (Window)
Executions.createComponents(CREATE_CLIENT, window, null);.doModal();
}
@GlobalCommand
@NotifyChange("clientListModel")void refresh() {=
new ListModelList<Client>(clientService.getAllClient());
((ListModelList<Client>)
clientListModel).setMultiple(true);
}
@Commandvoid close() {.postGlobalCommand(null, null,
SELECTED_CLIENT, .<String, Object>singletonMap("value",
selectedClient));.onClose();
}ListModel<Client> getClientListModel()
{clientListModel;
}void setClientListModel(ListModel<Client>
clientListModel) {.clientListModel = clientListModel;
}String getKeyWord() {keyWord;
}void setKeyWord(String keyWord) {.keyWord = keyWord;
}void setSelectedClient(Client selectedClient)
{.selectedClient = selectedClient;
}
}
Листинг файла client-list.zul
<window="@command('close')"="org.zkoss.bind.BindComposer"="@id('vm')
@init('ServiceCentre.ui.ClientListVM')">
<hbox width="100%" align="center">
Адрес:
<textbox value="@bind(vm.keyWord)"/>
<button iconSclass="z-icon-search"
onClick="@command('search')"/>
<button iconSclass="z-icon-plus"
onClick="@command('addClient') @global-command('refresh')"/>
<button iconSclass="z-icon-refresh"
onClick="@global-command('refresh')"/>
</hbox>
<listbox height="100%" width="100%"
model="@bind(vm.clientListModel)" emptyMessage="Клиентов не
найдено"="@bind(vm.selectedClient)"="paging"
pageSize="10">
<listhead>
<listheader width="15%" label="№"/>
<listheader width="15%"
label="Имя"/>
<listheader width="15%"
label="Фамилия"/>
<listheader width="15%"
label="Отчество"/>
<listheader width="15%"
label="Адрес"/>
<listheader width="15%"
label="Телефон"/>
</listhead>
<template name="model">
<listitem>
<listcell
label="@bind(each.id)"></listcell>
<listcell
label="@bind(each.name)"></listcell>
<listcell
label="@bind(each.midleName)"></listcell>
<listcell
label="@bind(each.surname)"></listcell>
<listcell label="@bind(each.address)"></listcell>
<listcell
label="@bind(each.phone)"></listcell>
</listitem>
</template>
</listbox>
<button label="Сохранить"
iconSclass="z-icon-save" onClick="@command('close')"
visible=" not @load('isMenuMod')"/>
</window>
Приложение 3
Диаграмма классов для функции сайта просмотр списка клиентов
Приложение 4
Диаграмма вариантов использования
Похожие работы на - Разработка информационной системы для автоматизации деятельности сервисного центра
|