[Из песочницы] Автоматическая визуализации python-кода с использованием блок-схем

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

image

Общий вид среды с альтернативными представлениями кода

Здесь окно среды разработки разбито на две части. Слева — привычный текстовый редактор, а справа — автоматически генерируемая диаграмма, по возможности приближенная к традиционным блок-схемам алгоритмов. Генерация и перерисовка диаграммы производится по ходу набивки текста. Среда разработки определяет паузу в действиях разработчика и обновляет диаграмму, если код остается корректным. В результате появляется возможность работы не только с текстом программы, но и с его графическим представлением.

Блок-схемы в дикой природе


А нужны ли блок-схемы вообще?

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

  • создание нового программного обеспечения с чистого листа
  • поддержка и модификация уже существующих программных продуктов

Я использую блок-схемы в обоих случаях, хотя и слегка по-разному.

В случае нового ПО я обычно использую подход «сверху вниз». Сначала рисуется архитектура в виде абстрактных блоков и действующих лиц, затем отдельные подсистемы прорабатываются более детально, в какой-то момент достигая уровня выбранного языка программирования. Разумеется, я не прорисовываю детально абсолютно все, а только те части, которые представляют затруднения или особый интерес. Имеющиеся на рынке ПО инструменты вроде MS Visio помогают мне рисовать диаграммы, но только на высоком уровне абстракции. Идеальный инструмент, если бы таковой имелся, должен был бы помогать и на уровне языка программирования, желательно в двух направлениях: генерация диаграммы по коду и наоборот, кода по диаграмме.

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

Для полноты картины имеет смысл обратить внимание и на крупные проекты, широко использующие диаграммы в промышленном производстве ПО. Имеются ли таковые? Ответ на этот вопрос — да. Наверное, самый крупный проект такого сорта, известный мне, это ПО для многоразового космического корабля Буран. В отличие от американских многоразовых кораблей, советский был не пилотируемым, а значит вся нагрузка по управлению легла на ПО, которое было разработано с использованием языка ДРАКОН. ДРАКОН использовал исключительно графические диаграммы на всех этапах проектирования, а разработчики не работали с традиционным текстом вообще. Проект доказал высокую надежность ПО успешным выходом на орбиту и возвращением корабля. В отчетах о результатах работы отмечается тот факт, что высокая скорость разработки и небольшое количество ошибок обусловлены широким применением диаграмм. И сейчас ДРАКОН используется для создания ПО в космической отрасли. К сожалению, некоторые ограничения технологии не дают возможности использовать все наработки ДРАКОНа в повседневной работе разработчика, пишущего на популярном языке программирования. Однако общий вывод можно сделать: диаграммы, подобные блок-схемам алгоритмов полезны и могут дать существенный выигрыш.

image

Пример диаграммы языка ДРАКОН (с сайта drakon.su)

Инструментарий


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

Увы, готового инструмента, похожего на описанный найти пока не удалось. Существуют хорошие пакеты для инженерной графики, такие как Dia или MS Visio, которые очень хороши в той области, для которой они проектировались. Они помогают на некоторых стадиях, но их очень трудно использовать тогда, когда требуются частые изменения. Есть пакеты, нацеленные на стадию дизайна — например UML инструменты —, но их неудобно использовать на низком уровне. Есть различные кодогенераторы для разнообразных предметных областей, но сгенерированный код трудно назвать легко читаемым если вообще предназначенным для чтения. Есть графические инструменты, ориентированные только на конкретную предметную область, но их практически невозможно использовать в проектах общего назначения, зачастую код вообще не доступен в таких инструментах.

Если такого инструмента нет, то может быть стоит заняться разработкой технологии, которая позволит его создать? Дальнейшее обсуждение будет о технологии и экспериментальной среде, реализующей ее. Среда позволяет посмотреть на существующие проекты как на текст и как на графику с автоматической синхронизацией между ними. Реализация сделана для языка Питон и, в основном, на Питоне.

