标签:pre use 入参 思考 com 成功 res 错误信息 场景
在最近的开发过程中,遇到这样一个问题,细想蛮有意思的,在此记录一下。
在进行具体讨论前,先将业务抽象,方便后续讨论。比方说,有一个业务Business
,它依赖三个子命令A
,B
和C
,每个命令都是异步收发且有先后顺序要求,暂且以A->B->C
为依赖关系,每个指令都可能出错(响应超时或者响应错误),并且只要有一个出错,后续请求不必再发送,直接返回错误。
以上是业务背景,下面来看下如何组织上述逻辑关系。
按照异步收发框架以及需求,这块逻辑,可以这样写:
void Business()
{ // 第一步,发送命令A
SendCommandA();
}
// 底层异步响应回调函数
void OnReply(CReq* pReq)
{
switch(pReq)
{
case CommandA:
{ // 收到A响应后,正确则继续发送B命令,错误则回复错误。
pReq->isRespRight() ? SendCommandB() : OnFinish(ECheckResult_Error, "指令A的错误信息");
}
break;
case CommandB:
{
pReq->isRespRight() ? SendCommandC() : OnFinish(ECheckResult_Error, "指令B的错误信息");
}
break;
case CommandC:
{
pReq->isRespRight() ? OnFinish(ECheckResult_OK, "正确结果") : OnFinish(ECheckResult_Error, "指令B的错误信息");
}
break;
default:
assert(0); // 未知情况
break;
}
}
上述写法,直观明了,前一个指令响应成功,再发下一个指令,否则提示错误。这种写法不好之处在于指令与指令之间耦合太紧。改进方案是利用消息来拆分调用关系。例如收到CommandA
的正确响应,发出一个类似OnReceiveCmdA
的异步消息。在消息中,带上CommandA
指令响应的相关信息。业务自身订阅该消息并进行后续处理。这样一来,可降低命令之间的依赖,增加灵活性。
这里,我想提到的是另外一点,在工程中,看到其他同事有写这样的响应处理:
// 其他的省略
case CommandA:
{
if (pReq->isRespRight())
{
OnFinish(EQryResult_CommandA_OK, pReq->GetRightRet());
}
else
{
OnFinish(EQryResult_CommandA_SysError, pReq->GetErrorMsg());
}
}
break;
}
enum EQryResult
{
EQryResult_CommandA_OK,
EQryResult_CommandB_OK,
// ...
EQryResult_CommandA_SysError
}
void OnFinish(EQryResult eRet, string& strMsg)
{
switch(eRet)
{
case EQryResult_CommandA_OK:
{
SendCommandB();
}
break;
case EQryResult_CommandA_SysError:
{
// tip user
}
breakl
}
}
上面这种组织逻辑的思路,是针对每种情况,无论是正确的还是错误的,都定义对应的类型码,提供一个统一的OnFinish
处理函数入口。通过入参,配合类型码来完成后续的操作。
这种组织逻辑的方法,笔者感觉不好,思考了下,有以下几点不好的地方:
OnFinish
函数,再根据具体入参,找到对应的处理分支,才能检查正确性,这种封装,降低代码可读性,不推荐。这种异步处理,建议错误情况统一处理,正确情况,通过消息来隔离各个具体的处理流程,每一个具体的处理,用类似OnRespCommandA
这样的函数包裹起来,明确表明职责,这是较为稳妥的组织方法。
标签:pre use 入参 思考 com 成功 res 错误信息 场景
原文地址:https://www.cnblogs.com/cherishui/p/14864411.html