4

メソッドの実行に依存するプロパティを処理する最善の方法は何ですか?

2 つのプロパティを持つクラスと、それら 2 つのプロパティで何かを行うメソッドがあるとします。クラスをインスタンス化し、プロパティを設定してから、(パラメータなしで) メソッドを実行する方がよいでしょうか。または、クラスをインスタンス化してからメソッドを実行し、プロパティを設定するパラメーターを渡しますか?

例えば:

class Person ...
    string Name ...
    string Address ...
    void Save() {
        Database.SavePerson(this.Name, this.Address);
    }

- - また - -

class Person ...
        string Name ...
        string Address ...
        void Save(string name, string address) {
            this.Name = name;
            this.Address = address;
            Database.SavePerson(this.Name, this.Address);
        }

最初の例では、Save メソッドが呼び出される前に Name と Address がまだ設定されていない場合、エラーが発生します。したがって、これらのプロパティがメソッドで設定されていることを検証する必要があるようです。

2 番目の例では、メソッドの実行に必要なデータをユーザーに提供するように強制します。ただし、渡されるパラメーターは既にオブジェクトのプロパティであるため、これは少し冗長に思えます。

これを行う「最良の」方法はありますか?

前もって感謝します。

4

5 に答える 5

2

まず、エンティティに独自の永続性を持たせることがあなたが望む設計であるかどうかを検討します。

そうでない場合は、Personエンティティがプロパティを公開し、別のタイプがそのエンティティを保存する責任を負いPersonます (たとえば、リポジトリ パターンのようなものを使用する場合がこれに該当します)。

エンティティがそれ自体を永続化する責任がある場合 (CSLA などのフレームワークで使用されるようなリッチ ドメイン モデルを使用している場合のように)、パラメーターのないSaveメソッドだけがあり、プロパティが必要な場合は、次に、何らかの形式の検証フレームワークが、欠落している要件をキャッチします。

于 2012-10-18T20:15:53.557 に答える
2

個人的には、どちらもしません。あなたが持っている最初の例はActive Recordに似ていますが、2番目の例は私にはまったく意味がありません.関数が引数を受け入れる場合、フィールド/プロパティを持つポイントは何ですか?

両方のメソッドの問題は、Personクラスがデータベースロジックを公開していることです。これは望ましくない場合があります。

私がすることは、リポジトリパターンを使用することです:

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
}

public class PersonRepository()
{
    public void Add(Person person)
    {
        // do some database stuff
    }
}

// ...

Person person = new Person() { Name = "Jim", Address = "123 Fake Street" };

PersonRepository personRepository = new PersonRepository();
personRepository.Add(person);
于 2012-10-18T20:19:06.630 に答える
0

私の頭に浮かぶのは、この方法で単一責任の原則を破っているということです。あなたは3つのことをするからです-エンティティを永続化すること、そして人の名前を変更すること、そしてそのアドレスを変更することです。これはメソッドの名前からは明らかではありません。これは副作用です。

したがって、メソッドが実際に何をするかを開発者に通知するには、メソッドの名前をに変更する必要がありますSaveAndRenameAndRelocate。あまり良い名前ではありませんか?同意。

したがって、エンティティを現在の状態で保存するためのパラメータなしのメソッドを作成しました。

public void Save()
{
   // code, which should be somewhere in repository
}

人の名前を変更する必要がある場合は、Nameプロパティを使用して名前を変更します。アドレスを変更する必要がある場合は、Addressプロパティを使用して変更します。名前や住所なしで人を保存することが許可されていない場合-コンストラクターを介してこれらのプロパティを初期化します。

public Person(string name, string address)
{
   // null-check goes here
   Name = name;
   Address = address;
}

ところで、エンティティを永続化するのはあまり良い考えではありません:)

于 2012-10-18T20:28:19.607 に答える
0

パラメーターが何らかの方法で推定/解決できる場合、または変更されない場合にのみ、メソッドをパラメーターなしにします。

そうしないと、メソッドを使用するためにメソッドがどのように機能するかを理解する必要がある、恐ろしい漏れのある抽象化になります。

于 2012-10-18T20:13:31.857 に答える
0

パラメーターなしで独自のプロパティを自動的に使用するインスタンス メソッドがあるか、渡されたパラメーターを受け入れる静的メソッドがあるかのいずれかです。

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }

    public void Save()
    {
        Database.SavePerson(Name, Address);
    }

    public static void Save(string name, string address)
    {
        Database.SavePerson(name, address);
    }
}

オブジェクトの一般的な考え方は、各オブジェクトが独自のデータに責任を持つということです。ただし、クラスには、グローバルに使用でき、どのオブジェクト インスタンスにもバインドされない静的メソッドを含めることができます。静的メソッドはインスタンス メンバーにアクセスできません。


Personしかし、基本的な問題は、保存メソッドをクラスに含める必要があるかどうかです。代わりに、Database.SavePersonメソッドのパラメーター リストを次のように変更します。

public static void SavePerson(Person person) { ... }

そして、このように使用します

var p = new Person { Name = "John", Address = "Wall Street, NY" };
Database.SavePerson(p);
于 2012-10-18T20:21:27.120 に答える