我听说过最小化代码和最大化数据的概念,并且想知道其他人在构建自己的系统时应该如何/为什么要这样做的建议给我什么?

有帮助吗?

解决方案

在现代软件中,代码和数据之间的界线可能会变得非常薄且模糊,并且并不总是很容易分开两者。毕竟,就计算机而言,一切都是 数据, ,除非由现有代码(通常为OS)确定,否则为另外。在CPU可以执行它们之前,甚至必须将程序加载到内存中。

例如,想象一下一种计算订单成本的算法,其中较大的订单获得较低的每项价格。它是用C编写的商店中较大软件系统的一部分。

该算法用C编写,并读取一个文件,该文件包含由管理层提供的输入表,其每个项目价格各不相同和相应的订单大小阈值。大多数人会认为,具有简单输入表的文件当然是数据。

现在,想象一下,商店将其政策更改为某种渐近功能,而不是预先选择的阈值,以便可以容纳疯狂的大订单。他们可能还想考虑汇率和通货膨胀 - 或管理人员提出的其他内容。

该商店聘请了一个合格的程序员,她在原始C代码中嵌入了一个不错的数学表达解析器。输入文件现在包含一个带有全局变量的表达式 log()tan(), ,以及一些简单的东西,例如 普朗克常数 以及 碳14 降解。

cost = (base * ordered * exchange * ... + ... / ...)^13

大多数人仍然会争辩说,即使不像表那样简单,这种表达实际上也是数据。毕竟,管理层可能是由管理层提供的。

该商店收到了大量的客户投诉,这些投诉成为脑死亡,试图估算他们的费用以及会计师的大量变化。商店决定回到桌子上以进行小订单,然后使用 斐波那契序列 用于较大的订单。

程序员厌倦了修改和重新编译C代码,因此她嵌入了Python的翻译器。现在,输入文件包含一个python函数,该函数轮询了一个房间 Fib(n) 猴子的大订单费用。

问题:这个 输入文件数据?

从严格的技术点来看,没有什么不同。桌子和表达式都需要在使用前进行解析。数学表达式解析器可能支持分支和功能 - 它可能不是图灵完整的,但它仍然使用了自己的语言(例如MathML)。

然而 现在 许多人会争辩说输入文件刚刚变成 代码.

那是什么 特色 从而使输入格式从 数据 进入 代码?

  • 可修改性: 必须重新编译整个系统以实现更改是一个 非常 以代码为中心的系统的良好指示。但是我很容易想象(嗯,更像我实际上 看到)软件的设计无能为力,可以在编译时内置一个内置的输入表。而且,不要忘记许多应用程序仍然有图标 - 大多数人会认为 数据 - 内置其可执行文件。

  • 输入格式: 我认为这是人们考虑的最常见因素: “如果使用编程语言,那就是代码”. 。很好,C是代码 - 您毕竟必须对其进行编译。我也会同意Python也是代码 - 它 完整的语言。所以为什么 不是 XML/XSL代码? XSL 本身就是一种非常复杂的语言 - 因此 L 以它的名义。

我认为,这两个标准都不是实际的 特色. 。我认为人们应该考虑其他事情:

  • 可维护性: 简而言之 用户 该系统必须雇用第三方来制作 专业知识 需要修改可用系统的行为,然后将系统视为以代码为中心的程度。

当然,这意味着至少应考虑系统是否是数据驱动的 与目标受众有关 - 如果不是逐案与客户有关。

这也意味着该区别可能会受到可用工具集的影响。这 规格是一场噩梦,但是这些天我们拥有所有这些图形UML编辑器来帮助我们。如果有某种第三方高级AI工具可以解析自然语言并产生XML/Python/erhit,那么系统即使在更复杂的输入中也将成为数据驱动。

一家小商店可能没有专业知识或资源来雇用第三方。因此,使工人能够通过知道在平均管理课程中获得的行为(数学,图表等)来修改其行为的东西可以被认为是对该受众的足够数据驱动的。

另一方面,一家数十亿美元的国际公司通常拥有一堆IT专家和网页设计师。因此,XML/XSL,JavaScript甚至Python和PHP可能很容易处理。它还具有足够复杂的要求,即简单的东西可能不会削减它。