Графические примитивы


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

Обсудим все необходимые примитивы по порядку.

Блоки кода


Очевидно, что не все операторы непосредственно влияют на поток управления. Такие операторы можно нарисовать как блоки кода.

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

Что касается примитива, то разумным кажется простой прямоугольник. Примеры ниже показывают один блок кода и два блока, следующих один за другим с разницей в коде в одну пустую строку между операторами (здесь и далее: для всех примеров сначала следует фрагмент кода на Питоне серии 2, а за ним предлагаемое графическое представление).

c = MyClass( 154 )
c.member = f( 17 )
c.doSomething()
print c

image
Один блок кода
c = MyClass( 154 )
c.member = f( 17 )

c.doSomething()
print c

image
Два блока кода один за одним

Комментарии


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

Независимые комментарии занимают одну или более соседних строк и отделены от всего остального по крайней мере одной пустой строкой. Строки независимых комментариев не содержат ничего, кроме комментариев.

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

Боковые комментарии располагаются справа от операторов. Здесь есть несколько важных деталей. Часто блок кода занимает несколько строк, тогда как разработчик может дать боковой комментарий только к некоторым из них. Это обстоятельство при выборе графики должно быть учтено. Еще одна деталь касается последней строчки блока кода: разработчику может понадобиться больше, чем одна строка комментариев для нее. Такой случай также должен быть учтен в графике.

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

Теперь можно подобрать подходящую графику для распознаваемых типов комментариев.

Независимые комментарии


a = 154

# Line 1
# Line 2

b = a

image
Независимый комментарий

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

Лидирующие комментарии


# Line 1
# Line 2
a = 154
b = a

image
Лидирующий комментарий

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

Боковые комментарии


a = 154
b = a       # No comment for the first line
c = b + 1   # Comment for c
            # A tail -----^

image
Боковой комментарий с «хвостом»

В случае с боковым комментарием требуется внимание к паре моментов. Во-первых, есть визуальное соответствие между строчками кода и комментариями. В примере выше нет комментария к первой строчке, и такие ситуации должны быть учтены в графике. Другими словами строки в прямоугольнике комментария должны быть по вертикали выровнены точно так же, как они выровнены в тексте. Во-вторых, иногда комментарий к последней строчке кода занимает больше чем одну строчку. Признаки такого «хвоста» взяты такими:

  • строка хвостового комментария следует непосредственно за предыдущей (нет пустых строк)
  • символ # находится в той же позиции, что и в предыдущей строке

Импорты


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

# Leading comment for import
from os.path import sep, \
                    isdir       # Side comment

from x import ( y,         # side for y
                name )     # side for name

image
Пример import

В примере второй и третий импорты занимают более одной строки, некоторые из которых снабжены боковыми комментариями.

Оператор if


Обсудим как должен выглядеть на графике блок условия. Традиционные блок-схемы алгоритмов предлагают ромб. Ромб отлично подходит, если условие, вписанное в него, короткое. На практике, однако, условия часто длинные и порой занимают больше, чем одну строчку, что делает сложной задачу вписать все условие в ромб разумного размера. Либо ромб становится слишком большим и отнимает много ценного вертикального пространства, либо шрифт приходится делать слишком мелким, либо надо прибегать к сокращениям в исходном тексте. Компромиссное предлагаемое решение такое: левые и правые грани будут от ромба, а верхние и нижние грани станут горизонтальным ради сохранения места по вертикали. То есть графика будет частично напоминать традиционный ромб. Такой графический примитив можно легко масштабировать в зависимости от сложности условия.

Следующая деталь для обсуждения — это как рисовать ветки yes и no. Один из возможных вариантов нарисовать ветки справа и слева от блока условия. Такой подход, к сожалению, может привести к ситуации, когда полная диаграмма будет трудна для чтения и не будет выглядеть красиво. Проблема в том, что ветви могут быть произвольной сложности, что приводит к большой ширине ветвей и горизонтальному смещению блока условия. В результате при просмотре потребуется и вертикальная и горизонтальная прокрутка, чего хотелось бы, по возможности, избежать.

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

