Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Создание программного обеспечения для нательных компьютерных сетей и носимых систем. Учебное пособие.pdf
X
- •ЧАСТНОЕ УЧРЕЖДЕНИЕ
- •Медицинский университет «РЕАВИЗ»
- •ВВЕДЕНИЕ
- •1.2. Исторический обзор развития носимых систем
- •ГЛАВА 2. ТЕХНОЛОГИЧЕСКИЕ АСПЕКТЫ РАЗРАБОТКИ
- •2.1. Выбор технологического стека для носимых систем
- •2.2. Архитектурные решения при разработке программного обеспечения
- •2.3. Управление энергопотреблением и оптимизация производительности
- •2.5. Интеграция с облачными сервисами в носимых приложениях
- •2.4. Работа с датчиками и взаимодействие с окружающей средой
- •2.6. Аспекты безопасности в технологическом контексте
- •3.1. Языки программирования и их роль в разработке для носимых систем
- •3.2. Принципы объектно-ориентированного программирования в контексте носимых технологий
- •3.3. Обзор паттернов проектирования для эффективной разработки приложений
- •3.4. Многозадачность и управление потоками в носимых приложениях
- •3.5. Оптимизация алгоритмов под ограниченные ресурсы носимых устройств
- •3.6. Работа с сенсорами и вводом данных в носимых приложениях
- •3.7. Адаптация пользовательского интерфейса к маленьким экранам и управлению сенсорами
- •4.1. Особенности дизайна интерфейса для различных типов носимых устройств (часы, очки, фитнес-трекеры)
- •4.2. Адаптация пользовательского опыта к ограниченным размерам экрана
- •4.3. Взаимодействие с пользователем через жесты и голосовые команды
- •4.4. Работа с уведомлениями и многозадачность в носимых приложениях
- •4.5. Применение принципов доступности в дизайне интерфейса
- •ГЛАВА 5. РАЗРАБОТКА КЛИЕНТ-СЕРВИСНОЙ ОРГАНИЗАЦИИ НАТЕЛЬНОЙ КОМПЬЮТЕРНОЙ СЕТИ (НА ПРИМЕРЕ watchOS)
- •5.3. Работа с данными и обеспечение их конфиденциальности
- •5.4. Разработка клиентских приложений
- •ЗАКЛЮЧЕНИЕ
- •БИБЛИОГРАФИЧЕСКИЙ СПИСОК
- •ПРИЛОЖЕНИЕ А
- •ПРИЛОЖЕНИЕ Б
- •ПРИЛОЖЕНИЕ В

«Цепочка обязанностей» (Chain of Responsibility) предоставляет механизм
обработки запросов последовательно по цепочке обработчиков. Каждый обработчик решает, может ли он обработать запрос, и передает его следующему обработчику в случае необходимости. Это уменьшает зависимость между отправителем запроса и его получателями.
«Шаблонный метод» (Template Method) определяет скелет алгоритма в
базовом классе, оставляя реализацию определенных шагов подклассам. Это
позволяет изменять части алгоритма, не изменяя его структуры.
Паттерн «Состояние» (State) позволяет объекту изменять свое поведение
при изменении своего внутреннего состояния.
Это особенно полезно, когда объект имеет множество различных состояний, и его поведение сильно зависит от текущего состояния.
«Прототип» (Prototype) используется для создания новых объектов путем
копирования существующего объекта, независимо от его конкретного класса.
Это удобно, когда создание объекта затратно или сложно.
3.4. Многозадачность и управление потоками в носимых приложениях
В этом контексте, носимые устройства, такие как умные часы или фитнес-трекеры, требуют оптимизированного управления задачами и потоками для
обеспечения плавной работы приложений [2].
Многозадачность в носимых приложениях означает способность устройства выполнять несколько задач одновременно или переключаться между ними
с минимальной задержкой.
Это особенно важно для обработки данных с датчиков, обновления пользовательского интерфейса и взаимодействия с внешними устройствами.
Пример многозадачности в псевдокоде:
plaintext
function mainLoop():
while true:
processSensorData()
updateUI()
function processSensorData():
// код обработки данных с датчиков
71

