与使用DB相对,何时将一个实际数据值硬编码到代码中?


17

对我来说,一个长期存在的问题是:何时将数据(实际值)存储在数据库表中,何时将其正确存储在代码中?

无法达成共识的通常是这样的(*):

如果它是单个变量或简单结构,或者是几个值的数组,则将数据放在代码中。

[* 共识已在评论和答案中进行了辩论,但基本上我希望有一个前提来启动这个问题,因此随时可以提出挑战并加以改进 ]

例:

$number = 44;
$colors = array("blue", "yellow", ... "mauve");

如果它具有数百行以上相同类型的数据,请使用数据库。

但是似乎有一个灰色地带。那么不清楚的情况又如何呢?做出决定时需要注意哪些注意事项和因素?

示例:
假设您的公司使用10-15种不同类型的电机框架,它们可以表示为“ 412T”。您大约有30个,并且它们很少更改。您可以为这些数据库创建数据库表,也可以在数据库中对其进行硬编码。在这种情况下,电动机是静态的,物理的东西,不太可能经常改变。

将它们保留在代码中会使它们受到源代码控制,而在数据库中,通常不会跟踪数据库更改。但是将它们保存在数据库中可以从数据中释放(分离)代码。

我可以使用的另一个(实际)示例是我的这个问题:https : //stackoverflow.com/questions/26169751/how-to-best-get-the-data-out-of-a-lookup-table(当前为48行选项数据)。


3
无法达成共识的情况通常并非如此:如果是单个变量或简单结构,或者是几个值的数组,则将数据直接放在代码中。
Pieter B

有一种中间方法:数据存储在数据库中。然后将其提取以写入源代码(例如,在global_constants.h文件中)。
mouviciel 2014年

@mouviciel,但是构成数据的是...您需要一些数据才能访问数据库,所以您不能在其中存储所有数据。
jwenting

Answers:


33

我认为这两个语句并不能真正代表何时对数据进行硬编码:

如果它是单个变量或简单结构,或者是几个值的数组,则将数据放在代码中

如果它具有数百行以上相同类型的数据,请使用数据库

简单的反例(我敢肯定会有更好的反例):编程语言语法表是复杂的大型结构,通常经过硬编码。看一下Perl源代码中的示例。

相反,我将首先关注于:

  • 数据多久更改一次?

  • 谁可能需要更改它?

如果“多久”的答案是“比我想部署我的应用程序的新版本更多”,那么您就不应该对数据进行硬编码。

如果“谁更改了它”的答案是“除了程序员以外的任何人”,那么您就不应该对数据进行硬编码。

在一家小商店中,编码人员和用户之间的区别可能消失了,“部署”的想法也消失了。在这种情况下,您是您自己领域的王者,您可以做任何喜欢的事情。

但是即使在那种情况下,也可能需要进行协作,如果自定义应用程序没有遵循程序员通常遵循的约定,则可能会很困难。


6
与常见问题类似,另一个问题是:“需要多长时间更改一次?” 选通因素可能是在整个用户群中部署需要多长时间。对于集中式服务器软件,答案可能是几分钟,但对于现场移动应用程序,则可能需要数周时间。
CuriousRabbit 2014年

在Perl示例中,我将其表示为an array with a few values,很少有377个基本数据类型的行。可能不止于“一些”,但仍然很小。我有类似但硬编码较少的扁平结构。如果是一千多行,我可能更不愿意用这种方式进行硬编码。
丹尼斯

14

我会选择第三个选项:配置文件!

对于我正在使用的应用程序(在Java中,因此所有示例都使用Java + Spring),此类值通常存储在配置文件中,并在应用程序启动时(通过Spring)注入需要它们的代码中。在属性文件中:

motorFramesString=412T, 413T, ...

在spring配置中:

<bean="motorFrameManager" class="myCompany.MotorFrameManager" >
    <property name="motorFrames" value="${motorFrames}"/>
</bean>

这样做的好处是您可以轻松地更改或添加更多这些大多数为静态的值,而无需重新编译,并且您不必担心用参考数据填充(关系)数据库(因为这似乎是一个关注,也许不是万能的需求是在数据库反正)。

至于为什么这些值应该放入配置文件而不是引用表中:您打算在代码中还是在数据库中使用这些值?如果您有许多现有查询以及依赖于这些值的视图和过程,那么最好将它们作为参考数据放入数据库中,因为比从配置文件中加载它们并将它们作为参数发送到每个可能的查询/查看/引用它们的过程。如果这些值主要用于应用程序代码中,则配置文件可能是一个更好的选择。


带有或不带有属性的更复杂的示例(如链接的对象)也可以完成。

在products.properties中:

productA.name=Product A 123
productA.hasMotor=true
productA.numFeet=1
productA.hasOutlet=true
productA.needsManual=true

productB.name=Product B 456
productB.hasMotor=false
productB.numFeet=1
productB.hasOutlet=true
productB.needsManual=true

在您的spring配置文件中:

<bean name="productA" class="com.mycompany.Product">
   <property name="name" value="${productA.name}"/>
   <property name="hasMotor" value="${productA.hasMotor}"/>
   <!-- rest omitted for brevity -->
</bean>
<bean name="productB" class="com.mycompany.Product">
   <property name="name" value="${productB.name}"/>
   <property name="hasMotor" value="${productB.hasMotor}"/>
   <!-- rest omitted for brevity -->