if 154 > 153:
    print "Well, yes"
else:
    pass

image
Простой пример оператора if

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

# Leading for ‘if’
if ( 154 > 153 and        # Side 1
     1 > 0 ):             # Side 2
    print "Well, yes"
# Leading for ‘else’
else:
    pass

image
Оператор if с комментариями

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

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

Функции


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

Одна из идей, которые приходят в голову при размышлении о графике для функций, касается областей видимости. Область видимости играет роль пространства с очерченными границами. У любой функции, очевидно, есть совершенно определенные точки где она начинается и заканчивается. Значит и графика для функций может напоминать замкнутую область, внутри которой содержится графическое представление тела функции. Делая шаг немного в сторону можно вспомнить, что когда просматриваешь незнакомый Питон код, часто не сразу понятен контекст: конкретная строчка кода может быть и внутри вложенных функций, и внутри классов и внутри условных конструкций. Идея с очерченными границами области видимости потенциально дает возможность быстрее понять контекст выполняемых действий.

Посмотрим сначала на простой пример предлагаемой графики.

def f( x ):
    print "Function f( x )"

image
Графика для функции

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

Теперь рассмотрим более сложный пример, в котором у функции есть лидирующий комментарий, есть строка документации, а параметры занимают более чем одну строчку и также прокомментированы.

# Leading comment
def g( x,     # x - first argument
       y ):   # y - second argument
    """ Docstring """
   print "Function g( x, y )"

image
Функция с комментариями и документацией

Графика лидирующего комментария очевидна, тогда как боковой комментарий для аргументов представляет проблему. Из-за того, что строчки бокового комментария должны быть выровнены по вертикали со списком аргументов, самым логичным оказалось поместить прямоугольник комментария непосредственно в заголовок функции. Не могу сказать, что предложенное решение кажется мне идеальным, но оно покрывает все случаи корректного Питон кода и не допускает неоднозначности.

Для документации заголовок области видимости расширен еще одной горизонтальной секцией, которая следует сразу за секцией прототипа функции.

Оператор return


Традиционные блок-схемы предлагают удачную графику для возвратов, которой можно воспользоваться с небольшими усовершенствованиями. Возьмем простой пример:
def f( x ):
    return x * 154

image
Простой return

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

Разумеется, операторы return могут занимать больше одной строчки и могут иметь комментарии. Ниже приведен пример для такого случая.

def f( x ):
    # Return leading
    return ( x * 154 +    # Side 1
             X / 154 )    # Side 2

image
Многострочный return с комментариями

Классы


После того как идея областей видимости была использована для функций, ее применимость к классам выглядит более чем логичной. Графика для классов может быть такой же за исключением другого цвета фона и беджа. Пример ниже иллюстрирует класс с комментариями и строкой документации.
# Leading
class C( ClassA,      # Side
         ClassB ):
    "Docstring"
   def __init__( self ):
        ClassA.__init__( self )
        self.__x = 0

image
Пример класса

Декораторы


В контексте функций и классов в Питоне могут появляться декораторы. По сути декораторы представляют собой оберточную функцию, то есть для их визуализации можно воспользоваться все той же идеей областей видимости. Для быстрой идентификации можно выбрать для них свой цвет фона и в бедж поместить символ @.
# Decorator leading
# comment
@decor( x, y )      # decorator
                 # side comment
def f():
    print "Function f()"

image
Декоратор с комментариями

Циклы


Питон поддерживает два типа циклов: for и while. Оба типа имеют условие и внутри могут встретиться операторы break и continue. Решение о графике для циклов было непростым и основывалось оно на следующих рассуждениях.

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

