3. Попова О.А. Информационная поддержка оценки показателей надежности для оборудования ответственного назначения // Информатизация и связь. 2015. № 3. С. 41-46.
4. Абрамов О.В. Возможности и перспективы функционально-параметрического направления теории надежности // Информатика и системы управления. - 2014. - №4(42). - С. 53-66.
5. Абрамов О.В. Алгоритм оценки и прогнозирования остаточного ресурса сложных технических систем // Надежность и качество: труды межд. симпозиума в 2-х томах. Том 1. / Под ред. Н.К. Юркова. -Пенза: Изд-во ПГУ, 2013. - С. 5-6.
6. Силин В.Б., Заковряшин А.И. Автоматическое прогнозирование состояния аппаратуры управления и наблюдения. - М.: Энергия, 1973. - 336 с
7. Федин С. С., Красюк К. А., Трищ Р. М. Марковская модель прогнозирования параметрической надежности измерительновычислительных комплексов // Восточно-Европейский журнал передовых технологий. - 2009. - №6 (38). - С.22-2 6.
8. Абрамов О.В. Марковские модели техногенных рисков // Информатика и системы управления. -2013. - №2(36). - С. 73-81.
УДК 004.94
Надейкина Л.А., Черкасова Н.И,
Московский государственный технический университет гражданской авиации (МГТУ ГА), Москва, Россия
ИСПОЛЬЗОВАНИЕ АРХИТЕКТУРНЫХ ПАТТЕРНОВ И ФУНКЦИОНАЛЬНОЙ ДЕКОМПОЗИЦИИ ДЛЯ ПОВЫШЕНИЯ КАЧЕСТВА И НАДЕЖНОСТИ
ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
В статье проводятся результаты анализа использования паттернов проектирования и функциональной декомпозиции, для реализации основных принципов дизайна в проектировании программных систем. Рассматриваются вопросы повышения надежности и качества программного обеспечения снижением связанностей модулей и использованием интерфейсов для описания взаимодействий между модулями.
Ключевые слова:
предметная область, паттерны, проектирование, шаблоны проектирования, декомпозиция, анализ и проектирование систем, программирование, информационная технология, языки программирования, тестирование.
Характерной чертой современных программных систем является высокий уровень сложности: один разработчик практически не в состоянии охватить все детали системы. Большая часть книги Роберта К. Мартина [1] состоит из практических сценариев нарастающей сложности программного кода.
Сложность программной системы обусловлена:
- сложностью реальной предметной области и соответственно трудностью анализа предметной области и проектирования программной системы;
- трудностью управления процессом разработки;
- необходимостью обеспечить достаточную гибкость программы;
- неудовлетворительными способами описания поведения больших дискретных систем.
Сложность, как правило, растет гораздо быстрее размеров программы. Нередко архитектура программы определяет то, выживет ваш проект или нет. Таким образом, чтобы программа хорошо работала, она должна быть хорошо организована, имела хорошую архитектуру.
Шаблонам проектирования и принципам проектирования посвящено много трудов [2, 3].
Пять основных принципов дизайна классов в проектировании [1], которые следует иметь ввиду при написании кода, сокращенно называются S.O.L.I.D., и расшифровываются так:
1. Single Responsibility Principle (Принцип единственной обязанности)
2. Open Closed Principle (Принцип открытости/закрытости)
3. Liskov's Substitution Principle (Принцип подстановки Барбары Лисков)
4. Interface Segregation Principle (Принцип разделения интерфейса)
5. Dependency Inversion Principle (Принцип инверсии зависимостей)
Рассмотрим, что включает в себя процесс создания архитектуры программы и какие критерии при этом применяются, а также всегда ли следует использовать принципы и какие инструменты лучше использовать в различных случаях.
Общепринятого термина хорошей архитектуры не существует. Тем не мене можно сформулировать разумные и универсальные критерии исходя из стандартных критериев качества программного обеспечения.
Эффективность системы. В первую очередь программа, конечно же, должна решать поставленные задачи и хорошо выполнять свои функции, причем в различных условиях. Сюда можно отнести такие характеристики, как надежность, безопасность,
производительность, способность справляться с увеличением нагрузки (масштабируемость).
Гибкость системы. С течением времени появляются новые требования встает необходимость изменять приложение. Архитектурное решение должно допускать внесение изменений. Изменение одного фрагмента должно практически не влиять на другие фрагменты.
Расширяемость системы. Архитектура должна позволять легко наращивать дополнительный функционал по мере необходимости.
Требование, чтобы архитектура системы обладала гибкостью и расширяемостью (то есть была способна к изменениям и эволюции) выделена в виде отдельного принципа SOLID — «Принципа открытости/закрытости»: программные сущности -классы, модули, функции и тому подобное - должны быть открытыми для расширения, но закрытыми для модификации.
Звучит немного противоречиво. Архитектура должна предоставлять возможность расширить или изменить поведение системы без изменения, переписывания уже существующих частей системы. То есть проектировать надо так, чтобы новая функциональность добавлялась путем написания нового кода и при этом существующий - не изменялся. Это так называемая «плагинная архитектура» - Plugin Architecture.
Литературы на эту тему практически нет. Можно назвать ряд современных технологий, где так или иначе реализуется такая архитектура приложений -аспектно -ориентированное программирова-
ние(АОП), DirectX12, SOAP. Ниже рассмотрим, где еще можно реализовать Plugin Architecture.
Масштабируемость процесса разработки. Архитектура должна позволять распараллелить процесс разработки.
Тестируемость. Тесты улучшают качество кода. Требование «хорошей тестируемости» является требованием к хорошему дизайну. Существует целая методология разработки программ на основе тестов, которая так и называется — Разработка через тестирование (Test-Driven Development, TDD).
Возможность повторного использования. Систему желательно проектировать так, чтобы ее фрагменты можно было повторно использовать в других системах. Код тяжело использовать повторно в другом приложении, если его тяжело «выпутать» из текущего приложения.
Хорошо структурированный, читаемый и понятный код. Сопровождаемость. Хорошая архитектура должна давать возможность относительно легко и быстро разобраться в системе новым людям. Проект
должен быть хорошо структурирован, не содержать дублирования, иметь хорошо оформленный код. И по возможности в системе лучше применять стандартные, общепринятые решения привычные для программистов.
Декомпозиция как основа как модульной архитектуры
Все перечисленные критерии важны, но главная задача при проектировании программных систем -это снижение сложности системы, которая решается декомпозицией сложной системы на более простые подсистемы [4]. Разбиение системы продолжается пока не будут получены части системы, простые для понимания и создания. Речь идет об иерархической декомпозиции. Данное решение одновременно обеспечивает требования и других описанных выше критериев.
Таким образом, когда создается архитектура программного обеспечения под этим, главным образом, подразумевается декомпозицию программной системы на подсистемы (функциональные модули, сервисы, слои, подпрограммы) и организацию их взаимодействия друг с другом и внешним миром. Причем, чем более независимы подсистемы, тем безопаснее сосредоточиться на разработке каждой из них в отдельности и при этом не заботиться об остальных частях.
Декомпозиция позволяет предоставить все преимущества «хорошей» архитектуры:
1. Масштабируемость - возможность расширять систему и увеличивать ее производительность, за счет добавления новых модулей.
2. Гибкость - изменение одного модуля не требует изменения других модулей.
3. Возможность тестирования - модуль можно отсоединить от всех остальных и протестировать.
4. Повторное использование - модуль может быть использован в других программах и другом окружении.
5. Сопровождаемость - разбитую на модули программу легче понимать и сопровождать.
Иерархическая декомпозиция
Систему разбивают на крупные функциональные модули - подсистемы, описывающие ее работу в самом общем виде. Затем, полученные модули, анализируются более детально и, в свою очередь, делятся на подмодули либо на объекты.
Для небольших приложений двух уровней иерархии оказывается вполне достаточно — система вначале делится на подсистемы/пакеты, а пакеты делятся на классы.
В качестве примера рассмотрим распространенный «архитектурный шаблон» Модель-Вид-Контроллер (MVC).
Суть шаблона состоит в отделении представления от бизнес-логики, то есть в том, что любое пользовательское приложение вначале делится на два модуля — один из которых отвечает за реализацию собственно самой бизнес логики (Модель), а второй — за взаимодействие с пользователем (Пользовательский Интерфейс или Представление). Затем, для того чтобы эти модули могли разрабатываться независимо, связь между ними ослабляется с помощью паттерна "Наблюдатель" - Контроллер и в результате получаем один из самых востребованных архитектурных шаблонов, которые используются в настоящее время.
Типичными модулями первого уровня (полученными в результате первого деления системы на наиболее крупные составные части) как раз и являются — «бизнес-логика», «пользовательский интерфейс», «доступ к БД», «связь с конкретным оборудованием или ОС».
Функциональная декомпозиция
Деление на модули - подсистемы лучше всего производить исходя из тех задач, которые решает система. Основная задача разбивается на составляющие ее подзадачи, которые могут решаться или выполняться независимо друг от друга.
Модуль — это не произвольный кусок кода, а отдельная функционально осмысленная и законченная программная единица, которая обеспечивает
решение некоторой задачи и в идеале может работать самостоятельно или в другом окружении.
Таким образом, грамотная декомпозиция основывается, прежде всего, на анализе функций системы и необходимых для выполнения этих функций данных.
High Cohesion + Low Coupling
Самым же главным критерием качества декомпозиции является то, насколько модули сфокусированы на решение своих задач и независимы. Обычно это формулируют следующим образом: "Модули, полученные в результате декомпозиции, должны быть максимально сопряжены внутри (high internal cohesion) и минимально связанны друг с другом (low external coupling)" (Кристофер Александер) [5].
High Cohesion, высокая сопряженность или «сплоченность» внутри модуля, говорит о том, модуль сфокусирован на решении одной узкой проблемы, а не занимается выполнением разнородных функций или несвязанных между собой обязанностей.
Следствием High Cohesion является принцип единственной ответственности (Single
Responsibility Principle — первый из пяти принципов SOLID), согласно которому любой объект (модуль) должен иметь лишь одну обязанность.
Low Coupling, слабая связанность, означает что модули, на которые разбивается система, должны быть, по возможности, независимы или слабо связанны друг с другом. Они должны иметь возможность взаимодействовать, но при этом как можно меньше знать друг о друге (принцип минимального знания). Это значит, что при правильном проектировании, при изменении одного модуля, не придется править другие или эти изменения будут минимальными.
Чем слабее связанность, тем легче писать, понимать, расширять, исправлять программу.
Нужно проводить декомпозицию таким образом, чтобы модули изначально слабо зависели друг от друга. Но кроме того, имеется ряд специальных методов и шаблонов, позволяющих затем еще и дополнительно минимизировать, и ослабить связи между подсистемами. Например, в случае MVC для этой цели использовался шаблон "Наблюдатель", но возможны и другие решения. Можно сказать, что методы для уменьшения связанности, как раз и составляют основной "инструментарий архитектора".
Интерфейсы. Фасад.
Интерфейсы позволяют уменьшать связанность системы, так же как стоящий за ними принцип Инкапсуляция + Абстракция + Полиморфизм.
Модули должны быть друг для друга "черными ящиками" (Инкапсуляция). Это означает, что один модуль не должен что-либо знать о внутренней структуре другого модуля. Объекты одной подсистемы не должны обращаться напрямую к объектам другой подсистемы
Модули (подсистемы) должны взаимодействовать друг с другом лишь посредством интерфейсов, то есть, абстракций, не зависящих от деталей реализации. Соответственно каждый модуль должен иметь четко определенный интерфейс или интерфейсы для взаимодействия с другими модулями.
Таким образом, взаимодействие между модулями нужно описывать в максимально общей (Абстрактной) форме — в форме интерфейса.
В этом случае код будет работать одинаково с любой реализацией, соответствующей контракту интерфейса. Собственно, именно эта возможность работать с различными реализациями (модулями или объектами) через унифицированный интерфейс и называется полиморфизмом. Полиморфизм — это не только переопределение методов, как иногда ошибочно полагают, а прежде всего — взаимозаменяемость модулей-объектов с одинаковым интерфейсом, или "один интерфейс, множество реализаций".
Для реализации такого полиморфизма механизм наследования совсем не нужен. Это важно понимать, поскольку наследования вообще, по возможности, следует избегать в архитектурных решениях.
Благодаря интерфейсам и полиморфизму, как раз и достигается возможность модифицировать и расширять код, без изменения того, что уже написано (Open-Closed Principle).
До тех пор, пока взаимодействие модулей описано исключительно в виде интерфейсов, и не завязано на конкретные реализации, возможно абсолютно "безболезненно" для системы заменить один модуль на любой другой, реализующий тот же самый интерфейс, а также добавить новый и тем самым расширить функциональность ("плагинная архитектура" ).
Интерфейсы дают возможность модулям взаимодействовать и при этом ничего не знать о внутренней структуре друг друга, тем самым в полной мере реализуя Принцип минимального знания, являющейся основой слабой связанности. Причем, чем в более абстрактной форме определены интерфейсы и чем меньше ограничений они накладывают на взаимодействие, тем гибче система. Отсюда фактически следует еще один из принципов SOLID — Принцип разделения интерфейса (Interface Segregation Principle), который выступает против «толстых интерфейсов» и говорит, что большие, интерфейсы надо разбивать на более маленькие и специфические, чтобы клиенты маленьких интерфейсов (зависящие модули) знали только о методах, которые необходимы им в работе.
Из вышесказанного следует, что концепция интерфейсов включает в себя и обобщает почти все основные принципы ООП — Инкапсуляцию, Абстракцию, Полиморфизм.
Когда проектирование идет не на уровне объектов, которые сами же и реализуют соответствующие интерфейсы, а на уровне модулей, реализацией интерфейса модуля является специальный объект — Фасад.
Фасад (Facade) предоставляет унифицированный интерфейс к множеству интерфейсов в некоторой подсистеме. Определяет интерфейс более высокого уровня абстракции, облегчающий работу с подсистемой.
Фасад позволит отделить подсистему как от клиентов, так и от других подсистем, что, в свою очередь, способствует повышению степени независимости и переносимости.
Если подсистемы зависят друг от друга, то зависимость можно ослабить, разрешив подсистемам обмениваться информацией только через фасады.
Клиенты общаются с подсистемой, посылая запросы фасаду.
Фасад делегирует запросы клиентов подходящим объектам внутри подсистемы.
Классы подсистемы ничего не «знают» о существовании фасада, то есть не хранят ссылок на него.
Фасад может также упростить процесс переноса системы на другие платформы, поскольку уменьшается вероятность того, что в результате изменения одной подсистемы понадобится изменять и все остальные.
Фасад — это объект-интерфейс, аккумулирующий в себе высокоуровневый набор операций для работы с некоторой подсистемой, скрывающий за собой ее внутреннюю структуру и истинную сложность. Обеспечивает защиту от изменений в реализации подсистемы. Служит единой точкой входа — "вы обращаетесь к фасаду, а он знает, кого надо нагрузить в этой подсистеме, чтобы получить нужное".
Таким образом, паттерн, позволяющий использовать концепцию интерфейсов при проектировании модулей и тем самым ослаблять их связанность — «Фасад».
Помимо этого, «Фасад» вообще дает возможность работать с модулями точно также как с обычными объектами и применять при проектировании модулей все те полезные принципы и техники, которые используются при проектировании классов.
Хотя большинство программистов понимают важность интерфейсов при проектировании классов (объектов), идея необходимости использовать интерфейсы также и на уровне модулей только зарождается.
В настоящее время практически нет проектов, в которых применялся паттерн «Фасад» для ослабления связанности между модулями, слоями. В частности, в «архитектурном шаблоном» MVC наряду с паттернами Observer и Composite более эффективно было бы применять паттерн Facade потому, что к объектам Модели, отвечающей за бизнес-логику приложения, нужно обращаться не напрямую, а через интерфейс, то есть «Фасад» Dependency Inversion.
Формально, требование, чтобы модули не содержали ссылок на конкретные реализации, а все зависимости и взаимодействие между ними строились исключительно на основе абстракций, то есть интерфейсов, выражается принципом Инвертирования зависимостей (Dependency Inversion — последний из пяти принципов SOLID)
Не будет преувеличением сказать, что использование интерфейсов для описания зависимостей между модулями (Dependency Inversion) + корректное создание и внедрение этих зависимостей (прежде всего Dependency Injection) являются центральными, базовыми техниками для снижения связанности. Они служат тем фундаментом, на котором вообще держится слабая связанность кода, его гибкость, устойчивость к изменениям, повторное использование. Но, если с фундаментом все в порядке, то знание дополнительных приемов может быть очень даже полезным.
Замена прямых зависимостей на обмен сообщениями
Иногда модулю нужно всего лишь известить других о том, что в нем произошли какие-то изменения и ему не важно, что с этой информацией будет происходить потом. В этом случае модулям вовсе нет необходимости «знать друг о друге», то есть содержать прямые ссылки и взаимодействовать непосредственно, а достаточно всего лишь обмениваться сообщениями (messages).
Связь модулей через обмен сообщениями является гораздо более слабой, чем прямая зависимость и реализуется она чаще всего с помощью следующих шаблонов:
Наблюдатель (Observer). Применяется в случае зависимости «один-ко-многим», когда множество модулей зависят от состояния одного — основного. Находит широкое применение в системах с пользовательским интерфейсом, позволяя ядру приложения (модели) оставаться независимым и при этом информировать связанные с ним интерфейсы о том, что произошли какие-то изменения и нужно обновиться. Качественно спроектированная подобная система допускает добавление или удаление модулей в любое время.
Посредник (Mediator). Применяется, когда между модулями имеется зависимость «многие ко многим». Медиатор выступает в качестве посредника в общении между модулями, действуя как центр связи и избавляет модули от необходимости явно ссылаться друг на друга. В результате взаимодействие модулей друг с другом («все со всеми») заменяется взаимодействием модулей лишь с посредником («один со всеми»). Говорят, что посредник инкапсулирует взаимодействие между множеством модулей.
Типичный пример — контроль трафика в аэропорту. Все сообщения, исходящие от самолетов, поступают в башню управления диспетчеру, вместо того, чтобы пересылаться между самолетами напрямую. А диспетчер уже принимает решения о том, какие самолеты могут взлетать или садиться, и в свою очередь отправляет самолетам соответствующие сообщения.
Замена прямых зависимостей на синхронизацию через общее ядро
Данный подход обобщает и развивает идею, заложенную в шаблоне «Посредник». Когда в системе присутствует большое количество модулей, их прямое взаимодействие друг с другом становится слишком сложным. Поэтому имеет смысл взаимодействие «все со всеми» заменить на взаимодействие «один со всеми». Для этого вводится некий обоб-
щенный посредник, это может быть общее ядро приложения, хранилище или шина данных, а все остальные модули становятся независимыми друг от друга клиентами, использующими сервисы этого ядра или выполняющими обработку содержащейся там информации. Реализация этой идеи позволяет модулям- клиентам общаться друг с другом через посредника и при этом ничего друг о друге не знать.
В сущности, именно этот подход реализован в «шаблоне» Модель-Вид-Контроллер (МУС), где с одной Моделью (являющейся ядром приложение и общим хранилищем данных) могут взаимодействовать множество Пользовательских Интерфейсов, которые работают синхронно и при этом не знают друг о друге. Ничто не мешает подключить к общей модели и синхронизировать таким образом не только интерфейсы, но и другие вспомогательные модули.
Композиция вместо наследования
Одну из самых сильных связей между объектами дает наследование, поэтому, по возможности, его следует избегать и заменять композицией.
Выводы
Разработка качественных программ — тяжелый труд. Между хорошей идеей, формулировкой требований, составлением "видения" и готовым программным продуктом лежит гораздо больше, чем просто программирование. Анализ и проектирование, определение способов решения задачи, выбор программных средств, удобное представление проектного решения, реализация и сопровождение программы — это основные вопросы, которые рассмотрены в данной статье и предложены некоторые решения. Хотя большинство программистов понимают важность интерфейсов при проектировании объектов программной системы, идея необходимости использовать интерфейсы также и на уровне модулей только зарождается. Для повышения надежности программного обеспечения большую роль играет правильная модуляризация программы. Фасад — это объект-интерфейс, аккумулирующий в себе высокоуровневый набор операций для работы с некоторой подсистемой, скрывающий за собой ее внутреннюю структуру и истинную сложность. Использование Фасада обеспечивает защиту от изменений в реализации подсистемы, чем повышает надежность и качество программных систем в целом.
ЛИТЕРАТУРА
1. Роберт С. Мартин Принципы, паттерны и методики гибкой разработки на языке C#. / Роберт С. Мартин, Мика Мартин / Пер. с англ.- Издательство "Символ-Плюс", 2011, 768 с.
2. Элизабет Фридман. Паттерны проектирования. / Элизабет Фридман, Эрик, Кэти Сиерра, Берт Бейтс. / 2-е издание: Пер с англ. -Издательство "Питер", 2016, 656 с.
3. Ларман Крэг. Применение UML и шаблонов проектирования. 2-е издание: Пер. с англ. — М.: Издательский дом "Вильямс", 2004. 624 с.
4. Роберт Мартин. Чистый код: создание, анализ и рефакторинг: Пер с англ. - Издательство "Питер", 2016, 464 о.
5. Кристофер Александер. Язык шаблонов. Города. Здания. Строительство. Пер. с англ. - М.: Издательство "Студия Артемия Лебедева", 2014, 1093 о.
6. Надейкина Л.А. Проблема отказа доступа к сетевым сервисам. / Надейкина Л.А., Черкасова Н.И./ Труды Международного симпозиума Надежность и качество. -2015.- Т .1. - С.258-261.
7. Петрянин Д.Л. Архивация как способ защиты информации. / Петрянин Д.Л. , Юрков Н.К., Разживина Г.П. / Труды Международного симпозиума Надежность и качество. -2015.- Т .1. - С.251-252.
УДК 658.512
Саушев А.В., Бова Е.В.
ФГБОУ ВО «Государственный университет морского и речного флота имени адмирала С.О. Макарова» Санкт-Петербург, Россия
К ПРОБЛЕМЕ ПАРАМЕТРИЧЕСКОЙ ОПТИМИЗАЦИИ СИСТЕМ УПРАВЛЕНИЯ АВТОМАТИЗИРОВАННЫХ ЭЛЕКТРОПРИВОДОВ
Рассматривается методы и алгоритмы оптимального параметрического синтеза систем управления автоматизированных электроприводов. Основу методов составляет информация о границе области работоспособности электропривода. В качестве критерия оптимальности предлагается использовать запас работоспособности электропривода. Предложенные методы и алгоритмы иллюстрируется примерами параметрического синтеза электроприводов постоянного тока.
Ключевые слова:
параметрическая оптимизация, область работоспособности, запас работоспособности, системы управления электропривода.
Введение. Проектирование автоматизированных электроприводов (АЭП) на этапе параметрического синтеза сводится к решению двух основных задач - определению номинальных значений внутренних параметров системы и допустимых пределов их изменения. Внутренние параметры - это параметры элементов АЭП, которые характеризуют состояние и свойства самой системы. При проектировании они определяют вектор X управляемых параметров. Математическая модель АЭП представляет собой алгоритм вычисления вектора выходных параметров У при заданных векторах внутренних параметров X и внешних параметров V. Внешние параметры характеризуют свойства внешней по отношению к АЭП среды и оказывают влияние на ее функционирование. Выходные параметры характеризуют свойства АЭП, интересующие потребителя. Они представляют собой параметры-функционалы, т.е. функциональные зависимости фазовых переменных АЭП и параметры, являющиеся граничными значениями диапазонов внешних переменных, в которых сохраняется работоспособность системы. К выходным параметрам при параметрическом синтезе относятся показатели назначения, параметрической надежности и экономичности [1]. Показателем параметрической надежности при ограниченных статистических данных о законах распределения внутренних параметров АЭП во времени является запас работоспособности [1].
Область работоспособности 0 = Р(~)М задает множество допустимых значений внутренних параметров, при которых выполняются все требования к выходным параметрам АЭП, и определяется условиями работоспособности [2]:
Yjm.n * Yj = Fj(X) < Yjmax, j = 1,m
J
' J
j max'
(1)
X min < X- < X i = 1 n
гд
е Yj max (Xi max ) , Yj min (Xi min )
соответственно
7 шах Vе I тах/ у п
максимально и минимально допустимые значения j-го выходного Yj (2-го внутреннего Х±) параметра; Р - оператор, устанавливающий связь между внутренними и выходными параметрами; В и Р - допус-ковые области, определяемые соответственно первым и вторым неравенствами (1). Области В в пространстве внутренних параметров соответствует допусковая область М.
Основными задачами эксплуатации АЭП являются задачи определения состояния электропривода в данный момент времени и прогнозирование его состояния на предстоящий момент времени.
В работе [3] показано, что задачи проектирования и эксплуатации динамических систем следует рассматривать с единых позиций параметрического и структурного управления состоянием этих систем. При этом важнейшим показателем параметри-