在项目的源代码中,我看到一个300行的switch / case子句。但它的结构非常好,因为每一个案例都是这样的:
case X:
{
msg_type_for_X msg;
if (msg.ParseFromArray (m_readBuffer))
recv_X (msg);
}
break;
这让我希望把它分成20行。对于每个案例X
,类msg_type_for_X
是由protobuf定义的类。对我来说这似乎很棘手,因为编译器无法知道msg具有什么类型。那么人们如何重构这样的东西呢?或者人们只是不管它?
答案 0 :(得分:2)
您可以在宏中使用令牌粘贴。看here。
这将是:
#define CASE_MSG(X) \
case X: \
{ \
msg_type_for_##X msg; \
if (msg.ParseFromArray (m_readBuffer)) \
recv_##X (msg); \
} \
break;
还有其他方法可以做这种事情,并且有一个msg_type_for_X结构数组,你将它们全部初始化,然后你甚至不需要使用一个案例:
if (messages[X].ParseFromArray(m_readBuffer))
messages[X].recv(msg);
当然,需要进行一些重构才能将recv_X
作为消息解析器的一种方法。
答案 1 :(得分:0)
从简单的基本界面开始,如
struct IMsgOperation { virtual int indexOf() const = 0; virtual bool ParseFromArray(param of type m_readBuffer) = 0; /*virt desturctor and etc*/}
然后为每个X类型定义特定的类:
struct XMsgOperation : public IMsgOperation { int indexOf() const { return hardcode_index_of_X_from_some_enum; }; virtual bool ParseFromArray(); }
并实施它; 为每个XMsgOperation创建实例数组,
vector<IMsgOperation *> parsers(num_of_parsers, NULL);
比填充数组
IMsgOperation *pOp=new FooMsgOperation; parsers[pOp->indexOf()]=pOp; ...
并发明映射函数以将X的每个值映射到正确的索引
static int IMsgOperation::type2index(type_of_X X) { switch(X) { case X: return 0; ...} }
比它可以使用:
parsers[IMsgOperation::type2index(type_of_X X)]->ParseFromArray(m_readBuffer)
注意,如果type_of_X是整数种类,那么您可以将type_of_X的值组织为线性顺序并消除type2index。以上不包含任何安全检查,添加它们的味道。