function updateUI():
// код обновления пользовательского интерфейса
В данном примере показан основной цикл приложения, который поочередно вызывает функции обработки данных с датчиков и обновления пользовательского интерфейса.
Эффективное управление потоками в носимых приложениях помогает
оптимизировать использование процессора и энергии, что критически важно
для устройств с ограниченными ресурсами.
Пример управления потоками в псевдокоде:
plaintext
class SensorThread extends Thread:
public void run():
while true:
sensorData = readSensor()
processSensorData(sensorData)
class UIThread extends Thread:
public void run():
while true:
updateUI()
function main():
sensorThread = new SensorThread()
uiThread = new UIThread()
sensorThread.start()
uiThread.start()
Здесь представлен пример использования потоков для асинхронного чтения данных с датчиков и обновления пользовательского интерфейса. Это позволяет обоим задачам выполняться параллельно, улучшая отзывчивость приложения.
Носимые устройства часто взаимодействуют с окружающей средой через
сенсоры, а также получают уведомления от других устройств. Эффективная обработка событий является ключевой частью разработки носимых приложений [5].
72

Пример работы с событиями в псевдокоде:
plaintext
class SensorEventListener:
public void onSensorDataReceived(data):
// обработка данных с датчика
processSensorData(data)
class NotificationListener:
public void onNotificationReceived(notification):
// обработка уведомления
displayNotification(notification)
function main():
sensorListener = new SensorEventListener()
notificationListener = new NotificationListener()
sensorService.registerListener(sensorListener)
notificationService.registerListener(notificationListener)
// Главный цикл приложения
while true:
handleEvents()
updateUI()
function handleEvents():
// обработка событий, таких как данные с датчиков и уведомления
sensorService.handleEvents()
notificationService.handleEvents()
Здесь демонстрируется пример использования слушателей для обработки
событий, таких как данные с датчиков и уведомления. Главный цикл приложения обрабатывает эти события, что позволяет реагировать на изменения в
окружающей среде.
73

Асинхронность в Носимых Приложениях
Использование асинхронных операций важно для обеспечения отзывчивости пользовательского интерфейса и предотвращения блокировки устройства
при выполнении длительных операций.
Пример асинхронности в псевдокоде:
class AsyncTask:
public void doInBackground():
// выполнение длительной операции
processLongOperation()
public void onPostExecute():
// обновление пользовательского интерфейса после завершения опе-
рации
updateUI()
function main():
asyncTask = new AsyncTask()
// Запуск асинхронной операции
asyncTask.execute()
// Приложение продолжает работу, не блокируясь
continueAppExecution()
Здесь представлен пример использования асинхронной задачи для выполнения длительной операции в фоновом режиме. Это позволяет приложению
продолжать свою работу, не ожидая завершения операции.
В многозадачных сценариях носимых приложений эффективное управление задачами требует использования алгоритмов планирования.
Например, планирование задач может включать в себя выбор оптимального времени для считывания данных с датчиков и обновления пользовательского интерфейса. Одним из таких алгоритмов может быть алгоритм планирования Round Robin, который обеспечивает равномерное распределение времени
между задачами. подробней
Алгоритм планирования Round Robin представляет собой простой и широко используемый метод в многозадачных сценариях. Он основан на идее равномерного распределения времени между всеми активными задачами. В кон-
74

