10

Visual Studio6を使用してC++で記述された大規模なアプリケーションの場合、現代に移行するための最良の方法は何ですか?

コードの一部をゆっくりと移動し、たとえばC#に新しい機能を書き込んで、それをレガシーアプリケーションから参照できるライブラリまたはdllにコンパイルするという段階的なアプローチを取りたいと思います。

これは可能ですか、それを行うための最良の方法は何ですか?

編集:現時点では、現在のアプリで頻繁に使用されているMFCライブラリの使用を許可していないと思われるExpressエディションに限定されています。また、ハードウェアに依存する非常に大きなアプリなので、大規模な移行がカードに含まれているとは思いません。

Edit2:COMでラップされたコンポーネントをC#で作成することを検討しましたが、COMの経験がないため、これは恐ろしくて複雑です。すべての管理された良さを内部に隠したストレートCインターフェイスでC#dllを生成することは可能ですか?それともCOMは必要悪ですか?

4

10 に答える 10

12

コードの一部をゆっくりと移動するインクリメンタルアプローチを採用したいと思います

それがそれを行う唯一の現実的な方法です。

まず、どのようなバージョン管理を使用していますか?(コードを危険にさらすリスクを最小限に抑えながら、実験を行って何が機能するかを確認できる分岐バージョン管理を使用する場合。他のバージョンも問題ありませんが、使用するものによっては十分に注意する必要があります)。

編集:あなたがSVNを使用しているのを見ました。それを行う自由がある場合は、mercurialまたはgitに移行する価値があるかもしれません(この変更により、コードベースで実行できることは飛躍的に向上します)。

たとえば、新しい機能をC#に書き込み、それをレガシーアプリケーションから参照できるライブラリまたはdllにコンパイルします。

それは...必ずしも良い考えではありません。C#コードは、C++でアクセス可能なCOMインターフェイスを公開できます。C#で記述されたモジュール用にC ++でクライアントコードを記述することは楽しいことですが、(利益に対する努力の比率の点で)負担がかかる場合があります。また、速度が遅く、エラーが発生しやすくなります(C ++で記述されたモジュールのC#クライアントコードを記述する場合と比較して)。

C#でアプリケーションフレームワークを作成し、コア機能にC ++で記述されたモジュール(すでに)を使用することを検討することをお勧めします。

これは可能ですか、それを行うための最良の方法は何ですか?

はい、可能です。

プロジェクトには何人の人が関わっていますか?

多くの場合、最良の方法は、新しいアプリケーションフレームワークでいくつか(2?4?)作業を行い、残りを通常どおり続行することです。

人数が少ない場合は、担当者かアルバイトをすることを検討してください。

それぞれ(古いコードの保守と新しいコードの開発)に割り当てられる人/労力の割合は、チームの規模と優先順位によって異なります(移行は優先度の低い問題ですか?特定の日付までに完了する必要がありますか?)

これを行うための最良の方法は、コードのモジュールを複数のシナリオで使用できるように(古いコードと新しいコードの両方で)適応させ始め、並行して開発を継続することです(これも、分散型の分岐を使用することで大幅に容易になりますバージョン管理システム)。

