c++ - 如何为遗留 API/框架实现大量复杂的包装器(C++ 宏与 C++ 模板与代码生成器)?

标签 c++ templates macros code-generation legacy-code

我们使用使用 VC6 编译器以 C++ 实现的非常古老的遗留系统。现在我们正在重构代码。我们还切换到 VC9 编译器。

我们使用外部专有框架,该框架也是遗留代码,不可进行单元测试。为了使我们的代码单元可测试,我们为框架类引入了接口(interface)和包装器(提示:请参阅 Martin Fowler 的“使用遗留代码”):

enter image description here

现在我们依赖接口(interface)。包装器调用框架方法,我们可以愉快地在单元测试中使用模拟。

现在我们来到了我们的问题......

框架类包含许多需要包装和模拟的方法。为了实现这一目标,我们的供应商团队编写了一个 API,它使用 C++ 宏生成接口(interface)、包装器和模拟实现。

封装头文件示例:

class PlanWrapper : public IPlan
{
  // ... 
  WRP_DECLARE_DEFAULTS(FrameworkPlan); // macro
  WRP_DECLARE_CSTR_ATTR(FrameworkPlanLabel); // macro
  // ...
};

宏 WRP_DECLARE_CSTR_ATTR 定义如下:

#define WRP_DECLARE_CSTR_ATTR(AttrName) \
    virtual bool set##AttrName (LPCTSTR Value_in); \
    virtual bool get##AttrName (CString& Value_out); \
    virtual bool unset##AttrName (); \
    virtual bool isSet##AttrName ()

包装器 cpp 文件示例:

#include "StdAfx.h"

using namespace SomeNamespace;

WRP_IMPLEMENT_MODDICOM_DEFAULTS(FrameworkPlan)
WRP_IMPLEMENT_W_CSTR_ATTR (FrameworkPlan,FrameworkType1, FrameworkPlanLabel)
// ...

宏 WRP_IMPLEMENT_W_CSTR_ATTR 定义如下:

#define WRP_IMPLEMENT_W_CSTR_ATTR(ClassName,AtrTypeObj,AttrName) \
    bool ClassName##Wrapper::set##AttrName (LPCTSTR Value_in) { \
            AtrTypeObj aValue = Value_in; \
        FrameworkLink<ClassName> convertedObj = NULL_LINK; \
        framework_cast(convertedObj, m_Object); \
        return convertedObj != NULL_LINK ? \
                       convertedObj->set##AttrName (aValue) : false; \
    }
    // ...

我们有一堆更复杂的东西,但我想你明白了。

API 的问题是它极其复杂,不可读,不可调试,不可测试。

我们想提出一个更好的机制来实现相同的目标。我们的想法是,我们使用新编译器附带的一些高级功能,如高级模板、类型列表、特征等。

使用模板我们几乎可以实现我们的目标,但是我们被方法名所困。我们可以概括类型,但我们如何处理属性名称?

我们还考虑过创建一个工具来自动生成包装器 + 接口(interface) + 模拟代码。然而,我们的外部框架的 API 非常复杂,编写这样一个工具的成本非常高。

您认为解决此类问题的最佳方法是什么?也许您已经处理过类似的事情并且可以提供很好的提示?我们期待看到您的回答!

最佳答案

我想我会选择代码生成工具。我可能会制作一些简单的实用程序:一个用于生成与遗留框架的类对应的接口(interface),一个用于生成包装器,一个用于生成模拟对象(或至少一个骨架)。

这意味着有一些方法可以解析遗留框架的代码。我会看看 Clang ,或者简单地运行 ctags在源文件上处理生成的标签。

关于c++ - 如何为遗留 API/框架实现大量复杂的包装器(C++ 宏与 C++ 模板与代码生成器)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8503457/

相关文章:

linux - 找不到 AX_CXX_COMPILE_STDCXX_11 宏

javascript - 从JavaScript向C++发送数据,超过127的字节值被替换为 "replacement character"

c++ - STL vector 之间的自动转换

c++ - xtensor - Tensor 包装器在运行时引发 trivial_assigner 错误

c++ - 如何实现is_polymorphic_functor?

c++ - C++ 模板元编程的最佳介绍?

c++ - 如何从 std::istream 加载 wxXmlDocument?

c++ - 如何一次包含所有的 C++ 标准库?

c - 通用预处理器宏启用检查

c++ - 嵌套宏中的 BOOST_PP_SEQ_ELEM 和 BOOST_PP_SEQ_ADD ?