【问题标题】:What's the difference between data and code?数据和代码有什么区别?
【发布时间】:2019-05-23 05:07:01
【问题描述】:

举个例子,考虑一组超市购物者可以享受的折扣。

我们可以以某种标准方式将这些规则定义为数据(合格商品列表、适用日期、优惠券代码)并编写通用代码来处理这些。或者,我们可以将每个代码写成一段代码,根据客户的购物清单检查适当的东西并返回任何适用的折扣。

您可以合理地将规则存储为对象、序列化为 Blob 或存储在代码文件中,以便每个规则可以选择自己的数据和代码划分,以允许未来的规则不适合通用处理器的类型上面考虑过。

通常很容易批评混合数据的代码,通过 if 语句检查应该在文件或数据库中的 6 种不同内容,但是有没有一条规则可以在边缘情况下有所帮助?

或者这就是面向对象设计的重点,让我们不再担心数据和代码之间的界限?

为了澄清,根本问题是:您将如何编写上述示例?是否有经验法则让您决定什么是数据,什么是代码?

(注意:我知道,代码可以编译,但在动态语言和 JIT 编译的世界中,即使这是一个模糊的概念。)

【问题讨论】:

  • 能否请您澄清这个问题。您的主要问题是主题,还是您实际在问什么?
  • 问题可能真的是你如何决定在代码中设置什么以及在数据中编码什么?
  • @JoonasPulakka:我在 MSDN 上的 What Is a Window? 中看到“代码和数据”,我在 MSDN 上的“窗口句柄”部分中说:“Windows 是对象——它们既有代码又有数据——但它们是不是 C++ 类。相反,程序通过使用称为句柄的值来引用窗口”,我想知道它们之间有什么区别!

标签: language-agnostic data-structures oop functional-programming


【解决方案1】:

从根本上说,数据和代码之间当然没有区别,但对于真正的软件基础架构,可能会有很大的区别。除了你提到的编译等显而易见的事情之外,最大的问题是:

大多数足够大的项目都设计为生成一个大捆绑包的“版本”,在 3 个月(或更长)周期内生成,经过广泛测试,之后不能更改,除非以严格控制的方式进行。 “代码”绝对不能更改,因此任何需要更改的内容都必须被分解并制作为“配置数据”,以便更改它的工作是确保发布有效的人变得可口。

当然,在大多数情况下,糟糕的配置数据会像糟糕的代码一样彻底破坏发布,所以整个事情在很大程度上是一种错觉——实际上,改变的是代码还是“配置数据”并不重要,重要的是主系统和更改部分之间的接口足够狭窄且定义明确,可以让您有很好的机会让进行更改的人了解他所做的事情的所有后果。

这已经比大多数人想象的要难,因为它实际上只是配置了几个字符串和数字(​​我亲眼目睹了生产大型机系统崩溃,因为它的一个布尔值设置与它正在与之通信的另一个系统不同) .当您的“配置数据”包含复杂的逻辑时,几乎不可能实现。但是情况不会好转,因为您使用了设计糟糕的临时“规则配置”语言而不是“真实”代码。

