вторник, 15 декабря 2015 г.

TDD with Mocks. "Mock Objects" framework

Почему TDD(write test first)?
1) Мы фокусируемся на исследовании предметной области, которую мы разрабатываем, и по определению не можем знать хорошо сразу, а не на продумывании реализации и архитектуры сразу(изобретении), что подразумевает - мы знаем домен уже хорошо сразу, что будет возможным только через, возможно, полгода работы с проектом.
2) Мы не смиряемся с "так получилось", мы пишем в ракурсе "нужно так".
3) Покрытость тестами, позволяет нам не бояться рефакторить, и наша архитектура эволюционирует и рождается, это какбы путь "обреченный" на хорошую архитектуру.



Все это нам позволяет писать код в канонической архитектуре обьектно-ориентированного программирования. Которое состоит в следующем своде:

0) OO program is a web of objects that collaborate by sending messages to each other.
1) Law of Demeter (Закон Деметры)- обьект должен общаться только c теми обьектами, которые являются непосредственными соседями с ним.

Этот закон означает, что нас не устраивает вариант, когда мы на вызов содседа получаем в отдет другой обьект, который мы дожны дергать глубже для получения результата.
То есть так делать не нужно(это называется “Train Wreck”):
dog.getBody().getTail().wag();

Наша цель - "Tell, Don't Ask":
dog.expressHappiness();

Соседей, в которых мы нуждаемся, мы называем outgoing interfaces.

2) Mock Objects убирают фокус TDD с мыслей о том, как изменяется состояние обьекта к мыслям,  какое общение происходит с другими обьектами. Мы пишем код так, как будто у нас в среде есть все, что нам нужно и мы концетрируемся только на сообщениях между обьектами и непосредственной реализацией только конткретного обьекта[одного].
Need-Driven Development - такой подходи приводит к тому, что мы получает систему узких интерфейсов, которые определяют их роли в процессе общениях обьектов по сети приложения, а не обширных, которые описывают все , что класс умеет делать. И класс "умеет" делать только то, что в текущий момент нужно для удовлетворения требований к работающей системе, а не все, что может потенциально потребоваться в будущем.
Мы какбы идем по технологии Top-Down Development, с единственным отличием, что проблему дублицирования на нижнем уровне(которая характерна дла Top-Down) нивелируем процессом рефакторинга.

3) Мы мокируем только собственные классы и никогда: ОС или сторонние библиотеки. Но создавать легкие обвертки вокруг таких классов хорошая идея - это нам позволяет делать моки и на них. А как на счет удаленных сервисов? Наверно это тоже плохая идея:-)


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

5) Использование абстракций позволяет нам сосредотачиваться без расмыления только на конкретном обьекте, и легче вносить изменения в систему.

6) Благодаря тому что мы концентрируемся не на состоянии обьекта, а на на взаимодействии с сетью обьектов, мы можем проверить на сколько правильно было получено состояние, тоесть мы можем проверить порядок обращений и отловить ошибки, которые явно требуют определенной последовательности.

7) Введение абастракций позволяет нам ускорить тесты - потому что нам не нужно выжидать реальное время при тестировании например кеширования, а реагировать мгновенно, подмокировав только место проверки.

8) Нужно избегать геттеров - это позволяет минимизировать связность модулей; не размещать зависимости в неправильных модулях; фокусирует на поведении, а не состоянии.

9) Лучше всегда явно определять, что по-любому не должно вызываться во время теста.

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

11) Мокировать поведением плохая идея - приходит необходимость? - пора рефакторить!, это сигнал, мы дожны тестировать только нашу реализацию, а не тестовую инфраструктуру.

12) Если моков сильно много, даже если все зависимость ближайшие соседи - это сигнал, что надо разбивать класс или вводить посредников.



http://www.jmock.org/oopsla2004.pdf

Комментариев нет:

Отправить комментарий