相信对于这个标题,用过lisp的朋友一定不陌生,本来也是准备了一大堆理论要讲,想了想还是直接举例子比较好。

就举最近产品提的一个产品需求吧,简单描述一下:

  1. 对于不同的第三方应用,有不同的频率限制。没有配置则使用默认值
  2. 对于不同的第三方应用,在不同的时间段,有不同的频率限制。没有配置则使用默认值

公司内部都是用C++,当时第一点想到的肯定是配置一个xml文件,里面配置上这些参数,在进程启动的时候,用tinnyxml或者其他xml解析器把xml解析成C++可以辨识的数据结构。
我们来看一下这个xml配置有多复杂:

这个配置可以说已经非常复杂了,而最重要的是,这种产品上的需求,说变就变,如果真的现有的配置格式满足不了新需求,那么只能变更了。做哪些变更呢?

  1. 配置文件格式
  2. 配置文件解析代码
  3. 数据结构代码
  4. 计算逻辑
  5. 重新编译发布

一个小小的产品需求变更居然会带来这么多修改量,这是很不合理的,况且需求变更从来都是最频繁的事情。

我们对这五个操作步骤考虑一下:
如果把计算逻辑从C++中剥离出来,放在脚本里,由脚本解析器作为一个通用的配置文件解析工具,那么1,2,3,4,5步就都不需要修改任何C++框架代码

好吧,我们已经得到答案了,其实C++框架只是想要一个频率限制的值而已,那么这个值究竟是怎么算出来的,就交给脚本去做吧。
而对脚本来说,xml什么的配置文件完全没有必要,因为在python,lua,lisp这样的脚本语言这里,数据和代码的界限已经越来越小(lisp的思想的数据=代码,实在是很有预见性的理论)。

OK,那我们来看一下实现,由于lua本身的小巧,这次的实现是使用了lua作为脚本(其实我更想用python,但是考虑到python的确有点太大了,不过如果想看C++中调用python的话,可以看这里:C,C++代码中调用python脚本C,C++中调用python脚本(2)-高级应用
lua的代码(没有写太复杂,只是示例而已):

C++封装类代码:

main调用代码:

输出结果:

OK,整个逻辑就是这样。其实实现方式是很简单的,无非就是在C++中调用了lua脚本,但是大家在辛苦的用C/C++写着ini解析类,xml解析类的时候,又在为产品需求变更而抱怨不已的时候,有没有想过能不能把这一切简化呢?

最近的一些技术整理(20120109)

前段时间一直没写博客,昨天更新了一篇,今天突然又来了兴致,那就再更新一篇吧(所以说啊,治疗拖延症最好的方法就是现在开始做) 这篇还是一些技术的整理,...

阅读全文

C++模板的几个应用

C++的模板其实是个挺纠结的东西,用的不好的话,编译的一堆错误够你调到崩溃,但要是用的好呢,又确实非常方便,我们来看看 一.获取数组长度 比如 ...

阅读全文

又见C++诡异问题

用C++越久,越是觉得C++太多陷阱,真是防不胜防。 我们看这样一段代码: C++ #include <stdio.h> using namespace std; ...

阅读全文

8则回应给“代码即数据,数据即代码(1)-把难以变更的代码变成易于变更的数据”

  1. 依云说道:

    哈,我之前用 C 写过一个 Linux 下的文件访问重定向的库,配置部分就是用的 Lua~

    [回复]

    Dante 回复:

    嗯嗯,可惜公司对新语言的接受太过保守,否则真想废掉ini,直接用lua不就得了,还不用再写代码解析。。

    [回复]

    Ace 回复:

    从这一点来说 还是创业公司适合hacker们啊 哈哈

    [回复]

  2. fy说道:

    好文,我顺便做一个小小的补充

    Mac OS X下

    首先,安装lua
    > sudo port install lua
    其次,建立lua_pub.h头文件到当前目录,内容:
    1 extern “C” {
    2 #include “lua.h”
    3 #include “lauxlib.h”
    4 #include “lualib.h”
    5 }
    6
    最后,编译运行
    > g++ -I/opt/local/include/ -L/opt/local/lib/ -llua main.cpp -o main

    > ./main
    limit:1024

    另外,lua可以这样写:
    1 tb_app2limit = {
    2 {100, 100},
    3 {23, 1000},
    4 {25668, 2^10}
    5 }
    有点意思;不过lua没有字典(dict)类型吗?

    我第一次成功运行这样的组合,初学者,见笑了;
    感谢博主。

    [回复]

  3. ryanking说道:

    楼主贴的是最终代码吗?貌似没有lua_close()

    [回复]

    Dante 回复:

    感谢提醒!貌似忘记写了。。

    [回复]

  4. [...] 二.lua解析器的加入 老博友应该都看过我之前写的一篇博客: 代码即数据,数据即代码(1)-把难以变更的代码变成易于变更的数据,而这一次的需求也非常符合使用脚本的原则: [...]

  5. [...] 二.lua解析器的加入 老博友应该都看过我之前写的一篇博客: 代码即数据,数据即代码(1)-把难以变更的代码变成易于变更的数据,而这一次的需求也非常符合使用脚本的原则: [...]

发表评论