如何组织几十个类似的try-catch块?

时间:2016-11-23 09:52:19

标签: c++ refactoring code-readability

我有外部界面,让我们说20种类似的方法。每个人都可以抛出任何东西。

所以,我有20种方法:

void Call3Wrapper(int& important_parameter)
{
try 
{
   external_namespace::IExternal::Call3(important_parameter);
}
catch(external_namespace::Exception& ex)
{
   LogIt(ex, "Call3");
   throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
   LogIt(ex, "Call3");
   throw mynamespace::MyException(ex);
}
catch(...)
{
   LogIt("Unresolved exception", "Call3");
   throw mynamespace::MyException("Unresolved exception");
}
}

每个Call1-Call20都是一样的(使用不同的参数调用)。

如:

  • void Call7Wrapper(std :: string& important_parameter)
  • void Call12Wrapper(bool& important_parameter,double& important_parameter2)

......等等。

我对所有这些案例都有很好的函数LogIt,我们自己的类型MyException也可以处理所有这些案例。

所有这20个(40,60)函数体看起来都很难看,因为90%的代码都是完全相似的try-catch检查。当一个开发人员需要修复所有这些内容时,他们就会死...

是否存在一种方法/实践如何组织它不那么丑陋的方式? 像构造函数和析构函数中的lock-unlock-idiom,但是对于try-catch?

我绝对不想使用#define CALLS_CATCH_BLOCK(call_name) ...

1 个答案:

答案 0 :(得分:1)

也许你可以模板化包装并通过函数对象调用它:

template<typename CALLABLE_T>
void CallWrapper(CALLABLE_T callable, const char* name)
{
try 
{
   callable();
}
catch(external_namespace::Exception& ex)
{
   LogIt(ex, name);
   throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
   LogIt(ex, name);
   throw mynamespace::MyException(ex);
}
catch(...)
{
   LogIt("Unresolved exception", name);
   throw mynamespace::MyException("Unresolved exception");
}
}

然后,您可以使用std::bind创建带参数的可调用对象,例如:

CallWrapper(std::bind(&external_namespace::IExternal::Call3,
                      std::ref(important_parameter)),
            "Call3");

(或boost::bind / boost::ref适用于较旧的编译器)

请注意,编译器仍会为每个不同的CALLABLE_T类型生成模板的实例化,但您不需要重复代码。

另请注意,通过这种方式,您还可以调用和处理类等的成员函数。

如果要由API接口使用它,您可能仍需要创建单独的方法,但在内部调用模板化包装器而不是重复异常处理代码。