тексте носимых приложений, где ограничены вычислительные ресурсы, этот
метод может быть особенно полезен.
Принцип Работы:
Задачи организуются в очередь, и каждая задача получает фиксированное
время для выполнения (квант времени).
Задачи выполняются по кругу. Каждая задача получает свой квант времени, и если она не завершена, она переходит в конец очереди.
Равномерное Распределение: Этот подход обеспечивает равномерное
распределение вычислительных ресурсов между всеми задачами, предотвращая
длительные блокировки и обеспечивая отзывчивость системы.
Пример в Псевдокоде:
class Task:
constructor(id, executionTime):
this.id = id
this.executionTime = executionTime
function roundRobinScheduling(tasks, timeQuantum):
queue = initializeQueue(tasks)
while queue.isNotEmpty():
currentTask = queue.popFront()
executeTask(currentTask, timeQuantum)
if !currentTask.isCompleted():
queue.pushBack(currentTask)
function initializeQueue(tasks):
queue = new Queue()
for task in tasks:
queue.pushBack(task)
return queue
function executeTask(task, timeQuantum):
remainingTime = task.executionTime - timeQuantum
if remainingTime > 0:
// Задача не завершена, возвращаем в очередь
task.executionTime = remainingTime
75

else:
// Задача завершена
task.executionTime = 0
task.markAsCompleted()
Преимущества и Недостатки:
Преимущества:
Простота реализации: Алгоритм Round Robin легко реализовать и поддерживать.
Отзывчивость: Задачи получают моменты времени для выполнения, что
обеспечивает отзывчивость системы.
Однако, в случае, когда у задач разные по сложности, возможно, что некоторые задачи будут ждать завершения более долгих задач.
Приведем несколько заданий, связанных с темой многозадачности,
управления потоками и асинхронности в контексте носимых приложений:
1. Разработайте носимое приложение, которое одновременно считывает
данные с нескольких датчиков (например, акселерометра и пульсометра) и
отображает информацию на пользовательском интерфейсе. Используйте многозадачность для оптимизации считывания данных и обновления интерфейса.
2. Напишите программу для носимого устройства, которая имитирует ситуацию асинхронного получения уведомлений от внешних источников (например, уведомлений о звонках, сообщений). Используйте потоки для обработки
уведомлений, при этом приоритизируйте уведомления в зависимости от их типа.
3. Создайте приложение для умных часов, которое реагирует на события
окружающей среды. Например, при изменении освещенности (считанной с датчика света) приложение должно автоматически регулировать яркость экрана.
Используйте обработку событий для реализации этого функционала.
4. Разработайте приложение для отслеживания физической активности на
носимом устройстве. Используйте асинхронные операции для отправки данных
о физической активности на удаленный сервер в фоновом режиме, не блокируя
пользовательский интерфейс.
5. Создайте приложение для умных очков, которое одновременно отслеживает движения пользователя (считанные с гироскопа) и управляет отображением контента на основе его направления взгляда (считанного с датчика
направления взгляда). Используйте комбинацию паттернов проектирования, таких как «Стратегия» и «Наблюдатель», для эффективной реализации этой
функциональности (рис. 3.3).
76

Рис. 3.3. Модальная модель «Наблюдателя»
Пример решения задания по многозадачности.
Задача: разработать носимое приложение, которое одновременно считы-
вает данные с нескольких датчиков (например, акселерометра и пульсометра) и
отображает информацию на пользовательском интерфейсе.
python
import threading
import time
from random import randint
class Sensor:
def read_data(self):
Считываем данные с датчика
return randint(1, 100)
class Accelerometer(Sensor):
pass
class HeartRateMonitor(Sensor):
pass
class UserInterface:
def display_data(self, data):
print(f»Displaying data: {data}»)
def read_sensor_data(sensor, ui):
while True:
77

