Как построить линейный программный поток, который обрабатывает асинхронный вывод в UML? - PullRequest
0 голосов
/ 15 июня 2019

Я работаю над программированием некоторого кода, который подключен к консоли, но читает из файла журнала. Это уникально тем, что данные постоянно записываются в журнал, и я и я могу проверить их только по мере их поступления. Данные поступают в пакетах, которые собираются в «строки», а затем я проверяю каждую строку, чтобы посмотреть, ищем ли это данные.

Например:

(output) -- ignore
(output) -- ignore
(output) -- ignore
(input ) -- > ask for A - enable regex for A
(output) -- ignore
(output) -- ignore
(output) -- regex match - A_START - enable regex for B and C
(output) -- regex match - B
(output) -- regex match - B
(output) -- regex match - B
(output) -- regex match - C
(output) -- regex match - A_END - process completed data set

Вывод записывается в журнал асинхронно из моего приложения, поэтому я не могу отправить команду и затем ожидать, что следующий вывод будет результатом; это будет выход в какой-то момент в будущем. Поэтому мой буфер чтения обычно состоит из одной строки.

Обратите внимание, что соответствующая строка для A может появиться в любое время, поэтому я явно включаю и отключаю эти шаблоны регулярных выражений по мере необходимости и в последовательности.

Это может показаться невозможным для разбора, но в этом безумии есть порядок. В то время как полученные данные являются асинхронными, они отправляются в «блоках», где каждый блок представляет собой полный набор данных. Например, если набор данных X, Y, Z представляет собой одну строку, он может появиться в журнале в любом порядке. Но если X - это три строки, то ВСЕГДА будет отображаться как три соседние строки, независимо от их относительного положения по отношению к Y и Z.

Это позволяет мне проводить регулярные выражения в очень явном НАЧАЛЕ блока, чтобы знать, когда включить жадное регулярное выражение, а затем в явном конце END для известного мне блока отключить жадное регулярное выражение.

В конце блока у меня теперь есть полный набор данных.

Хотя это довольно легко сделать после того, как написана хорошая основа кода, у меня возникает проблема, заключающаяся в том, что код для того, что на самом деле является очень линейным чтением некоторых данных, по своей природе является нелинейным, как он выглядит в исходный файл из-за необходимости переходить между разнородными триггерами регулярного выражения и дополнительными обратными вызовами.

Что я хочу сделать, так это детально прорисовать это как UML, чтобы я мог обратиться к нему позже, потому что я ЗНАЮ, что через три месяца у меня будет чертовское время, чтобы разобраться в этом.

Реальная процедура, которую я сейчас пишу, более сложна, чем короткий пример, который я описал выше. Это похоже, но для каждой записи B в A мне нужно отправить другую команду, чтобы получить дополнительный набор данных, связанный с A. Полный набор данных для A не закончен, пока у меня нет всего.

Вот краткое описание последовательности:

> invoke catalog show

(output) -- Catalog Begin
(output) Collection 1
(output) Collection 2
(output) Collection 3
(output) -- Catalog End

// foreach next entry in Catalog...

> invoke Collection 1 show

(output) -- Collection Begin
(output) ...
(output) ...
(output) ...
(output) -- Collection End

// Perform action on Collection 1

// foreach next entry in Catalog...

А вот более подробное изложение того же:

-- enable 'catalog begin' regex pattern

> invoke catalog show

(output) -- Catalog Begin
   -- REGEX MATCH
      -- disable 'catalog begin' regex pattern
      -- enable 'catalog entry' regex pattern

(output) Collection 1
-- REGEX MATCH
   -- add to catalog list
(output) Collection 2
-- REGEX MATCH
   -- add to catalog list
(output) Collection 3
-- REGEX MATCH
   -- add to catalog list

(output) -- Catalog End
   -- REGEX MATCH
      -- disable 'catalog end' regex pattern
      -- enable 'collection begin' regex pattern
      -- collections max = 3
      -- next collection = 1
      -- send command: invoke Collection 1 (next collection) show

> invoke Collection 1 show

(output) -- Collection Begin
   -- REGEX MATCH
      -- disable 'collection begin' regex pattern
      -- enable 'collection entry' regex pattern

(output) ...
-- REGEX MATCH
   -- add to collection entry list
(output) ...
-- REGEX MATCH
   -- add to collection entry list
(output) ...
-- REGEX MATCH
   -- add to collection entry list

(output) -- Collection End
   -- REGEX MATCH
      -- disable 'collection begin' regex pattern
      -- enable 'collection entry' regex pattern
      -- next collection + 1 (2)
      -- send command: invoke Collection 2 (next collection) show
      -- if next collection > 3 (collections max)... (false)

-- repeats for all 3 entries

> invoke Collection 2 show
...
-- collections invoked + 1 (3)
-- if next collection > 3 (collections max)... (false)

> invoke Collection 3 show
...
-- collections invoked + 1 (3)
-- if next collection > 3 (collections max)... (true)
-- perform processing on data (catalog list and collection lists)

Пожалуйста, помогите мне понять, как я могу четко изобразить это, чтобы я мог понять, как собрать все различные детали, которые составляют в противном случае очень линейную операцию.

UPDATE:

Я думаю, что это правильный подход?

У меня есть «Действие», в котором я хочу выполнить команду для запроса некоторой информации. Существует файл журнала «Вывод» из системы и «Дисплей», представляющий собой цикл, в котором я читаю каждую строку по мере ее получения с выхода.

Вывод является асинхронным (в своем собственном столбце), и отображение является асинхронным по отношению к этому, поскольку оно отображает каждую строку только в том случае, если она читается. И действие также выполняется асинхронно (его можно вызвать в любое время).

Я думаю, что это правильный подход. Теперь, как мне объединить этих троих вместе, чтобы проиллюстрировать их отношения?

enter image description here

1 Ответ

0 голосов
/ 15 июня 2019

Вы можете использовать диаграмму активности, диаграмму последовательности или диаграмму конечного автомата.Все три типа диаграмм имеют широкие возможности для моделирования асинхронных процессов.Для вашей цели, я думаю, что диаграмма деятельности должна быть предпочтительной.Используя символ «fork», вы можете создать два параллельных потока, каждый из которых будет прослушивать разные события.Для прослушивания события используйте соответствующий многоугольник, как показано на рисунке ниже.Потоки могут связываться, используя потоки объектов (оранжевые стрелки), необязательно через хранилище данных.Я попытался создать диаграмму деятельности, чтобы отразить часть вашего алгоритма.Цвета не предписаны UML.Я использовал цвета, чтобы выделить различные виды элементов модели.

ad

Надеюсь, это поможет.Обратите внимание, что диаграмма не имеет конечного узла.Если действие должно прекратиться при определенном условии, то вам придется добавить это.Кроме того, он ожидает еще один блок после каждого совпадения регулярного выражения.Вам придется расширить диаграмму, чтобы показать, что она применяет несколько регулярных выражений к одному блоку.

...