• Like
Benefits of unit-testing and inversion of controll
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Benefits of unit-testing and inversion of controll

  • 142 views
Published

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
142
On SlideShare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
2
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Inversion of Control - что такое,подходы, Service Locator, DI, простые примеры
  • 2. О пользе тестирования Жизнь программиста без тестирования● Пишет много кода и однажды... он перестает работать● Исправление ошибки может быть легкими не замысловатым, но процесс нахождения ошибки может затягиваться: ○ часы, потраченные на отладку и изучение вывода дампов в консоль● Исправление ошибки может поломать существующие в коде зависимости● Ошибка может проявиться снова на более позднем этапе В итоге: время разработки и поддержки кода растет с возрастом проекта
  • 3. О пользе тестирования Почему разработчики не пишут тесты Оправдания Причины● это работает на моем компьютере ● нет времени● предыдущий разработчик не знал об ● бюджет не предусматривает blah-blah-blah ● разработчики не знают как писать тесты● не могу воспроизвести ошибку ● написание тестов после релиза● когда я это делал было не так...
  • 4. О пользе тестирования"Once a test is made, it will always be tested" Michelangelo van Dam"Every time you wish to dump a variable, write a unit-test for this case." Chris Hartjes (The Grumpy programmer)"Мало плохих тестов лучше, чем вообще без них" кто-то на MageConf 2012
  • 5. О пользе тестирования Преимущества тестированияПоддержка существующего кода Уверенность● В процессе разработки ● Для разработчика ○ его код работает ○ тесты не пройдут, если допущена ○ тесты дают базовое понимание ошибка в месте которое они работы API приложения, упрощают покрывают процесс создания документации● После релиза ● Для менеджера ○ можно быстро узнать, является ли ○ проект удачен баг полинным или его "сочинили" ● Для продаж ○ решение проблемных вопросов не ○ прибыль ломает зависимостей в ● Для клиента существующем коде ○ доволен, т.к. получает то за что платит ■ если ломает, то тесты фейлятся и сразу видно где нужно исправить● Долгосрочные проекты ○ упрощает процесс рефакторинга
  • 6. О пользе тестирования Что есть unit-тестирование Unit-тестирование (модульное тестировани) - это автоматизированная,самопроверяющая процедура, которая отвечает за правильность работы модулей. Модули обычно ассоциируются с классами и задача unit-тестов сводится к проверки накорректность работы интерфейсных (или просто общедоступных) методов модуля (класса). Проверка класса должна происходить в его изоляции от приложения.Тест не является модульным, если: ● тест общается с базой данных ● тест общается с сетью ● тест касается файловой системы ● тест запускается одновременно с другим unit-тестом ● для его запуска нужно переконфигурировать приложение ● тест не тестируется в изоляции от других классов
  • 7. О пользе тестирования С чего все началось Началу эры тестирования положил Кент Бек в своей книге "Extremeprogramming Explained", в которой он так же изложил первые принцыпыTest-Driven Development (TDD) (разработка через тестирование). Основная мысль автора заключалась в следующем: если тестиованиеэто хорошо, значит программисты должны постоянно тестирвать свой код. Набор рекомендаций по правилам unit-тестирования и составляетоснову методологии TDD. Одно из определений TDD гласит - что TDD это методика,позволяющая оптимизировать использование модульных тестов. Задача TDD - достижение балланса между усилиями и результатом.
  • 8. О пользе тестирования Итерация в TDD ПроектированиеТестирование Тестирование Тестирование Реализация / Рефакторинг
  • 9. О пользе тестирования Цена ошибок без unit-тестов - кол-во багов - траты на проект - время на новую фичуколичество багов время на внедрение новой "фичи" запрос на запрос на запрос на изменение 1 изменение 2 изменение N жизнь проекта жизнь проекта
  • 10. О пользе тестирования Цена ошибок c unit-тестами - кол-во багов - траты на проект - unit-тесты - время на новую фичуколичество багов и новых тестов время на внедрение новой "фичи" запрос на запрос на запрос на изменение 1 изменение 2 изменение N жизнь проекта жизнь проекта
  • 11. О пользе тестированияСкорость разработки приложения - приект без unit-тестов - проект с unit-тестамивремя на внедрение нового функционала жизнь проекта
  • 12. О пользе тестирования Проблема модульного тестирования● Черезмерное покрытие тестами: ○ не стоит увлекаться в написании модульных тестов, достаточно что бы они покрывали, написанную Вами, бизнес логику приложения● Тесты должны быть простыми: ○ тесты, на написание которых у Вас уходит очень много времени - плохие, свозможно стоит их разбить на несколько тестов или убрать "лишний" функционал из, предварительно разработанного Вами дизайна модуля● Простота написания тестов зависит от архитектуры Вашего приложения ○ чем больше жестких зависимостей, тем хуже
  • 13. Зависимости Откуда берутся зависимости Приложение уровень контроллеров уровень сервисов и моделей з а в и с и м о с т иPHP extensions / Массивы данных Ваши классы Utils
  • 14. Зависимости Зависимости это плохо ? Обычно, объекты зависят друг от друга, и это нормальная ситуация. В ООП благороднымделом считается избавление объектов от излишних зависимостей, в то же время вообще уйтиот них - невозможно! На фоне этого основной задачей разработчика становится контрользависимостей и их разумное уменьшение."Hard-coded dependencies are bad" Stephan Hachdörfer Создание жестких зависимостей в классах делает их (классы) не изолированными(ортогональными) и, как следствие, приложение становится трудно-тестируемым. Тут на помощь приходит техника программирования - Inversion of Control.
  • 15. Inversion of Control Определения Inversion of Control - это техника объектно-ориентированного программирования, котораяиспользуется для устранение жестких зависимостей в коде, делая компоненты приложениямногоразовыми. Так же входит в состав SOLID-принцыпов, которые лежат в основе TDD. Техника релизует создание объектов "налету" с помощью специального контейнера,определяющего граф зависимостей кассов приложения, и предоставляющего возможностьустанавливать зависимости между объектами, которые не доступны на этапе компиляции илипри статическом анализе. Существует несколько техник применения Инверсии зависимостей: ● Factory method pattern ● Service locator pattern ● Dependency injection pattern ○ инъекция в constructor ○ инъекция через setter method ○ инъекция через интерфейс ● контекстный поиск
  • 16. Inversion of Control Service Locator Pattern Начальная ситуация Применение Шаблона Service Locator● что бы изменить зависимости - нужно ● декомпозиция класса изменить код ● класс не должен ничего знать о сервисах● зависимости должны быть при компиляции ● класс можно протестировать в изоляции● трудно протестировать класс в изоляции ● нет логики управления зависимостями● повторяемый код на создание, внутри класса локализацию и управление зависимостями ● приложение становится модульным, каждый модуль независим использует локализирует использует ServiceA ServiceA ClassA ClassA Locator использует локализирует ServiceB ServiceB диаграмма взята из MSDN
  • 17. Inversion of Control Factory Method Pattern Начальная ситуация Применение Шаблона Factory Method● что бы изменить зависимости - нужно ● декомпозиция класса изменить код ● класс не должен ничего знать о сервисах● зависимости должны быть при компиляции ● класс можно протестировать в изоляции● трудно протестировать класс в изоляции ● нет логики управления зависимостями● повторяемый код на создание, внутри класса локализацию и управление зависимостями ● приложение становится модульным, каждый модуль независим использует ServiceA использует ClassA Factory ClassA фабричный метод использует ServiceB ServiceA ServiceB
  • 18. Inversion of Control Dependency Injection Pattern Начальная ситуация Применение Шаблона Factory Method● что бы изменить зависимости - нужно ● декомпозиция класса изменить код ● класс не должен ничего знать о сервисах● зависимости должны быть при компиляции ● класс можно протестировать в изоляции● трудно протестировать класс в изоляции ● нет логики управления зависимостями● повторяемый код на создание, внутри класса локализацию и управление зависимостями ● приложение становится модульным, каждый модуль независим Пример использования интерфейсной использует инъекции с помощью Factory Method ServiceA создает ClassA Builder ClassA внедряет использует инстанциирует использует ServiceB IServiceA ServiceA диаграмма взята из MSDN
  • 19. Inversion of Control Простейший пример Dependency Injection (Di)Базовый класс Отрефакторен с использованием Diclass Foo class Foo{ { protected $_bar; protected $_bar; public function __construct() // инъекция через конструктор { public function __construct(Bar $bar) $this->bar = new Bar() { } $this->bar = $bar;} } // инъекция через setter public function setBar(Bar $bar) { $this->bar = $bar; } }
  • 20. Dependency Injection in frameworks ZendFramework 2 :: базовый примерОписание зависимостей Применение Di контейнера$definitions = array( use ZendDiDi, Foo => array( ZendDiConfiguration; setBar => array( type => Bar, $di = new Di(); required => true, $config = new Configuration(array( ) definition => array(class => $definition) ) ));); $foo = $di->get(Foo);Больше и более детальные примеры можно посмтреть тут:https://github.com/ralphschindler/Zend_DI-Examples/
  • 21. Dependency Injection in frameworks ZendFramework 2 :: Martin Fawlers Movie & Listernamespace MovieApp { namespace { // bootstrap ZendLoaderStandardAutoloader first class Lister { public $dbFinder; $di = new ZendDiDi; public function __construct(DbFinder $dbFinder){ $di->instanceManager()->setParameters( $this->dbFinder = $dbFinder; MovieAppDbFinder, } array( } username => my-username, password => my-password class DbFinder { ) public $username, $password = null; ); public function __construct($username, $lister = $di->get(MovieAppLister); $password) { $works = ( $this->username = $username; $lister->dbFinder instanceof MovieAppDbFinder $this->password = $password; && $lister->dbFinder->username == my-username } && $lister->dbFinder->password == my-password } );} echo (($works) ? Works! : Fails) . PHP_EOL; }
  • 22. Dependency Injection in frameworks Symfony 2class Mailer use{ SymfonyComponentDependencyInjectionContainerBuilder; private $transport; use SymfonyComponentDependencyInjectionReference; public function __construct() $container = new ContainerBuilder(); { $this->transport = sendmail; $container->setParameter(mailer.transport, sendmail); } $container ->register(mailer, Mailer) // ... ->addArgument(%mailer.transport%);} $container ->register(newsletter_manager, NewsletterManager) ->addArgument(new Reference(mailer));class NewsletterManager{ private $mailer; public function __construct(Mailer $mailer) { $this->mailer = $mailer; } // ...}