关于最小化代码和最大化数据哲学的思考

时间:2010-12-09 11:52:26

标签: data-driven

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

6 个答案:

答案 0 :(得分:23)

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

pragmatic programmers仍然是我所读过的最简单的小语言提倡者。运行少量输入语言的小型状态机可以用很小的空间完成 lot ,并且可以很容易地进行修改。

一个具体的例子:考虑累进所得税制,税率为1,000美元,10,000美元和100,000美元。低于1,000美元的收入是免税的。 1,000美元至9,999美元之间的收入税率为10%。 10,000美元至99,999美元之间的收入税率为20%。收入超过10万美元的税率为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脚本;)它们实际上是数据。

我希望这有助于激发数据驱动的编程;我担心我不像其他人那样有说服力,我当然没有得到,但我尝试了。

答案 1 :(得分:18)

答案 2 :(得分:5)

Unix Philosophy提供的Rob Pike下的五个格言之一是:

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

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

答案 3 :(得分:5)

其他答案已经探讨了如何使用简单的代码来编写复杂的行为,这些代码只对特定输入的模式做出反应。您可以将数据视为特定于域的语言,将您的代码视为解释器(可能是一个简单的解释器)。

根据大量数据,您可以更进一步:统计数据可以为决策提供动力。 Peter Norvig在great chapter中写了一个Beautiful Data来说明这个主题,文字,代码和数据都在网上提供。 (披露:我在致谢中感谢。)在第238-239页:

  

数据驱动方法与更传统的软件开发相比如何?   程序员编码显式规则的过程? ......显然,手写规则难以开发和维护。大   数据驱动方法的优点是在数据中编码了如此多的知识,   只需收集更多数据即可添加新知识。但另一个优点是   虽然数据量很大,但代码很简洁 - correct约为50行,而ht:// Dig的拼写代码则超过1,500行。 ...

     

另一个问题是可移植性。如果我们想要拉脱维亚语拼写纠错器,那就是英语   metaphone规则几乎没用。将数据驱动的correct算法移植到另一个算法   语言,我们所需要的只是拉脱维亚语的大型语料库;代码保持不变。

他使用Google收集的数据集在Python中使用代码具体展示了这一点。除了拼写纠正之外,还有用于分割单词和解密密码的代码 - 仅在几页中,Grady Booch's book花了几十个甚至没有完成它。

"The Unreasonable Effectiveness of Data"更广泛地发展同一主题,没有所有的细节。

我在另一家搜索公司的工作中采用了这种方法,我认为与桌面驱动/ DSL编程相比,它仍然未充分利用,因为我们大多数人在过去十年或二十年之前并没有那么多的数据。

答案 4 :(得分:4)

在可以将代码视为数据的语言中,这不是问题。根据解决方案的要求,您可以使用清晰,简洁和可维护的内容,倾向于数据,代码,功能,OO或过程。

在程序上,区别是标记的,我们倾向于将数据视为以特定方式存储的某种,但即使在程序中,也最好隐藏API背后的数据,或OO中的对象后面。

lookup(avalue)可以在其生命周期内以多种不同方式重新实现,只要它作为函数启动即可。

...我一直为不存在的机器设计程序并添加:“如果我们现在有一台机器包含这里假设的原语,那么工作就完成了。” ......在实际操作中,当然,这台理想的机器将不会存在,所以我们的下一个任务 - 结构上与原来的相似 - 是编程“上层”机器的模拟......但是这个一堆程序是为很可能不存在的机器编写的,所以我们的下一个工作是根据下一个较低级别机器的程序来模拟它,直到最后我们有一个程序可以执行我们的硬件......

<强>电子。 W. Dijkstra ,结构化编程注释,1969,引自 John Allen 解剖Lisp ,1978年。< / p>

答案 5 :(得分:3)

当我想到这个我同意的哲学时,首先想到的是代码效率。

当我制作代码时,我确信它并不总是接近完美甚至完全知识渊博。在需要的时候知道足够接近机器的最大效率,并且其余时间(可能为了更好的工作流程而牺牲)提高了效率,这使我能够生产出高质量的成品。

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

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

如果您有一个简单的数据库形式,则可以将相同的功能应用于许多状态。您还可以执行各种创造性的操作,例如根据文件标题数据或目录,文件名或扩展名更改程序正在执行的操作的上下文,但并非所有数据都必须必须存储在文件系统中

最后让你的代码处于一个简单处理数据的状态,让你处于一种心态,你可以更接近地想象实际发生的事情。这也可以大量减少代码,大大减少了臃肿软件。

我相信它使代码更易于维护,更灵活,更高效,而且我喜欢它。

感谢其他人对此的意见!我发现它非常令人鼓舞。