Приветствую, коллеги. Хочу представить вашему вниманию статью, написанную мной некоторое время назад для ХабраХабра. В целом, статья больше пригодится тем, кто знаком с LabVIEW поверхностно. Ее основная задача - показать базовые элементы LabVIEW, наличие которых в ряде случаев может стать определяющим моментом при выборе средства разработки.
Dataflow + G = LabVIEW
Некоторое время назад я сменил специализацию. Это был не просто переход к другому языку программирования или сосредоточение на иной области задач, но и весьма ощутимое изменение парадигмы, которой я придерживался. Год назад я окунулся в мир dataflow и визуального программирования. Наиболее ярким и мощным представителем этой ветви средств разработки является LabVIEW (National Instruments).
В оригинальной статье я ссылался на другой материал на Хабре, посвященный LabVIEW. Знакомство с ним необходимо в случае, если LabVIEW для вас - совершенно незанкома. Думаю, на этом портал вероятность появления таких пользователей стремится к нулю, поэтому, можно смело читать дальше.* * *
В этой публикации мне хотелось бы вкратце рассказать о том, как реализовать на LabVIEW простейший автомат. Не буду вдаваться в объяснения о том, что такое автоматное программирование, изображения скажут больше. Грамотно продуманная диаграмма состояний автомата позволит сделать код удобным для разработчика, а программу - стабильной. Но в начале, небольшое отступление. Я проясню некоторые моменты LabVIEW.
Туннели и шифт-регистры.

Итак, слева от цикла мы видим скалярную переменную со значением, раным нулю. Пятерка присоединенная к N говорит циклу о пяти итерациях, т.е. i = 0..4.
Заводим переменную в цикл двумя разными способами - либо через туннель, либо через сдвиговый регистр. Чуть позже увидим разницу между этими вариантами. Верхние три "провода" просто насквозь проходят цикл, однако на выходе - разное. Первый верхний выход имеет автоиндексацию, следовательно на выходе будет не ноль, а массив из пяти нулей. Второй выход выдаст нам тот же ноль, что и на входе. Третий выход, свдиговый регистр, так же даст нам ноль. Вроде бы, никаких отличий от простого туннеля, однако - читайте дальше.
Посмотрим теперь на "проводки", которые в цикле заводятся на узел сложения. Складывать будем с переменной i, т.е. с номером итерации.
Что же будет на выходе? Поскольку мы складываем с нулем (та переменная, что заведена снаружи цикла), мы увидим на четвертом выходе (с автоиндексацией) массив [0,1,2,3,4]. Логично. Что же будет в пятом? Последнее значение i. Туннель не имеет автоиндексации и перезаписывается.
А что в последнем выходе? А вот там будет 10. (0 + 1 + 2 +3 +4) Почему? Потому что сдвиговый регистр на входе будет передавать в следующую итерацию цикла предыдущее значение выхода, и, лишь на первой итерации - внешний нолик, который мы подали на вход.
Проверим.

Задача
Теперь попробуем сразу перейти к задаче. Предположим, что нам надо написать программу, которая ждет входящее TCP/IP соединение, отправляет данные клиенту, отключает его и возвращается в исходный режим.
Диаграмма приложения, реализующего этот сервис будет такой:

Теперь, взглянем на исходный код.
Главный цикл программы выглядит так:

Кейсы основной структуры и определяют состояния автомата: init, listen, say, quit.
А вот маленькие вложенные кейсы (обработка ошибки соединения и обработка нажатия кнопки выхода) подробнее:


Остальные кейсы основной структуры:



Запускаем программу, соединяемся telnet localhost 10000 и видим в консоли "hello, world!". Затем соединение рвется.
Сухой остаток
Одна из главных особенностей визуального программирования - код действительно может быть наглядным и красивым! С другой стороны, он может запросто превратиться в лапшу, все-таки мы имеем дело с "проводками" dataflow. Однако в LabVIEW есть ряд средств (очереди, локальные, глобальные, сетевые переменные, свойства элементов управления и прочее), который позволяет улучшить читаемость кода. Правда, в ущерб идеологии dataflow. Да что там говорить, есть даже специальные структуры для контроля за событиями пользовательского интерфейса. Есть ООП! А в LabVIEW 2009 есть даже рекурсия, которая ну никак не вписывается в dataflow. Однако, несмотря ни на что, LabVIEW более чем достоин того, чтобы иметь его ввиду при выборе инструмента разработки.
P.S. Начиная с версии 8.6 в LabVIEW появились специальные инструменты для автоматного программирования. Пока что мне не довелось использовать их в работе, однако, на первый взгляд, они делают модель автомата еще более наглядной. Представится возможность - расскажу.
Спасибо за внимание.
Павел Ш. Китьян / Этот e-mail адрес защищен от спам-ботов, для его просмотра у Вас должен быть включен Javascript


Комментарии
Хотелось бы добавить, что именно для таких автоматов удобно использовать ENUM Typedef, т.к. если использовать обычный ENUM, то добавлять состояния будет сложновато.
RSS лента комментариев этой записи