2011-12-14 8 views
10

VC6コンパイラを使用してC++で実装された非常に古いレガシーシステムで動作します。これでコードをリファクタリングしています。 VC9コンパイラにも切り替えました。レガシーAPI /フレームワーク(C++マクロvs. C++テンプレートvs.コードジェネレータ)に多数の複雑なラッパーを実装する方法は?

私たちは、独自のフレームワークを使用しています。これはレガシーコードであり、ユニットテスト可能ではありません。我々のコードユニットがテスト可能にするために、我々はフレームワーククラスのためのインタフェースとラッパーを導入しました(ヒント:は、Martin Fowler氏によるを「レガシーコードの操作」を参照してください):

enter image description here

今、私たちはインタフェースに依存します。ラッパーはフレームワークメソッドを呼び出します。単体テストではモックを喜んで使用します。我々は問題に来る

そして、ここでは...

フレームワーククラスは、ラップと嘲笑する必要がある多くのメソッドが含まれています。この目標を達成するために、サプライヤチームは、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は非常に複雑で、そのようなツールを書くことは非常にコストがかかるでしょう。

このような問題を解決するにはどうすればよいと思いますか?多分あなたは既にそのようなことに取り組んでいて、良いヒントを提供することができますか?私たちはあなたの答えを見ることを楽しみにしています!

答えて

1

私はコード生成ツールを使うと思います。私はおそらく、いくつかのシンプルなユーティリティプログラムを作っています:レガシーフレームワークのクラスに対応するインタフェースを生成するためのもの、ラッパーを生成するもの、モックオブジェクト(または少なくともスケルトン)を生成するもの。

これは、従来のフレームワークのコードを解析する方法があることを意味します。 Clangを見てみるか、ソースファイルでctagsを実行して、結果のタグを扱います。

+0

Thx。 Clangとctagsを見ていきます。 – nowaq

0

コードベースが十分に大きい場合(つまり、C++の数百、数千行)、そしてあなたがGCCでそれをコンパイルすることができるかどうか(最新のバージョン、すなわち4.6)あなたは、おそらく特定のGCCプラグインを作る検討することもでき、またはMELT内線です。(MELTは、GCCを拡張するための高度なドメイン固有の言語です)。しかし、そのようなGCCのカスタマイズは、かなりの努力(作業の数週間ではなく)を必要とします。

+0

私はGCCに行くことができたらいいと思います。残念ながら、私たちはVisual Studioコンパイラに完全に固執しています。 – nowaq

+0

レガシーコードまたは非利用可能なソースコード用のラッパーを使用する場合+1。 – umlcat

1

この問題を解決するには、マクロではなく抽象的な工場を使用してください。後

class IApiFactory{ 
virtual ISomeApi1* getApi1() =0; 
virtual ISomeApi2* getApi2() =0; 
..... 
}; 

のようなあなたの通常のAPIとMOC APIのために、このインタフェースを実装し、システムにあなたの工場のインスタンスを渡し:お使いのシステムが宣言されなければならない

MySystem system(new NormalApiFactory); 

または

MySystem system(new MocApiFactory); 

として:

class MySystem{ 
public: 
    MySystem(IApiFactory* factory); 
}; 

工場では、通常のAPI実装またはmocオブジェクトを返します。 もちろん、ルートファクトリから "他のファクトリやオブジェクトを返す"ファクトリを返すこともできます。

+1

しかし、問題は、このパターンにコードの大きな袋をどのようにリファクタリングするかです。 –

+0

@BasileStarynkevitch 'APIの問題は、非常に複雑で、読み込み不能で、デバッグできず、テストできないということです。 '同じ目標を達成するためのより良い仕組みを考え出したいと思います。このアイデアは、高度なテンプレート、タイプリスト、特性などの新しいコンパイラに付属する高度な機能のいくつかを使用していたということでした。私はちょうどこの問題を解決するための標準的なメカニズムを提案します。 – AlexTheo

+0

@AlexTheo申し訳ありませんが、説明が少し混乱する可能性があります。 「API」と言うことは、私たちが現在Wrappersを生成するために使用しているMACROSを意味していました。これは、より良い/より良い/より堅牢なものに置き換えたい "問題"です。 – nowaq

0

私はコードジェネレータが好きです。ラップされるすべてのものの辞書を作成することができます。時間がかかり、コードを生成するための簡単なツールを使用します。コードの横には、レガシーシステムの明確な参照情報、後でそれを置き換えるガイドもあります。

0

私たちのDMS Software Reengineering Toolkitは、ソースコードを読み込んでそれに対して任意の変換を実行するプログラム変換ツールです。

DMS C++ Front End(VC6以上のVisual Studio対応)を使用すると、おそらくモックされるコンポーネントのヘッダーファイルを読み込んでモックを生成することができます。

DMSは、特にインターフェースの変更を含む、種々の周りにインターフェイスをシャッフル、C++コードに大規模な変換を行うために使用されています。私の技術論文、 Re-engineering C++ Component Models Via Automatic Program Transformationを参照してください。

0

が完全に制御された方法で、あなたのコード生成をstructurize、まだ何が必要、これまで困難APIのものを生成し、すべての自由を維持するための方法があります。

http://blogs.msdn.com/b/t4/archive/2011/11/30/some-nice-new-getting-started-with-t4-videos.aspx

: - あなたは、Visual Studio(2005少なくとも、好ましくは2008または2010)を使用すると、構造化コード生成のこのT4チームの言及方法を使用することができますを使用している場合

ことは、T4のみXMLに基づいています

私はそのADM方法論の革新者でリードアーキテクトであり、そのブログの作成者ですhttp://abstractiondev.wordpress.com/

残念ながら私はあなたに合った具体的なケースはありませんが、あなたがコミュニティに利益をもたらしたい場合は、その事例を公開してください)。

関連する問題