В процессе интеграции 1С с внешними информационными системами (ИС) разработчики часто сталкиваются с жесткими ограничениями на длину полей. Стандартный внутренний идентификатор 1С (UUID/GUID) представляет собой 128-битное число, которое в строковом виде занимает 36 символов (с дефисами) или 32 символа (без дефисов). Если принимающая система ограничивает длину кода, например, 17 символами, стандартный подход передачи УникальныйИдентификатор() перестает работать. В этой статье мы разберем несколько стратегий решения этой задачи: от математического сжатия до использования особенностей структуры идентификаторов 1С.
Прежде чем приступать к сокращению, проанализируем, что представляет собой идентификатор 1С. Платформа использует GUID версии 1 (V1), который формируется на основе текущего времени (с точностью до 100 наносекунд) и MAC-адреса сетевой карты сервера. Рассмотрим стандартный вид: d6c20ebd-0276-11db-8007-0013d4609ea4.
Важные моменты:
Проанализируем ситуацию: если нам нужно обеспечить уникальность только внутри нашей базы для 3-5 тысяч записей, передавать MAC-адрес сервера избыточно. Мы можем использовать только «динамическую» часть идентификатора.
Стандартный GUID записан в 16-ричной системе (Hex). Чтобы уменьшить количество символов без потери информации, нам нужно перейти к системе счисления с большим основанием. Рассмотрим математическую прогрессию:
Однако использование системы с основанием 185 и выше требует применения спецсимволов и Unicode, что часто неприемлемо для ИС-приемников. Если же мы готовы пожертвовать избыточностью (например, отбросить статичную часть MAC-адреса), то Base62 идеально подходит. Рассмотрим программную реализацию перевода числа из одной системы в другую.
Для реализации этого метода воспользуемся функциями преобразования:
// Функция преобразует значение из одной системы счисления в другую
Функция AnyToAny(Знач ЗначениеСтр, АлфавитИсточник, АлфавитПриемник)
Возврат DecToAny(AnyToDec(ЗначениеСтр, АлфавитИсточник), АлфавитПриемник);
КонецФункции
Функция AnyToDec(Знач ЗначениеСтр, Т)
Результат = 0;
Основание = СтрДлина(Т);
Длина = СтрДлина(ЗначениеСтр);
Для i = 0 По Длина - 1 Цикл
Символ = Сред(ЗначениеСтр, Длина - i, 1);
Позиция = СтрНайти(Т, Символ) - 1;
Результат = Результат + Позиция * Pow(Основание, i);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция DecToAny(Знач ЧислоДесятичное, Т, Длина = 0)
Результат = "";
Основание = СтрДлина(Т);
Пока ЧислоДесятичное > 0 Цикл
Остаток = ЧислоДесятичное % Основание;
Результат = Сред(Т, Остаток + 1, 1) + Результат;
ЧислоДесятичное = Цел(ЧислоДесятичное / Основание);
КонецЦикла;
Пока СтрДлина(Результат) < Длина Цикл
Результат = Лев(Т, 1) + Результат;
КонецЦикла;
Возврат Результат;
КонецФункции
Используя этот подход, мы можем взять первые 16-20 символов GUID (без дефисов) и сжать их в 10-12 символов Base62, что гарантированно уместится в лимит 17 символов.
Как мы выяснили при анализе структуры, для небольших справочников (до 10-50 тысяч записей) первые три сегмента GUID обеспечивают достаточную уникальность. Рассмотрим пример: вместо полного d6c20ebd-0276-11db-8007-0013d4609ea4 мы берем только d6c20ebd027611db (16 символов).
Почему это работает? В GUID V1 эти сегменты содержат временную метку. Вероятность того, что два разных объекта в 1С получат одинаковую метку времени в этих разрядах, крайне мала, если только они не создаются на разных серверах в одну и ту же наносекунду с последующим слиянием баз.
Проанализируем ситуацию программно:
// Получение сокращенного идентификатора
ПолныйУИД = Строка(СсылкаНаОбъект.УникальныйИдентификатор());
СокращенныйУИД = СтрЗаменить(Лев(ПолныйУИД, 18), "-", ""); // Получаем 16 символов
Если нам не нужно восстанавливать исходный GUID из сокращенного кода, мы можем применить хеш-функцию, например MD5 или CRC64. Хеш MD5 выдает 128 бит (32 символа в Hex), что опять же много. Однако CRC64 дает 64 бита, которые в системе Base62 преобразуются в 11 символов.
Важно помнить: хеш-функция теоретически допускает коллизии (разные GUID могут дать одинаковый хеш). Но для объема данных в несколько тысяч записей при использовании 64-битного хеша вероятность коллизии стремится к нулю.
Если бизнес-процесс критичен к уникальности и вы не хотите полагаться на математические вероятности, следует использовать Регистр сведений. Это классический архитектурный паттерн в 1С для обмена данными.
Алгоритм действий:
СоответствиеОбъектовДляОбмена.Объект (Тип: ЛюбаяСсылка) и ИдентификаторИС (Тип: Строка 17).Этот метод позволяет полностью избежать «кракозябр» и математических проблем, обеспечивая 100% стабильность обмена, хотя и требует небольшого изменения конфигурации (добавления одного регистра).
Выясним причину выбора конкретного метода:
Base62.AnyToAny.Рассмотренные способы позволяют гибко подойти к ограничениям внешних систем, сохраняя при этом целостность данных при обмене из 1С.