我是一名家谱软件的开发人员(使用C++和Qt编写)。我之前没有遇到问题,直到有一位客户给我发送了一个错误报告。问题在于该客户有两个孩子都与自己的女儿生过孩子,导致我的软件出现错误而无法使用。
这些错误是因为我在处理家庭图表时使用了各种断言和不变量(例如,在遍历循环后,程序会声明X不能同时是Y的父亲和祖父)。
我如何解决这些错误而不必删除所有数据断言?
我是一名家谱软件的开发人员(使用C++和Qt编写)。我之前没有遇到问题,直到有一位客户给我发送了一个错误报告。问题在于该客户有两个孩子都与自己的女儿生过孩子,导致我的软件出现错误而无法使用。
这些错误是因为我在处理家庭图表时使用了各种断言和不变量(例如,在遍历循环后,程序会声明X不能同时是Y的父亲和祖父)。
我如何解决这些错误而不必删除所有数据断言?
除了可能存在的法律影响之外,显然您需要将家谱上的“节点”视为前任人物,而不是假设该节点可以是唯一的人物。
让家谱节点包括一个人以及他们的后代,然后您可以在树的深处再添加另一个节点,其中包含相同的人但具有不同的后代。
你的家谱应该使用有向关系。这样就不会出现循环了。
家谱数据是循环的,不适合于非循环图,因此如果您有反对循环的断言,则应将其删除。
在不创建自定义视图的情况下处理此问题的方法是将循环父级视为“虚拟”父级。换句话说,当一个人既是某人的父亲又是祖父时,祖父节点会正常显示,而父亲节点则呈现为具有简单标签(如“见祖父”)的“虚拟”节点,并指向祖父。
为了进行计算,您可能需要改进逻辑以处理循环图,这样如果有循环,则不会访问节点超过一次。
通常情况下,断言很难经受住与真实世界数据的接触。在软件工程的过程中,决定要处理哪些数据以及哪些数据超出范围是其中的一部分。
关于家庭“树”(实际上是包括循环在内的完全图),有一个有趣的轶事:
当你考虑到代孕或“模糊父亲身份”时,事情变得更加奇怪。我娶了一位寡妇,她有一个成年女儿。我父亲经常来看我们,爱上了我的继女并娶了她。结果,我的父亲成了我的儿子,我的女儿成了我的母亲。一段时间后,我给我的妻子生了一个儿子,他是我父亲和我的叔叔。我的父亲的妻子(也是我的女儿和我的母亲)生了一个儿子。因此,我在同一个人身上得到了兄弟和孙子。我的妻子现在是我的祖母,因为她是我母亲的母亲。换句话说,我是我的妻子的丈夫,同时也是我的妻子的继孙子。换句话说,我是自己的祖父。
或者它们可以是技术性的:
通过运行模拟测试,您将发现许多奇怪的角落案例。修复它们需要很长时间。此外,您会失去很多优化,您的软件将运行得更慢。您必须决定是否值得,并且是否属于您的软件范围。
不要移除所有断言,仍然应检查诸如一个人是他/她自己的父母或其他不可能的情况,并呈现出错误。如果不太可能,可以发出警告,以便用户仍然可以检测常见的输入错误,但如果一切正确,它将正常工作。
我会将数据存储在向量中,每个人都有一个永久的整数,将父母和孩子存储在个人对象中,其中该 int 是向量的索引。这将很快地在各个世代之间转换(但对于诸如名称搜索之类的事情则较慢)。这些对象将按创建时间顺序排列。
复制父级 (或使用符号链接 / 引用)。
例如,如果您正在使用分层数据库:
$ #each person node has two nodes representing its parents.
$ mkdir Family
$ mkdir Family/Son
$ mkdir Family/Son/Daughter
$ mkdir Family/Son/Father
$ mkdir Family/Son/Daughter/Father
$ ln -s Family/Son/Daughter/Father Family/Son/Father
$ mkdir Family/Son/Daughter/Wife
$ tree Family
Family
└── Son
├── Daughter
│ ├── Father
│ └── Wife
└── Father -> Family/Son/Daughter/Father
4 directories, 1 file