2009-07-17 3 views
23

После нескольких лет после неудачной практики, переданной от «архитекторов» на моем месте работы, и думая, что должен быть лучший способ, я недавно читал о TDD и DDD и мне подумайте, что принципы и практика будут отлично подходить для сложности программного обеспечения, которое мы пишем.TDD, DDD и инкапсуляция

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

С другой стороны, несколько уважаемых людей в отрасли (Грег Янг наиболее заметно с его переговорами о CQRS) защищают полностью инкапсулирование каждого объекта домена, удаляя все «геттеры».

Мой вопрос заключается в следующем: как проверить функциональность объекта домена, если ему запрещено получать его состояние?

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

+1

ХА, я хотел прочитать немного больше об этом принципе «без геттеров» после прочтения этого сообщения ... и этот пост стал первым результатом Google. –

+0

Я предполагаю, что я искал имя для шаблона, который я видел в другом месте. Сначала я смотрел видео о разделении команд-запросов, которое выступало за домен с записью и альтернативный путь для запроса хранилища данных. Затем я прочитал еще несколько статей, в которых обсуждались геттеры, нарушающие инкапсуляцию и т. Д. Возможно, эти условия приведут к лучшим результатам поиска? – Justin

+0

С вашего комментария, я думаю, что, скорее всего, вы слышали «не-сеттеры». Многие считают, что сеттеры нарушают инкапсуляцию.Я на самом деле соглашаюсь в целом, что они злоупотребляют, но по-прежнему полезны и необходимы во многих случаях. –

ответ

17

Что вы описываете, это подтверждение состояния, в котором вы указываете состояние объекта домена. Существует ветвь TDD, которая называется верификацией поведения, которая использует объекты Mock.

Проверка поведения позволяет указать, какие методы следует вызывать, а если хотите, какие методы не вызывают.

За дополнительной информацией обратитесь к этой статье Мартина Фаулера: Mocks Aren't Stubs.

+0

Awesome - это дало мне несколько ключевых слов для поиска и загрузки большего количества материалов для чтения! Спасибо за большой и быстрый ответ. – Justin

+0

Читайте на Мартине Фаулере - он написал тон на эту тему и является отличным ресурсом. Кроме того, я нашел тестовое развитие на примере. Написал Кент Бек, чтобы быть хорошим праймером в TDD. –

+0

Я рассматривал книгу Кента Бекка, но некоторые из обзоров, которые я видел (особенно Amazon), не настолько благоприятны. Это определенно то, что вы бы порекомендовали? – Justin

2

Пара вещей.

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

Во-вторых, архитектура OO oldschool пытается сделать программное обеспечение безопасным, используя языковые гарантии, чтобы предотвратить доступ к вещам. Архитектура TDD делает программное обеспечение более надежным, написав тесты, которые проверяют, что на самом деле делает код, уделяя меньше внимания использованию языковых конструкций, чтобы гарантировать, что программа не делает.

Последнее, что проверка свойства не является единственным способом проверки кода, сделал то, что он должен был делать. В книге xUnit Design Patterns описаны другие подходы здесь: http://xunitpatterns.com/Result%20Verification%20Patterns.html

+0

Спасибо за быстрый ответ - ссылка потрясающая, и я начинаю фотографировать. – Justin

+0

Если вы связываете ссылку, вам понравится книга (я сделал хотя бы). –

4

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

На практике я обнаружил, что BDD более хрупкий во многих случаях, чем просто проверка состояния. Хотя некоторые люди могут призывать к определенной теории, она работает только в том случае, если она работает для вас. Государственное тестирование по-прежнему составляет 90% всех модульных тестов, которые мы пишем, и мы хорошо знаем BDD в нашей команде.

Сделайте то, что лучше всего подходит для вас.

2

Я вызываю общедоступные методы ввода системы (т. Е. Вставляю входные данные в систему), а затем получаю (и утверждаю) вывод системы.Я не тестирую внутреннее состояние системы, а скорее ее общедоступное/видимое поведение: Should one test internal implementation, or only test public behaviour?

2

То, что вы упомянули, называется государственным тестированием. Также проводится тестирование поведения. Методы, используемые для этого: Инъекция зависимостей, Инверсия управления и Сфокусировка:

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

Существует множество Mocking Framework, которые автоматизируют создание имитирующего объекта, динамически генерируя классы, реализующие данный интерфейс. Наиболее популярными являются Rhino.Mocks и Moq.

+0

+1 Для краткости ответа. Не могли бы вы объяснить, предоставив и пример или ссылку на пример того, как IoC будет использоваться таким образом, чтобы отслеживать вызовы метода для объекта. Неясно, будут ли внедренные объекты отслеживать определенные вызовы внешних методов на других объектах или же они касаются отслеживания внутренних вызовов метода на одном и том же объекте или, возможно, обоих. – jpierson

2

Эй, как и вы, я недавно думал о добавлении геттеров к моему доменному объекту только для записи для модульного тестирования, но теперь я убежден, что ошибался. Предполагая, что вы впервые приобрели идею о домене только для записи, тогда, если у вас есть получатели, вы просите о неприятностях. Принцип домена только для записи хотел бы, чтобы вы запускали событие из вашего объекта домена или читали из проекции, которую написал объект вашего домена, или что-то в этом роде. Когда вы открываете геттеры, вы начинаете раскрывать «форму» объекта, и, как говорит Грег Янг, «объекты домена имеют поведение, а не форму».

Это, как говорится, я борюсь с тем же вопросом ... как вы можете протестировать объект домена только для записи? Вот мой текущий план: я подумываю о том, чтобы мой объект домена загорелся в домене, назвав «Эти свойства изменены», и в своем модульном тесте я зарегистрирую его, прежде чем отправить «EditCommand». Проверьте сообщение Уди Дахана о событиях домена here, а также см. what Eric Evans says about Domain Events.

1

Мне было интересно то же самое, пока я, наконец, не наткнулся на следующие документы. Я нашел их большие праймеры на выполнение проверки поведения, особенно первый предоставление мне несколько «ага моменты»:

  1. Using Mocks and Tests to Design Role-Based Objects
  2. Mock Roles, Not Objects
+0

ссылки сломаны. Вот PDF для второго пункта: http://www.jmock.org/oopsla2004.pdf и вот ссылка на большую часть первого элемента: http://msdn.microsoft.com/en-us/magazine/dd882516.aspx – sivabudh

+0

Вторая ссылка работает для меня, и первая работает, если вы меняете mockobjects.com на www.mockobjects.com – SCFrench

9

OK, этот ответ один год слишком поздно ;-)

Но если вы хотите протестировать модели CQRS, вы можете делать утверждения на событиях с включенным доменом вместо утверждений о состоянии сущности.

например. Если вы хотите проверить, звоните ли вы: customer.Rename («Foo») приводит к правильному поведению.

Вместо проверки, если customer.Name равно "foo", вы скорее проверяете, есть ли ожидаемое событие CustomerRename со значением "Foo" в вашем ожидающем хранилище событий. (в вашем уроне или в списке событий сущности в зависимости от реализации)

 Смежные вопросы

  • Нет связанных вопросов^_^