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

Источник

Оставить комментарий