Как реализовать большое количество сложных оболочек для устаревшего API / фреймворка (макросы C ++ против шаблонов C ++ против генератора кода)?

Мы работаем с очень старой устаревшей системой, реализованной на C ++ с компилятором VC6. Сейчас мы находимся в процессе рефакторинга кода. Мы также перешли на компилятор VC9.

Мы используем внешнюю проприетарную структуру, которая также является устаревшим кодом и не подлежит модульному тестированию. Чтобы сделать наш код тестируемым, мы ввели интерфейсы и оболочки для классов фреймворка (подсказка: см. «Работа с устаревшим кодом» Мартина Фаулера):

enter image description here

Теперь мы зависим от интерфейсов. Обертки вызывают методы фреймворка, и мы с радостью можем использовать имитацию в наших модульных тестах.

И вот мы подошли к нашей проблеме ...

Классы фреймворка содержат множество методов, которые нужно обернуть и имитировать. Для достижения этой цели наша команда поставщиков написала API, который генерирует интерфейсы, оболочки и фиктивные реализации с использованием макросов C ++.

Пример файла заголовка оболочки:

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 в том, что он чрезвычайно сложен, не читается, не поддается отладке и тестированию.

Мы хотели бы придумать лучший механизм для достижения той же цели. Идея заключалась в том, чтобы мы использовали некоторые расширенные функции, которые поставляются с новым компилятором, такие как расширенные шаблоны, списки типов, свойства и т. Д.

С помощью шаблонов мы можем почти достичь нашей цели, но мы застряли с именами методов. Мы можем делать обобщения для типов, но как нам поступать с именами атрибутов?

Мы также думали о создании инструмента для автоматической генерации оболочки + интерфейсов + имитационного кода. Однако API нашего внешнего фреймворка чрезвычайно сложен, и написание такого инструмента будет очень дорогостоящим.

Как вы думаете, как лучше всего решить такую ​​проблему? Может быть, вы уже сталкивались с подобным и можете дать хорошие подсказки? Ждем ваших ответов!

10
задан fortran 14 December 2011 в 11:20
поделиться