Советы по разработке формата файла сериализации, который позволит легко объединять

Скажем, я создаю инструмент моделирования UML. Данные имеют некоторую иерархическую организацию, и элементы модели должны иметь возможность ссылаться на другие элементы. Мне нужен способ сохранить файлы моделей на диск. Если несколько человек могут работать над файлами одновременно, придет время объединить эти файлы моделей. Также неплохо было бы сравнить две ревизии в системе контроля версий и посмотреть, что изменилось. Похоже, это будет общая проблема во многих доменах.

Чтобы это хорошо работало с использованием существующих инструментов различия и слияния, формат файла должен быть текстовым, разделенным на несколько строк.

Какие существующие форматы сериализации хорошо (или плохо) решают такие проблемы? Или, если вы разрабатываете собственный формат файла, какие есть советы/рекомендации/подводные камни?

Дополнительный вопрос: какие-либо дополнительные рекомендации, если я хочу в конечном итоге разделить модель на несколько файлов, каждый из которых контролируется отдельно?


person Dan    schedule 24.01.2011    source источник


Ответы (2)


Я давно решил эту проблему для октавы/матлаба, теперь мне нужно что-то для С#. Задача состояла в том, чтобы объединить две октавные структуры в одну. Я не нашел ни инструмента слияния, ни подходящего сериализатора, поэтому мне пришлось что-то придумать.

Самое важное концептуальное решение заключалось в том, чтобы разделить дерево структур на строки с полным путем и содержимым листа.

Основная идея была

  1. Сериализация структуры в строки, где каждая строка представляет базовую переменную (матрицу, строку, число с плавающей запятой,...)
  2. Массив или матрица структуры будут иметь индекс в пути.
  3. объединить два полученных текстовых файла, отсортировать строки
  4. обнаруживать коллизии и выполнять обработку коллизий (очень просто, потому что одни и те же свойства будут располагаться непосредственно друг над другом после сортировки строк)
  5. десериализовать

Пример:

>> s1

s1 =

скалярная структура, содержащая поля:

b =

  2x2 struct array containing the fields:

    bruch

t = Textstring
f =  3.1416
s =

  scalar structure containing the fields:

    a =  3
    b =  4

будет сериализован в

root.b(1,1).bruch=txt2base('isfloat|[ [ 0, 4 ] ; [ 1, 0 ] ; ]');
root.b(1,2).bruch=txt2base('isfloat|[ [ 1, 6 ] ; [ 1, 0 ] ; ]');
root.b(2,1).bruch=txt2base('isfloat|[ [ 2, 7 ] ; [ 1, 0 ] ; ]');
root.b(2,2).bruch=txt2base('isfloat|[ [ 7 ] ; [ 1 ] ; ]');
root.f=txt2base('isfloat|[3.1416]');
root.s.a=txt2base('isfloat|[3]');
root.s.b=txt2base('isfloat|[4]');
root.t=txt2base('ischar|Textstring');

Преимущество этого метода в том, что его очень легко реализовать и он удобочитаем для человека. Сначала вам нужно написать две функции base2txt и txt2base, которые преобразуют базовые типы в строки и обратно. Затем вы просто рекурсивно проходите по дереву и записываете для каждого свойства структуры путь к свойству (здесь разделенный знаком «.») и содержимое в одну строку.

Большой недостаток в том, что, по крайней мере, моя реализация этого очень медленная.

Ответ на второй вопрос: Есть ли уже что-то подобное? Я не знаю... но я искал какое-то время, так что я так не думаю.

person Marco Haschka    schedule 19.10.2016

Некоторые рекомендации:

Формат должен быть разработан таким образом, чтобы при изменении только одной вещи в модели в файле было только одно соответствующее изменение. Некоторые контрпримеры:

  • Плохо, если формат файла использует произвольные идентификаторы ссылок, которые меняются каждый раз, когда вы редактируете и сохраняете модель.
  • Плохо, если элементы массива хранятся с явно указанными их индексами, поскольку вставка элементов в середину массива приведет к тому, что все последующие индексы будут перетасованы вниз. Это приведет к тому, что эти элементы будут отображаться в «diff» без необходимости.

Что касается ссылок: если идентификаторы создаются последовательно, то два человека, редактирующие одну и ту же версию модели, могут в конечном итоге создать новые элементы с одним и тем же идентификатором. Это станет проблемой при слиянии.

person Dan    schedule 24.01.2011
comment
Использование UUID здесь может быть хорошей идеей. Не обязательно 128-битные идентификаторы, вы также можете использовать что-то вроде хеша (имя пользователя) + серийный номер или что-то в этом роде. - person ordnungswidrig; 28.01.2011
comment
Я бы также избегал полей фиксированной длины и списков, разделенных запятыми (черт возьми, чтобы объединить). - person louisgab; 03.02.2011
comment
@Dan Дэн - это не ответ, почему ты просто не обновил вопрос этим содержанием? Как это выглядит (со страницы указателя), кто-то обратился к вашему вопросу. - person Rudu; 03.02.2011
comment
@Руду: я согласен. У меня нет ответа... надеялся получить некоторые предложения. Я подумал, может быть, это отсутствие ответа было отправной точкой. Я тоже собирался сделать этот CW, но не смог найти галочку. Похоже на вопрос, который может иметь несколько правильных предложений и, возможно, не иметь правильного ответа. - person Dan; 04.02.2011
comment
@rene: пользовательский инструмент слияния - интересная идея - возможно, ожидать, что вы сможете выполнять слияние, не зависящее от содержимого, с использованием общих инструментов (например, diff3), нереалистично. - person Dan; 04.02.2011
comment
@Dan Возможно, ответа нет;) Итак, вы хотите выбрать формат файла, который помогает использовать общую систему контроля версий (GIT, SVN и т. Д.?) - person Rudu; 04.02.2011
comment
@Руду: Верно. Текущий формат файла имеет некоторые проблемы. У меня есть идеи по улучшению, но похоже, что это будет обычная проблема, с которой другие люди сталкивались раньше. В любом случае, на самом деле это не является высоким приоритетом, поэтому я буду продолжать думать об этом и обновлять здесь все, что придумаю. - person Dan; 04.02.2011