0

あらかじめ定義された (既定の) 値を持つ複雑な DTO オブジェクトを作成する必要があるとします。このオブジェクトはシリアル化に使用され、シリアライザーにはパラメーターなしのコンストラクターが必要です。そのために静的ファクトリ メソッドを使用したいのですが、このアプローチの適切な使用方法について疑問があります。

次の 2 つの例を考えてみてください。

public class Foo
{
    public void DoSomething()
    {
        // the first way of creating the object
        var addressDtoFirstWay = AddressDtoFirstWay
            .CreateWithPredefinedValues();
        addressDtoFirstWay.StreetName = "Street";
        addressDtoFirstWay.HouseNumber = 100;
        addressDtoFirstWay.PostalCode = "1000";

        // the second way of creating the object
        var addressDtoSecondWay = AddressDtoSecondWay
            .CreateWithPredefinedValues("Street", 100, null, "1000");
    }
}

public class AddressDtoFirstWay
{
    public string RecipientName { get; set; }
    public string StreetName { get; set; }
    public int HouseNumber { get; set; }
    public int? FlatNumber { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
    public string CountryName { get; set; }

    public static AddressDtoFirstWay CreateWithPredefinedValues()
    {
        return new AddressDtoFirstWay
        {
            RecipientName = "John Doe",
            City = "City",
            CountryName = "Country"
        };
    }
}

public class AddressDtoSecondWay
{
    public string RecipientName { get; set; }
    public string StreetName { get; set; }
    public int HouseNumber { get; set; }
    public int? FlatNumber { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
    public string CountryName { get; set; }

    public static AddressDtoSecondWay CreateWithPredefinedValues(
        string streetName,
        int houseNumber,
        int? flatNumber,
        string postalCode)
    {
        return new AddressDtoSecondWay
        {
            RecipientName = "John Doe",
            StreetName = streetName,
            HouseNumber = houseNumber,
            FlatNumber = flatNumber,
            PostalCode = postalCode,
            City = "City",
            CountryName = "Country"
        };
    }
}

最初の例では、ファクトリ メソッドは事前定義されたフィールドのみを初期化します。ユーザーは、オブジェクトの作成後に残りのフィールドを初期化する必要があります。2 番目の例では、事前定義されたフィールドと必須フィールドを初期化しますが、欠点として、ユーザーは null 許容 (この場合は必須ではありませんが、他のフィールドでは必須) フィールドに入力する必要がありますflatNumber

これら 2 つのソリューションの長所と短所の両方を理解していますが、どちらがより好ましいか、またその理由を検討しています。たぶん、他のアプローチがさらに良いでしょう。私はどんな提案も受け入れますが、ビルダーパターンが適用される問題はそれほど複雑ではないことに注意してください。

4

1 に答える 1

2

あなたが

  • 特定のデフォルトで DTO を作成するメソッドが必要
  • デフォルトのコンストラクタが必要で、ファクトリ メソッドの使用を強制したくない

おそらく答えは、2つを分離することです。あなたのDTOに独自のことをさせてください:

public class AddressDto
{
    public string RecipientName { get; set; }
    public string StreetName { get; set; }
    public int HouseNumber { get; set; }
    public int? FlatNumber { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
    public string CountryName { get; set; }
}

...そして、さまざまなデフォルト オプションでごちゃごちゃにしないでください。時間が経つにつれて、さまざまなシナリオに対して異なる既定値が必要になることがわかります。私はそれが少し乱雑になるのを見ることができました。

次に、まったく同じ静的メソッドを取得して、独自のクラスに配置します。

public static class AddressDtoFactory
{
    public static AddressDto CreateWithPredefinedValues()
    {
        return new AddressDto
        {
            RecipientName = "John Doe",
            City = "City",
            CountryName = "Country"
        };
    }
}

私は、ファクトリ メソッドがデフォルト値のみを入力する「最初の方法」に傾倒します。その理由は、特にプロパティが検証されていない場合、すべてのプロパティをパラメーターとして渡す必要があるのは少し面倒だからです。さらに、プロパティを追加するたびにそのコンストラクターを更新する必要があります。

別のオプションは、次のような拡張クラスです。

public static class AddressDtoExtensions
{
    public static AddressDto PopulatePredefinedValues(
        this AddressDto dto)
    {
        dto.RecipientName = dto.RecipientName ?? "John Doe";
        dto.City = dto.City ?? "City";
        dto.CountryName = dto.CountryName ?? "Country";
        return dto;
    }
}

これにより、次のようなことができます。

var dto = new AddressDto
{
    HouseNumber = 5,
    PostalCode = "12345"
}.PopulatePredefinedValues();

プロパティの初期化とデフォルトの追加の両方を使用できます。また、Automapper などを使用することにした場合は、少し使いやすくなるかもしれません。

于 2019-04-04T18:54:32.857 に答える