高端的写if/else

作者: | 更新日期:

十行代码改成七百行代码

本文首发于公众号:天空的代码世界,微信号:tiankonguse

一、背景

一周没写公众号了。

因为这周比较忙,前三天在忙上云的事情,后两天在思考如何把 if/else 写的高大上点。

这里将思考过程写下来。

二、if else

最近接到一个需求,如果返回的值中存在4,则增加6

面对这个需求,最简单的方式就是 if/else 实现。

由于最近有很多项目在同时进行,而且都很紧急。
我便提出:如果想快速实现的话,可以hard code来实现,十行代码就搞定了。

if(field_name == "xxxx") {
    auto vec = split(field_val, "+");
    if(vec.has(4) && !vec.has(6)) {
        vec.insert(6);
        field_val = join(vec, "+");
    }
}

大老板说,这个还是要花点时间做的通用点,尽量做到 DB 配置化。

我争论道:

1、其他需求还蛮紧急的,如果这个花太多时间,其他的就需要延后了。
2、目前这个服务两三年没需求与变更了,没必要为了通用而通用。经常会遇到花很多时间设计一个通用的功能,结果几年下来从来没复用过。

当然,最近在做中台,老板想的是任何功能都要通用化。
所以只能多花一些时间来通用化了。

三、映射

如果 if/else 很多,且比较有规律的话,可以通过映射实现。

DB 中储存字段需要计算的函数名,比如callback

然后通过函数的输入与输入标准化,每个逻辑都实现一个小函数。

// 实现的每个小逻辑  
string CopyValueCallback(const string& in,
                         const FieldConfig& params);

初始化的时候,使用map 维护函数名与函数指针的关系。

// 小逻辑映射注册
map<string, FuncCallBack>  callbacks;
callbacks["copy_value"] = CopyValueCallback;

具体的业务代码,通过查找映射执行对应的代码

string callback = field_config["callback"];
if(CopyValueCallback.has(callback)) {
    auto f = CopyValueCallback[callback];
    field_value = f(field_value, field_config);
}

通过这样的设计,在业务代码中只有一个判断语句,就是查询这个字段是否需要特殊运算,需要了,调用对应的处理函数。

这个代码实现后,小老板说我们要做的更通用点。
每个功能尽量原子化,然后通过各种原子功能的配置化组装来做到想要的运算。

我一想,这不就是前段时间说的 DAG 与 图计算嘛。
业界在大数据的流计算上也运用的很成熟了。

于是我只能继续花点时间来思考怎么设计流计算了。

四、流计算

思考了一段时间后,发现对于流计算想要自由的组装,需要满足几个条件。

条件一:每个算子的输入与输出必须要标准化。

所以这里需要设计一个通用的协议结构,可以表示任意形式的数据。

其实,json 就可以代表任意结构。 我们使用 protobuf 设计了一个结构化的支持无限递归的协议。
当然,实际上和 json 是等价的。

条件二:需要一个图配置,来表示怎么组装算子与运算。

我想了想,这个由于是存在 DB 中的,只能使用 json 储存了。

由于是单链计算,可以简单一个数组搞定。

条件三:使用一个工厂管理所有的算子。

这个简单,实现一个通用的抽象接口类,然后所有的原子继承这个算子即可。
每个算子在实现文件里也可以做到自动注册,这样就是可插拔无耦合的了。

条件四:流计算引擎

有了标准的协议、算子工厂,通过计算引擎,就可以自动根据图配置来计算任意想计算的功能了。

五、最后

就这样,原来的 10 行 if/else 代码,转化为了高大上的 700 行流式计算代码。

流计算由于涉及协议、算子工厂、每个具体算子、引擎、图配置等,这些功能的正确性就很重要了。
所以很有必要引入单元测试了。

等全部编写完单元测试,原先的 10 行 if/else 代码,后面应该至少会变成 1000 行代码。

本来想把项目从 makefile 转化为 bazel ,然后快速引入单元测试。
了解了一下 bazel 文档,发现这是一个大工程,没有三天搞不定。
所以,只能研究怎么使用 makefile 引入单元测试了。

思考题:你的if/else是怎么写的呢?

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越