В мире программирования существует мощная, но часто недооцененная концепция — иммутабельность (неизменяемость). Проще говоря, иммутабельный объект — это объект, состояние которого нельзя изменить после его создания. Если вам нужно "поменять" его, вы создаете совершенно новый объект с обновленными данными.
В контексте 1С, где часто приходится иметь дело с сложными бизнес-процессами и большими объемами данных, понимание и применение этой концепции может значительно повысить качество вашего кода. И самый наглядный пример иммутабельности в 1С — это константы.
Что такое константа в 1С? Краткое напоминание
Константа — это объект метаданных 1С, предназначенный для хранения информации, которая либо не меняется совсем, либо меняется очень редко. Классические примеры:
- Название организации
- ИНН
- Курс валюты, фиксируемый на целый день
- Email для рассылки уведомлений
- Различные настройки системы
С точки зрения кода, константа объявляется и используется так:
// Получаем значение константы (чтение)
НаименованиеОрганизации = Константы.НаименованиеОрганизации.Получить();
// Установить новое значение может только авторизованный пользователь с правами (запись)
Константы.НаименованиеОрганизации.Установить("ООО 'Рога и копыта'");
Сама операция .Установить() технически изменяет значение в базе данных, но с точки зрения логики приложения в любой конкретный момент времени у нас есть единственное, неизменное значение константы.
Преимущества иммутабельности на примере констант
Почему же использование неизменяемых (или условно-неизменяемых) данных, таких как константы, так полезно?
1. Предсказуемость и отсутствие побочных эффектов
Это главное преимущество. Если вы в начале процедуры получили значение константы, можете быть уверены, что оно не изменится до конца её выполнения.
СтавкаНДС = Константы.СтавкаНДС.Получить(); // Предположим, получили 20
// Долгий и сложный расчет.
// где-то в другом месте кода другой разработчик мог бы попытаться изменить СтавкуНДС
//но он не может этого сделать "тихо", ему нужны права и явный вызов .Установить()
// Мы спокойно используем СтавкуНДС, будучи уверенными, что она осталась равной 20
СуммаСНДС = СуммаБезНДС * СтавкаНДС / 100;
КонецПроцедуры
Если бы вместо константы использовалась глобальная переменная сессии, которую может изменить любой модуль, предсказать поведение кода было бы гораздо сложнее.
2. Безопасность в многопоточности
Хотя платформа 1С в основном однопоточная в коде приложения, сервер 1С:Предприятие — многопоточное окружение. Несколько сеансов работают параллельно. Константа, будучи по сути иммутабельным в рамках транзакции значением, безопасна для чтения из любого количества сеансов одновременно. Не возникает ситуации "гонки данных" (race condition), когда один поток читает данные, а второй в этот же момент их изменяет.
3. Упрощение отладки и логирования
Когда вы видите в журнале регистрации или отладочном выводе значение константы, вам не нужно гадать, в какой момент оно могло измениться. Вы можете мысленно "привязать" это значение ко всему жизненному циклу операции, что значительно упрощает поиск ошибок.
4. Кэширование и производительность
Платформа 1С умеет эффективно кэшировать значения констант на сервере. Поскольку они меняются редко, нет необходимости обращаться к базе данных для их чтения при каждом вызове. Это повышает общую производительность системы. Если бы они менялись часто, такой механизм кэширования был бы неэффективен.
Иммутабельность за пределами констант: как применять принцип в повседневном коде
Концепцию иммутабельности можно и нужно применять не только к объектам метаданных.
1. Служебные переменные в модулях
Вместо того чтобы изменять параметры процедуры или функции, создавайте новые переменные.
- Не очень хорошо (мутабельно):
Для i = 0 По МассивДанных.Количество() - 1 Цикл
// Прямое изменение исходного массива
МассивДанных[i] = МассивДанных[i] * 2;
КонецЦикла;
КонецПроцедуры
- Вызывающий код не ожидает, что его массив будет изменен. Это может привести к тонким ошибкам.
Функция ОбработатьМассив(МассивДанных)
Результат = Новый Массив;
Для каждого Элемент Из МассивДанных Цикл
// Создаем новый массив, не трогая исходный
Результат.Добавить(Элемент * 2);
КонецЦикла;
Возврат Результат;
КонецФункции
- Исходные данные защищены от изменений. Функция чистая и предсказуемая.
2. Работа с датами и другими примитивами
В 1С даты, строки и числа по своей природе иммутабельны. Вы не можете "изменить" день в переменной типа Дата. Вы можете только создать новую дату.
НоваяДата = ТекДата; // Это не изменение ТекДаты, это создание новой переменной с тем же значением
НоваяДата = КонецМесяца(ТекДата); // ТекДата осталась '20231027', НоваяДата стала '20231031'
Использование иммутабельных данных — это не просто модный тренд, а практика, которая делает ваш код в 1С:
- Более надежным: меньше неожиданных изменений состояния.
- Более понятным: логику легче отслеживать.
- Более безопасным: минимизируются риски в параллельных процессах.
1. Виды констант: периодические и подчиненные измерениям
Константы в 1С не всегда являются одиночными значениями. Они могут быть более сложными:
а) Периодические константы
Это константы, которые могут иметь разные значения в разные периоды времени. Самое классическое применение — курс валюты.
- Как работает: Вы устанавливаете значение константы на определенную дату. При получении значения система возвращает то, которое действовало на запрашиваемую дату.
- Преимущество: Вам не нужно вручную управлять историей изменений. Платформа делает это за вас.
- Пример в коде:
Константы.КурсДоллара.Установить(96.50, '20231026');
КурсНа24 = Константы.КурсДоллара.Получить('20231024');
КурсНа25 = Константы.КурсДоллара.Получить('20231025');
КурсНа26 = Константы.КурсДоллара.Получить('20231026');
КурсНаСегодня = Константы.КурсДоллара.Получить();
б) Константы с подчинениями
Это константы, которые могут иметь разные значения для разных элементов справочников (измерений). Например, "Норма отпуска" для разных "Складов" или "Ответственный менеджер" для разных "НаправленийДеятельности".
- Как работает: В конфигураторе для константы включается возможность подчинения и выбирается один или несколько справочников-измерений.
- Преимущество: Позволяет хранить "настройки по умолчанию" в разрезе аналитик, не создавая отдельные регистры сведений.
- Пример в коде:
НормаОтпуска = Константы.НормаОтпуска.Получить(Склад);
// Установить норму для другого склада
ДругойСклад = Справочники.Склады.НайтиПоНаименованию("Склад готовой продукции");
Константы.НормаОтпуска.Установить(100, ДругойСклад);
2. Производительность и кэширование: что нужно знать
- Кэш констант: Платформа 1С действительно кэширует значения констант в памяти сервера. Это одна из причин, почему обращение к константе происходит очень быстро.
- Сброс кэша: Кэш констант сбрасывается при:
- Завершении сеанса (не всегда, зависит от настроек кластера).
- Явном вызове метода СброситьКонстанты() (редко используется).
- Изменении значения любой константы в базе данных. Важный нюанс: изменение одной константы приводит к сбросу кэша всех констант для всех пользователей. Это нужно учитывать в высоконагруженных системах
3. Использование в Запросах и Отчетах
Константы можно и нужно использовать непосредственно в языке запросов.
- Синтаксис: Для доступа к константе в запросе используется псевдотаблица Константы.
- Пример:
Запрос = Новый Запрос;
Запрос.Текст = "
ВЫБРАТЬ
Константы.НаименованиеОрганизации КАК Организация,
Константы.ИНН КАК ИНН,
Константы.КурсДоллара КАК Курс
ИЗ
РегистрСведений.Константы.Константы КАК Константы
";
- Для периодических констант в запросе можно использовать функцию КонстантаЗначение() с указанием даты.
4. Обработка отсутствующих значений
Всегда стоит помнить, что константа может быть не заполнена. Надёжный код должен это учитывать.
НаименованиеОрганизации = Константы.НаименованиеОрганизации.Получить();
// Сообщить(НаименованиеОрганизации); // Упадёт с ошибкой, если значение Неопределено
Если НаименованиеОрганизации = Неопределено Тогда
Сообщить("В константе 'НаименованиеОрганизации' не задано значение!", СтатусСообщения.Важное);
// Или подставить значение по умолчанию
// НаименованиеОрганизации = "Организация не указана";
Иначе
Сообщить(НаименованиеОрганизации);
КонецЕсли;
5. Константы vs Перечисления vs Общие макеты
Иногда разработчики путают, где что использовать.
-
Константы: Для значений, которые могут меняться администратором в процессе эксплуатации, но редко (название фирмы, email, настройки поведения).
- Перечисления: Для строго фиксированного набора значений, который не меняется без изменения конфигурации (виды документов, статусы заказов: "Новый", "В работе", "Выполнен"). Это "константы для разработчика".
- Общие макеты: Для хранения статических данных, которые являются скорее "ресурсами", а не "настройками" (шаблоны Excel, HTML-макеты для писем, картинки).
Константы в 1С — это встроенный и мощный инструмент для применения этого принципа. Используйте их для хранения всей информации, которая не должна меняться в рамках бизнес-операций. А в своем коде старайтесь мыслить в парадигме "создать новое, а не изменить старое". Это один из признаков зрелого и качественного программного обеспечения. Это мощный инструмент метаданных, который при правильном использовании позволяет:
- Структурировать настройки системы в одном месте.
- Эффективно работать с историей через периодичность.
- Учитывать аналитику через подчинение измерениям.
- Строить производительные решения за счёт встроенного кэширования.