Отладчик и типичные ошибки новичка
Учимся не гадать, а видеть: ставим точку останова, идём по коду по шагам и ловим три самые частые ошибки новичка.
Отладчик — встроенный инструмент 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— продолжить до следующей точки.- Табло показывает реальные значения переменных и выражений — это главный инструмент диагностики.
- «Значение не является значением объектного типа» почти всегда означает обращение к свойству пустой ссылки; лечится проверкой
ЗначениеЗаполнено(). - Работа с базой — на сервере, интерфейс — на клиенте; между ними явный вызов серверного метода.
- Изменения объекта сохраняются только после
Записать(); ссылка сама по себе доступна лишь для чтения.