关于代码解耦

xiaoxiao2021-02-28  79

烂的代码,都有各自烂的地方,不过基本都有一个共同的特点:耦合重,各个模块各个类各个功能点 之间关系牵扯不清,经常你调用我调用你,或者全局变量漫天飞; 对于怎么理清这些模块或者类,《代码大全》讲了很多,比如要形成金字塔型的调用层级关系,如果 不能保证,也一定要保证单向的调用关系,绝对不能形成环状的调用关系; 即:A->B->C 而不能是 A->B->C->A,尤其要避免 A<->B 如果不能避免这种循环调用,A和B将无法区分开来,A和B不可避免的扯到了一起,不能单独开发,不 能单独编译,无论改动A或者B中的一个,都会影响到另外一个;这样,随着功能一多,模块一多,最后全 扯到了一起;造成了你中有我,我中有你的感概恶心的耦合!! 如果能保证这种单调单向的调用关系,那代码将形成一定的上下有别的层级,其中任何一层只能调用 下层,绝对不能调用上层,最好是完全不用知道有上层!!即每层都把自己当作是最上层; 这样有几个好处: 1,模块解耦了,如果每层接口设计的好,那每层内部的改动对其他层或者其他模块完全是透明的, 这样有利于分工; 2,模块解耦之后,得到另外的一个好处是:能极大的增强代码模块的复用度,很多模块也许用着用 着就发现提取出来,可以供很多的上层模块调用; 对于集群中的svr节点来说,一般可以划分成一些固定的层:比如:核心数据模块,驱动模块,业务 模块,RPC模块,基础框架模块等等; 上面这些说的都是理论的玩意,而且很多人也都知道,但其实真正写代码的时候,往往发现事情没这 么简单,很多情况下,会发现A->B,B确实要反过来调用B;比如我经常发现有人这样写代码: 状态机FSM模块需要通过RPC模块拉取数据,得到数据后,然后才能接着往下继续处理;一般的 RPC 模块的接口是 rpc::get_data(req, fsm_id),rpc得到数据后,根据fsm_id从全局FSM管理器 g_fsm_mgr  取出FSM,然后调用 FSM::on_data_back(resp)... 看到没有,rpc 和 fsm 完整的融合在了一起,而且必须要通过全局变量融合(这里就会发生非常多的 恶心的地方,比如svr里面有两类都可能调用此rpc状态机...),明显这里是有非常大的问题,rpc 明明和 业务是没半点关系的,rpc应该做的就是远程操作,至于操作的结果,rpc是不应该管的,他只需要简单的 把结果返回给调用者(即上层)即可; 按上面这种做法,rpc 是无法重用的,如果另外写一个svr,而这个svr用的同一套rpc,那他就只能 把这套rpc代码拷贝过来,然后再改几个地方...重复?恶心?低效?bug滋生? 其实对于这个问题,有极其简单极其有效却完全被人忽视的办法:回调!! rpc提供的接口应该是这样的: typedef (*on_data_back)(resp,...) rpc:get_data(req, on_data_back cb, void* params) rpc只需要在内部建立这个req的标志(比如序列号)和 callback以及params的映射即可,当结果返回 时,只需要通过resp的标志找到回调信息,然后 cb(resp, params) 即可,至于cb到底是干什么的,rpc无 权知道,也不需要知道!! 对于所有的下层需要调用上层的情况,回调都应该是最好的选择,也是必须的选择; C语言的精华是指针,指针的精华是函数指针,C的生命,C的灵动,C的多变来源于函数指针;君不见 稍微大点的纯C项目,函数指针都是极其常见的; 说起来其实很简单,确实够简单,却极致够用;那为什么很多项目中还是组织乱成一团麻呢?? 对于C++,回调没C这么简单,以前一直没有找到好用的自然的类函数指针的玩意,后来发现了boost的 function和bind这两个玩意,能完全实现类的回调,而且能随心所欲的携带参数,用多了感觉比C的函数指

针还好用,特别是携带参数这块;C完全依靠void*这个指针携带,而boost的回调不限!!

转自 http://blog.chinaunix.net/uid-26443921-id-3361188.html

转载请注明原文地址: https://www.6miu.com/read-56931.html

最新回复(0)