【讨论】:

    【解决方案2】:

    这是一个相当哲学的问题(我喜欢),所以我将以哲学的方式回答它:没有什么可以支持的。 ;)

    数据是系统中可以改变的部分。代码定义行为;数据可以更改为新数据的方式。

    更准确地说:数据可以由两部分来描述:一个描述,说明数据应该代表什么(例如,一个具有名称和类型的变量)和一个值。 变量的值可以根据代码中定义的规则而改变。当然,描述不会改变,因为如果改变了,我们就有了全新的信息。 代码本身不会改变,除非需求(我们对系统的期望)改变。

    对于编译器(或虚拟机)来说,代码实际上是它执行操作的数据。但是,要编译的代码并没有为编译器指定行为,编译器自己的代码会这样做。

    【讨论】:

    • +1 表示数据是信息,代码是行为(实际上几乎在同一时间回答了相同的问题)——尽管/实时数据非常高,但不太同意调用静态数据“动态”,尽管通常作为测量值处理,但很难描述差异
    • 代码是“行为”是什么意思?谁的行为?计算机?如果是,那么它的微处理器数据。想想这个。
    • 当然,数据是可以改变的。一个更好的术语可能是数据 values 可以被认为是“不可变的”。因此,这些值是静态的,并且数据可以根据代码定义的规则改变——或者更准确地说,改变它的值。
    • 我认为这种区别并不成立。考虑一种声明式编程语言:它是代码还是数据?
    • @troelskn 检查我的答案,我实际上并没有深入了解定义,而是进入了“这不是关于”的论点......我认为解释什么是信息并不难与行为相比,但进入他们去的地方会增加混乱
    【解决方案3】:

    这一切都取决于要求。如果数据类似于查找数据并且经常更改,那么您真的不想在代码中执行此操作,但是诸如星期几之类的内容在接下来的 200 年左右不应该更改,因此请编写代码。

    您可能会考虑更改您的主题,当我看到它时,我首先想到的是古老的 LISP 对代码与数据的讨论。幸运的是,Scheme 代码和数据看起来是一样的,但仅此而已,您永远不会意外地将代码与数据混合在一起,这在 LISP 中很可能会使用不卫生的宏。

    【讨论】:

      【解决方案4】:

      数据是由称为代码的指令处理的信息。我不确定我是否觉得 OOD 中存在模糊,仍然存在属性(数据)和方法(代码)。 OO 理论将两者封装在一个称为类的格式塔实体中,但它们在类中仍然是离散的。

      您希望使您的代码在选择方面具有多大的灵活性。在不重新处理源的情况下包含常量值(您通过使用上述 if 语句所做的事情)是不灵活的,而使用动态来源的数据则更加灵活。两种方法都是错误的吗?我会说这真的取决于具体情况。正如 Leppie 所说,某些“数据”点是不变的,例如可以硬编码的星期几,但即使在某些情况下动态编码也可能是有利的。

      【讨论】:

      • 但是在使用一个对象时,你无法分辨什么是作为数据存储的,什么是由代码生成的。因此 .Net 中的参数:obj.Length 可以生成(代码)或仅存储(数据)。模糊之处在于你在使用它时并不在意。
      【解决方案5】:

      在 Lisp 中,您的代码就是数据,而您的 数据就是代码

      Prolog 中的子句是术语,而术语 是子句。

      【讨论】:

        【解决方案6】:

        重要的一点是,您希望将代码中每次都执行相同的部分(即应用折扣)与代码中可能发生变化的部分(即要打折的产品,或折扣的百分比等)

        这只是为了安全。如果折扣发生变化,您无需重新编写折扣代码,您只需进入折扣存储库(DB、或应用程序文件或 xml 文件,或者您选择实施它)并制作一个数字的小改动。

        此外,如果折扣代码被分离到一个 XML 文件中,那么您可以将整个应用程序交给经理,并且只要有足够的说明,他们就不需要在想要更改折扣率时纠缠您。

        当您将数据和代码混合在一起时,当任何事情发生变化时,您的崩溃几率就会成倍增加。所以,正如leppie所说,你需要把不断变化的部分提取出来,放在一个单独的地方。

        【讨论】:

          【解决方案7】:

          巨大的差异。数据是系统的一部分,而代码是系统的一部分。

          错误的数据是没有意义的:我们的代码===处理程序很好,你放什么你拿什么,你的意思不是系统的问题。但是如果代码不好 - 系统就是坏的。

          例如,让我们考虑一些 JSON,一些我编写的错误代码 parser.js,让我们说好的 V8。对于我的系统来说,parser.js 是一个代码错误,我的系统工作错误。但是对于 Google 系统,我糟糕的解析器是无法说明 V8 质量的数据。

          这个问题非常实用,没有复杂性。 https://en.wikipedia.org/wiki/Systems_engineering 试图做出好的回答和金钱。

          【讨论】:

            【解决方案8】:

            数据就是信息。这与您决定将其放在何处无关,无论是数据库、配置文件、通过代码配置还是在类内部。

            行为/代码也是如此。这与您决定将其放在哪里或您选择如何表示它无关。

            【讨论】:

            • 不确定我的问题是否正确,但您可以拥有分层数据,就像拥有分层代码一样,这是对它们进行组织,不会改变它们的性质
            【解决方案9】:

            数据和代码(程序)之间的界限很模糊。归根结底,这只是术语 的问题——例如,您可以说数据就是非代码的一切。但是,正如您所写,它们可以愉快地混合在一起(尽管通常最好将它们分开)。

            【讨论】:

              【解决方案10】:

              代码是可以执行的任何数据。现在,由于所有数据在某个时间点都用作某个程序的输入,因此可以说这些数据是由程序执行的!因此,您的程序充当数据的虚拟机。所以理论上数据和代码没有区别!

              最后,重要的是软件工程/开发考虑因素,例如性能、效率等。例如,数据驱动程序可能不如硬编码(因此很脆弱)条件语句的程序高效。因此,我选择将代码定义为任何可以有效执行的数据,而其他所有数据都是普通数据。

              这是灵活性和效率之间的权衡。可执行数据(如 XML 规则)提供了更大的灵活性(有时),而将相同的数据/规则编码为应用程序的一部分时将更有效地运行,但频繁更改它会变得很麻烦。换句话说,可执行数据易于部署但效率低下,反之亦然。所以最终决定权在你——软件设计师。

              如果我错了,请纠正我。

              【讨论】:

              • 无论如何,这一切都归结为 1 和 0
              • 如果您的数据被“执行”,那么实际数据肯定会形成某种编程语言并成为存储代码而不是数据?
              • 是的,另一种看待它的方式。将此与能量和质量之间的等价性进行比较。
              • “因此我选择将代码定义为任何可以有效执行的数据,而其他所有数据都是纯数据”——什么决定了它是否可以“有效执行”?
              • Ans: 它(数据)有什么形式,并且通常在哪里执行。例如。 XML 配置数据由程序(VM)执行,而 C++ 代码则直接在微处理器上进行描述。
              【解决方案11】:

              代码与数据的关系如下:

              编译成程序后的代码在执行时处理数据

              程序可以提取数据、转换数据、加载数据、生成数据...

              还有 程序可以提取代码、转换代码、加载代码、生成代码……

              因此没有编译或interperator的代码是无用的,数据总是值得的......,但是编译后的代码可以完成上述所有活动......

              例如)

              Sourcecontrolsystem流程源码

              这里的源代码本身就是代码

              Backupscripts 进程文件

              这里的文件是数据等等......

              【讨论】:

                【解决方案12】:

                我会说数据、代码和配置之间的区别是在特定组件的上下文中进行的。有时很明显,有时不太明显。

                例如,对于编译器来说,它使用的源代码和它创建的目标代码都是数据 - 并且应该与编译器自己的代码分开。

                在您的情况下,您似乎在描述一个特别强大的配置文件的选项,该文件可以包含代码。例如,GIMP 允许您使用 Scheme 来“配置”插件。作为读取此配置的组件的开发人员,您会将其视为数据。在不同级别工作时——编写配置——你会认为它是代码。

                这是一种非常强大的设计方式。

                将此应用于基本问题(“您将如何编写上述示例?”),一种选择可能是采用或设计一种高级域特定语言 (DSL) 来指定规则。在启动时或第一次需要时,服务器会读取规则并执行它。

                提供一个管理界面,让管理员可以

                • 测试新规则文件
                • 用新规则文件中的配置替换当前配置

                ...所有这些都将在运行时发生。

                DSL 可能像表解析器或 XML 解析器一样简单,也可能像脚本语言一样复杂。在 C 中,很容易嵌入 Python 或 Lua。从 Java 中嵌入 Groovy 或 Clojure 很容易。

                您可以使用巧妙的链接或类加载器技巧在运行时切换已编译的代码。在我看来,这似乎比嵌入式 DSL 选项更困难且价值更低。

                【讨论】:

                • 但是大多数配置文件不是在启动时读取的吗?当然,对于 24/7 的连锁超市来说,一个动态获取这些折扣规则的动态系统是必要的。在哪种情况下,您是选择添加新对象(代码)的灵活性,还是数据的限制?
                • 读取配置文件时由设计人员决定 - 在启动时;曾经偷懒;总是;当由管理员命令触发时。我在考虑嵌入式脚本语言,但您也可以在运行时(重新)链接目标代码。
                【解决方案13】:

                我发现这个问题的最佳实用答案是: 任何需要序列化的类,无论是现在还是在可预见的未来,都是数据。 其他一切都是代码。 这就是为什么,例如,Java 的 HashMap 是数据 - 尽管它有很多代码、API 方法和特定实现(即,它可能乍一看像代码)。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-05-30
                  • 2014-05-13
                  • 1970-01-01
                  • 2021-12-08
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-01-19
                  • 2018-11-13
                  相关资源
                  最近更新 更多