4

与えられた: (人々が何年も一緒に暮らしている非常に厄介なフレームワークの一部)LegacyControllerClassを拡張するA。MonsterFrameworkClassフレームワーク クラスは、デフォルト コンストラクターの大量のロジックから、反射的にクラスをロードする静的ブロックに至るまで、多くの魔法を実行します。

LegacyControllerClassグローバルな状態を変更する、の多くのライフサイクル メソッド。メソッドは、execute()あなたが考えることができるすべての悪を持っている千ライナーです。

public class LegacyControllerClass extends MonsterFrameworkClass {

   //Life-cycle method
   public void validate(){...}

   //Life-cycle method
   public void preExecute() {...}

   //Life-cycle method
   public void execute() {
       //oodles of legacy code here:
       //    examples: call static methods of 'Util' classes
       //              lots of new X().y(..)
       //              call databases, services
       //              Even call super.execute()!!
       //              More rubbish
       //              More rubbish 
   }
}

さて、アクションのシーンは execute() メソッドです。私は、彼らが「ストーリー」と呼んでいるアイテムをテスト駆動することによって、これらの持っていないものにテスト駆動開発を導入しています。「ストーリー」には、ビュー (jsp) が読み取って表示できるように、responseProperties にエラー メッセージを追加することが含まれます。擬似コードは次のようなものです。

if (error) {
    Build the error message
    Add the error message into the responseProperties
}

execute()残念ながら、このコードは、メソッド内のごみの間にサンドウィッチする必要があります。

私の質問は、私ができる最善のことは何ですか? 私が思いつく解決策は次のとおりです。

  1. 2 つのメソッドを抽出rubbish1()し、rubbish2()
  2. テストコードで期待どおりにそれらをスタブします(たとえば、エラーフラグを設定します)
  3. rubbish1()との間に私のコードを入れてくださいrubbish2()

私はこの方法で実装を開始しましたが、MonsterFrameworkClass静的ロード、ResourceBundleランダムなプロパティ ファイルをロードするコンストラクタ マジックなどのように、本当に邪魔になっています。

同じことに対処する別の方法はありますか?

小さな免責事項:私は間違いなくMichael Featherの「Working with Legacy Code」を購入してそれを飲み込むつもりですが、SOは簡単に達成できるように思えました。

4

1 に答える 1

1

ごみをメソッドにリファクタリングすることは問題ありません。これで、Powermock をダウンロードして、コード内のひどいゴミをすべてモックアウトできます。モッキングが完了したら、コードをテストできます。

この怪物に何も追加しない方が良い. MonstrosityRubbish新しいもののために独自のクラスを作成することにより、機能を(または何でも)構成できます。

主なことは、可能であればレガシーコードに触れないことです。代わりに、コードを構成することができます。

コードでは:

private MyShinyClass yourShinyObject; // init

public void execute(Param param0) {
    rubbish1();
    yourShinyObject.handleError(param0);
    rubbish2();
}

public class MyShinyClass {

    public void handleError(Param param0) {
        // your code here
    }
}

このように新しいものを書くことができれば、モック/スタブできるものだけに依存しParam、髪に火をつけることなくコードをテストできます。

responseProperties分離されたコードで操作する必要がないように、機能的な方法で記述できればさらに良いです。

public void execute(Param param0) {
    rubbish1();
    responseProperties.add(yourShinyObject.fetchErrors(param0));
    rubbish2();
}

public class MyShinyClass {

    public List<HopelessError> fetchErrors(Param param0) {
        // your code here
    }
}

もちろんexecute()、必要な変数/フィールドを渡すことができるパラメーターは必要ありませんhandleErrors()

于 2013-10-25T12:01:08.450 に答える