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

Структура регистра
Регистр сведений СоответствияОбъектов, независимый. Периодичность — по необходимости: если важно знать, какое значение действовало на дату, делайте периодическим.
| Поле | Вид | Тип | Назначение |
|---|---|---|---|
| ПервичныйКлюч | Измерение | Строка(100) | Назначение настройки: «СкладБрака», «Директор» |
| ВторичныйКлюч | Измерение | Строка, Число, ЛюбаяСсылка | Разрез: организация, подразделение; может быть пустым |
| Значение | Ресурс | ЛюбаяСсылка, Строка, Число, Булево, Дата | Само значение |
| Описание | Реквизит | Строка(200) | Где и зачем используется |
Строковое измерение должно быть ограниченной длины — платформа не позволяет использовать в измерениях строки неограниченной длины.
Зачем вторичный ключ: без него ключи быстро превращаются в «ДиректорРомашка», «ДиректорВасилек», «ГлавбухРомашка». С составным ключом первичный — «Директор», вторичный — ссылка на организацию. И можно одним запросом получить все записи по первичному ключу, не зная заранее список организаций.
Методы в модуле менеджера
#Область ПрограммныйИнтерфейс
// Возвращает значение настройки по ключам.
//
// Параметры:
// ПервичныйКлюч - Строка - назначение настройки.
// ВторичныйКлюч - Произвольный - разрез настройки, Неопределено - без разреза.
// ДатаСреза - Дата - дата, на которую нужно значение; по умолчанию текущая дата сеанса.
//
// Возвращаемое значение:
// Произвольный - значение настройки или Неопределено, если запись не найдена.
//
Функция Значение(ПервичныйКлюч, ВторичныйКлюч = Неопределено, ДатаСреза = Неопределено) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 2
| Соответствия.Значение КАК Значение
|ИЗ
| РегистрСведений.СоответствияОбъектов.СрезПоследних(
| &ДатаСреза,
| ПервичныйКлюч = &ПервичныйКлюч
| И ВторичныйКлюч = &ВторичныйКлюч) КАК Соответствия";
Запрос.УстановитьПараметр("ДатаСреза",
?(ЗначениеЗаполнено(ДатаСреза), ДатаСреза, ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("ПервичныйКлюч", ПервичныйКлюч);
Запрос.УстановитьПараметр("ВторичныйКлюч", ВторичныйКлюч);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Количество() > 1 Тогда
ВызватьИсключение СтрШаблон(
НСтр("ru = 'Неоднозначная настройка «%1»: найдено несколько записей.'"), ПервичныйКлюч);
КонецЕсли;
Возврат ?(Выборка.Следующий(), Выборка.Значение, Неопределено);
КонецФункции
// Проверяет, что все перечисленные первичные ключи заполнены.
//
// Параметры:
// ПервичныеКлючи - Массив из Строка - ключи, которые нужны алгоритму.
//
// Возвращаемое значение:
// Массив из Строка - незаполненные ключи; пустой массив, если всё заполнено.
//
Функция НезаполненныеКлючи(ПервичныеКлючи) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Соответствия.ПервичныйКлюч КАК ПервичныйКлюч
|ИЗ
| РегистрСведений.СоответствияОбъектов.СрезПоследних(
| &ДатаСреза,
| ПервичныйКлюч В (&ПервичныеКлючи)) КАК Соответствия";
Запрос.УстановитьПараметр("ДатаСреза", ТекущаяДатаСеанса());
Запрос.УстановитьПараметр("ПервичныеКлючи", ПервичныеКлючи);
Заполненные = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ПервичныйКлюч");
Результат = Новый Массив;
Для Каждого Ключ Из ПервичныеКлючи Цикл
Если Заполненные.Найти(Ключ) = Неопределено Тогда
Результат.Добавить(Ключ);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
#КонецОбластиОбратите внимание: вторичный ключ сравнивается строго. Пустая настройка без разреза хранится с ВторичныйКлюч = Неопределено, и вызов без второго параметра находит именно её. Смешивать «общее» и «по организации» в одном вызове не нужно — лучше явно: сначала ищем по организации, если не нашли — общее значение.
Использование в алгоритме
Незаполненные = РегистрыСведений.СоответствияОбъектов.НезаполненныеКлючи(
СтрРазделить("СкладБрака,ВидЦеныСписания", ","));
Если Незаполненные.Количество() > 0 Тогда
ВызватьИсключение СтрШаблон(НСтр("ru = 'Не заполнены настройки: %1'"),
СтрСоединить(Незаполненные, ", "));
КонецЕсли;
СкладБрака = РегистрыСведений.СоответствияОбъектов.Значение("СкладБрака");
Директор = РегистрыСведений.СоответствияОбъектов.Значение("Директор", Документ.Организация);Проверка в начале алгоритма даёт понятную ошибку сразу, а не неверный результат через двадцать строк.
Правила, без которых регистр превращается в свалку
- Ключи — в одном месте. Заведите общий модуль или область с функциями-обёртками:
НастройкиАлгоритмов.СкладБрака(). Строковые ключи по всему коду — тот же хардкод, только в другой форме. - Описание обязательно. Запись без описания через полгода никто не решится удалить.
- Права. Изменять регистр должны только администраторы или ответственные; читать — через привилегированный режим или с ролью на чтение.
- Не храните здесь учётные данные и большие объёмы — для этого есть отдельные механизмы.
- Перенос между базами. При развёртывании новой базы записи регистра нужно перенести: держите выгрузку или обработку заполнения.
Типичные ошибки
- Поиск элемента по наименованию в коде «на время» — временное остаётся навсегда.
- Проверка пустой ссылки отсутствует: код идёт дальше с
Справочники.Склады.ПустаяСсылка(). - Строковое измерение без ограничения длины — регистр не сохранится в конфигураторе.
- Использование
ТекущаяДата()вместоТекущаяДатаСеанса()для среза: на клиенте и сервере время может отличаться. - Отсутствие контроля дублей: две записи на один ключ дают недетерминированный результат.
Если в доработанной конфигурации «гвоздей» уже десятки, их удобно собрать и вынести за одну итерацию в рамках аудита 1С. Новые алгоритмы сразу проектирую с вынесенными настройками — это стандартная часть доработки 1С.
Итог
- Хардкод в 1С опасен тем, что ломается без ошибки при перенумерации, переименовании или в другой базе.
- Для небольшого числа стабильных значений подойдут константы и предопределённые элементы, обращение — через
ОбщегоНазначения.ПредопределенныйЭлемент(). - Для множества настроек в разрезе объектов удобен регистр сведений с первичным и вторичным ключом.
- Проверяйте заполненность настроек в начале алгоритма и выдавайте понятную ошибку.
- Строковые ключи держите в одном модуле, иначе хардкод просто переедет в другое место.




