`

СПЕЦІАЛЬНІ
ПАРТНЕРИ
ПРОЕКТУ

Чи використовує ваша компанія ChatGPT в роботі?

BEST CIO

Определение наиболее профессиональных ИТ-управленцев, лидеров и экспертов в своих отраслях

Человек года

Кто внес наибольший вклад в развитие украинского ИТ-рынка.

Продукт года

Награды «Продукт года» еженедельника «Компьютерное обозрение» за наиболее выдающиеся ИТ-товары

 

Rigi, или Один из путей к пониманию

+11
голос

Программист становится частично -- историком, частично -- детективом и частично -- ясновидящим.
Томас А. Корби, IBM

Естественно, вполне допустимо думать, что современный "программист-одиночка" невозможен исключительно по причине недоступной для одиночки стоимости процедур проверки его творений на предмет патентной чистоты (думать вполне допустимо вообще, а так думать -- вполне допустимо в частности). Но давайте на секунду задумаемся и о другом -- о том, что любой программист, даже работающий в коллективе, все равно в каком-то смысле остается одиночкой. И даже не в одном "каком-то" смысле. Только о низкоуровневом программисте-кодировщике, трансформирующем спецификации модулей или функций невидимого для него в целом проекта в код, можно говорить как о "винтике большой машины", что исключает подчеркнутый индивидуализм слова "одиночка" (ну какой же это "одиночка", которому в любой момент можно найти замену). Но как только порожденный "винтиками" код проживет своей "жизнью" некоторое время, приобретет статус legacy, тут-то и начнется самое интересное. Винтики-авторы давным-давно позабыты, сменили работу и даже профессию, а код продолжает "жить". В него надо вносить изменения -- добавлять (или наоборот, сокращать) функциональность, исправлять ошибки. К этой работе привлекаются новые специалисты -- и каждый из них в большинстве реальных (некнижных) проектов непременно проходит этап "одиночки". Хотя бы потому, что любой занятый сопровождением чужого кода программист в начале этой своей работы остается с исходными кодами чужих программ один на один. Естественно, существуют исключительные legacy-проекты, качество документирования которых позволяет программисту-новичку (не в профессиональном смысле) увидеть проект в целом и в благодарность предшественникам использовать ставшее идиоматическим высказывание сэра Исаака Ньютона о плечах титанов. Но такие проекты являются скорее исключениями из правил. В проектах же, соответствующих правилам, программисты-новички используют куда менее пафосную и совсем уж ненаучную идиоматику. Возможно, современные принципы проектирования ПО и ведения проектной документации ситуацию изменят к лучшему, но это изменение "почувствуется" тогда, когда созданный на их основе современный код сам станет legacy. Пока же программист-одиночка вынужден самостоятельно сражаться со сложностью и некачественным документированием унаследованных программ. И даже если таких одиночек в проекте будет использовано много, на достаточно продолжительном временном участке они так и останутся одиночками, пытающимися из разрозненных и полученных эмпирическим путем "проекций" восстановить видение всей системы в целом.


Восстановление структуры

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

Например, в считающемся каноническим издании "Практика программирования" (авторы -- Брайан Керниган и Роб Пайк) вопросам документирования, точнее, комментирования кода, уделено не так уж много внимания. "Назначение комментариев -- помогать читателю программы. Комментарии не должны повторять то, что очевидно в коде программы, не должны противоречить коду или отвлекать внимание читателя искусным оформлением. Высшее предназначение комментариев -- оказание помощи в понимании программы благодаря кратким описаниям скрытых деталей или высокоуровневых механизмов обработки" (недословный перевод автора статьи). В более чем неплохой современной и менее ориентированной на программистов-кодировщиков книге "The Pragmatic Programmer" (A. Hunt, D. Thomas) специальному обсуждению процессов документирования не посвящено ни одной главы. Если Керниган и Пайк отнесли вопросы документирования (комментирования) к стилю программирования, то авторы "Прагматичного программиста" прагматично решили, что с документированием программист должен разбираться сам. Можно, конечно, списать эти отдельные недостатки отдельных книг на их "сугубо программистский" характер. Дескать, вопросы документирования -- не дело программистов, этим должны заниматься системные инженеры и архитекторы. Но, во-первых, архитекторы вырастают именно из программистов, да и, во-вторых, авторы современных книг тематики "software engineering" документированию проекта также уделяют не очень много внимания.

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

Такой "традиционный подход" к документированию (если вообще можно называть подходом либо практически полное игнорирование документации, либо определение ее как вопроса стиля) принято называть низкоуровневой техникой документирования (documenting in the small). Назначение низкоуровневой документации вполне очевидно из приведенных выше наставлений Кернигана и Пайка, а вот объектами процесса документирования в этом случае в основном являются применяемые нетривиальные алгоритмы и структуры данных. Техника высокоуровневого документирования (documenting in the large), напротив, предназначена не столько для программистов, работающих с кодом, сколько для системных администраторов, архитекторов и инженеров, обеспечивающих использование программного продукта. В большинстве случаев унаследованная "высокоуровневая" документация ориентирована именно на разных специалистов этих классов и посему представляет собой описания различных аспектов или изолированных подсистем программы, но не дает архитектурной картины всей системы в целом.

Естественно, уделять столь пристальное внимание вопросам документирования жизненно важно не всегда. Но именно в тех случаях, когда оно действительно необходимо, оно не так уж и часто встречается. Речь идет о больших унаследованных программных системах, для которых многие специалисты оценивают нижний порог, с которого становится справедливым термин "большая система", в 100 тыс. строк кода. Кстати, термин "строка кода" (дословный перевод -- "физическая строка кода", PSLC -- Physical Source Line of Code) имеет весьма точную формулировку, и на его основе строятся формальные механизмы определения сложности программ (такие как метрики, рекомендованные Институтом программной инженерии Carnegie Mellon University, -- SLOC).

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


Инструмент понимания

Проект Rigi (rigi.uvic.ca/index.html), результатом которого является предлагаемая вниманию читателя одноименная программная система, -- не однодневка, но и не нечто академически-заумное. Команда разработчиков во главе с доктором Хази Мюллером (Hausi A. Maller) ставила перед собой абсолютно реальные задачи: создать простой в использовании, удобный, относительно несложный в реализации и при этом гибкий кросс-платформенный инструмент, облегчающий программисту (или системному инженеру) понимание больших унаследованных (legacy) программ. Надо сказать, что и текущая версия (5.4.1), и размеры инсталляционного файла (порядка 2,2 MB для платформы Windows -- следует учесть, что Rigi разработана на основе языковых средств системы Tcl/Tk и включает ее среду времени исполнения) если не подтверждают, то иллюстрируют "унаследованный" характер самой Rigi. Немного перефразируя девиз создателей Rigi, назовем эту программу "интерактивной визуальной legacy-системой для понимания legacy-систем" (a visual tool for understanding legacy systems).

Архитектурную модель Rigi можно укрупненно отобразить в виде двух основных взаимодействующих компонентов -- редактора графов rigiedit и набора "подстегиваемых" к нему программ-препроцессоров или модулей синтаксического и грамматического разбора (parsers). Функциональность такого скромного комплекта также вполне очевидна. Сначала препроцессоры или программы разбора трансформируют нечто (например, исходные тексты изучаемых программ) в промежуточное представление. Цель этого этапа -- выделить из исследуемого потока данных некоторые структурные элементы и неупорядоченную информацию об их взаимосвязях. В случае когда поток данных формируется исходными текстами программ, такими элементами могут быть константы и переменные, модули, функции (или процедуры), классы и объекты и т. д. Впоследствии выделенные множества структурных элементов и взаимосвязей используются интерактивным редактором графов rigiedit для визуализации, аннотирования, документирования и графического изображения графа, отражающего некоторые аспекты структуры исследуемой системы.

Казалось бы, ничего принципиально нового в Rigi нет. Но на самом деле вся соль этой разработки заключаеться не в крайне простой высокоуровневой архитектуре, а в функциональности редактора графов rigiedit. Во-первых, rigiedit обеспечивает удобное выделение и группировку структурных элементов (вершин графа) и отображение такого сгруппированного "суперэлемента" одной вершиной. Это ведет к резкому сокращению визуального представления архитектуры исследуемой системы и позволяет говорить о поддержке механизма формирования абстракций в ходе реинжиниринга. Так, группировка структурных элементов может производиться как на основе "очевидных" критериев, навязанных существующей реализацией системы (таковым является, например, принадлежность к явно выделенным элементам структуры типа отношений "функция содержится в модуле"), так и на основе критериев-гипотез -- скажем, об использовании группы разрозненных переменных и констант для описания свойств определенного, явно не выраженного объекта. Последнее исключительно важно: во многих случаях задачи реинжиниринга legacy-систем надо решать не только для поддержания нормального эволюционного процесса их функционирования, но и для частичной или полной модернизации отдельных подсистем. И именно в этом случае обеспечиваемый Rigi стиль работы изучающего программу специалиста "что будет, если?" может позволить найти неожиданно красивые решения.

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

И наконец, главное. В задачах визуализации больших графов самое ценное -- это, естественно, алгоритмы визуализации. Если граф состоит из нескольких тысяч вершин и десятка тысяч ветвей, никакой ценности его отображение в виде равномерного месива из точек и отрезков линий, представлять не будет. Rigiedit предлагает исследователю очень мощный (но чувствительный к числу вершин графа) алгоритм Сугийямы (Sugiyama), в результате применения которого к графу в его изображении минимизируется число пересечений ветвей. Кроме него, rigiedit поддерживает алгоритмы так называемых обзорных режимов, включая и нелинейное масштабирование -- "рыбий глаз".

Внимательный читатель к этому моменту должен заметить, что, несмотря на то что данная статья ориентирована именно на решение задач реинжиниринга legacy-программ с доступными исходными текстами, описание специфических возможностей Rigi по анализу программных систем ограничивалось упоминанием о наличии в архитектуре подсистем синтаксического и грамматического разбора. В качестве дополнительного уточнения стоит сообщить разве что о включении в дистрибутив Rigi анализаторов (parsers) для языков С и Cobol, наиболее распространенных в программных системах класса legacy. Необходимую информацию заинтересованный читатель может получить из документации проекта Rigi, благо она более чем неплоха. Мы же подчеркнем универсальность rigiedit: так как входной язык описания структурных элементов и взаимосвязей для него элементарен (файл, состоящий из строк, содержащих тройки понятий "действие субъект объект"), вся система в целом может использоваться для решения любых задач. Например, для анализа дерева зависимостей в дистрибутивах операционных систем.

Особого внимания заслуживает и "врожденная" способность Rigi к расширению функциональности базовой системы пользователем. Особого не потому, что это свойство уникально (упоминания Tcl/Tk вообще-то вполне достаточно для сообщения о такой способности), а потому, что наращивать функциональность системы Tcl-скриптами (которые в Rigi называются RCL-скриптами) элементарно, а для изучения немногим более тридцати специализированных Tcl-функций, являющихся ядром rigiedit и отображенных на интерактивные команды редактора, требуется буквально час.

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

Ready, set, buy! Посібник для початківців - як придбати Copilot для Microsoft 365

+11
голос

Напечатать Отправить другу

Читайте также

 

Ukraine

 

  •  Home  •  Ринок  •  IТ-директор  •  CloudComputing  •  Hard  •  Soft  •  Мережі  •  Безпека  •  Наука  •  IoT