これが私がそれをどのように進めるかです(小さなステップと多くの妥当性チェックを間に挟んだ反復型開発):

  1. 古いコードベースで機能モジュール(GUIに関連しないもの)を選択します。

  2. 手順1で選択したモジュールから、MFCコード(およびVS2010 Expressで使用できない他のライブラリ-ATLなど)の参照を削除します。

    小さな変更がない限り、MFC / ATL機能をカスタムコードで書き直そうとしないでください(つまり、独自のGUIフレームワークを作成することはできませんが、次のような独自のCOMインターフェイスポインターラッパーを作成することはできます。 ATLのCComPtr)。

    コードがライブラリに大きく依存している場合は、可能な限り分離してから、新しいテクノロジーを使用して将来書き直すためにマークを付けてください。いずれにせよ、MFCに大きく依存しているライブラリの場合は、他の何か(C#?)を使用してコードを書き直す方がよいでしょう。

  3. 選択したモジュールとの結合を可能な限り減らし(コードが別のライブラリにあることを確認し、モジュールがクライアントコードに公開する機能を明確に決定します)、決定された公開インターフェイス(古いコード)を介してのみ区切られた機能にアクセスします。

  4. 古いコードベースが変更されたモジュールで引き続き機能することを確認します(テスト-最終的にこのモジュールのテストを自動化します)-新しいバージョンを出荷するまで市場にとどまる必要がある場合、これは重要です。

  5. 現在のアプリケーションを維持しながら、GUIおよび最新化する必要のあるその他の部分(MFCに大きく依存する部分など)を実装する新しいプロジェクト(C#ベース?)を開始します。これはシンレイヤーアプリケーションである必要があり、できればビジネスロジックに依存しないようにする必要があります(可能な限りレガシーコードに残す必要があります)。

    古いコードの機能と定義するインターフェイスによっては、コードの一部にC#ではなくC ++ / CLIを使用するのが理にかなっている場合があります(ネイティブC ++ポインターとマネージコードで機能するため、次の場合に簡単に移行できます。マネージ.NETコードとC++ネイティブコード間の通信)。

  6. 手順1で選択したモジュールを新しいアプリケーションで使用するようにします。

  7. 新しいモジュールを選択し、手順2に戻ります。

利点:

  • リファクタリングが実行されます(モジュールの分離に必要)

  • 最後に、機能モジュールの一連のテストを行う必要があります(まだ行っていない場合)。

  • あなたはまだ間に出荷する何かを持っています。

いくつかの注意:

  • 分散分岐バージョン管理システムを使用しない場合は、一度に1つのモジュールで作業することをお勧めします。分岐/分散ソース管理を使用する場合は、さまざまなモジュールをさまざまなチームメンバーに配布し、新しいものが移植されるたびに変更を一元化できます。

  • 各ステップが明確に区切られていることが非常に重要です(変更を最後の安定バージョンにロールバックしたり、新しいことを試したりできるようにするため)。これは、SVNでは難しく、Mercurial/Gitでは簡単なもう1つの問題です。

  • 開始する前に、すべてのプロジェクトファイルの名前を.2005.vcproj拡張子に変更し、ソリューションファイルに対しても同じことを行います。新しいプロジェクトファイルを作成するときは、プロジェクトファイルとソリューションに対して.2010.vcxprojを使用して同じことを行います(ソリューション/プロジェクトを変換する場合は、これを行う必要があります)。アイデアは、いつでも好きな方を並行して開いておく必要があるということです。IDEを切り替えるためだけに、ソース管理で別のラベル/タグ/日付にソースツリーを更新する必要はありません。

Edit2:COMでラップされたコンポーネントをC#で作成することを検討しましたが、COMの経験がないため、これは恐ろしく複雑です。

ラッパーコードを作成することで、それを行うことができます(たとえば、COMインターフェイス用の小さなテンプレート化されたスマートポインタークラスは、ATLのCComPtrと同様に失敗しません)。一部のラッパーの背後にあるCOMコードを分離した場合、(COMに関係なく)クライアントコードを(ほとんど)問題なく記述できます。

すべての管理された良さを内部に隠したストレートCインターフェイスでC#dllを生成することは可能ですか?それともCOMは必要悪ですか?

私が知っていることではありません。C#で書かれたサーバーコードとC ++で書かれたクライアントコードを使うつもりなら、COMは必要悪だと思います。

逆の可能性もあります。

于 2010-06-15T13:38:41.933 に答える
6

同じタスクに直面すると、私の戦略は次のようになります。

  1. 2010年の開発に移行することで得たいものを特定します。

    • 品質保証の改善:単体テスト、モックは最新の開発ツールの一部です
    • 滑らかなUI:WPFはモダンなルックアンドフィールを提供します。
    • 生産性:一部の領域では、.NET開発はC++開発よりも生産性が高い
    • サポート:新しいツールがサポートされ、改善とバグ修正が行われました。
  2. システムのどの部分がC#に移動しても得られないかを特定します。

    • ハードウェアアクセス、低レベルのアルゴリズムコード
    • ほとんどのカスタムメイドの非UI動作コード-すでに動作している場合はそれを捨てても意味がありません
  3. システムのどの部分をc#に移行する必要があるかを特定します。これらのパーツについては、C ++の現在の実装が分離され、モジュール化されていることを確認して、これらのパーツを交換できるようにします。アプリがモノリスの場合、アプリを分割してc#で再実装された部分を選択できるように、アプリをリファクタリングするためにかなりの作業が必要になります。(何もリファクタリングすることはできません。代わりに、c#での新しいアプリケーション機能の実装に集中するだけです。)

  4. どの部分がC++に残り、どの部分がc#に実装されるかを特定したので(または、新しい機能がc#にあることを指定するだけで)、c#とc++を単一のソリューションに統合する方法に焦点を当てます。

    • COMラッパーを使用する-既存のC++プロジェクトがOOをうまく利用している場合、これは見た目ほど難しくないことがよくあります。MSVC 6では、ATLクラスを使用して、クラスをCOMコンポーネントとして公開できます。
    • ネイティブコードとc#コードを直接統合します。「レガシー」コンパイル済みコードを統合するには、中間DLLが必要です。詳細については、こちらを参照してください。

MFC UIとc#UIを混在させることは、おそらく達成不可能であり、2つの異なるスタイル(1990年代のグレーと2010年の雰囲気)のUIミックスを生成するためお勧めできません。c#で新しいアプリケーションコードを実装し、ネイティブC ++コードから呼び出すなど、増分移行の実現に集中する方が簡単です。これにより、移行されるc#コードの量が最初から少なくなります。2010の開発に取り掛かるにつれて、UIなど、段階的に移行できない大きなチャンクを取得できます。

于 2010-06-15T01:35:56.793 に答える
4

まず、あなたの近世の定義は物議を醸しています。C#がC++よりも優れていると考える理由はありません。C#がメモリ管理エラーを回避するのに役立つかどうかについては多くのことが言われていますが、これはC ++の最新の機能ではほとんどそうではなく、リソース取得のタイミングの点でC#を混乱させるのは非常に簡単です。他のプログラムがやっています。

于 2010-06-11T19:44:20.180 に答える
3

6から2010に直接移行すると、プロジェクト設定が混乱する可能性があります。これがかなり大規模なプロジェクトではなく、変換する必要がある数少ないプロジェクトの1つである場合は、それで問題ありません。2010年に開いて、変換ウィザードに従います。必ず最初にプロジェクトをバックアップし、完了したらプロジェクト設定を確認してください。

私の意見では、最善の方法は、VisualStudioの各反復を通じて段階的に変換することです。2003年から2010年にかけて1400のプロジェクトを最新化する必要がありました。私が見つけた最善の方法は、すべてを2005、2008、最後に2010に変換することでした。これにより、発生する問題の量が最小限に抑えられました。

Visual Studioが6つしかない場合は、ウィザードを使用して新しいVisualStudioに直接アクセスする必要があります。すべてが再び正しくビルドされる前に、手動でクリーンアップすることを期待してください。

また、もう一度、最初にバックアップしてください!:)

于 2010-06-02T14:39:36.840 に答える
3

低レベルのC#コードを呼び出す高レベルのC ++コードは、良い考えとは思えません。.NET言語が優れている分野は、ユーザーインターフェイス、データベースアクセス、ネットワーク、XMLファイルの処理です。計算、ハードウェアアクセスなどの低レベルのものは、ネイティブC++コードとして保持する方が適切です。

.NETに移行すると、ほとんどの場合、WPFまたはWindowsフォームテクノロジを使用してUIを完全に書き直すことをお勧めします。低レベルのものはネイティブのままであり、C#とネイティブコードを接続するためにさまざまな相互運用性テクノロジが使用されます:PInvoke、C ++ / CLIラッパー、またはCOM相互運用性。しばらくすると、本当に必要な場合にのみ、C#で低レベルのネイティブコンポーネントを書き直すことができます。

VS2010でのネイティブC++コードのコンパイルについて-問題はありません。すべてのコンパイルエラーを修正するだけです。新しいコンパイラには、より厳密な型チェックと構文制限があり、コンパイル時にはるかに多くのバグをキャッチします。

于 2010-06-02T14:59:19.340 に答える
3

なぜそんなに多くの人々がCOMを提唱しているのか分かりません。まだ多くのCOMを使用していない場合は、C ++側でそれを行う方法を学ぶことは害を及ぼし、管理側から可能な限り遅い相互運用機能を使用します。私の最初の選択ではありません。

理想的には、ビジネスロジックからUIをリファクタリングしました。次に、新しいUI(WPF、WinForms、ASP.NET、他のクライアントをサポートするWebサービスなど)を構築し、P/InvokeまたはC++/CLIラッパーを作成してビジネスロジックを呼び出すことができます。@mdmaは、リファクタリングが可能であると仮定して、あなたに良いアドバイスを提供します。

しかし、もしあなたが私に来てあなたを助けるためにお金を払っていたら、私の最初の質問はなぜあなたはこれをしたいのですか?一部のクライアントは、C ++開発者にこれ以上支払いたくないと言っているので、すべてのC++コードを削除したいと考えています。私たちは皆、機能するコードに触れることを嫌うので、これは恐ろしい目的です。一部のクライアントは、ロジックをASP.NETやReporting Servicesなどに公開したいので、リファクタリングに集中します。そして、「1999年のように見える」と言う人もいます。彼らのために、私はMFCが現在どのように見えるかを示します。色、オフィスとwin7の外観を含むスキニング/テーマ、リボン、フローティング/ドッキングペインとウィンドウ、Windows 7タスクバーの統合...見た目を変えたいだけの場合は、VS2010のMFCを見てください。調整する必要がない場合があります。すべてのコード。

最後に、VS 2010の非エクスプレスバージョンを手頃な価格で提供するために、マイクロソフトパートナープログラムを調べてください。まだあなたと話している少なくとも3人の顧客にソフトウェアを販売し、Windows 7ロゴのセルフテストを通過できる場合(私は1日か2日でVB 6アプリを取得しました)、5〜10個のコピーを作成できます。住んでいる場所にもよりますが、すべて(Windows、Office、VS)の年間1900ドル程度です。

于 2010-06-17T11:54:20.393 に答える
2

まず、書き直しを避けるために、できるだけ多くのコードを保持するようにします。また、変換を開始する前に、未使用のコードをすべて削除します。

VC ++ 6.0以降、MicrosoftはMFCライブラリとC++標準ライブラリを変更しました。

依存関係のないDLLの構築を開始し、次にサードパーティのライブラリを調べてから、一度に1つの依存するDLL/EXEを再構築することをお勧めします。

単体テストを導入して、コードの動作が変わらないことを確認します。

異なるバージョンのVC++を使用する混合ビルドの場合は、異なるバージョンのVCランタイムを使用するDLL間でリソース(ファイルハンドル)が渡されないように保護する必要があります。

于 2010-06-02T15:04:34.023 に答える
2

経済的に可能であれば、必要なバージョンのVisual Studioにお金を払うことを強く検討します。これは、費やす時間により多くのお金を失う可能性があるためです。Express Editionについては、良い答えを出すのに十分な知識はありませんが、C ++で記述された下請け業者からのコードを統合するときは、C ++/CLIを使用しました。コードベースのほとんどを再利用でき、言語に精通している可能性がありますが、マネージコードとライブラリにもアクセスできます。また、C#で新しいコードを書き始めたい場合は、それを行うことができます。私が抱えていた最大の問題は、VS2010ではC++/CLIにインテリセンスがないことでした。

于 2010-06-17T11:37:07.920 に答える
1

Visual Studio 6は、バグが多く遅いことで有名です。現代への移行は、新しいコンパイラを入手することによって行うのが最善です。おそらく最も簡単な方法は、レガシーアプリをDLLに書き込んでから、exeをC#に書き込んで、P/Invokeを使用することです。そうすれば、古いコードに再度触れる必要はありません。C#で記述を増やし、古いDLLの使用量を減らすことができます。

古いコードが非常にOOである場合は、C ++ / CLIを使用して、.NETがC ++オブジェクトのメソッドを呼び出すことを可能にするラッパークラスを記述し、参照カウントスマートポインターを使用する場合はそれらも収集できます。

于 2010-06-02T14:44:55.147 に答える
0

C#を使用して、COMまたはCOM +(System.EnterpriseServices)ラッパーを使用して新しいコンポーネントを作成できます。これらのラッパーは既存のC++コードから呼び出すことができます。

于 2010-06-02T14:46:59.197 に答える