Отладчик и типичные ошибки новичка

Учимся не гадать, а видеть: ставим точку останова, идём по коду по шагам и ловим три самые частые ошибки новичка.

Отладчик — встроенный инструмент 1С, который останавливает выполнение кода в нужном месте и показывает, что происходит внутри: значения переменных, порядок вызовов, реальный путь исполнения.

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

Зачем это нужно на практике

Ошибка в 1С почти никогда не говорит прямо, что не так. Сообщение «Значение не является значением объектного типа» не назовёт вам ни строку, ни переменную-виновника. Отладчик превращает загадку в факт: вы своими глазами видите, что переменная пустая, что цикл не выполнился ни разу, что вы попали не в ту ветку Если. Умение отлаживать отличает того, кто чинит баг за пять минут, от того, кто сидит над ним полдня.

Точка останова

Точка останова (breakpoint) — это метка на строке кода: дойдя до неё, платформа замирает и отдаёт вам управление. Ставится кликом на левом поле строки в конфигураторе или клавишей F9. Чтобы отладка работала, в свойствах информационной базы должна быть включена отладка, а сеанс запущен в режиме отладки (F5).

Функция РассчитатьСкидку(Клиент)

    Процент = 0;                          // ← ставим сюда точку останова (F9)
    Если Клиент.ВИП Тогда
        Процент = 10;
    КонецЕсли;

    Возврат Процент;

КонецФункции

Как только выполнение доходит до отмеченной строки, оно останавливается, и вы можете посмотреть, что лежит в переменной Клиент, зайти ли выполнение в ветку ВИП и каким уйдёт Процент.

Пошаговое выполнение и Табло

Когда выполнение остановлено, вы управляете им по шагам. Три главные клавиши:

КлавишаЧто делает
F11 — Шаг внутрьвыполнить строку; если это вызов процедуры — зайти внутрь неё
F10 — Шаг черезвыполнить строку целиком, не заходя в вызванные процедуры
F5 — Продолжитьбежать дальше до следующей точки останова

Табло — это окно, куда вы добавляете выражения и следите за их значениями в реальном времени. Достаточно выделить переменную и перетащить её в Табло (или ввести выражение руками). Можно смотреть не только переменные, но и вычисления:

// В Табло можно вписать любые выражения, например:
// Клиент.Наименование          → "ООО Ромашка"
// Клиент.ВИП                    → Ложь
// Заказ.Строки.Количество()     → 3
// ЗначениеЗаполнено(Клиент)     → Истина

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

Ошибка №1: «Значение не является значением объектного типа»

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

Заказ = Документы.ЗаказПокупателя.НайтиПоНомеру("НЕТ-ТАКОГО");
// НайтиПоНомеру вернул пустую ссылку, потому что документ не найден
Сообщить(Заказ.Контрагент.Наименование);  // ← падает здесь

Метод НайтиПоНомеру() при неудаче возвращает не ошибку, а пустую ссылку. Обращение Заказ.Контрагент к пустой ссылке и роняет программу. Правильно — проверять результат перед использованием:

Заказ = Документы.ЗаказПокупателя.НайтиПоНомеру("НЕТ-ТАКОГО");
Если НЕ ЗначениеЗаполнено(Заказ) Тогда
    Сообщить("Заказ не найден");
    Возврат;
КонецЕсли;
Сообщить(Заказ.Контрагент.Наименование);  // сюда попадём только с реальным заказом

ЗначениеЗаполнено() — ваш главный оберег: он честно скажет, пустая ссылка или нет, и убережёт от падения.

Ошибка №2: путаница «клиент/сервер»

В управляемом приложении код разделён директивами &НаКлиенте и &НаСервере. На клиенте нет прямого доступа к базе данных, а на сервере — к элементам интерфейса. Новичок пишет обращение к базе в клиентской процедуре и получает ошибку компиляции.

&НаКлиенте
Процедура ПриНажатии(Команда)
    // ОШИБКА: на клиенте нельзя напрямую читать из базы
    Остаток = РегистрыНакопления.Товары.Остаток();
КонецПроцедуры

Правильно — вынести работу с базой на сервер, а с клиента лишь вызвать серверный метод:

&НаКлиенте
Процедура ПриНажатии(Команда)
    Сообщить(ПолучитьОстаток());
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьОстаток()
    // здесь база доступна
    Возврат 42;
КонецФункции

Директива &НаСервереБезКонтекста — самый лёгкий вид серверного вызова: он не тащит на сервер всю форму, поэтому работает быстрее. Правило простое: интерфейс — на клиенте, база — на сервере, между ними — явный вызов.

Ошибка №3: забытый .Записать()

Мы уже касались этого, но повторим, потому что грабля вечная. Вы получили объект, поменяли реквизит — и уверены, что данные сохранились. А они нет.

ЭлементЗадача = Справочники.Задачи.НайтиПоНаименованию("Свёрстать главную страницу");
Объект = ЭлементЗадача.ПолучитьОбъект();
Объект.ПлановыеЧасы = 24;
// забыли Объект.Записать();  ← изменения потеряны, в базе по-прежнему старое значение

Ссылка (ЭлементЗадача) — только для чтения. Чтобы изменить данные, надо получить объект через ПолучитьОбъект(), поменять реквизиты и обязательно вызвать Записать(). Нет вызова — нет сохранения.

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

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

Частые ошибки

  • Отладка не включена в свойствах базы — точки останова не срабатывают, и кажется, что инструмент сломан.
  • Путают F11 и F10 — проваливаются F11 в чужой служебный код и теряются; для «просто следующей строки» нужен F10.
  • Не смотрят в Табло, а гадают — половина багов чинится за секунду, стоит лишь взглянуть на реальное значение переменной.
  • Считают, что НайтиПоКоду()/НайтиПоНомеру() при неудаче выбрасывают ошибку — на самом деле они возвращают пустую ссылку, которую надо проверять через ЗначениеЗаполнено().

Итоги

  • Точка останова (F9) замораживает выполнение на нужной строке; сеанс должен идти в режиме отладки.
  • F11 — шаг внутрь процедуры, F10 — шаг через, F5 — продолжить до следующей точки.
  • Табло показывает реальные значения переменных и выражений — это главный инструмент диагностики.
  • «Значение не является значением объектного типа» почти всегда означает обращение к свойству пустой ссылки; лечится проверкой ЗначениеЗаполнено().
  • Работа с базой — на сервере, интерфейс — на клиенте; между ними явный вызов серверного метода.
  • Изменения объекта сохраняются только после Записать(); ссылка сама по себе доступна лишь для чтения.
Проверьте себя
1. Код падает с ошибкой «Значение не является значением объектного типа» на строке Заказ.Контрагент.Наименование, где Заказ = Документы.ЗаказПокупателя.НайтиПоНомеру(...). Что произошло?
AНайтиПоНомеру выбросил исключение
BНайтиПоНомеру не нашёл документ и вернул пустую ссылку, а к её свойству нельзя обращаться
CУ документа нет реквизита Контрагент
DКод выполнялся на сервере вместо клиента
2. В отладчике вы остановились на строке и хотите выполнить её целиком, НЕ проваливаясь внутрь вызванной в ней процедуры. Какую клавишу нажать?
AF11 (Шаг внутрь)
BF10 (Шаг через)
CF9 (поставить точку останова)
DF5 (Продолжить до конца)