VC6コンパイラを使用してC++で実装された非常に古いレガシーシステムで動作します。これでコードをリファクタリングしています。 VC9コンパイラにも切り替えました。レガシーAPI /フレームワーク(C++マクロvs. C++テンプレートvs.コードジェネレータ)に多数の複雑なラッパーを実装する方法は?
私たちは、独自のフレームワークを使用しています。これはレガシーコードであり、ユニットテスト可能ではありません。我々のコードユニットがテスト可能にするために、我々はフレームワーククラスのためのインタフェースとラッパーを導入しました(ヒント:は、Martin Fowler氏によるを「レガシーコードの操作」を参照してください):
今、私たちはインタフェースに依存します。ラッパーはフレームワークメソッドを呼び出します。単体テストではモックを喜んで使用します。我々は問題に来る
そして、ここでは...
フレームワーククラスは、ラップと嘲笑する必要がある多くのメソッドが含まれています。この目標を達成するために、サプライヤチームは、C++マクロを使用してインターフェイス、ラッパー、および模擬実装を生成するAPIを作成しました。
class PlanWrapper : public IPlan
{
// ...
WRP_DECLARE_DEFAULTS(FrameworkPlan); // macro
WRP_DECLARE_CSTR_ATTR(FrameworkPlanLabel); // macro
// ...
};
マクロWRP_DECLARE_CSTR_ATTRこのように定義される:ラッパーCPPファイルの
#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()
例:
#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は非常に複雑で、そのようなツールを書くことは非常にコストがかかるでしょう。
このような問題を解決するにはどうすればよいと思いますか?多分あなたは既にそのようなことに取り組んでいて、良いヒントを提供することができますか?私たちはあなたの答えを見ることを楽しみにしています!
Thx。 Clangとctagsを見ていきます。 – nowaq