让我问您一个完全严肃的反问:您认为“数据”和“代码”之间的区别是什么?
当我听到“数据”一词时,我认为是“状态”。从定义上讲,数据是应用程序本身旨在管理的事物,因此,它是应用程序在编译时永远无法知道的事物。这是不能够进行硬编码的数据,因为只要你硬编码,就变成行为-没有数据。
数据类型因应用程序而异;商业发票系统可能会将客户和订单信息存储在SQL数据库中,而矢量图形程序可能会将几何数据和元数据存储在二进制文件中。在这两种情况之间以及两者之间的所有情况下,代码和数据之间都存在清晰且牢不可破的分离。数据属于用户而不是程序员,因此永远不能进行硬编码。
您似乎在谈论的是,使用当前词汇表中可用的技术上最准确的描述:控制程序行为的信息,该信息不是用开发大多数应用程序的主要编程语言编写的。
即使这个定义比“数据”一词的意义要小得多,也存在一些问题。例如,如果程序的重要部分各自以不同的语言编写,该怎么办?我亲自参与了多个项目,这些项目的C#比例约为50%,JavaScript的比例约为50%。JavaScript代码是“数据”吗?大多数人会拒绝。那么HTML是“数据”呢?大多数人还是会拒绝。
CSS呢?那是数据还是代码?如果我们认为代码是控制程序行为的东西,那么CSS并不是真正的代码,因为它只会(主要是)影响外观,而不影响行为。但这也不是真正的数据。用户不拥有它,应用程序甚至都不真正拥有它。这等效于UI设计人员的代码。它类似于代码,但不完全是代码。
我可能将CSS称为一种配置,但是更实际的定义是它只是使用特定于域的语言编写的代码。这就是您的XML,YAML和其他“格式化文件”经常代表的内容。而且,我们之所以使用特定领域的语言,是因为通常来说,与使用C或C#或Java这样的通用编程语言对相同信息进行编码相比,它在特定领域中同时更加简洁和更具表现力。
您能识别以下格式吗?
{
name: 'Jane Doe',
age: 27,
interests: ['cats', 'shoes']
}
我敢肯定大多数人都会这样做。它是JSON。这是关于JSON的有趣的事情:在JavaScript中,它显然是代码,在其他每种语言中,它都是清晰格式的数据。几乎每种主流编程语言都至少具有一个用于“解析” JSON的库。
如果我们在JavaScript文件中的函数内使用完全相同的语法,则除了代码之外,其他语法都不可能。但是,如果我们采用该JSON,将其存储在.json
文件中,然后在Java应用程序中进行解析,则突然间它就是“数据”。这真的有意义吗?
我认为,以“数据性”或“配置性”或“码率”是与生俱来的东西被描述,而不是如何它被描述。
如果您的程序需要一百万个单词的字典才能生成随机密码,那么您是否要像这样编写代码:
var words = new List<string>();
words.Add("aa");
words.Add("aah");
words.Add("ahhed");
// snip 172836 more lines
words.Add("zyzzyva");
words.Add("zyzzyvas");
还是只是将所有这些单词推到以行分隔的文本文件中,并告诉程序从中读取?单词列表是否永不改变并不重要,这不是您要硬编码还是软编码(在不适当应用的情况下,许多人正确地认为这是反模式),这仅仅是一个问题。哪种格式最有效,并且最容易描述“东西”,无论“东西”是什么。称它为代码还是数据是无关紧要的。它是程序运行所需的信息,而平面文件格式是管理和维护程序的最便捷方法。
假设您遵循正确的做法,那么所有这些东西都将进入源代码控制,因此您最好将其称为代码,只是以不同且可能是非常简约的格式进行代码。或者,您可以将其称为配置,但真正将代码与配置区分开来的唯一一件事就是是否编写文档并告诉最终用户如何进行更改。您可能会发明一些关于在启动时或运行时而不是在编译时解释配置的虚假论点,但是随后您将开始描述几种动态类型的语言,几乎可以肯定其中嵌入了脚本引擎的任何内容(例如,大多数游戏)。代码和配置是您决定将其标记为的内容,仅此而已。
现在,存在将实际上无法安全修改的信息外部化的危险(请参见上面的“软编码”链接)。如果将元音数组外部化到配置文件中,并将其作为配置文件记录给最终用户,您将为他们提供一种几乎简单的方法来立即破坏您的应用程序,例如通过将“ q”作为元音。但这不是“代码和数据分离”的根本问题,这只是糟糕的设计意义。
我告诉初级开发人员的是,他们应该始终外部化他们希望根据环境进行更改的设置。其中包括连接字符串,用户名,API密钥,目录路径等。它们在您的开发人员环境和生产环境中可能是相同的,但可能并非如此,系统管理员将决定他们希望它在生产环境中(而不是开发人员)的外观。因此,您需要一种方法,将一组设置应用到某些计算机上,并将其他设置应用到其他计算机上-ergo,外部配置文件(或数据库中的设置等)
但我强调,简单地将一些“数据”放入“文件”与将其外部化为配置不同。将单词词典放入文本文件并不意味着您想要用户(或IT)对其进行更改,而只是使开发人员更容易理解到底发生了什么,并且在必要时进行修改的一种方式。偶尔的变化。同样,如果该表是只读的和/或指示DBA永不使用该表,则将相同的信息放入数据库表中不一定会将其视为行为的外部化。配置意味着数据是可变的,但实际上是由流程和职责而不是格式选择来确定的。
因此,总结一下:
“代码”不是严格定义的术语。如果您将定义扩展到包括特定于领域的语言以及任何其他会影响行为的语言,那么许多明显的摩擦将简单地消失,并且都将变得有意义。您可以在一个平面文件中包含未编译的DSL“代码”。
“数据”表示由用户或至少开发商以外的其他人拥有的信息,通常在设计时不可用。即使您愿意,也无法对其进行硬编码。除了可能自行修改的代码外,代码与数据之间的分隔只是定义问题,而不是个人喜好。
当过度使用“软编码”时,这可能是一个糟糕的实践,但是并非每个外部化实例都必须构成软编码,并且在“平面文件”中存储信息的许多实例也不一定是进行外部化的真正尝试。
配置是一种特殊类型的软编码,该编码的是因为知识的应用程序可能需要在不同的环境中运行的必要。与向每个环境部署不同版本的代码相比,与应用程序一起部署单独的配置文件要少得多(工作也更少危险)。因此,某些类型的软编码实际上是有用的。