3

このコードから始めて:

 new Person("ET").WithAge(88)

どのようにリファクタリングできますか:

 new Person("ET", 88)

変換を完了するには、どのようなリファクタリングのシーケンスを実行する必要がありますか?

なんで?これらは何百もある可能性があり、手動で実行してエラーを発生させたくないからです。

流暢なインターフェースの欠点は、簡単にリファクタリングできないことだと思いますか?

注:コードを手動で入力せずに、これを自動的に実行したいと思います。

4

5 に答える 5

4

おそらく、これをリファクタリングする最も簡単な方法は、名前「WithAge」を「InitAge」に変更し、InitAgeプライベートにして、代わりにコンストラクターから呼び出すことです。次に、のすべての参照を更新しnew Person(string).WithAge(int)て、新しいコンストラクターを使用します。

WithAgeがワンライナーの場合は、代わりにコードを新しいコンストラクターに移動しInitAge、追加のメソッドが追加の可読性を提供しない限り、完全に廃止することができます。

適切な単体テストを行うことで、エラーが発生した場所を特定できます。

于 2009-04-11T04:14:32.647 に答える
3

WithAgeがPersonを返すPersonのメソッドであるとすると、次のようなものはどうでしょうか。

Person(string name, int age)
{
    this.name = name;
    this.WithAge(age);
}

またはより一般化:

Person(SomeType originalParameter, FluentParamType fluentParameter)
{
    //Original constructor stuff
    this.FluentMethod(fluentParameter);
}

次に、FluentMethodを不要な場合はプライベートにし、両方の方法を許可する場合はパブリックのままにします。

于 2009-04-11T04:13:40.327 に答える
2

これがC#の場合(理想的には質問に言語のタグを付ける)、Personクラスには次のコンストラクターが必要です。

public Person(string name, int age)
    : this(name) { WithAge(age); }

次に、すべてのクライアントコードを変更して、必要に応じてこの新しいコンストラクターを呼び出すには、パターンのすべての出現箇所を見つける必要があります。

new Person(x1).WithAge(x2)

ここで、x1とx2は式であり、次のように置き換えます。

new Person(x1, x2)

WithAge以外に他の修飾子メソッドがある場合は、さらに複雑になる可能性があります。例えば:

new Person(x1).WithHair(x2).WithAge(x3)

おそらくあなたはそれを次のようにしたいと思うでしょう:

new Person(x1, x3).WithHair(x2)

それはすべて、そのような言語対応の検索/置換パターンを定義できるIDEがあるかどうかによって異なります。一連のキー押下を再生するマクロと組み合わせて、単純なテキスト検索と置換を使用して、ソリューションへの長い道のりを得ることができます。

流暢なインターフェースの欠点は、簡単にリファクタリングできないことだと思いますか?

特にそうではありません-IDEのリファクタリング機能は、新しいリファクタリングを創造的に発明できるように十分に柔軟に設計されているか、特定の一般的なケースに合わせてハードコーディングされています。一般的なケースは、新しいケースを発明するために変更できる例として定義することをお勧めします。

于 2009-04-11T08:17:24.750 に答える
1

私はそのようなことについて実際的な経験はありませんが、私があなたの状況にあった場合、私が探しに行く場所はカスタムEclipseリファクタリング(またはRefactor!Pro for .Netの同等のもの)です。使用)。

正規表現がプレーンテキストではなく抽象構文木と一致する必要があることを除いて、基本的に必要なのは一致と置換です。それが自動リファクタリングです。

このリファクタリングのリスクの1つは、ターゲットバージョンの精度が元のバージョンよりも低いことです。検討:

クラスPerson{
  public Person(String name、int age);
  public Person(String name、int numberOfChildren);
}

Person.WithAgeへの連鎖呼び出しをこれらのコンストラクターのどれに置き換える必要があるかを判断する方法はありません。

したがって、これを自動サポートするには、続行する前にそのようなあいまいさをチェックする必要があります。ターゲットパラメーターを持つコンストラクターがすでに存在する場合は、リファクタリングを中止します。

それ以外はかなり簡単に思えます。新しいコンストラクターに次のコンテンツを提供します。

public Person(String name、int age){
  この名前);
  withAge(age);
}

その後、元の呼び出しを新しい呼び出しに安全に置き換えることができます。

(コンストラクター内、つまり部分的に構築されたオブジェクトでwithAgeを呼び出すことは、コンストラクターの後で呼び出すこととまったく同じではないという点で、微妙な追加のリスクがあります。継承チェーンがある場合withAgeが何かを行う場合は、違いが重要になります。自明ではありませんが、それがユニットテストの目的です...)

于 2009-04-11T08:01:21.900 に答える
0
  1. 古いコードの単体テストを記述します。

  2. テストが再び合格するまでリファクタリングします。

于 2009-04-11T04:11:13.640 に答える