gifts2017

Построение дерева вызовов процедур и функций

Опубликовал Сергей (TSSV) в раздел Программирование - Инструментарий

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

  Построение дерева вызовов проведения реализации в демо-базе "Управление торговлей, редакция 11.1 (11.1.2.10)":

 
  Порядок подготовки конфигурации к исследованиям:

1. Выгрузить модули исследуемой конфигурации

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

3. В начало процедуры УстановкаПараметровСеанса модуля сеанса добавить строку:
ПостроениеДереваВызовов.УстановитьПараметрыСеанса(Константы.ПостроениеДереваВызовов.Получить());

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

5. Загрузить обработанные файлы модулей в исследуемую конфигурацию

  Решение разработано для конфигураций на управляемых формах.

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

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

  Решение может быть полезным для:

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

  Во вложении - конфигурация с подсистемой "Построение дерева вызовов" и примеры построенных в демо-базе УТ 11.1.2.10 деревьев нескольких операций, в формате Excel:

- проведение документа "Реализация товаров и услуг";

- проведение документа "Заказ клиента";

- запуск конфигурации.

   Как это работает

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

  О возможных ошибках

 
Конечно, решение не может охватить всех возможных вариантов синтаксиса, которые могут встретиться в исследуемых алгоритмах. Критерием для меня являлось отстутствие ошибок формирования деревьев приведенных выше операций в типовой УТ 11.1. То есть, основная масса испльзуемых конструкций корректно отрабатывается подсистемой. Но наверняка ошибки встретятся  и тогда их исправление как правило не составляет большого труда (исправления вносятся непосредственно в коде исследуемой конфигурации). Вообще же написать алгоритм обработки текстов модулей для всех возможных случаев видится мне неоправданно сложным или даже не возможным. Легкий пример: в случае, когда вызов процедуры происходит из попытки и в вызванной таким образом процедуре происходит ошибка, то процедура прерывается "на полуслове", что приводит к ее завершению. Что делать с этим? Можно в отладчике отловить ошибку и вставить строку завершения модуля непосредственно перед оператором, на котором происходит ошибка (заглянув в тексты обработанных подсистемой модулей, вам сразу станет понятно о чем идет речь), по крайней мере я поступал именно так. Короче говоря, подсистема предоставляет инструмент, с помощью которого можно довольно просто решить задачу построения дерева, не претендуя при этом ни на что другое.
  Все значимые синтаксисческие конструкции помещены в подсистему "Тест" прилагаемой конфигурации. Если вам встретится конструкция, не отрабатываемая подсистемой и заслуживающая отдельного описания в алгоритме вставки служебных вызовов построения дерева (а если еще и вместе с предложением метода решения, то будет вообще замечательно), присылайте ее мне и я постараюсь включить ее обработку в подсистему.

  На этом все, хорошего кода!



 

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Построение дерева вызовов
.rar 83,35Kb
16.10.13
48
.rar 83,35Kb 48 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Сергей Сторожев (ssa) 16.10.13 10:32
Судя по описанию, полезная штука. Надо будет попробовать. Спасибо.
2. Евгений Сосна (pumbaE) 16.10.13 11:41
3. Tsaregorodtsev (TSSV) 16.10.13 12:18
(2) pumbaE, вещь похожая, но есть различия в деталях. В предлагаемом мной варианте есть время вызовов, разработана для УФ, обозначенная в вашей ссылке проблема ; решена изначально, так же есть возможность анализа циклов и условий (об этом в описании не написано, но скачав можно увидеть и такую возможность) и т.д. А вообще о существовании этой разработки я честно говоря не знал... Вобщем предлагаю свой вариант решения данной задачи.
4. Alever (Alever) 16.10.13 13:13
5. Сергей Марченко (MarSeN) 17.10.13 10:07
Штука клевая, однозначно +
как мысль по развитию.... (я правда не качал, но думаю что на первой итерации такое не делается :) )
Надо бы обрабатывать команды Выполнить и Вычислить. Оснобенно это важно для новой УТ11...
6. Tsaregorodtsev (TSSV) 17.10.13 19:41
(5) MarSeN,спасибо! Наличие конструкуции Выполнить не является проблемой, так как строится дерево реально отработавших процедур/функций. Если в Выполнить будет вызов процедуры или функции, то он отобразится в дереве как потомок вызова, в котором находится сама конструкция Выполнить. При этом делать сами конструкции Выполнить потомками процедуры/функции, в которой они находятся с текстом кода инструкции не составит никаких проблем и это хорошая мысль, так что спасибо еще раз!
7. Сергей Марченко (MarSeN) 18.10.13 09:07
(6) Tsaregorodtsev,
Да, об этом я не подумал... Действительно, текст модулей не парсится на предмет вызова процедур-функций. И это здорово! Данный метод действительно покрывает 100% всех вызовов, в отличии способа при котором частично выгружаются модули и обрабатываются (вариант, который реализован в статье комментария №2).
Сергей, на видео видно что все вызовы выстраиваются в дерево.
А как обрабатываются (отображаются в дереве) рекурсивные вызовы (рекурсивные процедуры/функции)? Не происходит зацикливания при построении дерева?
8. Tsaregorodtsev (TSSV) 18.10.13 10:24
(7) MarSeN, Рекурсивные вызовы отрабатываются корректно (ведь количество этих вызовов конечно). В формируемом дереве рекурсивный вызов будет иметь множество одинаковых подчиненных веток - по числу вызовов рекурсивной функции и при просмотре Вы будете видеть сначала первый вызов, потом, раскрыв его - второй и так далее. И Вы правы, задав этот вопрос - спасибо! Я тоже думал о том, чтобы анализировать код функции на предмет ее рекурсивности и ограничиваться выводом одной "внешней" ветки, а пока, встретив слишком "длинную" рекурсию, можно убрать из нее служебные строчки подсистемы.
9. Сергей Марченко (MarSeN) 18.10.13 11:00
(8) Tsaregorodtsev,
Спасибо!
Класная штука. Однозначно время потрачено не зря!
10. Alexander Khudoev (identificator) 18.10.13 14:17
В УТ 11.1 не показывается дерево.
11. Tsaregorodtsev (TSSV) 18.10.13 14:22
(10) identificator, можно более подробно - что происходит при этом и что Вы проделали?
12. Tsaregorodtsev (TSSV) 18.10.13 14:42
(10) identificator, сделаю предположение - я тоже в УТ 11.1 проводил тестирование. Возможно дело в том, что процесс построения зашел в рекурсию и там он может находиться довольно долго. Чтобы понять, где находится процесс в отладчике Отладка - Остановить, потом в стеке вызовов посмотреть где находится процесс. Если он действительно в рекурсивной функции, то просто уберите из нее вызовы процедур подсистемы.
13. Андрей Медведев (1cspbru) 18.10.13 15:42
Автор болшой молодец. Спасибо! То, что нужно для глубокого погружения в код. И ведь работает (ну почти:))))) на всех объектах. Идеей замерять через начало и окончание - очарован. Если бы не этот флажок, то была бы дикая куча хлама при замерах.

