如何处理程序版本更新时更改的数据结构?

Maw*_*awg 10 c c++ embedded

我做嵌入式软件,但我猜这不是一个嵌入式问题.我不(不能出于技术原因)使用像MySQL这样的数据库,只是C或C++结构.

是否存在如何处理从程序版本到版本的这些结构的布局变化的一般原理?

我们来一本地址簿.从程序版本x到x + 1,如果:

  • 一个字段被删除(看起来很简单)或添加(确定如果所有可以使用一些新的默认值)?
  • 字符串变长还是变短?一个int从8位到16位有符号/无符号?
  • 也许我将姓氏/名字或分割名称合并为两个字段?

这只是一些简单的例子; 我不是在寻找那些答案,而是寻找通用的解决方案.

显然,我需要一些硬编码逻辑来处理每个变化.

如果有人没有从版本x升级到x + 1但等待x + 2怎么办?我应该尝试组合更改,还是仅应用x - > x + 1后跟x + 1 - > x + 2?

如果版本x + 1有问题并且我们需要回滚到s/w的先前版本但是已经"升级"了数据结构怎么办?

我倾向于TLV(http://en.wikipedia.org/wiki/Type-length-value),但可以看到很多潜在的麻烦.

这不是什么新鲜事,所以我只是想知道别人怎么做......

pet*_*hen 11

我确实有一些代码,如果有必要,可以从两个较短的段中将较长的字符串拼凑在一起.呸.这是我保持一些数据兼容12年后的经验:

确定目标 - 有两个:

  • 新版本应该能够读取旧版本编写的内容
  • 旧版本应该能够读取新版本的内容(更难)

向版本0添加版本支持 - 至少编写版本标头.保持(可能很多)旧的阅读器代码,可以原始地解决第一种情况.如果你不想执行情况2,开始拒绝新的数据,现在!

如果您只需要案例1,并且随着时间的推移而预期的变化相当小,那么您已经设置好了.无论如何,在第一次发布之前完成的这两件事可以为您节省许多麻烦.

序列化期间转换 - 在运行时,仅将数据保留在内存中的"新格式"中.在持久性限制下进行必要的转换和测试(在读取时转换为最新版本,在编写时实现向后兼容性).这将版本问题隔离在一个地方,有助于避免难以追踪的错误.

保留所有版本的一组测试数据.

存储可用类型的子集 - 将实际序列化数据限制为几种数据类型,例如int,string,double.在大多数情况下,额外的存储大小由减少的代码大小组成,支持这些类型的更改.(但这并不总是可以在嵌入式系统上进行权衡).

例如,不要存储短于原始宽度的整数.(当您需要存储长整数数组时,可能需要这样做).

添加一个断路器 - 存储一些密钥,允许您故意使旧代码显示错误消息,表明此新数据不兼容.您可以使用作为错误消息一部分的字符串 - 然后您的旧版本可能会显示它不知道的错误消息 - "您可以使用我们网站上的ConvertX工具导入此数据"在本地化方面不是很好应用但仍然比"Ungültiges格式"更好.

不要直接序列化结构 - 这是逻辑/物理分离.我们混合使用两种,都有其优点和缺点.如果没有一些运行时开销,这些都无法实现,这几乎可以限制您在嵌入式环境中的选择.无论如何,在持久性过程中不要使用固定的数组/字符串长度,这应该已经解决了一半的麻烦.

(A)一个正确的序列化机制 - 我们使用一个bianry序列化器,它允许在存储时启动一个"块",它有自己的长度头.在读取时,会跳过额外的数据,并且缺少数据的默认初始化(这简化了序列化代码中大量实现"读取旧数据".)块可以嵌套.这就是你在物理方面所需要的一切,但需要一些糖衣来完成常见任务.

(B)使用不同的内存中表示 - 内存中的表示基本上可以是map<id, record>id woukld可能是整数,并且record可能是

  • 空(未存储)
  • 一个原始类型(字符串,整数,双 - 你用得越少越容易)
  • 一组基本类型
  • 和记录数组

我最初写道,所以这些人不会问我每个格式兼容性问题,虽然实现有很多缺点(我希望我能认识到今天的清晰度问题......)它可以解决

查询非现有值将默认返回默认/零初始化值.当你在访问数据时记住这一点,并且在添加新数据时,这有很大帮助:想象版本1将自动计算"foo长度",而在版本2中,用户可以覆盖该设置.值为零 - 在"计算类型"或"长度"中应表示"自动计算",并且您已设置.

以下是您可以预期的"更改"方案:

  • 标志(是/否)扩展为枚举("是/否/自动")
  • 设置分为两个设置(例如,"添加边框"可以拆分为"在偶数天添加边框"/"在奇数天添加边框".)
  • 添加设置,覆盖(或更糟糕地,扩展)现有设置.

为了实现案例2,您还需要考虑:

  • 没有任何价值可以被另一个重新转移或替换.(但是在新格式中,它可以说"不支持",并添加了一个新项目)
  • 枚举可能包含未知值,有效范围的其他更改

唷.那是很多.但它并不像看起来那么复杂.