Автоматическая визуализация python-кода. Часть третья: новые возможности графического представления кода

    Ссылки на предыдущие части:

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

    Пример среды, поддерживающей такое графическое представление показан на картинке ниже.

    image

    Среда, поддерживающая графическое представление кода

    В третьей части статьи речь пойдет о новых возможностях графического представления кода.

    Мелочи


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


    Контекстное меню выбранных графических элементов

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

    В случае выбора одного из первых двух пунктов меню демонстрируется дополнительный диалог для выбора цвета или ввода текста соответственно. После завершения ввода в исходный текст добавляются/модифицируются необходимые cml комментарии и вся диаграмма немедленно перерисовывается с учетом изменений.

    Подавление примитивов


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

    Были определены следующие кандидаты: строки документации, комментарии и блоки except. Для управления подавлением примитивов на панель инструментов графического представления добавлены три кнопки, каждая из которых может находиться в одном из двух положений: нажата/отжата.


    Управление подавлением примитивов на диаграмме

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

    Подавление строк документации


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


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

    Однако строки документации не являются обязательными, и в случае, если разработчик не позаботился о документации, Codimension не рисует соответствующую секцию совсем. Например:


    Функция без строки документации

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


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

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

    Подавление комментариев


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


    Комментарии показаны


    Комментарии подавлены

    Подавление блоков except


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


    Два показанных блока except


    Подавленные блоки except

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

    Умное масштабирование


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

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


    Управление умным масштабированием

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

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

    Уровень 0


    Это уровень максимальной детализации. Показаны все графические элементы.

    Уровень 1


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


    Умное масштабирование: уровень 1

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

    Уровень 2


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


    Умное масштабирование: уровень 2

    Уровень 3


    На этом уровне на диаграмме остаются только классы и функции. Такое отображение задумывалось как «взгляд с высоты птичьего полета», только крупные объекты в модуле остаются видимыми.


    Умное масштабирование: уровень 3

    Больше уровней


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

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

    Группы


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

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

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

    CML для групп


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

    # cml 1 gb id=101 title="Module imports"
    import sys
    import logging
    import json
    # cml 1 ge id=101
    

    Первый комментарий имеет код gb (от слов group begin) и располагается перед первым элементом группы. Второй комментарий имеет код ge (от слов group end) и располагается после последнего элемента группы. Codimension понимает, что комментарии парные по значению обязательного атрибута id, который может быть произвольной строкой.

    Очевидно, что для формирования группы есть ряд ограничений. Группа должна иметь один вход и один выход. При выделении элементов для группы на графике, все они должны быть выделены без пропусков. Если выделено условие if, то все ветки также должны быть выделены. Для циклов похожее требование связано с конструкцией else: если она присутствует, то должны быть выделены обе части, и сам цикл и его else блок. Аналогично нельзя разрывать составные части try-except-else-finally. Все эти ограничения учитываются, когда интерфейс пользователя разрешает выполнить группировку.

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

    item = self.__processes[index]
    if item.widget:
        # cml 1 gb id=102 title="Script started"
        msg = item.widget.appendIDEMessage('Script started')
        item.procWrapper.startTime = msg.timestamp
        # cml 1 ge id=102
    

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

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

    Графика для групп


    Для отрисовки групп требуются три варианта примитивов: свернутая группа, раскрытая группа и пустая группа.

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


    Свернутая группа

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

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


    Раскрытая группа

    В левом верхнем углу раскрытой группы нарисована ее «чувствительная точка». Когда курсор мыши находится над ней, обводка группы рисуется сплошной линией, а над группой показывается ее заголовок.


    «Чувствительная точка» раскрытой группы

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

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


    Пустая группа

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

    Управление группами осуществляется из контекстного меню. Для создания группы выделяются нужные примитивы, а затем из контекстного меню выбирается пункт Group… После ввода заголовка группы нужные CML комментарии добавляются в код и диаграмма немедленно перерисовывается. При этом вновь созданная группа рисуется в свернутом виде.

    Все остальные манипуляции с группами — раскрытие, скрытие, удаление, редактирование заголовка, смена цветов — выполняются по выбору из контекстного меню группы.

    Как попробовать


    Попробовать новую функциональность можно установив Codimension IDE. Codimension поддерживает Linux и Mac. Инструкции по установке доступны на codimension.org
    Поддержать автора
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 11

      0

      Похоже на редактор leo. В свое время он мне очень нравился, но пришлось прекратить им пользоваться, так как сам редактор текста в блоках был довольно примитивен. Но сама концепция Literate Programming и ее реализация в Leo мне очень нравится.

        0

        Блин, вот бы под винду. И ещё такой же бы для JS. Я бы купил, вероятно, оба.

          +1
          github.com/alexmojaki/birdseye
          Не идеально то (тут в первую очередь для отладки), но весьма схоже.
            0
            Вы правы, технологию можно адаптировать к любому языку. Нужен только парсер, который представит текст программы в таком же виде, как я сделал это для питона.

            Однако у меня нет планов разработки парсера для JS, и я не планирую портирование на Windows. Коммерческий проект, разумеется, возможен. Но для этого нужно, чтобы какая-нибудь большая компания заинтересовалась, например майкрософт, и добавила технологию в свои коммерческие продукты. Индивидуально я не смогу сделать IDE коммерческим продуктом.
              0
              технологию можно адаптировать к любому языку
              А можно что-то сделать с метапрограммированием? Шаблоны, макросы…
                0
                На мой взгляд шаблоны выходят за рамки предложенной технологии. Их можно отображать как блоки кода.

                А вот макросы и вообще препроцессор — это большая проблема. Я, в основном, использую C/C++, но сделать Codimension для этих языков не решился. И парсер сложнее, и так и не придумал ничего хорошего для препроцессора, когда получаются совсем странные конструкции — например, директивы препроцессора могут запросто приходить из командной строки. Теоретически можно было бы прогонять файлы через препроцессор и компилятор и потом как-то вытаскивать информацию о структуре, но это будет медленно и не будет такой интерактивности, как это удалось сделать для питона. К тому же работы слишком много для одного человека, а результат не гарантирован. В теории можно, а на практике слишком сложно.
              0

              Возможно, стоит попробовать leo-editor. Это немного другое, но идея похожая. И, насколько я помню, в leo можно писать на любом языке.

              +1

              Думаю if then else лучше сделать вертикальным к тому же это лучше для case (switch) или сопоставления с образцом. https://docs.google.com/drawings/d/1Ymw1gbfFLMiV2_HhvnqXg_jtRqY-0FFQi_rhJ-k1qzo/edit?usp=sharing

                0
                Для случая, когда действия в каждой ветке короткие, как в вашем примере, я согласен — ваш пример выглядит привлекательно. Но в реальной практике сложность кода в каждой ветке может быть произвольной, а это означает, что горизонтальные соединители нескольких веток условия будут на значительном расстоянии по вертикали друг от друга. Соответственно зависимость условий хуже отображена на графике. Я рассматривал этот вариант, когда думал над графическими примитивами и предпочел тот, который реализован сейчас.

                С другой стороны, я признаю, что и у реализованного мной варианта есть недостатки. Но чего-то лучшего пока найти не удалось.
                0

                Когда планируется поддержка Windows или, может быть, онлайн редактор?

                  0
                  У меня таких планов нет.
                  Теоретически портирование на Windows может быть выполнено относительно легко, но нужно чтобы кто-нибудь за это взялся. Я могу помочь с ответами на вопросы и подсказать с чего и как начать, но основная работа ляжет на волотера. Мое рабочее окружение почти Windows free и я не планирую его менять.
                  С онлайн редактором, мне кажется, это скорее утопично.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое