Найти в Дзене

Инструкции по разработке на 1С

Вы когда-нибудь получали задачу «сделай как-нибудь, а потом разберёмся»? А потом это «как-нибудь» жило в боевой базе три года — и сломалось именно в конце квартала, при сдаче отчётности. Знакомо. Я лично через это прошёл — и не один раз. И это не проблема конкретного разработчика. Это проблема отсутствия стандартов. Здесь — практическое руководство по разработке на 1С: от соглашений по именованию до работы с транзакциями и обменами. То, что реально используется в серьёзных командах. То, что спасает нервы и деньги. Типичная картина: программист пишет код, всё работает, уходит в другую компанию. Через полгода приходит новый разработчик, открывает модуль и видит переменные вида «х1», «ТемпПеременная2», «РезультатФинальный_НОВЫЙ». И три часа уходит только на то, чтобы понять — что вообще здесь происходит. По данным опросов в 1С-сообществе, до 60% времени разработчика уходит на чтение и понимание чужого кода. Не на написание нового — на разбор старого. Это деньги заказчика, которые букваль
Оглавление
Инструкции по разработке на 1С
Инструкции по разработке на 1С

Инструкции по разработке на 1С: что должен знать каждый программист, чтобы не переделывать по три раза

Вы когда-нибудь получали задачу «сделай как-нибудь, а потом разберёмся»? А потом это «как-нибудь» жило в боевой базе три года — и сломалось именно в конце квартала, при сдаче отчётности.

Знакомо. Я лично через это прошёл — и не один раз. И это не проблема конкретного разработчика. Это проблема отсутствия стандартов.

Здесь — практическое руководство по разработке на 1С: от соглашений по именованию до работы с транзакциями и обменами. То, что реально используется в серьёзных командах. То, что спасает нервы и деньги.

Почему стандарты разработки в 1С — это не бюрократия, а выживание

Типичная картина: программист пишет код, всё работает, уходит в другую компанию. Через полгода приходит новый разработчик, открывает модуль и видит переменные вида «х1», «ТемпПеременная2», «РезультатФинальный_НОВЫЙ». И три часа уходит только на то, чтобы понять — что вообще здесь происходит.

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

Хорошие стандарты решают три задачи:

  • Новый разработчик входит в проект за дни, а не недели
  • Баги находятся быстрее, потому что код предсказуем
  • Обновление типовой конфигурации не превращается в ад

Ладно, погнали к конкретике.

Соглашения по именованию в 1С: как называть переменные, процедуры и функции

Платформа 1С использует русскоязычный синтаксис. Это и преимущество, и ловушка. Преимущество — код читается как текст. Ловушка — разработчики начинают называть переменные как попало, потому что «и так понятно».

Переменные и параметры

Правило первое: венгерская нотация для типов. Да, в 1С она не обязательна, но помогает.

  • стр — строка (стрНаименование, стрКомментарий)
  • н — число (нКоличество, нСумма)
  • б — булево (бПроведён, бАктивен)
  • д — дата (дНачала, дОкончания)
  • Сп — список значений
  • Таб — таблица значений
  • Рез — результат запроса

Плохой пример — то, что реально встречается в проектах. На одном из моих проектов весь модуль проведения был написан именно так:

// ПЛОХО — так писать не надо
Процедура Обработать(Парам1, Парам2, ФлагНовый)
Перем ТемпДата;
Перем РезФин;

ТемпДата = Парам2;
РезФин = Парам1 * 1.2;
КонецПроцедуры

Хороший пример — тот же код, но понятный:

// ХОРОШО — читается как документация
Процедура РассчитатьСуммуСНДС(нСуммаБезНДС, дДатаРасчёта, бПримененьСпецСтавка)
Перем дАктуальнаяДата;
Перем нСуммаСНДС;

дАктуальнаяДата = ?(ЗначениеЗаполнено(дДатаРасчёта), дДатаРасчёта, ТекущаяДата());
нСуммаСНДС = нСуммаБезНДС * ПолучитьСтавкуНДС(дАктуальнаяДата, бПримененьСпецСтавка);
КонецПроцедуры

Разница очевидна. Второй вариант — самодокументирующийся код. Через год откроете его и сразу поймёте, что происходит.

Процедуры и функции: глагол + существительное

Процедура — это действие. Функция — это вычисление с результатом. Называйте соответственно.

  • Процедура: ЗагрузитьДанные, ОчиститьТаблицу, ОтправитьУведомление
  • Функция: ПолучитьСуммуДокумента, ВычислитьОстаток, НайтиКонтрагента

Если функция возвращает булево — добавляйте префикс «Это» или «Есть»: ЭтоПроведённыйДокумент, ЕстьОстатокНаСкладе.

Структура модулей в 1С: как организовать код, чтобы не потеряться

Открываете модуль объекта в чужом проекте — и видите 3000 строк кода без единого комментария и логической структуры. Всё вперемешку: обработчики событий, вспомогательные функции, бизнес-логика.

Это типичная история. Я видел такое в 4 из 5 проектов, куда приходил как новый разработчик.

Стандарт структуры модуля — это договорённость команды о том, в каком порядке располагается код. Рекомендуемый порядок:

  • Область «Переменные модуля» — объявления переменных модуля
  • Область «Программный интерфейс» — экспортные процедуры и функции
  • Область «Обработчики событий» — ПриЗаписи, ПриПроведении и т.д.
  • Область «Служебные процедуры и функции» — внутренняя логика
  • Область «Инициализация» — код, выполняемый при создании объекта

Используйте директивы #Область / #КонецОбласти — они сворачивают блоки кода и делают навигацию по модулю человеческой:

#Область ПрограммныйИнтерфейс

// Рассчитывает итоговую сумму документа с учётом скидок и НДС
// Параметры:
// Ссылка - ДокументСсылка - ссылка на документ
// Возвращаемое значение: Число - итоговая сумма
Функция ПолучитьИтоговуюСумму(Ссылка) Экспорт

Возврат РассчитатьСумму(Ссылка);

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

#КонецОбласти

Обратите внимание на комментарий перед функцией. Это не опционально — это обязательно для экспортных процедур. Такой формат поддерживается Синтакс-помощником и отображается в подсказках при написании кода.

Работа с запросами в 1С: 5 правил, которые спасут производительность

Запросы — это то место, где большинство проектов теряют производительность. Один неправильный запрос в документе с 500 пользователями — и сервер падает каждый вечер в 18:00.

Правило 1: Никаких запросов в циклах

Это правило №1. Его нарушают чаще всего. Запрос в цикле по 1000 строк — это 1000 обращений к базе данных вместо одного.

// ПЛОХО — запрос в цикле, база рыдает
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Цена ИЗ РегистрСведений.ЦеныНоменклатуры
|ГДЕ Номенклатура = &Ном";
Запрос.УстановитьПараметр("Ном", СтрокаТЧ.Номенклатура);
Рез = Запрос.Выполнить().Выбрать();
КонецЦикла// ХОРОШО — один запрос для всей таблицы
СписокНоменклатуры = ТабличнаяЧасть.ВыгрузитьКолонку("Номенклатура");

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура, Цена
|ИЗ РегистрСведений.ЦеныНоменклатуры
|ГДЕ Номенклатура В (&СписокНом)";
Запрос.УстановитьПараметр("СписокНом", СписокНоменклатуры);
ТаблицаЦен = Запрос.Выполнить().Выгрузить();

// Дальше работаем с ТаблицаЦен.НайтиСтроки() — без запросов

Правило 2: Используйте виртуальные таблицы с параметрами

Виртуальные таблицы — это готовые срезы регистров. Но многие используют их неправильно: сначала получают все данные, потом фильтруют через ГДЕ.

Это катастрофа для производительности — и я не преувеличиваю.// ПЛОХО — фильтр после виртуальной таблицы
ВЫБРАТЬ КоличествоОстаток
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ГДЕ Остатки.Склад = &НужныйСклад

// ХОРОШО — параметр передаётся В виртуальную таблицу
ВЫБРАТЬ КоличествоОстаток
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(
,
Склад = &НужныйСклад
) КАК Остатки

Разница: в первом случае база читает ВСЕ остатки и потом фильтрует. Во втором — только нужный склад. На большой базе это может быть разница в 10-100 раз по скорости.

Правило 3: Временные таблицы для сложных запросов

Если запрос сложный и использует одни и те же данные несколько раз — выносите их во временную таблицу. Это читаемо и быстро.

МенеджерВТ = Новый МенеджерВременныхТаблиц;

// Шаг 1: Получаем нужные документы во временную таблицу
Запрос1 = Новый Запрос;
Запрос1.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос1.Текст = "ВЫБРАТЬ Ссылка
|ПОМЕСТИТЬ ВТ_Документы
|ИЗ Документ.РеализацияТоваровУслуг
|ГДЕ Дата МЕЖДУ &НачалоПериода И &КонецПериода
| И Проведён = ИСТИНА";
Запрос1.УстановитьПараметр("НачалоПериода", НачалоПериода);
Запрос1.УстановитьПараметр("КонецПериода", КонецПериода);
Запрос1.Выполнить();

// Шаг 2: Используем ВТ в основном запросе
Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос2.Текст = "ВЫБРАТЬ ...
|ИЗ ВТ_Документы КАК Документы
|ЛЕВОЕ СОЕДИНЕНИЕ ...";
РезультатЗапроса = Запрос2.Выполнить();

Транзакции и обработка ошибок в 1С: как не потерять данные

Транзакции — это то, о чём многие разработчики думают в последнюю очередь. А потом получают частично записанные данные в базе и звонок от бухгалтера в 9 утра. Помню случай — клиент позвонил в пятницу вечером: «у нас документы провелись, но остатки не изменились». Три часа разбирались. Причина — отсутствие транзакции при записи связанных объектов.

Правило простое: если вы записываете несколько связанных объектов — используйте транзакцию. Либо всё записалось, либо ничего.

Процедура ПровестиДокументСПривязкой(ДокументОбъект, СвязанныйОбъект)

НачатьТранзакцию();
Попытка

// Записываем основной документ
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);

// Записываем связанный объект
СвязанныйОбъект.ДокументОснование = ДокументОбъект.Ссылка;
СвязанныйОбъект.Записать();

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

// Логируем ошибку — не глотаем её!
ЗаписьЖурналаРегистрации(
"Ошибка проведения документа",
УровеньЖурналаРегистрации.Ошибка,
,
,
ОписаниеОшибки()
);

ВызватьИсключение;

КонецПопытки;

КонецПроцедуры

Обратите внимание на ВызватьИсключение в блоке Исключение. Это критически важно. Многие разработчики пишут Исключение — и не перевызывают его. В результате ошибка «проглатывается», транзакция откатывается, но пользователь видит успешное завершение. Данные не записаны, пользователь не знает. Это катастрофа.

Вложенные транзакции: подводный камень

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

Это значит: если внутренняя «транзакция» откатилась, а внешняя пытается зафиксироваться — получите исключение. Проектируйте архитектуру так, чтобы минимизировать вложенность.

Работа с RLS и правами доступа в 1С: типичные ошибки разработчиков

RLS (Record Level Security — ограничение на уровне записей) — мощный механизм. И источник самых загадочных тормозов, которые вы когда-либо видели.

Типичная история: запрос работает за 0.1 секунды под администратором. Под обычным пользователем — 15 секунд. Разработчик в панике. А проблема в том, что RLS добавляет условие к каждому запросу — и если это условие неоптимально, всё рушится.

Правило: всегда тестируйте под пользователем с ограниченными правами

Звучит очевидно. Но я считаю, что именно это нарушение — самое массовое в 1С-разработке. По моим наблюдениям, минимум 8 из 10 разработчиков тестируют только под администратором — и это системная проблема, не личная.

Обязательные проверки перед сдачей задачи:

  • Запустить под пользователем с минимальными правами для данной задачи
  • Проверить время выполнения ключевых операций
  • Убедиться, что нет ошибок «Недостаточно прав» в неожиданных местах
  • Проверить журнал регистрации на ошибки доступа

Привилегированный режим: когда использовать и когда нет

Привилегированный режим отключает проверку прав. Это нужно в конкретных случаях — например, в фоновых заданиях или при записи служебных данных. Использовать его «чтобы не разбираться с правами» — это не решение, это бомба замедленного действия.

// Правильное использование привилегированного режима
// Только для конкретной операции, не для всего модуля

&НаСервере
Процедура ЗаписатьСлужебныеДанные(ДанныеДляЗаписи)

УстановитьПривилегированныйРежим(Истина);

Попытка
// Записываем только служебные данные
РегистрСведений.СлужебныеДанные.УстановитьЗначения(ДанныеДляЗаписи);
Исключение
УстановитьПривилегированныйРежим(Ложь);
ВызватьИсключение;
КонецПопытки;

УстановитьПривилегированныйРежим(Ложь); // Всегда снимаем!

КонецПроцедуры

Ключевое правило: привилегированный режим всегда снимается после использования — в том числе при исключении.

Обмены данными в 1С: стандарты, которые сэкономят вам недели отладки

Обмены — это отдельный мир боли. Данные не приходят, приходят дважды, приходят в неправильном формате. Если нет стандартов — каждый обмен становится уникальным квестом.

Логирование обменов: минимальный стандарт

Каждый обмен должен писать в журнал регистрации. Не «если что-то пошло не так» — а всегда. Успешная загрузка, количество обработанных записей, время выполнения. Сейчас будет важное — не пропустите: именно итоговая запись в журнал спасает вас, когда заказчик говорит «данные не пришли».

Процедура ВыполнитьОбменСВнешнейСистемой()

ВремяНачала = ТекущаяДата();
КоличествоОбработано = 0;
КоличествоОшибок = 0;

Попытка

ДанныеОбмена = ПолучитьДанныеИзВнешнейСистемы();

Для Каждого ЗаписьОбмена Из ДанныеОбмена Цикл
Попытка
ОбработатьЗапись(ЗаписьОбмена);
КоличествоОбработано = КоличествоОбработано + 1;
Исключение
КоличествоОшибок = КоличествоОшибок + 1;
ЗаписьЖурналаРегистрации(
"Обмен: ошибка обработки записи",
УровеньЖурналаРегистрации.Ошибка,
,
ЗаписьОбмена.Идентификатор,
ОписаниеОшибки()
);
КонецПопытки;
КонецЦикла;

Исключение
ЗаписьЖурналаРегистрации(
"Обмен: критическая ошибка",
УровеньЖурналаРегистрации.Ошибка,
, ,
ОписаниеОшибки()
);
ВызватьИсключение;
КонецПопытки;

// Итоговая запись в журнал
Сообщение = СтрШаблон(
"Обмен завершён. Обработано: %1, Ошибок: %2, Время: %3 сек.",
КоличествоОбработано,
КоличествоОшибок,
(ТекущаяДата() - ВремяНачала)
);
ЗаписьЖурналаРегистрации("Обмен", УровеньЖурналаРегистрации.Информация, , , Сообщение);

КонецПроцедуры

Этот шаблон спасёт вас, когда заказчик скажет «данные не пришли» — откроете журнал и за 30 секунд найдёте проблему.

Работа с интерфейсом в 1С: управляемые формы и производительность

Управляемые формы — это клиент-серверная архитектура. И главный источник непонимания у разработчиков, которые пришли из 1С 7.7 или из обычных форм.

Главное правило: всё тяжёлое — на сервере. На клиенте — только UI-логика.

Директивы компиляции: используйте правильно

  • &НаКлиенте — только UI: открыть форму, показать сообщение, обработать нажатие кнопки
  • &НаСервере — запросы, запись объектов, тяжёлые вычисления
  • &НаКлиентеНаСервереБезКонтекста — простые вычисления без обращения к базе
  • &НаСервереБезКонтекста — серверные операции без передачи всей формы (быстрее!)

// Правильная структура обработчика команды
&НаКлиенте
Процедура ЗагрузитьДанные(Команда)
ОчиститьСообщения();

// Показываем индикатор загрузки
Состояние("Загружаю данные...");

// Вся тяжёлая работа — на сервере
ЗагрузитьДанныеНаСервере();

КонецПроцедуры

// Серверная процедура без контекста — не тащим всю форму
&НаСервереБезКонтекста
Процедура ЗагрузитьДанныеНаСервере()