Молодец, однозначно +
14. Tsaregorodtsev (TSSV) 18.10.13 17:34
(13) 1cspbru, спасибо за такую "обратную связь", это очень ценно для меня!
15. Alexander Khudoev (identificator) 18.10.13 23:57
(12) Tsaregorodtsev, я 5-ый пункт забыл выполнить! Невнимателен был! По три раза считывал модули в каталоге, и теперь конфигурация умерла..
16. Максим Кулбараков (zlakizla) 21.10.13 05:39
Пытаюсь воткнуть дерево вызовов в БП 3.0, но во время обновления ИБ в самом конце постоянно лезут ошибки (последняя, которая была "ожидается имя формального параметра"). Может я что-то не так делаю?
1) Выгрузил модули конф-ии. Конфигурация->Выгрузить файлы конфигурации, выбираю все объекты и ниже ставлю галочку только на модули. Все выгружается в каталог.
2) Включаю возможность редактирования конф-ции и сравниваю/объединяю с конфой из файла. После объединения обновляю конфу.
3) В начало процедуры УстановкаПараметровСеанса модуля сеанса добавить строку:
ПостроениеДереваВызовов.УстановитьПараметрыСеанса(Константы.ПостроениеДереваВызовов.Получить()); Она у меня уже там есть... Причем кроме вызова этой процедуры там ничего нет. Пробовал и вставлять еще одну строку и без вставки :)
4) Захожу в пользовательском режиме, запускаю обработку "Вставить процедуры построения дерева вызовов", выбираю каталог с модулями и жму "Вставить процедуры дерева вызовов". Обработка благополучно вставляет в каждый модуль свои процедурки.
5) В конфигураторе загружаю обработанные модули. Конфигурация->Загрузить файлы конфигурации. Выбираю каталог и ставлю галочку на модули и для всех объектов.
6) После загрузки обновляю конфигурацию и захожу в ИБ. Начинается процесс обновления ИБ, который никак не доходит до конца и постоянно вылетает с какой-нибудь ошибкой.
17. Alexander Khudoev (identificator) 21.10.13 10:19
(12) Tsaregorodtsev, сделайте защиту "от дурака". Чтобы при повторном считывании выгруженных модулей возникало сообщение, что уже модули были считаны. Или возможность удалить строки из уже прочитанных модулей. Особенно полезно для больших конфигураций.
18. Tsaregorodtsev (TSSV) 21.10.13 11:34
(17) identificator, спасибо, тоже думл об этом - возможность удалить вставки и не обрабатывать файлы где уже есть вставки. Сделаю.
19. Tsaregorodtsev (TSSV) 21.10.13 12:01
(16) zlakizla, думаю ошибка в следующем. Вам нужно добавить в БП 3.0 только то, что относится к подсистеме ПостроениеДереваВыозовов. Тот факт, что

