我有一个应用程序,它有很多数据库关系,它们相互依赖,可以成功运行应用程序。应用程序中的铰链是一个名为Schedule的模型,但是计划将拉出Blocks,Employee,JobTitle和Assignment(除此之外,每个Block也会从数据库中提取一个赋值)到全天组织员工日程安排。
当我构建应用程序时,我非常重视验证,以确保在将所有内容保存到数据库之前所有部分都必须到位。到目前为止,这已经非常出色,应用程序已经上线了近6个月,每月提供大约150,000个请求,没有打嗝或错误。直到上周。
上周,当某人正在改变计划时,看起来数据库出错,并且计划已保存到数据库,其分配缺失。因为在每个视图中都调用了关联,所以无论何时从数据库调用此调度,应用程序都会在调用nil时抛出NoMethod错误。
以我所声明的方式设计应用程序时,您是否防止数据库/验证可能出现故障?如果是这样,你如何编程防御呢?在将其发送到视图之前,您是否检查了每个关系以确保它不是nil?
我知道这个问题很普遍,如果我的意思更具体,请在评论中告诉我。
答案 0 :(得分:5)
我建议添加database-enforced foreign key constraints和wrapping important groups of operations into transactions。
如果某处的Schedule和Assignment之间存在外键,则数据库强制的外键约束将阻止错误插入。此外,如果将特定操作包装在事务中,则可以确保整个插入/更新/删除流发生或失败,恢复到干净状态。
答案 1 :(得分:5)
除了验证和添加其他答案中提到的一些数据库约束之外,您还可能运行后台作业,定期扫描数据库以查找孤立。
当它找到一个时,它会清理它(如果可能的话),或删除它,或者只是将它标记为非活动状态并向您发送电子邮件,以便您以后查看。根据数据的数量和性质,每分钟一次,每小时一次,每天一次......
这样一来,如果不管你有什么保障措施,不良数据就会进入,你很快就会知道它。
答案 2 :(得分:1)
我会在这方面争论非常规的智慧。您描述的约束不属于数据库,它们属于您的OO代码。并且“数据库错误”并不是真的,应用程序插入不正确验证的数据无疑是正确的。
当您开始期望数据库承担这些检查的负担时,您将业务规则放入架构中。至少,这使得编写单元测试变得更加困难(这可能是你应该首先发现的;但现在你有机会再添加一个测试。)
理想情况下,您应该能够将RDBMS替换为其他一些通用数据存储,并且仍然可以在适当的其他位置正确激活所有功能逻辑并保持不变。用户界面不应该与DAL交谈,更不用说直接处理数据库异常了。
如果需要,您可以添加其他数据库约束,但它应该严格地作为备份。正如您所看到的,优雅地处理数据库结构错误(特别是涉及UI时)要困难得多。
答案 3 :(得分:-1)
如果要使应用程序正常运行必须符合要求,那就是assert()
的真正含义。我几乎没用过Ruby,但我想它必须有这个概念。使用它们可以在整个代码中的各个位置强制执行前提条件。结合清理和验证外部(用户)输入应该足以保护您。我认为如果在经过大量检查后出现问题,您的应用程序将被允许崩溃(当然是以受控方式)。
我怀疑您遇到的问题是数据库中的错误。更有可能的是,您的验证中存在一些您忽略的边缘情况。