在处理查找表和相关业务逻辑时去掉硬编码值

时间:2009-10-30 14:56:58

标签: sql sql-server database-design business-logic

示例案例:

我们正在使用SQL Server构建租赁服务。有关可以租借的项目的信息存储在表格中。每个项目的状态可以是“可用”,“已租用”或“已损坏”。不同的状态驻留在查找表中。

ItemState表:

id name
1'可用'
2'租用'
3'破碎'

除此之外,我们还有一个业务规则,规定每当退回一个项目时,它的状态就会从“已租用”更改为“可用”。
这可以通过更新语句来完成,例如“update Items set state = 1 where id = @ itemid”。在应用程序代码中,我们可能有一个映射到ItemState id:s的枚举。但是,这些包含可能导致以后出现维护问题的硬编码值。假如开发人员要更改状态集但忘记修复相关的业务逻辑层......

有哪些好的方法或替代设计可以解决这类设计问题? 除直接答案外,还欢迎链接到相关文章。

9 个答案:

答案 0 :(得分:5)

根据我的经验,这是一个实际 进行硬编码的情况,最好是使用Enum,其中整数值与查找表的id匹配。我不能说“1”总是“可用”等等。

答案 1 :(得分:3)

我见过的大多数系统都会对查找表值进行硬编码并使用它。这是因为,在实践中,代码表很少会像您认为的那样发生变化。如果他们做了改变,你通常需要重新编译任何依赖于DDL的程序。

也就是说,如果你想让代码可维护(一个值得称赞的目标),最好的方法是将值外部化为属性文件。然后,您可以稍后编辑此文件,而无需重新编码整个应用程序。

这里的限制因素是你的应用程序依赖于你自己的内部状态来查找从查询表获得的值,因此这意味着一定量的耦合。

对于依赖该代码的查找(例如,如果您的代码表存储了用于地址下拉列表的双字母状态代码列表),然后你可以懒洋洋地将代码加载到一个对象中,并仅在需要时访问它们。但这对你正在做的事情不起作用。

答案 2 :(得分:2)

如果您在代码中定义了查找表和枚举,那么始终存在使它们保持同步的问题。这里没有太多可以做的事情。两者都有效地存在于两个不同的世界中,并且通常彼此不了解。

您可能希望拒绝使用查找表,只让业务逻辑运行这些值。在这种情况下,您会错过依赖参照完整性来支持数据完整性的选项。

另一种选择是以这种方式构建应用程序,使您在代码中永远不需要这些值。这意味着将业务逻辑的一部分移动到数据库层,这意味着将它们放在存储过程和触发器中。这也将具有与客户无关的好处。任何人都可以调用SP,并确保数据将保持在一致状态,与业务逻辑规则一致。

答案 3 :(得分:1)

你需要有一些永不改变的预定义值,无论是整数,字符串还是别的。

在您的情况下,状态的数值是状态的代理PRIMARY KEY,它在设计良好的数据库中永远不会改变。

如果您担心一致性,请使用CHAR代码:ARB

但是,你应该坚持使用它和数字代码,以便A总是意味着Available等。

您应该记录数据库结构以及代码。

答案 4 :(得分:1)

答案完全取决于您使用的语言:Java,PHP,Smalltalk甚至汇编程序中的解决方案都不一样......

但是,让我告诉你一些事情:虽然真正的硬编码值并不是一件好事,但有时你确实需要它们。这一个几乎就是其中之一:您需要在代码中声明您对业务逻辑的当前知识,包括这些硬编码状态

因此,在这种特殊情况下,我会对这些值进行硬编码。

答案 5 :(得分:1)

不要过度设计它。在尝试解决此问题之前,您需要弄清楚它是否是一个问题。你能想到任何合法的假设场景,你会改变itemState表中的值吗?不只是“如果有人改变了这张桌子怎么办?”但是“有人想因为Y的原因以X方式改变这张桌子,会有什么影响?”。你需要保持现实。

新州?你添加一行,但它不会影响现有的行。 删除状态?无论如何,您必须删除代码中对它的引用。 改变国家的身份?这样做没有合理的理由。 改变州名?没有合法的理由这样做。

所以真的没有理由担心这个。但是如果你必须在非理性的人的情况下干净地维护这个,他们随机决定将Available更改为2,因为它更适合他们的风水,请确保所有表都是通过从配置文件中读取这些值的脚本生成的,并且然后确保所有代码都从同一配置文件中读取常量。然后,您有一个定义位置,并且只要您想要更改修改该配置文件而不是DB /代码的值。

答案 6 :(得分:1)

我认为这是一个常见的问题和一个有效的问题,这就是为什么我用谷歌搜索并首先发现这篇文章。

如何创建一个公共静态类来保存所有查找值,而不是硬编码,我们在加载应用程序时初始化这些值并使用名称来引用它们?

在我的应用程序中,我们试过这个,它有效。你也可以做一些检查,例如代码中查找的不同可能值的数量应与db中的相同,如果不是,则log / email / etc.但我不想手动为40+商业实体的状态编码。

此外,这可能是OR映射这个更大问题的一部分。我们暴露了持久层的太多细节,因此我们必须处理它。使用像Entity Framework这样的技术,我们不需要担心“同步”部分,因为它是自动化的,我是对的吗?

谢谢!

答案 7 :(得分:0)

我使用了与您所描述的方法类似的方法 - 数据库中的表格,包含值和描述(对报告有用等)和代码中的枚举。我用代码中的注释来处理同步,这些注释说“这些值来自数据库ABC中的表X”,这样程序员就知道数据库需要更新。为了防止数据库端的更改而没有代码中的相应更改,我在表上设置了权限,以便只有某些人(希望他们也记得需要更改代码)才能访问。

答案 8 :(得分:0)

值必须是硬编码的,这实际上意味着它们不能在数据库中更改,这意味着将它们存储在数据库中是多余的。

因此,对它们进行硬编码并且在数据库中没有查找表。而是将项目状态直接存储在项目表中。