// Здесь запросы, запись, вся логика
РезультатЗапроса = ВыполнитьЗапросЗагрузки();
ОбработатьРезультат(РезультатЗапроса);

КонецПроцедуры

Минимизируйте серверные вызовы

Каждый вызов сервера — это сетевой round-trip. На тонком клиенте через интернет это может быть 200-500 мс. Если у вас 10 серверных вызовов при открытии формы — пользователь ждёт 2-5 секунд. Это неприемлемо.

Группируйте серверные операции: лучше один вызов, который делает 5 вещей, чем 5 вызовов по одной вещи.

Документирование кода в 1С: минимум, который обязателен

«Хороший код не требует комментариев» — это миф, который придумали люди, не поддерживавшие чужой код через три года после написания. Честно? Я раньше тоже так думал, пока не открыл собственный модуль двухлетней давности и не провёл полчаса, пытаясь вспомнить логику.

В 1С есть стандарт документирования — он поддерживается BSP (Библиотекой стандартных подсистем) и отображается в Синтакс-помощнике.

Что обязательно документировать:

  • Все экспортные процедуры и функции — всегда
  • Нетривиальную бизнес-логику — «почему именно так»
  • Обходные решения и костыли — с указанием причины и ссылкой на задачу
  • Параметры сложных процедур — типы и допустимые значения

// Рассчитывает сумму скидки для строки документа.
// Учитывает накопительные скидки контрагента и акционные предложения.
// ВНИМАНИЕ: не учитывает ручные скидки — они применяются отдельно.
//
// Параметры:
// СтрокаТЧ - СтрокаТаблицыЗначений - строка табличной части
// Контрагент - СправочникСсылка.Контрагенты - контрагент документа
// ДатаДокумента - Дата - дата документа для определения акций
//
// Возвращаемое значение:
// Число - процент скидки от 0 до 100
Функция РассчитатьПроцентСкидки(СтрокаТЧ, Контрагент, ДатаДокумента) Экспорт

// Логика расчёта...

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

Чек-лист перед сдачей задачи: 10 пунктов, которые спасут вас от возврата

Это практический чек-лист — тот самый, который я использую сам и который внедрял в командах. Распечатайте и повесьте над монитором.

  • Нет запросов в циклах — проверить все циклы в коде
  • Виртуальные таблицы с параметрами — не фильтровать через ГДЕ после виртуальной таблицы
  • Транзакции закрыты — каждый НачатьТранзакцию имеет Зафиксировать или Отменить
  • Исключения не проглочены — в блоке Исключение есть ВызватьИсключение или обработка
  • Тест под ограниченным пользователем — не только под администратором
  • Логирование ключевых операций — журнал регистрации пишется
  • Экспортные функции задокументированы — есть описание параметров и возвращаемого значения
  • Нет жёстко зашитых значений — никаких магических чисел и строк прямо в коде
  • Обновление типовой — изменения в расширении или с минимальным вмешательством в типовой код
  • Проверка на пустые значения — ЗначениеЗаполнено() перед использованием ссылок

Этот чек-лист сокращает количество возвратов задач на доработку в среднем в 2-3 раза. Проверено на практике в командах от 5 до 30 разработчиков.

Итог: стандарты — это инвестиция, а не трата времени

Написать код без стандартов быстрее. На 20-30% быстрее — в моменте. Но потом вы платите за это годами: медленный онбординг новых разработчиков, долгий поиск багов, мучительные обновления конфигурации.

Реальные цифры из практики: внедрение стандартов разработки в команде из 8 человек сократило время code review с 3 часов до 45 минут на задачу. За год это 500+ часов сэкономленного времени. При ставке разработчика 3000 рублей в час — это 1,5 миллиона рублей.

Ну вы поняли, к чему я веду. Стандарты — это не про перфекционизм. Это про деньги и нервы.

Начните с малого: договоритесь об именовании, структуре модулей и обязательном логировании. Остальное придёт со временем.

Если вам нужен опытный разработчик 1С, который уже знает все эти стандарты и не будет учиться на вашем проекте — заходите на koderion.ru. Это биржа проверенных специалистов 1С: программисты, консультанты, DevOps. Найдёте нужного человека под конкретную задачу — будь то разовая доработка или долгосрочный проект.