Unified Entity Definition (UED)
Если вы разрабатывали программную систему, то, вероятно, искали в интернете разные справочники вроде государств, языков, единиц измерения, форматов данных и т.д. Если да, то у меня с вами есть что-то общее. Я тоже искал и находил. Потом снова, но уже другие. Все это старался как-то впихнуть в проект. Но многие категории — многие печали.
Скажем, на 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 — буду рад исправлять дефекты и развивать технологию с учетом коллективного разума.
Автор: antonsobolev