С другой стороны, циклы, подобно областям видимости, имеют совершенно определенные точки начала и конца. На роль заголовка области видимости хорошо подходит условие цикла, содержимое области видимости играет роль тела цикла. Еще одно соображение состоит в том, что в случае использования области видимости, идея отображения основных действий программы на одной вертикали выражена более явно, так как имеется замкнутая геометрическая фигура. Кроме того, соединители в случае традиционных блок-схем не отвечают принципу «сверху вниз» — выход из цикла находится справа от условия в начале. Еще одна проблема с традиционной графикой в том, что совершенно непонятно что делать с else частью, которая может появиться в Питон циклах.

Последнее соображение касается операторов break и continue. В случае использования области видимости точки, в которые ведут break и continue, становятся совершенно очевидным — нижняя и верхняя кромки прямоугольника. Тогда как в случае традиционных блок-схем необходимо рисовать соединитель, который в случае сложного разветвленного кода трудно нарисовать (если вообще возможно) так, чтобы диаграмма была очевидна и не было пересечений с другими соединителями.

Используя идею области видимости для циклов, вопрос с ведущими и боковыми комментариями тоже становится уже решенным.

for x in [ 1, 17, 42, 154 ]:
    print x

image
Цикл for

В более сложных случаях цикл может иметь комментарии и блок else. Рассмотрим пример ниже.

x = 0
# While loop leading comment
while x < 154:     # while side
                   # comment
    x += 1
# else leading comment
else:              # else side comment
    pass

image
Цикл while с else блоком и комментариями

Блок else нарисован в виде отдельной области видимости справа от области видимости цикла. Области видимости соединены друг с другом пунктирной линией для того, чтобы подчеркнуть тесную ассоциацию между ними. Комментарии показаны уже знакомым образом. А бедж области видимости блока else перемещен с границы в заголовок. Иначе заголовок остается совершенно пустым и смотрится не так изящно.

Операторы break и continue


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

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

while True:
    if True:
        continue
    else:
        break

image
Простой пример break и continue

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

while True:
    if True:
        # Leading 1
        continue     # Side 1
    else:
        # Leading 2
        break        # Side 2

image
Операторы break и continue с комментариями

Try, except, else, finally


Наверное, это самая сложная конструкция в Питоне. Помимо try блока возможно наличие множества except блоков и необязательные else и finally блоки. Поскольку каждый из этих блоков имеет собственное тело, то было решено использовать графику области видимости для каждого из них.
try:
    a = x / y
except ZeroDivisionError:
    print "?"
else:
    print "a = ", a
finally:
    print "finally"

image
Пример try — except — else — finally

Блоки except предназначены для обработки ошибок, а значит лежат вне основной линии выполнения. Поэтому они располагаются справа от блока try. С целью дополнительного акцента на тесную связь между try и except блоками между ними проведена пунктирная линия. Если бы было более одного блока except, то диаграмма «выросла» бы вправо, где блоки except располагались бы один за одним.

Блоки else и finally скорее принадлежат основной линии выполнения программы, поэтому на диаграмме они следуют за try блоком.

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

Оператор with


Оператор with определяет контекст выполнения, поэтому для него как нельзя лучше подходит идея областей видимости.
# Leading
with open( "my-data.txt" ) as f:    # Side
    data = f.read()
    print data

image
Оператор with

Оператор raise


Нет сомнений, что генерация исключения имеет сильнейшее влияние на поток управления. Поэтому графика оператора raise должна быть такой, чтобы привлекать внимание даже при поверхностном взгляде. Еще одно соображение, которое имеет смысл принять во внимание состоит в том, что у оператора raise есть общие свойства с оператором return: оба ведут к выходу из текущей области видимости. Исходя из этого принято решение использовать для raise ту же графику, что и для return с измененной иконкой в левой части — raise будет иметь бросающуюся в глаза красную стрелку.

Как обычно, оператор raise может занимать несколько строк и иметь ведущие и боковые комментарии.

# Leading
raise Exception( "first line "     # Side 1
                 "Second line" )   # Side 2

image
Оператор raise

Assert