ПостроениеДереваВызовов.УстановитьПараметрыСеанса(Константы.ПостроениеДереваВызовов.Получить()); Она у меня уже там есть...

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

То есть, при сравнении - объединении нужно:
1. Конфигурация - Сравнить, объединить с кофнигурацией из файла, указать скачанный файл с подсистемой.
2. В открывшемся окне сравнения, снять галочку с корневого элемента, при этом все остальные галочки снимутся автоматически.
3. В этом же окне. Действия - отметить по подсистемам файла. Отметить только подсистему "Построение дерева вызовов" (в результате корневой элемент конфигурации будет отмечен полутоновой галочкой на сером фоне - на всякий случаай это отмечаю).
Далее как обычно.
20. Alexander Khudoev (identificator) 21.10.13 16:43
(18) Tsaregorodtsev, Сергей, не подскажите, как возвратить конфигурацию к первоначальному виду с возможностью корректного запуска? Исходную конфигурацию (в которой добавились строки ";ПостроениеДереваВызовов.") объединил с родительской конфигурацией и закомментировал все строки вида ";ПостроениеДереваВызовов.**". В том числе и в модуле сеанса. Но конфигурация не запускается все равно в режиме предприятия.
21. Tsaregorodtsev (TSSV) 21.10.13 17:52
(20) identificator, В конфигураторе, меню Конфигурация - Загрузить конфигурацию из файла - указать исходный файл конфигурации. Произойдет полная замена конфигурации. Не забудьте сделать бэкап перед этим, чтобы не потерять данные если что то пойдет не так.
22. Alexander Khudoev (identificator) 22.10.13 09:22
(21) Tsaregorodtsev, такой способ не подходит, так как в моей конфигурации было сделано много правок относительно функционала. А бэкапа не осталось.
23. Tsaregorodtsev (TSSV) 22.10.13 10:11
(22) identificator,случай тяжелый. Лучше конечно обратиться к специалисту за помощью. Нужно сделать следующее - найдите конфигурацию, которую дорабатывали (изначальный релиз УТ), объедините ее с той что у Вас получилась в части свойств конфигурации (имя, синоним, модуль управляемого приложения и пр.) и если у Вас там были доработки, то их придется восстанавливать по памяти - писать заново. Далее, через меню Правка - Глобальная замена - замените во всех модулях строку ";ПостроениеДереваВызовов." на "//;ПостроениеДереваВызовов." (без кавычек естественно). Получите результат максимально близкий к оригиналу из возможных в такой ситуации. Но все таки лучше Вам обратиться к специалисту.
24. Alexander Khudoev (identificator) 22.10.13 14:39
(23) Tsaregorodtsev, Сергей, я и есть специалист.
25. Сергей Марченко (MarSeN) 22.10.13 15:47
(24) identificator,
Если Вам нужно избавиться от вставок текста, которые сделаны подсистемой автора, попробуйте выгрузить все файлы модулей и воспользоваться какой-нить утилитой для поиска и замены текста в файлах.
26. Сергей Марченко (MarSeN) 22.10.13 15:51
(25) MarSeN, (24) identificator,
сори, ступил ) есть же глобальная замена. Об этом автор уже написал.
27. Сергей Марченко (MarSeN) 22.10.13 15:57
(22) identificator,
Если у Вас конфа не обновилась, то Вы можете вернуться к конфигурации БД. (Хотя если Вы пишите, что являетесь специалистом, значит проблема в чем-то другом)
в посте 16 Вы пишете
6) После загрузки обновляю конфигурацию и захожу в ИБ. Начинается процесс обновления ИБ, который никак не доходит до конца и постоянно вылетает с какой-нибудь ошибкой.

