2.7.3 划分模块的方法
《设计模式:可复用面向对象软件的基础》是一本非常知名的书,其中介绍了20多种设计模式。我在很早之前就看过这本书,但是说实话一直没有完全掌握书中的内容。这里给出一种比较简单的方法用于划分模块,供读者参考。
根据是否封装数据,可以把模块划分为两类:
(1)数据类的模块:用于实现对数据的封装。
(2)过程类的模块:其中不包含数据封装。
1. 数据类的模块
数据类的模块基于以下两种方法之一实现对数据的封装。
(1)模块内的全局静态变量。这种方法用于像C语言这样不支持类和对象的语言。
(2)类的内部变量。这种方法用于支持类和对象的语言,如C++语言、Java语言、Python语言、Go语言等。
在以上两种方法中,优先使用第二种。第一种方法其实已经是比较过时的方法了,它的局限是只能同时运行一个实例,如果想同时支持多个实例,会出现数据冲突。在C++语言、Python语言、Go语言中,大家都要避免使用第一种方法。
即使对于C语言这样不支持类和对象的语言,其实也可以支持多个实例,可以在每个接口中都传入数据实例的指针。针对2.7.2节中“题外话:C语言是面向过程的吗”中的例子,可以将程序改造为:
下面是使用Python语言实现的例子,其中使用了类的内部变量来实现数据的封装。
数据类的模块要对外提供明确的数据访问接口。大家所熟悉的数据结构和算法属于模块内部的工作。在上面C语言和Python语言的例子中,都提供了读接口和写接口。
在做程序的模块划分时,首先考虑有哪些数据类的模块,并用上面的方法定义出来。
2. 过程类的模块
过程类的模块本身不包含数据,在执行过程中,它会调用其他“数据类的模块”或“过程类的模块”。
例如,在图2.9中,module_D是一个过程类模块,它调用的module_A和module_B是数据类模块,而module_C也是一个过程类模块。
图2.9 过程类模块对其他模块的调用
3. 以BFE开源项目为例
在BFE(Beyond Front End)开源项目[7]中,使用了以上介绍的划分模块的方法。
BFE是一个七层负载均衡软件,原来的开发初衷用于百度内部服务。截至2019年年底,BFE所支持的转发平台的日转发请求约1万亿次,日峰值请求超过每秒1000万次查询。2019年年中,BFE转发引擎对外开源,2020年6月BFE开源项目被CNCF(Cloud Native Computing Foundation,云原生计算基金会)接受为Sandbox Project(沙盒项目)。
BFE开源项目位于GitHub官网中的/bfenetworks/bfe。在BFE开源项目中,数据类模块的例子包括:
(1)/bfe_balance/bal_table.go。
(2)/bfe_modules/mod_block/product_rule_table.go。
过程类模块的例子包括/mod_block/mod_block.go。