Как создать построитель в C # для объекта, свойства которого являются ссылочными типами? - PullRequest
0 голосов
/ 10 сентября 2009

Я начал создавать конструктор, чтобы легко создавать тестовые данные для написанных модульных тестов.

Основная структура застройщика:

public class MyClassBuilder
{
    public int id = 0; //setting the default value here

    //allows MyClass to be built with a specific id
    public MyClassBuilder WithId(int id)
    {
        this.id = id;
        return this;
    }

    public MyClass Build()
    {
        return new MyClass(id);
    }
}

Использование этого шаблона затем становится:

MyClass mc = new MyClassBuilder().WithId(5).Build();

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

public class MyClassBuilder
{
    public int id = 0; //setting the default value here

    //do I construct the default value using a MySecondClassBuilder?
    public MySecondClass mySecondClass;

    //allows MyClass to be built with a specific id
    public MyClassBuilder WithId(int id)
    {
        this.id = id;
        return this;
    }

    public MyClassBuilder WithMySecondClass(MySecondClass mySecondClass)
    {
        this.mySecondClass = mySecondClass;
    }

    public MyClass Build()
    {
        return new MyClass(id);
    }
}

Я предполагаю, что я бы создал компоновщик для MySecondClass и использовал бы его для создания реализации по умолчанию.

Может ли кто-нибудь подтвердить, что мое предположение верно и является наилучшей практикой?

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

Ответы [ 2 ]

1 голос
/ 10 сентября 2009

Как с большинством вещей - это зависит.

Если вы хотите ссылочную семантику в поле mySecondClass (то есть: вы хотите сохранить ссылку на другой класс), то это точно как ваше целое число. Значение по умолчанию, равное нулю, может быть вполне приемлемым.

Однако, если вы хотите всегда гарантировать значение, вам нужно либо создать, либо просто создать новый объект для вашего второго класса.

Кроме того, если вы хотите клонировать, а не по ссылочным копиям, вам необходимо создать новый объект и назначить его для ссылки.

Тем не менее, во многих случаях традиционные конструкторы являются более подходящими, чем попытка создать свободный интерфейс в стиле сборки. Действительно легко «испортить» свободный интерфейс для создания подобного построения, поскольку вы полагаетесь на пользователя больше, чем на традиционный конструктор.

Например, что в вашем коде происходит, если пользователь никогда не вызывает Build? Он по-прежнему что-то возвращает (так как каждый из методов возвращает объект), но допустимо ли это? Я не был бы уверен как потребитель вашего класса. Традиционные конструкторы с перегрузками, с другой стороны, показывают мне, что является допустимым, а что нет, и применяются во время компиляции.

0 голосов
/ 01 марта 2010

Как только у меня появится сложный объект, в котором я хочу использовать пустышку в модульных тестах, я обычно обращаюсь к фальсификации / подделке / изоляции. В C # я предпочитаю Moq, но есть несколько таких, как Rhino Mocks, Typemock и так далее.

Преимущество заключается в том, что они, как правило, имеют возможность заглушить все свойства, существующие в исходном типе, со значениями по умолчанию и пустыми объектами, без необходимости делать что-либо, кроме оператора одной строки, для создания поддельного объекта. В то же время вы можете легко настроить объект так, чтобы он возвращал значения, которые вы хотите для свойств, имеющих значение для вашего теста. Кроме того, большинство таких фреймворков поддерживают рекурсивное подделывание, так что сложные объекты внутри вашего типа также будут поддельными и т. Д.

Есть причины, по которым кто-то может не захотеть использовать отдельную структуру, и в этом случае я думаю, что предложение Рида Копси было бы ручным способом сделать это.

Если нет причин избегать добавления фреймворка (который будет зависеть только от ваших тестовых проектов, если вы разделите тестирование), я бы искренне рекомендовал его для сложных типов.

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