Известная поговорка гласит: «Лучше один раз увидеть, чем сто раз услышать». Поэтому мы решили заимпрувить статический анализатор таким образом, чтобы он визуализировал код в виде блок-схем (Flowcharts) и диаграмм вызовов (Call Trees). Хоть и нарисовать блоки и их связи несложно, оптимизировать их расположение на «листе» представлялось задачей, требующей значительных усилий. Чтобы стрелки минимально пересекались и обтекали блоки, блоки объединялись в группы, и диаграмма при этом не превращалась в «кашу», нужно было потратить много сил и времени.
И тогда мы решили поискать готовое решение, дабы не изобретать велосипед. Наше внимание сразу привлек Graphviz – open source решение по визуализации диаграмм. Первые его версии были разработаны компанией AT&T, а теперь он доступен как набор утилит и библиотек, а также в исходниках под лицензией Eclipse Public License (EPL).
Его движок диаграмм использует язык описания графов DOT, который представляет собой текстовое описание структуры графа: вершины, их связи, группы и атрибуты для их визуального оформления.
Описание простейшего графа:
digraph graphname {
a -> b;
}
Если необходимо добавить узлам атрибуты, например подписи, то необходимо отдельно описать узлы:
digraph graphname {
a [label="source"]
b [label="destination"]
a -> b;
}
Далее покажу на примере простой процедуры на PL/SQL:
CREATE PROCEDURE WRITE_STRING(
P_MESSAGE_TYPE IN NUMBER
, P_MESSAGE IN VARCHAR2
)
IS
BEGIN
IF P_MESSAGE_TYPE >= LOG_LEVEL THEN
ADD_LOG_RECORD(P_MESSAGE_TYPE, P_MESSAGE);
END IF;
END WRITE_STRING;
Код понятен, даже если вы не знакомы с синтаксисом PL/SQL.
А теперь опишем этот код на языке DOT. Пояснения снова излишни:
digraph G {
N0 [label="”]
N1_COND [label="P_MESSAGE_TYPE \>= LOG_LEVEL ?"];
N2 [label="ADD_LOG_RECORD(P_MESSAGE_TYPE, P_MESSAGE);"];
EXIT_LABEL [label="END"];
N0 -> N1_COND
N1_COND -> N2
N1_COND -> EXIT_LABEL
N2 -> EXIT_LABEL
}
Теперь можно «скормить» этот файл Graphviz, подставив соответственно вместо %PNGFILE% и %DOTFILE% имена выходного (png) и входного (dot) файлов:
dot -v -Tpng –o%PNGFILE% %DOTFILE%
При помощи Graphviz из описания выше получается такая картина:
Наглядно, но весьма аскетично.
Можно сделать диаграмму привлекательнее, добавив атрибуты для определения формы блоков
(shape=diamond)
, подписи стрелок (label="Yes")
и цвета color
, fontcolor
. Также мы можем объединить в подграф блоки, которые являются исполняемыми. Это реализуется конструкцией
subgraph {}
, внутри которой мы можем перечислить имена блоков, включенных в подграф, и указать атрибуты для визуального оформления (цвет рамки).digraph G {
comment="PL/SQL flowchart generated by ClearSQL";
node [fontname="Arial", fontsize=8, height=.2, width=.25, color="#000000", fontcolor="#000000"];
edge [fontname="Arial", fontsize=8, arrowsize=.8, color="#000000", fontcolor="#000000"];
N0 [shape=plaintext, label="", style=invis];
N1_COND [shape=diamond, conditional=true, label="P_MESSAGE_TYPE \>= LOG_LEVEL ?"];
N2 [shape=box, label="ADD_LOG_RECORD(P_MESSAGE_TYPE, P_MESSAGE);"];
EXIT_LABEL [shape=Msquare, label="END"];
N0 -> N1_COND [color=darkgoldenrod];
N1_COND -> N2 [label=" Yes " color="#228b22" fontcolor="#228b22"];
N1_COND -> EXIT_LABEL [label=" No " color="#ff7e40" fontcolor="#ff7e40"];
N2 -> EXIT_LABEL
subgraph "cluster_#1" {
color="#0000ff";
N1_COND; N2
}
}
Получается вполне симпатичная блок-схема, которую и людям показать не стыдно.
Чтобы код могли читать не только программисты, но и «простые смертные», мы придумали такую фишку: приделали распознавание специальных тегов в комментариях, которые бы разработчик писал как псевдокод – язык описания алгоритмов. Это помогло увеличить ценность блок-схемы, которая теперь может отображать бизнес-логику, а не только визуализировать листинг.
CREATE PROCEDURE WRITE_STRING(
P_MESSAGE_TYPE IN NUMBER
, P_MESSAGE IN VARCHAR2
)
IS
BEGIN
--## Уровень данного сообщения по отношению к порогу журналирования
--##@true Выше
--##@false Ниже
IF P_MESSAGE_TYPE >= LOG_LEVEL THEN
--## Добавляем запись в журнал
ADD_LOG_RECORD(P_MESSAGE_TYPE, P_MESSAGE);
END IF;
END WRITE_STRING;
Вуаля! Graphviz дает возможность делать потрясающие визуализации с минимальными затратами.
Комментарии (8)
AlexVist
04.09.2017 12:27Я в своем проекте сппр так же использую Graphviz. Это позвояет визуализировать логическую структуру. Так же следует упомянуть о других возможностях. Это использование svg формата. Что позволяет визуализировть в браузерах (более удобно) и возможностях гипер-ссылок. Что позволяет сделать отображение еще и интерактивным.
raydac
04.09.2017 12:33решение интересное, правда риски всё теже — разъедется содержимое псевдокода с реализацией при активной разработке
kspksp Автор
04.09.2017 12:34Согласен. Актуальность комментариев в коде тоже надо поддерживать.
AlexVist
04.09.2017 12:56Так же есть возможность в блоке данных выводить дополнительную информацию. Это могут быть и комментарии. Визуально выглядит как два блока текста разделенных чертой горизонтальной или вертикальной. Правда не проверял наифигурах отличных по форме от прямоугольных.
kspksp Автор
04.09.2017 14:44Мне кажется это не совсем так. Есть два типа блока, с помощью которых можно выводить данные в виде таблицы:
shape=record|Mrecord
. Отличие второго от первого — скругленные наружные углы. Больше ни в каких типах блоков сделать столбцы/строки нельзя.
flatscode
04.09.2017 16:33+1Часто блок-схемы (Activity Diagram) составляю с помощью plantuml, который для некоторых случаев использует graphviz под капотом.
У plantuml, по-моему, язык попроще.
Такой текст:
@startuml start if (Graphviz installed?) then (yes) :process all\ndiagrams; else (no) :process only __sequence__ and __activity__ diagrams; endif stop @enduml
Отрисует такую диаграмму:
Так же есть плагины для использования в IDE от Jetbrains.
Еще пара-тройка примеров
habradante
04.09.2017 16:55Используем Graphviz + PlantUML для авто генерации диаграмм классов и для составления документации (Sequence Diagram). Очень удобно для составления документации по проекту.
MetaDone
Graphviz еще используется в https://symfony.com/doc/current/components/workflow.html
Удобно и наглядно получаются графики возможных переходов состояний у объекта