Правильное использование статического метода фабрики для создания объекта DTO с предопределенными значениями - PullRequest
0 голосов
/ 04 апреля 2019

Давайте предположим, что нам нужно создать сложный объект DTO с некоторыми предопределенными (по умолчанию) значениями.Этот объект используется для сериализации, а сериализатору требуется конструктор без параметров.Для этого я хотел бы использовать статический метод фабрики, но у меня есть некоторые сомнения относительно правильного использования этого подхода.

Пожалуйста, рассмотрите следующие два примера:

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"
        };
    }
}

В первом примере фабричный метод инициализирует только предопределенные поля - остальные пользователи должны инициализировать их после создания объекта.Во втором примере инициализируются предварительно определенные поля, а также поля, которые являются обязательными, но в качестве недостатка пользователь должен заполнить пустое (не обязательное в этом случае, но обязательное в другом) поле flatNumber.

Я вижу как преимущества, так и недостатки этих двух решений, но я думаю, какое из них предпочтительнее и почему.Может быть, какой-то другой подход будет еще лучше.Я открыт для любых предложений, но хочу заметить, что проблема не в том, что шаблон компоновщика будет применим.

1 Ответ

1 голос
/ 04 апреля 2019

Предполагая, что вы

  • хочу методы создания DTO с определенными значениями по умолчанию
  • хочет конструктор по умолчанию и не хочет принудительно использовать фабричные методы

Возможно, ответ состоит в том, чтобы разделить их. Пусть ваш 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 или что-то в этом роде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...