程序模块化设计时通过配置模块间的依赖关系来控制各个模块启动的先后顺序

程序模块化设计时通过配置模块间的依赖关系来控制各个模块启动的先后顺序

接上一篇文章“分享一个C++下使用简单的反射实现的程序模块化的思路”,现在要解决的问题是,如果程序的各个模块在启动时要有先后顺序,那我们该怎么办呢?

举个例子

比如我们在写网络应用程序时:

  1. 首先我们要接收数据,而接收数据的途径可能有多种,如通过tcp接收,或通过udp接收,或通过串口接收,且接收的数据格式也可能有多种,如厂家A的私有协议格式,或厂家B的私有协议格式;此时,我们可以针对这些各种不同的情况分别写一个模块,每个模块负责处理不同的数据,然后所有的这些模块将数据重新组织成我们自己统一的一种格式,再把统一格式的这个数据交给数据处理模块去处理即可。

  2. 其次我们要处理数据,由于前面已经将各种不同的数据类型统一成了一种格式,所以这里就写一个数据处理模块即可。

  3. 处理完数据之后,我们通常要把数据分发出去,而数据分发也可能要支持多种格式,比如用户A希望咱们给他的数据格式是json格式的,用户B希望咱们给他的数据格式是http格式的,此时我们针对这两种情况就可以写两个模块,一个模块分发json格式数据,一个模块分发http格式数据。

OK,我们看上面三个步骤,肯定是有先后顺序的,也就是按照上面描述的1 2 3这个顺序依次执行即可。

细化一下:

  1. 数据接收模块有:tcp_data_recver 和 udp_data_recver

  2. 数据处理模块有:data_handler

  3. 数据分发模块有:json_data_publisher 和 http_data_publisher

那么上面这些模块在启动时,我希望tcp_data_recver 和 udp_data_recver最先启动,然后是data_handler启动,最后才是json_data_publisher 和 http_data_publisher启动;

我们用什么办法来实现这个启动顺序控制呢?

之前我一直用的是zorder这个办法,就是类似界面编程中窗口次序那个办法。手工给每个不同的模块分配一个排序值(即zorder),然后调用排序函数对模块数组按照zorder进行排序,然后顺序启动即可。

但是用着用着就发现,这个办法用起来很费劲,每次新增模块,还要人肉去统计一下所有模块的zorder,然后给这个新模块分配一个合适的zorder值,程序经常改动,模块增加的比较频繁的时候,问题就越发严重。

后来我在用到UE5的subsystem时,发现里面有个设计很好,这个设计就是子系统依赖,即每个子系统在初始化时可以配置他依赖其它的哪些子系统,当配置好了之后,程序在启动时就会根据你配置的依赖关系自动计算先启动谁后启动谁。这个子系统实际上我们就把它当成这里的模块即可。

OK,现在我们知道可以用这个办法来解决这个问题了。但我并不知道配置了这些复杂的模块依赖之后,用什么算法去将这些依赖关系计算成先后顺序。于是我在各个大模型里问了一下,得到了一些答案和相应的C++算法代码。这里复制一下算法原理,就是:在处理复杂的依赖关系时,可以使用图论中的拓扑排序(Topological Sorting)来确定各个子系统的初始化顺序。拓扑排序是一种对有向无环图(DAG, Directed Acyclic Graph)进行排序的算法,它能够确保在图中没有环路的情况下,所有节点按照依赖关系排序,使得每个节点在其依赖节点之后被处理。

我觉得这个依赖关系设计比zorder要好用很多,再添加新模块时,只需要配置好它依赖哪些模块就完了,比人肉配置zorder舒服很多。

这里仅是提供了一种思路,不再做过多的代码层面的分析了,贴上完整的演示代码,下载之后即可编译,未依赖任何其它第三方库,在这里:https://github.com/zhllxt/subsystem

这个演示代码没有写什么注释,可能不太方便理解,有需要的就结合着看看吧。

程序运行的输出为:

tcp_data_recver::init
udp_data_recver::init
data_handler::init
json_data_publisher::init
http_data_publisher::init

tcp_data_recver::start
udp_data_recver::start
data_handler::start
json_data_publisher::start
http_data_publisher::start

http_data_publisher::stop
json_data_publisher::stop
data_handler::stop
udp_data_recver::stop
tcp_data_recver::stop

http_data_publisher::uninit
json_data_publisher::uninit
data_handler::uninit
udp_data_recver::uninit
tcp_data_recver::uninit

可以看到模块的启动和停止顺序已经符合了我们的意图了。

最后更新于 2024-09-25

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值