В процессе разработки и модификации типовых конфигураций на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда отладчик ведет себя «странно»: точка останова, установленная в коде, просто игнорируется системой. Особенно часто это происходит в процедурах, где пользователю задается уточняющий вопрос (например, «Очистить табличную часть?»). Рассмотрим детально причины этого поведения и разберем по шагам, как правильно организовать отладку и модификацию такого кода.
Проанализируем ситуацию: в современном интерфейсе «Такси» (и вообще в управляемых формах при работе в асинхронном режиме) использование модальных окон запрещено. Вместо старой функции Вопрос(), которая останавливала выполнение кода до ответа пользователя, используется метод ПоказатьВопрос() с объектом ОписаниеОповещения.
Выясним причину «пропадания» точки останова. Когда выполнение кода доходит до метода ПоказатьВопрос(), происходит следующее:
ОписаниеОповещения.Посмотрим на пример из практики. В коде автора процедура ОбработчикПоОстаткам заканчивает свою работу сразу после вызова ПоказатьВопрос. Когда пользователь нажимает кнопку «Да», система инициирует совершенно новый поток выполнения, вызывая процедуру, имя которой было передано в оповещении. Стек вызовов при этом пуст, и «вернуться» в исходную точку отладчик не может. Именно поэтому точка останова в основной процедуре после вопроса не срабатывает — код там просто больше не выполняется.
Для того чтобы успешно отладить процесс заполнения после ответа пользователя, выполним следующие действия:
ВопросПриЗаполненииСпецодеждыПоОстаткамЗавершение.&НаСервере, в которую передается управление.Рассмотрим, как выглядит процедура обратного вызова в коде:
&НаКлиенте
Процедура ВопросПриЗаполненииСпецодеждыПоОстаткамЗавершение(РезультатВопроса, ДополнительныеПараметры) Экспорт
Если РезультатВопроса = КодВозвратаДиалога.Да Тогда
// Именно здесь нужно ставить точку останова
тн_ЗаполнитьСпецодеждуПоОстаткамВЭксплуатации(ДополнительныеПараметры);
КонецЕсли;
КонецПроцедуры
Часто при копировании кода из типовых конфигураций разработчики забывают переопределить обработчик оповещения. Разберем ситуацию: вы создали свою кнопку и свою процедуру заполнения, но в ОписаниеОповещения указали имя типовой процедуры. В итоге, при нажатии «Да», система вызывает старый типовой код, игнорируя ваши изменения.
Проанализируем пример создания команды программно:
Команда = ЭтаФорма.Команды.Добавить("ЗаполнитьПоОстаткам");
Команда.Действие = "ОбработчикПоОстаткам";
Кнопка = ЭтаФорма.Элементы.Добавить("ЗаполнитьПоОстаткам", Тип("КнопкаФормы"), ЭтаФорма.Элементы.ГруппаЗаполнить);
Кнопка.ИмяКоманды = "ЗаполнитьПоОстаткам";
Если внутри ОбработчикПоОстаткам вы вызываете ПоказатьВопрос и передаете туда типовую процедуру ВопросПриЗаполнении...Завершение, то управление уйдет в типовой код. Чтобы этого избежать, необходимо создать свою процедуру завершения с уникальным префиксом (например, тн_ВопросПриЗаполнении...Завершение) и указать её при создании ОписаниеОповещения.
Если точка останова стоит в серверной функции, например, в тн_ЗаполнитьСпецодеждуПоОстаткамВЭксплуатации, но отладчик её игнорирует, следует проверить технические настройки связи клиента и сервера.
Разберем основные моменты настройки:
-debug. Без этого отладка серверного кода невозможна в принципе.Проанализируем ситуацию, когда код визуально правильный, но выполняется старая версия. Это может быть связано с кэшированием конфигурации.
Во-первых, всегда используйте уникальные префиксы для своих процедур (например, тн_, как в примере). Это гарантирует, что вы не перепутаете свою процедуру с типовой при поиске или вызове. Если вы изменили код в расширении или основной конфигурации, а отладчик все равно «промахивается» мимо строк, попробуйте перезапустить сеанс с параметром /ClearCache.
Во-вторых, обратите внимание на ДополнительныеПараметры в оповещении. Это отличный способ передать данные из начальной процедуры в финальную, так как локальные переменные первой процедуры будут уничтожены сразу после вывода вопроса на экран. Посмотрим на пример передачи флага:
// В исходной процедуре
ПараметрыОповещения = Ложь; // Флаг "С истекшим сроком"
Оповещение = Новый ОписаниеОповещения("МояПроцедураЗавершения", ЭтотОбъект, ПараметрыОповещения);
// В процедуре завершения
&НаКлиенте
Процедура МояПроцедураЗавершения(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// ДополнительныеПараметры содержат наше значение "Ложь"
ЗаполнитьНаСервере(ДополнительныеПараметры);
КонецЕсли;
КонецПроцедуры
Подводя итог, можно сказать, что «неработающая» точка останова — это почти всегда следствие асинхронного разрыва кода. Правильное использование ОписаниеОповещения, проверка серверных настроек отладки и внимательный контроль имен процедур обратного вызова позволят вам эффективно решать задачи любой сложности.