本記事はこちらのブログを参考にしています。
翻訳にはアリババクラウドのModelStudio(Qwen)を使用しております。
レガシーコードへの対処方法とTongyi Lingmaの活用
by Yunyue
1. レガシーコードとは何か?
古い技術に関連するコード:
- サポートが終了したオペレーティングシステムやソフトウェアライブラリに関連するコード。
- 廃れた技術スタックやプログラミング言語に依存しているコード。
後方互換性のために保持されているコード:
- 古いバージョンとの互換性を確保するために現代のソフトウェアに残されているコードセグメント。
- 後方互換性を維持するために保存しなければならないコード。
ドキュメントやメンテナンスが不足しているコード:
- 十分なドキュメントがない古いコード。
- ユニットテストやコードレビューなどの現代的な開発プラクティスを欠いているコード。
2. レガシーコードに対処する方法
レガシーコードを解決するための3つのアプローチがあります:
アプローチ | 利点と欠点 |
---|---|
スクラッチからの書き直し | コストが高く、システムが稼働中のため、コードリスクを引き起こす可能性がある。 |
リファクタリング | |
ユニットテストの追加 | 既存のコードの問題を特定し、将来のコード変更に品質保証を提供する。 |
上記の説明によると、ユニットテストを追加することはレガシーコードに対処する有効な方法です。しかし、このアプローチにはいくつかの問題があります:
- 大量のレガシーコードはユニットテストがなく、コードセグメント間の複雑な依存関係によりテストコストが非常に高い。
- 具体的な測定基準が十分に明確でなく、優れたユニットテストを定義できない。
- どのコードにユニットテストを追加すべきか?
3. ユニットテストに関する一般的な誤解
- アサーションのない疑似ユニットテスト:開発者がカバレッジ指標を改善するためにアサーションなしで関数を呼び出すことがあり、多くの無効なユニットテストが生じる。
- ユニットテストをホワイトボックステストとみなす:一部の意見ではユニットテストをホワイトボックステストとして分類するが、関数シグネチャに対してブラックボックステストと考えるべきである。
- 実環境への依存:ユニットテストの主な障害要因には怠慢と環境設定への依存がある。外部環境(ネットワークIPやデータベースなど)からStubsやMocksを使用して分離しない場合、ユニットテストはFIRST原則(高速、独立、再現可能、自己検証、タイムリー)を満たすのが難しい。
4. 選択的ユニットテスト
ユニットテストは利益をもたらすだけでなく、一定のコストも伴います。レガシーコードを費用便益の観点から分析することで、レガシーコードにユニットテストを追加する戦略を明確にすることができます。この戦略は選択的ユニットテストと呼ばれます。では、どのようにコストと利益を定義すればよいでしょうか?
4.1 レガシーコードのユニットテストの費用対効果四分類
レガシーコードに対するユニットテストは、そのコストと利益に基づいて四分類できます。分類基準と各四分類の詳細な説明は以下の通りです:
分類基準
- X軸(コスト):コードの依存度が高いほど、テストコストが大きくなる。
- Y軸(利益):コードの複雑さが高いほど、品質向上の利益が大きくなる。
四分類
コードカテゴリ | 特徴 | 説明 | 利益 | コスト |
---|---|---|---|---|
アルゴリズムコード | 高いサイクロマチック複雑度と高いファンイン。多数の条件文やループ文を含み、他のコードへの依存が少ないが、大量のコードによって参照される。 | 高い | 低い | |
些細なコード | 低いサイクロマチック複雑度と高いファンイン。通常、シンプルで1、2行程度のコード。 | 低い | 低い | |
コーディネーターコード | 低いサイクロマチック複雑度と高いファンアウト。呼び出し階層の上位に位置し、他のコードを呼び出して具体的なビジネスシナリオを反映する。 | 低い | 高い | |
複雑すぎるコード | 高いサイクロマチック複雑度と高いファンアウト。多くの依存関係、長い関数、多数のパラメータを持つ複雑なロジックによる典型的な「コードスメル」。 | 高い | 高い |
サイクロマチック複雑度と依存関係の概念
- サイクロマチック複雑度:コード内の論理分岐の数を測定する。
- ファンイン:現在のモジュールを呼び出すモジュールの数。ファンインが高いほど再利用性が高い。
- ファンアウト:現在のモジュールが呼び出すモジュールの数。ファンアウトが高いほど依存関係が多い。
4.2 異なるタイプのコードに対処するための戦略
上記の分析に基づき、レガシーコードに対処するための戦略が明確になります:
- アルゴリズムコード:ユニットテストを生成する。
- コーディネーターコード:インターフェーステストを実施する。
- 複雑すぎるコード:リファクタリングの機会を探す。
- 些細なコード:何も行動を取る必要はない。
4.3 Tongyi Lingmaを使用してレガシーコードに対処する
-
プロジェクトを理解する
レガシーコードをプロジェクト内で保守する際、まず@workspace機能を使用してプロジェクト全体の目的や関連するさまざまなモジュールを理解できます。
- 異なるタイプのコードを処理する
-
アルゴリズムコードのユニットテストを生成する
生成が必要な生産コードに基づく部分を選択します。生成時には必要なフレームワークや依存関係(Mockなど)に注意してください。この情報をユニットテスト生成コマンドに追加することで補足できます。例:/generate unit testingCppUTest
。
一般的に、既存のコードに基づいて生成されるユニットテストケースの数は限られています。テストシナリオやユニットテストのユースケース数に特定の要件がある場合は、新しく生成されたユニットテストファイルでテスト機能を継続してさらに多くのユニットテストを生成できます。継続プロセスでは、Tongyi Lingmaは既存のテストケースを参考コンテキストとして使用しようとします。
-
コーディネーターコードのインターフェーステストを実施する
コーディネーターコードの場合、ユニットテストは理想的な解決策