В соответствии с описанием структура системы может быть представлена следующим образом (Рис. 26).
Рис. 26. Структурная схема
Приложение через интерфейс обращается к функциям модуля. В зависимости от вызываемой функции интерфейс обращается к соответствующим компонентам и возвращает результат.
Компонент «Асинхронный вызов» предназначен для выполнения асинхронных вызовов. «Наблюдатель» предназначен для отслеживания пороговых значений. «Контейнер» хранит список датчиков. Компонент «Датчик» через компонент «драйвер» обращается к аппаратному обеспечению.
6.1.3. Декомпозиция системы
Итак, в соответствии методологией объектно-ориентированного анализа необходимо определить состав классов и связи между ними, отражающие предметную область. Нам будут необходимы следующие классы:
• класс для работы с датчиком;
• контейнер для хранения указанных классов;
• драйвер, обеспечивающий низкоуровневое взаимодействие с аппаратурой;
• очередь для выполнения асинхронных запросов;
• класс для отслеживания пороговых значений;
• интерфейсный класс, который будет взаимодействовать с приложением для вызовов соответствующих функций модуля.
Обобщенная диаграмма классов модуля представлена на Рис. 27 35 35 Диаграмма классов изображена в формате UML. Читателям, которые не знакомы с указанным графическим языком моделирования, можно порекомендовать книгу «Леоненков А. В. Самоучитель UML 2».
.
Рис. 27. Обобщенная диаграмма классов
Класс ISensorControlобъявляет интерфейс модуля, класс SensorControlреализует указанный интерфейс. SensorControlсодержит классы Observer(отслеживает пороговые значения), CommandQueue(очередь комманд для асинхронных запросов), SensorContainer(реализует контейнер для хранения классов для работы с датчиком).
Интерфейс для работы с датчиками объявлен в классе ISensor, обощенная реализация интерфейса осуществляется в классе SensorAbstract. Указанный класс хранит указатель на IDriver, который используется для получения значений датчиков. В классе IDriverобъявляется интерфейс для взаимодействия с аппаратурой.
В Листинг 86 представлены общие объявления типов.
Листинг 86. Общие объявления типов (SensorDef.h)
namespace sensor
{
class ISensor;
class IDriver;
using SensorNumber = unsigned int; // (1)
using SensorValue = double; // (2)
using CheckAlertTimeout = unsigned int; // (3)
enum class SensorType : uint32_t // (4)
{
Spot = 0,
Smooth = 1,
Derivative = 2,
};
enum class DriverType : uint32_t // (5)
{
Simulation = 0,
Usb = 1,
Ethernet = 2
};
enum class AlertRule : uint32_t // (6)
{
More = 0,
Less = 1
};
using SensorPointer = std::shared_ptr; // (7)
using DriverPointer = std::shared_ptr; // (8)
using SensorValueCallback = std::function; // (9)
using SensorAlertCallback = std::function; // (10)
}; //namespace sensor
В строке 1 объявлен тип для номера датчика, в строке 2 объявлен тип значения, возвращаемого датчиком. В строке 3 объявлен тип значения интервала опроса датчиков для сигнализации пороговых значений.
В строке 4 объявлены идентификаторы типов датчиков, в строке 5 объявлены идентификаторы драйверов. В строке 6 объявлены идентификаторы правил для задания пороговых значений (сигнализация превышения или опускания ниже заданного значения).
В строке 7 объявлен тип для хранения указателей классов датчиков, в строке 8 – тип для хранения указателей классов драйверов. В строке 9 объявлен тип обратного вызова, в который передается значение датчика, в строке 10 – тип обратного вызова, в который передается значение датчика в случае срабатывания сигнализации порогового значения.
В процессе работы любой программы могут ситуации, приводящие к ошибкам. Причины ошибок могут быть самыми различными: неправильные действия пользователя, некорректная работа ПО, сбои в работе оборудования и т. п. Таким образом, возникает необходимость реализации подсистемы обработки ошибок, которая осуществляет восстановление работоспособности компонента после возникновения ошибочной ситуации и уведомление об этом пользователя.
Читать дальше