Оператор assert генерирует исключение условно, то есть может влиять на поток управления аналогично оператору raise. Исходя из этого на графике для assert хотелось оставить иконку с красной стрелкой как у raise, но подчеркнуть условность генерации исключения.
assert x == 97

# Leading
assert type( x ) is IntType, \
       "x is not an integer"     # Side

image
Пример двух операторов assert

Условность исключения показана ромбом слева, в котором нарисована уже знакомая красная стрелка. Разумеется, оператор assert может иметь лидирующие и боковые комментарии. Этот случай показан для второго оператора в примере выше.

sys.exit ()


Строго говоря, вызов sys.exit () не является частью языка, однако вызов имеет непосредственное влияние на поток управления. Поэтому идея распознавания sys.exit () и отображение его подходящим образом кажется привлекательной.

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

if True:
    import sys
    sys.exit( 1 )

    from sys import exit
    exit( 2 )
else:
    from sys import exit as f
    f( 3 )

    from sys import *
    # Leading
    exit( 4 )    # side

image
Пример sys.exit ()

Конечно, есть также возможность сделать вызов sys.exit () через eval (), и такие варианты распознать затруднительно, однако они редки, а покрытие даже традиционных вариантов уже достаточно хорошо.

Вызов sys.exit () досрочно завершает выполнение программы, то есть является аналогом возврата, минующего все промежуточные уровни. Поэтому графика заимствована у оператора return, а иконка заменена на отражающую суть.

Файл


Последний элемент, для которого нужна графика, это отдельный файл. Питон файл имеет несколько атрибутов, которые необходимо показать на графике:
  • Строка документации
  • Кодировка
  • Указание для запуска

Естественным образом файл формирует область видимости, в которой находятся все остальные элементы. Пример ниже показывает размещение перечисленных выше элементов на графике для файла.
#!/usr/bin/env python
# encoding: utf-8

"""
A file docstring may occupy
a few lines
"""

print "Hello flowcharts"

image
Питон файл

Proof of concept: Codimension Python IDE


Теперь, имея хорошее представление о том, какие элементы языка необходимо распознать и как их отобразить на графическом представлении, можно приступать к созданию инструмента. Очевидно важным вопросом здесь является такой: каким образом текст и графика должны взаимодействовать друг с другом? Один из возможных путей — отказаться от текста вообще и использовать только графику. Этот подход был отвергнут сразу. Я убежден, что в зависимости от ситуации может выигрывать в наглядности или текст, или графика.

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

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

image
Общий вид Codimension Python IDE

Разработка Codimension IDE не начиналась с чистого листа. Некоторые идеи и часть кода были заимствованы от другой Питон IDE с открытыми исходными кодами: eric 4.

На настоящий момент Codimension реализует автоматическую отрисовку графического представления для произвольного Питон (серии 2) кода. Среда определяет паузу в набивке кода и перерисовывает диаграмму справа от текста. Если в какой-то момент код перестает быть синтаксически корректным, то диаграмма не обновляется, а индикатор состояния диаграммы по отношению к тексту меняет цвет на красный.

Также реализован показ пути через области видимости к той, которая находится под курсором мыши. Двойной щелчок по элементу на диаграмме приводит к переходу к соответствующему фрагменту в тексте. А комбинация клавиш, нажатая когда фокус ввода находится в текстовой части, наоборот, приводит к переходу и подсветке соответствующего графического элемента. Поддержаны функции экспорта диаграммы в популярные форматы SVG, PNG и PDF. Разумеется, здесь перечислены не все возможности IDE, а в планах новой функциональности для графического представления еще больше.

Во второй части будет рассказано о реализации Codimension IDE с акцентом на графическую составляющую. Будут описаны новые еще не реализованные возможности, микро язык разметки диаграмм и т.п.

Комментарии (1)

  • 23 января 2017 в 10:28

    0

    Было бы интересно получить такой инструмент, например, в виде плагина для PyCharm…

© Habrahabr.ru