我面临以下问题。
我正在为人类的信息创建一个数据库。所有人类可分为三类:成年女性,成年男性,儿童。很明显,“高度”和“重量”等参数适用于所有类别。参数“儿童数”仅适用于成年人,而参数“怀孕次数”仅适用于女性。此外,根据类别,每个参数可以分类为强制参数或可选参数(例如,对于成年人,参数“前伴侣数量”是可选的。)
当我加载(说)“高度”和“重量”时,我检查这两个字段中的信息是否是自洽的。即,我将高度= 6'4''且重量= 10磅的记录标记为错误(显然,这在物理上是不可能的)。我有几个类似的验证规则。
当我插入关于人类的记录时,我需要反映信息的以下特征:
所以我的问题是如何在技术上组织它。目前,所有这些必需的功能要么是硬编码的,没有统一的逻辑,要么分成完全独立的块。我需要创建一个统一的方法。
在这方面,我脑子里有一些天真的想法。例如,对于每个类别的人类,我可以创建并存储可能字段的列表(我称之为“模板”)。 A可以标记那些必需的字段。
当我插入关于人类的记录时,我会复制模板并标记实际处理了此模板中的哪些字段。在下一阶段,我可以在模板的这个副本中标记当前要验证的字段。
验证模块通过以下方式进行了特别更正:对于每个验证程序,我创建了一个在此特定验证程序中使用的字段列表。然后,我只调用那些在要验证的特定人的模板副本中具有实际标记为“待验证”的字段的验证程序(参见上一段)。
如您所见,这是解决此问题最直接的方法。但我的猜测是,有很多非常标准化的方法我都不知道。我真的怀疑我是世界上第一个解决这个问题的人。我不喜欢我的解决方案,因为编写代码以正确反映此复制模板中记录发生的所有“更新”真的很痛苦。
所以,我请你分享你的意见,你将如何解决这个问题。
答案 0 :(得分:2)
我认为这里有两个问题:
你应该单独解决它们 - 试图同时解决这两个问题可能太难了。
在RDBMS中有一些多态数据的方法 - 例如,ORM使用术语inheritance mapping。这里的三个解决方案 - 每个类层次结构的表,每个子类的表和每个具体类的表 - 是“纯粹的”关系解决方案。您还可以使用“Entity-Attribute-Value”设计,或使用文档方法(以XML或JSON等结构化格式存储数据) - 这些不是“纯粹的”关系选项,而是取而代之。
验证复杂的业务规则通常是使用rule engines完成的 - 这些都是超酷的技术,但您必须确保您的问题确实适合他们的解决方案 - 决定投资规则引擎意味着您的项目改变为规则引擎项目,而不是“人类”项目。或者,大多数主流解决方案都体现了应用程序业务逻辑层中实体的业务逻辑。听起来你已经超出了这个。
答案 1 :(得分:1)
在健康方面和金融工具方面,这个确切的问题被用作Martin Fowlers书籍分析模式的主要例子。这是一个广泛的主题。正如@NevilleK所说,你正试图处理两个问题,最好分别处理它们。解决这些问题的一种超简化方法是:
1多态数据的存储 - 仅在类别表中放置类别所共有的必需数据。对于可选数据,将它们放在一个单独的表中1-1与类别表的关系。仅当存在要记录的值时,才会在这些可选表中创建条目。验证数据的记录也可以放在这些附加表中。
2验证复杂的业务规则 - 考虑可能出现的错误类型很有用。有许多方法可以对错误进行分类,但我发现最有用的方法是(a)类型错误,只要通过查看数据就可以判断出值是错误的 - 例如1980-02-30。 (b)背景错误,只能通过参考先前捕获的日期来检测错误 - 例如DoB 1995-03-15,结婚日期1996-08-26。 (c)系统所在 - 数据类型正常;上下文没问题;但是,当更多信息曝光时,信息只能在以后被检测为不正确,例如,如果我在1990-12-31注册我的DoB,那时它就是不同的东西。后一类错误通常必须由正在开发的系统之外的程序来处理。
答案 2 :(得分:0)
我会使用Party Role模式(Silverston):
Party
id
name
Individual : Party
current_weight
current_height
PartyRole
id
party_id
from_date
to_date (nullable)
AdultRole : PartyRole
number_of_children
FemaleAdultRole : AdultRole
number_of_pregnancies
Postgres具有时间扩展,以便您可以强制执行一方只能一次扮演一个角色(但保持其角色历史)。
使用表继承。为简单起见,使用单表继承(具有空值),对于无空值,使用类表继承。