Если вы разрабатывали программную систему, то, вероятно, искали в интернете разные справочники вроде государств, языков, единиц измерения, форматов данных и т.д. Если да, то у меня с вами есть что-то общее. Я тоже искал и находил. Потом снова, но уже другие. Все это старался как-то впихнуть в проект. Но многие категории - многие печали.
Скажем, на github’е достаточно много открытых справочников. И они пользуются популярностью, но подходы к организации данных везде отличаются.
В общем, я сделал один большой реестр общеизвестных данных, назвал UED и жизнь стала чуть лучше.
Чаще всего нам что нужно? А немного: идентификатор и название. Название предложим пользователю выбрать, а по идентификатору определим что он там выбрал и дальше будем разруливать это кодом. Есть там несколько деталей, которые хотелось бы учесть:
(immutability) пусть идентификатор, однажды сопоставленный, скажем, с валютой “Австралийский доллар”, никогда не меняется
(internationalization) пользователи не всегда понимают по-русски, потому неплохо было бы для сущностей иметь наименования на нескольких языках
кроме цифровых идентификаторов очень полезно иметь аналог в виде короткой мнемоники (ну это как dns-имена в web’е - никому не нравится помнить цифры, и все радостно пользуются доменными именами). Кстати, такую мнемонику, как и цифровой идентификатор, лучше держать константной - по тем же причинам.
Да, никаких адских нагромождений миллиона атрибутов и сложных взаимосвязей. Точнее, пусть они будут, но мы не хотим о них думать пока время не пришло.
Так и сделали: плоский текстовый файл в наипростейшем виде (и с нормальными комментариями, что немаловажно). Говоря “наипростейший” я подразумеваю, что базовое описание сущности состоит из двух полей, разделенных пробелом (можно несколькими). А определение человеко-читаемого названия состоит из трех полей: между идентификатором и самим названием помещаем мнемонику языка.
Примеры:
Государство Япония: 0000003f00000074 "jp" так по-русски: 0000003f00000074 ru "Япония" а так по-итальянски: 0000003f00000074 it "Giappone"
Это - ссылка на полный исходный файл (он не маленький, лайфхак: если сгрузить хотя бы часть этого файла LLM’у, то можно получить весьма подробные пояснения.). Вы сможете побродить по нему и оценить насколько это может быть вам полезно.
А я продолжу.
Насчет анатомии числового идентификатора. Это всегда 64-разрядное целое число, в старших битах которого содержится мета-информация о том, что следует в младших битах. Применительно к примеру с государством, мета-информация представлена шестнадцатеричным значением 3f. В том же реестре мы можем найти вот такую запись:
000000010000003F "statu"
Она представляет мета-тип государство (в некоторых случаях я использую латынь для мнемоники как альтернативу английским словам, чтобы минимизировать путаницу с их бытовыми применениями). Здесь мета-информация занимает 32 бита, но это не всегда так. Для перечисляемых типов да, оставшихся 4 байт хватит почти для всех случаев. Но UED также способен хранить плотно упакованные квази-непрерывные величины. Например: ARGB-цвета, геокоординаты, дату, время и даже такие экстравагантные данные, как автомобильные номера или коды ИНН.
Например:
ARGB-представление цвета: 0000004fffbdb76b "darkkhaki" Российский автомобильный номер У114АХ750: 40A230405AB1C03E
Само собой разумеется, что в исходном файле значения автомобильных номеров не перечислены - здесь я просто показал для иллюстрации то, как номер кодируется в UED-значении. Для цветов же некоторые стандартные (и не очень) символы представлены в исходном файле, что не запрещает работать с любыми вариантами, кодируя их соответствующим образом.
Обращу внимание читателя на то, что в примере автомобильного номера информация о типе занимает 2 байта, а остальные 6 байт кодируют сам номер (вместе с кодом государства, который тоже сопоставляется с UED-значением).
Для некоторых же типов полезная нагрузка может занимать 56 бит. Это касается геолокации, специального представления десятичных чисел и некоторых других сущностей. Увы, этих других типов может быть не более 127 штук (8 минус один бит индикатора и минус ноль), потому приходится аккуратно расходовать такие значения.
Диаграммы распределения бит:
Режим 'перечисление' — 32 бита тип + 32 бита значение Флаг: старший байт 0x00 ┌──────────────────────────────┬──────────────────────────────┐ │ мета-тип (32 бита) │ значение (32 бита) │ │ 0x0000003F (statu) │ 0x00000074 → Япония │ └──────────────────────────────┴──────────────────────────────┘ Также: цвета (0x0000004F | 0xFFBDB76B → darkkhaki) Режим 'плотная упаковка' — 16 бит тип + 48 бит данные Флаг: старший байт 0x40..0x7F (бит 0x40 установлен) ┌────────────────┬─────────────────────────────────────────────┐ │ мета-тип │ данные (48 бит) │ │ (16 бит) │ │ │ 0x40A2 │ 0x3040 5AB1C03E → У114АХ750 │ │ (ru_licplate) │ │ └────────────────┴─────────────────────────────────────────────┘ Также: EAN-13, EAN-8, UPC, GLN, ИНН, КПП, СНИЛС и т.д. Режим 'максимальная упаковка' — 8 бит тип + 56 бит данные Флаг: старший байт 0x80..0xFF (бит 0x80 установлен) ┌────────┬─────────────────────────────────────────────────────┐ │ мета- │ данные (56 бит) │ │ тип │ │ │(8 бит) │ 24 бита (HiDWord) + 32 бита (LoDWord) │ │ 0x8A │ → время в мс от 1601-01-01 │ │(time) │ │ └────────┴─────────────────────────────────────────────────────┘
Далее. Какую пользу это все может принести?
Самое простое - использование перечисляемых типов как общего “источника истины” в программных проектах.
Вспомогательный инструмент для интернационализации популярных слов и выражений (дни недели, месяцы, государства).
Компактное представление специализированных типов данных для обработки больших массивов информации.
Какая инфраструктура сейчас есть вокруг UED?
Тот файл, ссылку на который я привел, используется как исходник. Далее он транслируется несложным компилятором в почти такой же, но лишенный комментариев, с однообразными пробелами и прочими полировками (ued-id.dat в репозитории). Это дает возможность более-менее адекватно сохранить хэш файла и сравнивать его с предыдущей версией. Благодаря этому есть возможность проконтролировать неизменяемость числовых и мнемонических идентификаторов и не допустить удаления оных - так достигается постоянство. В свою очередь такое постоянство дает некоторую опору под ногами для применения идентификации в программных кодах. С этой целью упомянутый компилятор генерирует заголовочный файл с определениями для языков C/C++ и аналогичный для Java (ued-id.h и ued-id.java соответственно).
Вся инфраструктура доступна в исходных кодах, но пока только в составе проекта OpenPapyrus. Это, к сожалению, не просто неудобно, а очень неудобно - тот проект огромный (собственно, одна из причин почему приходится изобретать всевозможные технологии типа UED).
Приведу неполный список перечислений:
dimension(физические размерности)uom(единицы измерения)atom(химические элементы)script(варианты письменностей)lingua(естественные языки)lingualocus(лингвистические локали)statu(государства)currency(валюты)dataformat(форматы данных)barcodesymb(стандарты кодирования штриховых кодов)colorrgb(стандартные цвета)calendar(календари)jcmensis(месяцы по юлианскому и григорианскому календарям)dayofweek(дни недели)ruchznprodtype(стыдно признаться, но это товарные категории честного знака, я вынужден взаимодействовать с этим)phonenumberkind(типы телефонных номеров)
А вот (опять же, неполный) список квази-непрерывных данных
colorrgb(цвет в ARGB-представлении)date_day(григорианская дата с градацией в днях, отсчитываемая от 25 ноября 4714г. до н.э.)time_msec(время в миллисекундах от 1601-01-01)time_sec(время в секундах от 1601-01-01)time_min(время в минутах от 1601-01-01)gln(GLN-код адреса)barcode_ean13(товарный код EAN13)barcode_ean8(товарный код EAN8)barcode_upc(товарный код UPC, включающий и UPC-A и UPC-E)ru_inn(российский налоговый идентификатор ИНН)ru_kpp(российский идентификатор КПП)ru_snils(российский идентификатор СНИЛС)ru_licplate(российские автомобильные номера)ar_dni(аргентинский персональный идентификатор DNI)cl_rut(чилийский налоговый идентификатор RUT)geoloc(геолокация)decimal(хитрое представление десятичного числа, никем кроме меня не признанное но, тем не менее, рабочее)
Есть еще что-нибудь?
Да. Кое какие задумки на будущее. Я планирую расширить все это до полноценной онтологии и даже включил в описание специальные мета-значения, которые позволят определять связи между сущностями.
На очереди свойства сущностей, которые позволили бы определять базовые атрибуты понятий.
Ну и кое-что еще попроще: нужны синонимы для символов и описаний на естественных языках, дабы можно было бы легко идентифицировать сущности в текстах.
Условия использования
Никаких. Если вам это нравится - берите и пользуйтесь. Есть замечания, предложения - welcome - буду рад исправлять дефекты и развивать технологию с учетом коллективного разума.
Комментарии (4)

SergeyProkhorenko
03.11.2026 10:49Когда Вы пытаетесь в идентификатор вставить метаданные, Вы этим портите идентификатор и закладываете мину под возможные в будущем изменения. Идентификатор не должен содержать в себе никакого бизнес-смысла. Совет: используйте UUIDv7, а под типы отводите отдельные поля таблиц. Вы не обойдетесь одной плоской табличкой
nin-jin
А чем обычная rdf онтология не угодила? Вам все равно нужны доп справочники, ибо одного только названия не достаточно.
antonsobolev Автор
Это - не онтология. Скорее, унифицированные, жестко идентифицируемые понятия. Онтологию я бы хотел добавить (и, вероятно, сделаю это), но как раз пере-изобретать rdf и прочие существующие подходы как-то неловко. То есть, это - прагматически выстроенные данные для использования в реальных программных проектах, а не академический продукт.