data = sensor.read_data()
ui.display_data(data)
time.sleep(1)
if __name__ == «__main__»:
accelerometer = Accelerometer()
heart_rate_monitor = HeartRateMonitor()
user_interface = UserInterface()
Запускаем потоки для каждого датчика
accel_thread = threading.Thread(target=read_sensor_data,
args=(accelerometer, user_interface))
heart_rate_thread = threading.Thread(target=read_sensor_data,
args=(heart_rate_monitor, user_interface))
accel_thread.start()
heart_rate_thread.start()
Главный поток может выполнять другие задачи или ожидать заверше-
ния работы датчиков
accel_thread.join()
heart_rate_thread.join()
В этом примере создаются два класса датчиков (Accelerometer и
HeartRateMonitor), а также класс для отображения данных на пользовательском
интерфейсе (UserInterface). Затем создаются два потока для считывания данных
с каждого датчика и отображения их на интерфейсе.
Рис. 3.4. Каждая строка представляет отображение данных с одного из датчиков
(значения данных (в данном случае, случайные числа) могут меняться
при каждом выполнении программы)
78

3.5. Оптимизация алгоритмов под ограниченные ресурсы носимых устройств
Оптимизация алгоритмов для носимых устройств, ограниченных вычис-
лительными и энергетическими ресурсами, представляет собой важный аспект
разработки приложений. Эти устройства, такие как умные часы или фитнестрекеры, обладают ограниченной мощностью процессора, объемом памяти и
запасом энергии, что требует специального внимания к оптимизации кода [2].
Одним из ключевых принципов оптимизации является минимизация вычислительных нагрузок. Это может включать в себя сведение к минимуму операций с высокой вычислительной сложностью, использование эффективных
структур данных и алгоритмов, а также избегание избыточных вычислений [15].
Другим важным аспектом оптимизации является эффективное использование энергии. Использование алгоритмов с низким энергопотреблением, таких
как алгоритмы сэмплирования событий или глубокого сна, может продлить
срок службы устройства.
Кроме того, оптимизация работы с датчиками, периодическое управление частотой процессора и активное управление энергосберегающими режимами являются важными стратегиями.
Специальное внимание следует уделять оптимизации работы с памятью.
Использование легковесных структур данных, эффективное управление жизненным циклом объектов и минимизация использования оперативной памяти
способствуют уменьшению нагрузки на ресурсы устройства.
Рассмотрим пример оптимизации на Python, связанный с эффективным
использованием памяти при работе с большим объемом данных. Допустим, у
нас есть задача нахождения суммы всех элементов списка чисел. Реализация
без оптимизации может потреблять много оперативной памяти, особенно при
работе с большими списками.
Пример без оптимизации:
python:
def sum_of_elements(numbers):
result = 0
for num in numbers:
result += num
return result
Пример использования
79

large_list = list(range(1, 1000001))
result = sum_of_elements(large_list)
print(result)
В этом примере сначала создается большой список чисел, и затем происходит итерация по этому списку для нахождения суммы. Однако, этот код может потреблять много памяти, поскольку список хранится полностью в памяти.
Оптимизированный пример:
python
def sum_of_elements_optimized(numbers):
return sum(numbers)
Пример использования
large_list = list(range(1, 1000001))
result = sum_of_elements_optimized(large_list)
print(result)
В оптимизированном примере мы используем встроенную функцию sum,
которая эффективно обрабатывает элементы списка и возвращает их сумму.
Это позволяет избежать явного цикла и минимизировать использование памяти.
Использование встроенных функций, таких как sum, часто более эффективно, чем явные циклы, так как они реализованы на уровне языка C и оптимизированы для производительности.
При работе с большими данными важно использовать функции или
структуры данных, которые минимизируют расход памяти.
Использование более компактных и лаконичных конструкций, когда это
возможно, помогает уменьшить объем кода и повысить его читаемость.
В дополнение к оптимизации использования памяти в Python для работы
с большими объемами данных, также стоит уделить внимание оптимизации
времени выполнения алгоритмов, особенно на устройствах с ограниченными
ресурсами [18].
Рассмотрим пример оптимизации времени выполнения на примере алгоритма поиска максимального элемента в списке чисел.
Пример без оптимизации:
def find_max_element(numbers):
max_element = float('-inf')
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
