バックグラウンド
現在進行中のC#プロジェクトに取り組んでいます。私はC#プログラマではなく、主にC ++プログラマです。そのため、基本的に簡単でリファクタリングするタスクが割り当てられました。
コードはめちゃくちゃです。それは巨大なプロジェクトです。お客様が新機能とバグ修正を含む頻繁なリリースを要求したため、他のすべての開発者はコーディング中にブルートフォースアプローチをとることを余儀なくされました。コードはメンテナンスが非常に難しく、他のすべての開発者はそれに同意します。
私は彼らがそれを正しくしたかどうかを議論するためにここにいるのではありません。私はリファクタリングしているので、リファクタリングされたコードが複雑に思えるので、正しい方法でそれをやっているかどうか疑問に思っています!これが簡単な例としての私の仕事です。
問題
6つのクラスがありますA
、B
、C
、D
、E
とF
。すべてのクラスには関数がありますExecJob()
。6つの実装はすべて非常に似ています。基本的に、最初A::ExecJob()
は書かれました。次に、のB::ExecJob()
copy-paste-modificationによって実装されたわずかに異なるバージョンが必要でしたA::ExecJob()
。別のわずかに異なるバージョンが必要になったとき、C::ExecJob()
書かれたなど。6つの実装すべてに共通のコードがあり、次にいくつかの異なるコード行があり、さらにいくつかの共通コードがあります。実装の簡単な例を次に示します。
A::ExecJob()
{
S1;
S2;
S3;
S4;
S5;
}
B::ExecJob()
{
S1;
S3;
S4;
S5;
}
C::ExecJob()
{
S1;
S3;
S4;
}
SN
まったく同じ文のグループはどこにありますか。
それらを共通にするために、別のクラスを作成し、関数内の共通コードを移動しました。パラメータを使用して、実行するステートメントのグループを制御します。
Base::CommonTask(param)
{
S1;
if (param.s2) S2;
S3;
S4;
if (param.s5) S5;
}
A::ExecJob() // A inherits Base
{
param.s2 = true;
param.s5 = true;
CommonTask(param);
}
B::ExecJob() // B inherits Base
{
param.s2 = false;
param.s5 = true;
CommonTask(param);
}
C::ExecJob() // C inherits Base
{
param.s2 = false;
param.s5 = false;
CommonTask(param);
}
この例では、3つのクラスと単純化されたステートメントのみを使用していることに注意してください。実際には、CommonTask()
関数はこれらすべてのパラメーターチェックで非常に複雑に見え、さらに多くのステートメントがあります。また、実際のコードには、いくつかのCommonTask()
見た目の関数があります。
すべての実装は共通のコードを共有しており、ExecJob()
機能はよりキュートに見えますが、次の2つの問題があります。
- の変更については
CommonTask()
、テストするために6つすべての(将来的にはさらに増える可能性がある)機能が必要です。 CommonTask()
すでに複雑です。時間とともに複雑になります。
私はそれを正しい方法でやっていますか?