4

私はレガシーコードに取り組んでおり、次のようなコードをたくさん見ました。

public class Person
{
    public Person(PersonData data)
    {
        this.Name = data.Name;
        this.Gender = data.Gender ;
    }

    public String Name { get; private set;}
    public String Gender { get; private set;}
}

public class PersonData
{
    public String Name;
    public String Gender;
}

public static Person ReadPerson(Reader reader)
{
    PersonData data = new PersonData;
    data.Name = reader.ReadString();
    data.Gender = reader.ReadString();

    Person p = new Person(data);
    return p;
}

PersonDataクラスは、コンストラクターのPersonクラスにプライベートフィールドを設定するために存在します。それ以外に、PersonDataクラスは冗長なコードを導入します。これで、PersonクラスとPersonDataクラスの両方にNameとSexが含まれていることがわかります。

私の意見では、この種のデザインは拡張性がありません。新しいフィールド「Age」を読み取る必要があるため、2つの異なる場所に「Age」プロパティを追加する必要があります。

これは有効な設計上の選択ですか(レガシーコードにこのようなコードがたくさんある場合)?
これをリファクタリングするにはどうすればよいですか?

編集:

これらの2つのクラスは、実際のコードの簡略化されたバージョンです。したがって、性別の列挙型の代わりに文字列を使用することはご容赦ください。

実際のコードでは、PersonDataにはPersonクラスのように10を超えるフィールドがあります。

4

5 に答える 5

3

コンストラクター インジェクションを使用し、コンストラクターで多数のパラメーターを取得し始める場合、パラメーター オブジェクトを使用することは有効なアプローチですが、パラメーターが少ない場合は不要です。

ここに提案があります:

public class Person
{
    public Person(string name, string sex)
    {
        _name = name;
        _sex = sex;
    }

    public string Name { get {return _name; }}
    public string Sex { get {return _sex; }}

    private readonly string _name, _sex;
}

これにより、クラスが不変になります。

于 2012-11-17T01:11:14.683 に答える
1

それがある種の外部に面したオブジェクトである場合(あなたの場合のように見えるデータ転送オブジェクトとは異なり)、それらを構築するための流暢なインターフェースを検討できます。クラスの数を減らすことはありませんが、オブジェクトをより派手に構築できます必要なものとオプションのものをより適切に制御できます。

興味のある方は、 fluent-interfaceでタグ付けされた投稿を参照してください。つまり、 Conditional Builder Method Chaining Fluent Interface :

var person = PersonBuilder
  .CreatePerson()
    .Named(reader.ReadString())
    .Sex(reader.ReadString())
    .Build()
于 2012-11-17T01:36:14.240 に答える
0

1つの方法は、代わりに

public String Name { get; private set;}
public String Sex { get; private set;}

タイプのプロパティを公開するPersonData

public class Person
{
    public PersonData PersonData { get; }
}

Personからの派生も見ることができますPersonData

于 2012-11-17T01:10:43.993 に答える
0

を取り除きPersonDataReaderコンストラクターに渡します。

public sealed class Person
{
    public Person(Reader reader)
    {
        this.Name = reader.ReadString();
        this.Sex = reader.ReadString();
    }

    public string Name { get; private set; }

    public string Sex { get; private set; }
}
于 2012-11-17T01:15:09.957 に答える
0

一般に、私はあなたがモデリングしている現実世界 (またはビジネス :)) システムに戻ります。クラスがその世界の何かと一致する場合は、それで問題ありません。クラスが純粋にプログラミング システムの成果物であり、不要に見える場合は、破棄します。「データ」クラスを使用すると、明示的なパラメーターを使用すると発生するさまざまな問題を隠すこともできます。たとえば、「年齢」を追加すると、すべてのケースが見つかったことをどのように検出しますか? コンストラクターのパラメーターとして追加すると、欠落しているすべてのケースに対してエラーが発生します。

于 2012-11-17T01:22:43.407 に答える