我相信,在设计软件系统时,应该努力在目标受众可以做他们的工作中实现良好的平衡 需要 至, 没有 必须经常呼吁第三方。

应该注意的是,外包更加模糊。有很多问题,目前的技术根本不允许外行人通用该解决方案。在这种情况下,解决方案的目标受众可能被认为是将操作外包到的第三方。可以期望第三方雇用大量的专家。

其他提示

通常,数据驱动的代码更易于读取和维护。我知道我已经看到了已经将数据驱动到极端的案例,并且非常无法使用(我正在考虑我使用过的一些SAP部署),但是编码自己的“域特定语言”以帮助您构建构建您的软件通常可以节省大量时间。

务实的程序员 在我看来,我读过的小语言是最生动的倡导者。运行很少输入语言的小型机器可以得到 很多 在很少的空间方面完成,使其易于进行修改。

一个具体的例子:考虑一个渐进式所得税制度,税收括号为1,000美元,10,000美元和100,000美元。低于$ 1,000的收入是不动的。收入在1,000美元至9,999美元之间的收入为10%。收入在10,000美元至99,999美元之间的收入为20%。收入超过100,000美元,税率为30%。如果您用代码全部编写所有这些内容,那么您会怀疑它:

total_tax_burden(income) {
    if (income < 1000)
        return 0
    if (income < 10000)
        return .1 * (income - 1000)
    if (income < 100000)
        return 999.9 + .2 * (income - 10000)
    return 18999.7 + .3 * (income - 100000)
}

添加新的税括号,更改现有括号或更改括号中的税收负担,都需要修改代码和重新编译。

但是,如果是数据驱动的,则可以将此表存储在配置文件中:

1000:0
10000:10
100000:20
inf:30

编写一个小工具来解析这张桌子并进行查找(不是很困难,对吧?) 任何人 可以轻松维护税率表。如果国会决定1000个支架会更好,那么任何人都可以使桌子与IRS桌子一致,并可以完成,无需重新编译代码。相同的通用代码可以用于一个支架或数百个括号。

现在,对于一些不太明显的东西:测试。这 Apparmor 项目有数百次测试,用于加载各种配置文件时系统调用应进行的测试。一个样本测试看起来像这样:

#! /bin/bash
# $Id$

#   Copyright (C) 2002-2007 Novell/SUSE
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public License as
#   published by the Free Software Foundation, version 2 of the
#   License.

#=NAME open
#=DESCRIPTION 
# Verify that the open syscall is correctly managed for confined profiles.  
#=END

pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`

bin=$pwd

. $bin/prologue.inc

file=$tmpdir/file
okperm=rw
badperm1=r
badperm2=w

# PASS UNCONFINED
runchecktest "OPEN unconfined RW (create) " pass $file

# PASS TEST (the file shouldn't exist, so open should create it
rm -f ${file}
genprofile $file:$okperm
runchecktest "OPEN RW (create) " pass $file

# PASS TEST
genprofile $file:$okperm
runchecktest "OPEN RW" pass $file

# FAILURE TEST (1)
genprofile $file:$badperm1
runchecktest "OPEN R" fail $file

# FAILURE TEST (2)
genprofile $file:$badperm2
runchecktest "OPEN W" fail $file

# FAILURE TEST (3)
genprofile $file:$badperm1 cap:dac_override
runchecktest "OPEN R+dac_override" fail $file

# FAILURE TEST (4)
# This is testing for bug: https://bugs.wirex.com/show_bug.cgi?id=2885
# When we open O_CREAT|O_RDWR, we are (were?) allowing only write access
# to be required.
rm -f ${file}
genprofile $file:$badperm2
runchecktest "OPEN W (create)" fail $file

它依靠一些辅助功能来生成和加载配置文件,测试功能的结果并向用户报告。扩展这些小测试脚本要比编写这种功能而没有一点语言要容易得多。是的,这些是Shell脚本,但是它们与实际的Shell脚本相距甚远;)实际上它们是数据。

我希望这有助于激励数据驱动的编程;恐怕我不像其他关于它的人那样雄辩,我当然还没有得到 好的 在它上,但是我尝试。

五个格言之一 Unix哲学, ,如 罗布·派克(Rob Pike), , 这是:

数据主导。 如果您选择了正确的数据结构并很好地组织了事物,那么算法几乎总是不言而喻的。数据结构而不是算法是编程的核心。

它通常缩短为“编写使用智能数据的愚蠢代码”。

其他答案已经挖掘出您通常可以使用简单代码对复杂行为进行编码,这些代码只能对其特定输入的模式做出反应。您可以将数据视为一种特定领域的语言,而您的代码是解释器(也许是一个琐碎的语言)。

给定很多数据,您可以进一步: 统计数据 可以为决策提供动力。彼得·诺维格(Peter Norvig)写了 伟大的章节美丽的数据, ,带有文本,代码和数据,全部可在线可用。 (披露:我在致谢中表示感谢。)第238-239页:

数据驱动的方法与更传统的软件开发过程相比,程序员代码明确规则? ...显然,手写规则很难制定和维护。数据驱动方法的最大优点是,数据中编码了很多知识,并且只需收集更多数据就可以添加新知识。但是另一个优点是,尽管数据可能很大,但代码很简洁 - 大约50行 correct, ,相比之下,ht:// dig的拼写代码超过1,500。 ...

另一个问题是可移植性。如果我们想要拉脱维亚的拼写式 - 形式规则,将很少使用。移植数据驱动 correct 对另一种语言的算法,我们只需要大量的拉脱维亚语料库。代码保持不变。

他使用Google收集的数据集在Python中使用代码来表明这一点。除了拼写校正,还有一些代码可以分割单词和破译密码图 - 仅在几页中, 格雷迪·布赫(Grady Booch)的书 花了数十个没有完成。

“数据的不合理有效性” 没有所有的螺母和螺栓,更广泛地开发相同的主题。

我在另一家搜索公司的工作中采取了这种方法,我认为与桌面驱动/DSL编程相比,它仍然没有被淘汰,因为直到过去十年或两年来,我们大多数人都没有在数据中进行游泳。

在可以将代码视为数据的语言中,这是一种非问题。您使用解决方案所需的清晰,简短和可维护的内容,倾向于数据,代码,功能,OO或程序。

在程序中,区别被标记了,我们倾向于将数据视为 某物 存储在一个 具体的 方式,但即使在程序中,也最好隐藏 数据 在API后面或OO中的物体后面。

一个 lookup(avalue) 只要它作为功能启动,就可以在其一生中以许多不同的方式重新成熟。

...我一直都在为无用的机器编写程序,并补充说:“如果我们现在有一台计算机包含这里假定的原始操作,那么就完成了工作。” ...在实际实践中,当然,这台理想的机器将不存在,因此我们的下一个任务 - 结构与原始机器相似 - 是为“上层”机器的模拟进行编程...但是为一台机器编写了一堆程序,这绝对不存在,因此我们的下一个工作将是根据下一个较低级计算机等的程序进行模拟的,直到我们最终有一个程序可以由我们的硬件...

ew dijkstra关于结构化编程的注释, ,1969年,引用 约翰·艾伦, , 在 LISP解剖学, 1978.

当我想到我同意的这种理念时,想到的第一件事就是代码效率。

当我制作代码时,我确定它并不总是接近完美甚至是完全知识渊博的东西。在需要时了解足够的时间,可以在机器上获得最大的效率,并且剩余时间(也许要为更好的工作流动)良好的效率使我能够生产高质量的成品。

以数据驱动方式进行编码,您最终会使用代码来代码。要去和“外包”每个变量到文件都是愚蠢的极端,程序的功能需要在程序中,并且可以通过程序来管理内容,设置和其他因素。

这也允许更多动态的应用程序和新功能。

如果您甚至具有简单的数据库形式,则可以将相同的功能应用于许多州。您也可以执行各种创造性的事情,例如根据文件标头数据或目录,文件名或扩展名更改程序的上下文,尽管并非所有数据都是 一定 存储在文件系统上。

最终将您的代码保持在一个简单地处理数据的状态 在您更接近设想实际发生的事情的情况下。这也可以使您的代码范围内,从而大大减少了膨胀软件。

我相信它使代码更加可维护,更灵活,更高效,我喜欢它。

感谢其他人对此的投入!我发现这很令人鼓舞。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top