</bean>
<!-- configure as many beans as needed -->
<bean="motorFrameManager" class="myCompany.MotorFrameManager" >
    <property name="motorFrames"> <!-- assumes that MotorFrameManager has a property motorFrames which is a List<Product> -->
        <list>
            <ref bean="productA"/>
            <ref bean="productB"/>
        </list>
    </property>
</bean>

这样做的好处是,如果您的源数据是电子表格(例如您链接到的问题),则可以在Excel中使用宏来自动生成属性和弹簧片段。


在框架示例中,它非常简单(只有一个字符串值)。对于具有混合变量n元组的选项表(在我的问题底部链接),您的方法是否基本相同?
丹尼斯2014年

@Dennis:添加了一个更复杂的示例。
FrustratedWithFormsDesigner 2014年

8
配置文件只是db的一种形式。
DougM 2014年

3
@DougM,我同意,但是在Oracle中设置一系列配置表与拥有一个简单的XML配置文件之间存在很大的差异。配置文件还具有受版本控制控制的优点。配置文件是中间立场,它鼓励编码人员将更多配置数据分离出来。我正在努力思考现实的情况,在这些情况下,时间不是一件好事
mcottle14年

2
@gbjbaanb:对于大多数应用程序而言,RDBMS对于WAAAAAY来说是过大的,即使对于其他相当广泛的系统也是如此。更不用说它们运行缓慢,需要付出大量努力才能保持和集成。“ ini”文件不提供任何类型安全性,您必须自己编写解析器,并且必须编写自己的类型检查。至少在.Net中,XML Config文件基本上可以免费获得任何一个首选选项所提供的所有好处。因此,您断言XML配置文件始终是更糟糕的选择,这再错不过了。
邓肯2014年

10

我认为问题的前提并不完全正确。划分因素不是需要更改的记录数量,而是更改的频率以及更改

频率

当数据是易失性的时,从某种意义上说,它经常更改并且在软件的发布周期之外,因此必须能够在硬编码值甚至配置文件之外进行配置。数据库在这里很有意义,尤其是在应用程序本身能够维护数据库的情况下。

客户需要能够更改数据时,需要以用户友好的方式在发布周期之外对其进行修改。

共同点

这里的共同点是,当需要在软件发行版之外更改数据时,应将其存储在数据库中。在发行期间可能会升级数据库,但是数据可以保留下来而不会被重置或大量修改。当客户需要能够修改数据(或配置功能)时,应将其存储在数据库中,并且前端要具有防傻瓜功能。

测试中

确保编写单元测试来验证您在各种配置中的软件。也许您的客户打开了一个可选提示,或者将一米重新定义为等于十二英尺。不管更改有多合理,如果您的软件允许更改,那么无论更改多么愚蠢,都可以更好地验证更改是否按预期工作。


4

决定存储数据的位置既不是更改的频率也不是数据量。

如果运行程序需要数据,则它是程序代码的一部分,因此请将其存储为常量。所有其他数据进入数据库。

当然,配置文件,图像,声音等通常可以更好地存储在文件系统中。


我制作了一个完全由数据库驱动的呼叫中心协助程序;数据是“运行代码”所必需的,但是编译它是荒谬的。
DougM 2014年

1
我曾担任Oracle开发人员达8年之久,但我仍然不喜欢与基础数据库紧密耦合的应用程序。
winkbrace 2014年

2

如果您几乎没有机会接到电话,导致由于硬编码的某些更改而不得不重新构建应用程序,那么就不要对其进行硬编码。至少将其保存在配置文件或数据库表中。您不必提供任何UI来维护它,但拨入并更改配置文件或在表上运行SQL UPDATE肯定比重建整个射击比赛更可取。


1

区别的确是一个灰色地带,但是我对这类问题的处理方法是:生产中的数据是否会发生变化??在生产环境中部署后发生的任何更改都应存储在数据库中,即使是很少更改的内容也应存入数据库。

因此,您应该问的问题不是“它将多久更改一次”,而是“它可以更改吗?”。如果属性的值可以在生产环境中的同一代码迭代(而不涉及代码中的任何其他内容)内变化,则它将进入数据库。


0

您还缺少的是“程序控制”类型信息,例如最大缓冲区大小,订单中大声显示的项目数,屏幕的最大页面大小,无论是在程序中还是在配置文件中进行硬编码,总是更好。

如果将此类数据保存在数据库中,则总是有可能有人即时更改它并完全改变系统的行为。

另一个问题是,没有简单的方法可以通过您应使用的源代码控制/变更管理/自动构建系统获取数据库条目。


0

您永远不应保留在数据库中的一件事是访问数据库所需的详细信息。
如果您最终需要访问数据库以检索同一数据库的连接字符串,用户名和密码,则可能会遇到22点问题。

硬编码吗?嗯,如果您使用某种随应用程序一起安装和提供的数据库,则可能会起作用。
配置文件?更有希望的但是帐户安全性如何?

当然,您可以将数据库信息以加密形式存储在该配置文件中,但是随后您需要将解密密钥存储在某个位置,并且几乎可以肯定将其硬编码。

除此之外,有些事情永远不会改变。诸如自然常数(G,pi,e,随便命名)之类的事物,诸如某些正则表达式之类的事物,诸如电子邮件验证之类的事物。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.