ООП в графических языках программирования. ч.2 МОП и ООП |
||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2021-08-19 02:00 В первой части я попытался показать, что черная кошка ООП в темной комнате графических языков существует, даже если это не кошка, а полудохлый кот живодера Шредингера, который то есть, то его нет. Был показан пример реализации методологии объектно-ориентированного программирования, когда программа – это не код на языке С++ или Java, а диаграмма Simulink, SimInTech, SimulationX или SCADE Esterel, — любая графическая нотация описания алгоритма. В рекламных материалах Мatlab Simulink часто используют термин МОП — Модельно Ориентированное Проектирование (Model-based design). Во многих текстах они подчёркивают, что графическая схема алгоритма это модель, что, конечно, верно. Однако в первоначальном определении МОП, модель – это прежде всего модель объекта, к которому разрабатывают систему управления, включая управляющее программное обеспечение. Таким образом, разрабатывая систему управления по методологии МОП можно и нужно использовать методологию ООП для разработки управляющего ПО. И что бы окончательно закрыть вопрос с моделями, вот вам картинка с отличиями одного от другого. Если все понятно, то можно дальше не читать. Но и тут, как бы удивительно это не звучало, разработка все равно идет с использованием методологии ООП. Потому как, когда ООП использовать нельзя, но очень хочется, то можно. Правда, потом нужно все вернуть назад, и что бы никакого С++ и итоговом коде не оказалось, ибо безопасность и нормативы «?ber alles». Как говорится, и рыбку съесть, и за нарушения не сесть. Чтобы сделать настоящий объект по определению ООП, мы связываем структуры данных и схемы их обработки в единый объект, это называется инкапсуляция. А поскольку для надежных систем АЭС нам нельзя использовать С++, мы при генерации кода должны все это разобрать обратно. Как пояснили в комментариях к предыдущей статье, первая компилятор С++ СFront работал так же, осуществлял трансляцию ООП С++ кода в чистый Си. В первом варианте реализации ООП в графическом языке у нас был создан специальный блок, содержащий графическую расчетную схему. Этот блок при инициализации привязывал схему (метод) класса к конкретному «экземпляру класса» — набору переменных, поименованных специальным способом. Рассмотрим второй вариант реализации методологии ООП в графических языках программирования. На рисунке 1 изображена схема работы алгоритма обработки датчика. Это метод класса. Ему соответствует в базе данных своя категория «Датчики» — абстрактный класс с заданным наборов полей и экземпляр класса KBA31CFO1 конкретный датчик. У данного датчика поля имеют конкретные значения, часть полей задаются пользователем, часть полей рассчитывается процессе выполенения программы. см. рис. 2 Пока все как в первом варианте, где у нас формировалась привязка расчетной схемы к конкретному датчику при установке блока на схему. «А где разница?» — спросите вы. А разница – внутри блока. Если в первом варианте внутри была расчетная схема, которая копировалась при каждой установке блока, то в этом варианте внутренность выглядит примерно так: Вместо расчетной схемы внутри блока «изображены» только передача и прием данных. Таким образом, одна схема обработки реализует обработку всех датчиков в проекте, причем каждый датчик обрабатывается со своими параметрами, заданными в базе данных как характеристики конкретного экземпляра класса. Например, ограничитель берет из базы данных максимальное значение, которое задано одинаковым для первых трех датчиков и отличается у четвёртого. (см. рис. 5) А что там с результирующим кодом, который автоматически сгенерируется по этой чудесной схеме, как удается избежать артефактов ООП? Все просто: никакого обмана и никакого ООП, в коде чистый Си. Для каждого блока схемы векторной обработки будет сформирован цикл, обеспечивающий столько вычислений, сколько экземпляров класса есть в проекте. В нашем случае датчиков 4, поэтому мы сначала формируем массивы размерностью «4», путем чтения сигналов из датчиков: /* Index=104 UID=104 GeneratorClassName=TSignalReader Name=buz1.sensor.Macro6.Macro3.Macro157.SignalReader3 Type=Чтение из списка сигналов */ }; state_vars->kbastdv104_out_0_[0] = kba31cf001_mf_type; state_vars->kbastdv104_out_0_[1] = kba32cf001_mf_type; state_vars->kbastdv104_out_0_[2] = kba33cf001_mf_type; state_vars->kbastdv104_out_0_[3] = uf40y329084320_mf_type Потом сортируем все блоки по порядку и запускаем их в цикле. Для каждого элемента массива типа каждый блок вычислений выполнится для всех датчиков. /* Index=211 UID=211 GeneratorClassName=TAndSrc Name=buz1.sensor.Macro6.And61 Type=Оператор И */ for(i=0;i<4;i++){ locals->v211_out_0_[i] = state_vars->kbastdv125_out_0_[i] && (!(locals->v191_out_7_[i] > 0.5)); /* Index=212 UID=212 GeneratorClassName=TMulDbl Name=buz1.sensor.Macro6.Mul_oper1 Type=Перемножитель */ locals->v209_out_2_[i] = consts->kbastdv121_a_[i]*state_vars->kbastdv127_out_0_[i]; /* Index=213 UID=213 GeneratorClassName=TSumSrc Name=buz1.sensor.Macro6.Add_oper1 Type=Сумматор */ locals->v209_out_3_[i] = (1)*consts->kbastdv122_a_[i]+(1)*locals->v209_out_2_[i]; … } После расчета записываем сигналы для каждого экземляра класса: /* Index=776 UID=776 GeneratorClassName=TSignalWriter Name=buz1.sensor.Macro6.Macro3.SignalWriter4 Type=Запись в список сигналов */ kba31cf001_mf_xb01 = state_vars->kbastdv207_out_0_[0]; kba32cf001_mf_xb01 = state_vars->kbastdv207_out_0_[1]; kba33cf001_mf_xb01 = state_vars->kbastdv207_out_0_[2]; uf40y329084320_mf_xb01 = state_vars->kbastdv207_out_0_[3]; Как видим, в конечном коде никаких объектов нет. Чистый, невинный и безопасный СИ. В приведенном примере реализации ООП в графическом языке векторная схема обсчитывает все однотипные датчики. Такой прием позволяет изменить одну схему для изменения обработки всех датчиков. Другим дополнительным преимуществом такого подхода является страховка от ошибок. Представьте себе: вы вручную добавляете датчик и в одном месте забыли увеличить в цикле количество повторений при обработке. Никаким статическим анализатором кода эту ошибку обнаружить будет невозможно, код корректный. И даже на работе это может не сказаться сразу и очевидным образом. Ну, и в конце, обещанный полиморфизм и наследование. В первом методе пользователь получал множество одинаковых схем, которые он мог править уже после установки блока субмодели и, тем самым, осуществлять полиморфизм, изменяя поведение конкретного экземпляра класса. Я думаю, все догадались, что можно для конкретного датчика изменить схему обработки, и мы получим новый класс, у которого совпадают поля, но методы отличаются. Так же можно добавить новые поля и получить новый класс с другим полями, содержавшими все поля родителя и методы родителя. На рисунке 6 — пример двух блоков классов «родитель» и «наследник». Внутри блока сохраняется схема расчета родительского класса. Все данные уходят в общий векторный блок, аналогичный блоку на рис. 4. Полностью повторяется метод родительского класса. А потом у класса-наследника появляются дополнительное поле Yатм и дополнительный пересчет величины с помощью блока линейной интерполяции. Таким образом, сохраняется возможность менять методы обработки родителя, которые поменяются во всех классах-наследниках, а так же индивидуально настраивать поведение наследника. Подводя итог, можем утверждать, что методология ООП может быть использована при создании ПО в графических языках программирования. Абстрагирование, инкапсуляция, наследование, полиморфизм – все эти принципы легко и непринужденно реализуются правильными средствами разработки. Важно отметить, что итоговый код, после автоматической генерации из графического языка, остается чистым безопасным Си без всякого ООП В некторых случаях результатом разработки управляющего ПО, в графическом виде явялется не код Си, для загрузки в контроллеры, а принципиальная электрическая схема «железная логика», но при этом методика изложенавя выше ООП так же работает прекрасно работает. Источник: m.vk.com Комментарии: |
|