т.е. ИБ у Вас не обновлена, следовательно содержит предыдущий cf.
PS: и не забываем про бекапы
28. Tsaregorodtsev (TSSV) 22.10.13 16:58
(27) MarSeN,
6) После загрузки обновляю конфигурацию и захожу в ИБ. Начинается процесс обновления ИБ, который никак не доходит до конца и постоянно вылетает с какой-нибудь ошибкой.

речь скорей всего идет об обновлении ИБ в связи со сменой версии, так как были затерты свойства исходной конфигурации при добавлении подсистемы, то есть, при сравнении - объединении не был установлен отбор по подсистеме файла "Построение дерева вызовов".
29. Сергей Марченко (MarSeN) 22.10.13 17:07
(28) Tsaregorodtsev,
ааа) ну да, надо же внимательнее читать, что написано )
сори за получившийся флуд.
PS: больше надо отдыхать )
30. Саша Безымяный (help1Ckr) 23.10.13 10:59
За идею плюс, но вписывать в каждою процедуру код не вариант для типовых на поддержке
31. Олег Веселов (sml) 24.10.13 09:23
И зачем столько трудов, когда есть стандартный механизм 1С в конфигураторе:
Останавливать по ошибке -> стэк вызовов
identificator; +1 1 Ответить
32. Максим (Maxisussr) 20.01.14 17:05
Т.е. для того, чтобы она работала, придется в конец каждого из тысячи методов конфы (половина из них на поддержке с замком) вставлять вызов некоей процедуры - счетчика? А в чем смысл разработки?
33. Виктор Батарейкин (RockLeeSan) 19.10.14 19:20
Здравствуйте! Обнаружил ошибку, которая возникает при огромном количестве вызовов процедур или функций (более тысячи). Привожу текст кода до исправления и после:
1) Функция ВернутьСтрокуОбращенияПоИндексам(СтрокаДерева)
...
...
...
Для Каждого ЭлМассива Из МассивИндексов Цикл
СтрокаОбращенияПоИндексам = ".Строки[" + ЭлМассива+ "]" + СтрокаОбращенияПоИндексам;
КонецЦикла;

2) Функция ВернутьСтрокуОбращенияПоИндексам(СтрокаДерева)
...
...
...
Для Каждого ЭлМассива Из МассивИндексов Цикл
СтрокаОбращенияПоИндексам = ".Строки[" + СтрЗаменить(СокрЛП(ЭлМассива),Символы.НПП,"") + "]" + СтрокаОбращенияПоИндексам;
КонецЦикла;


Как видно из текста, переменная "ЭлМассива" в первом варианте, имея числовой вид 1000 и более, конвертируется в строковый вид "1 000" (после первого знака вставляется неразрывный пробел, что приводит к ошибке обращения по индексу). Это старый прикол 1С, который необходимо учитывать при использовании конвертируемых из чисел в строку переменных.
34. Виктор Батарейкин (RockLeeSan) 11.11.14 13:39
И еще раз здравствуйте! И снова обнаружена проблема, но скорей всего это уже косяк платформы. (в данном случае - 8.2.19.83):
при использовании методов "ПоместитьВоВременноеХранилище" и "ПолучитьИзВременногоХранилища", расположенных в разных процедурах, в начале и конце которых используется конструкция
//{Построение дерева вызовов
; ;ПостроениеДереваВызовов.НачалоБлока("........................");
//}

, ПОМЕЩЕННОЕ ВО ВРЕМЕННОЕ ХРАНИЛИЩЕ ЗНАЧЕНИЕ ОЧИЩАЕТСЯ !!!
(и становится в значение
Неопределено
)

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