SlideShare una empresa de Scribd logo
1 de 22
Descargar para leer sin conexión
Inversion of Control - что такое,
подходы, Service Locator, DI, простые
              примеры
О пользе тестирования

    Жизнь программиста без тестирования

●   Пишет много кода и однажды... он перестает работать
●   Исправление ошибки может быть легкими не замысловатым, но процесс нахождения
    ошибки может затягиваться:
     ○ часы, потраченные на отладку и изучение вывода дампов в консоль
●   Исправление ошибки может поломать существующие в коде зависимости
●   Ошибка может проявиться снова на более позднем этапе

    В итоге: время разработки и поддержки кода растет с возрастом
    проекта
О пользе тестирования

    Почему разработчики не пишут тесты

              Оправдания                                Причины

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

"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
О пользе тестирования

    Преимущества тестирования

Поддержка существующего кода                     Уверенность
●   В процессе разработки                        ●   Для разработчика
                                                      ○ его код работает
     ○ тесты не пройдут, если допущена                ○ тесты дают базовое понимание
         ошибка в месте которое они                       работы API приложения, упрощают
         покрывают                                        процесс создания документации
●   После релиза                                 ●   Для менеджера
     ○ можно быстро узнать, является ли               ○ проект удачен
         баг полинным или его "сочинили"         ●   Для продаж
     ○   решение проблемных вопросов не               ○ прибыль
         ломает зависимостей в                   ●   Для клиента
         существующем коде                            ○ доволен, т.к. получает то за что
                                                          платит
          ■   если ломает, то тесты фейлятся и
              сразу видно где нужно исправить
●   Долгосрочные проекты
     ○ упрощает процесс рефакторинга
О пользе тестирования

     Что есть unit-тестирование

     Unit-тестирование (модульное тестировани) - это автоматизированная,
самопроверяющая процедура, которая отвечает за правильность работы модулей.

  Модули обычно ассоциируются с классами и задача unit-тестов сводится к проверки на
корректность работы интерфейсных (или просто общедоступных) методов модуля (класса).

  Проверка класса должна происходить в его изоляции от приложения.

Тест не является модульным, если:

 ●    тест общается с базой данных
 ●    тест общается с сетью
 ●    тест касается файловой системы
 ●    тест запускается одновременно с другим unit-тестом
 ●    для его запуска нужно переконфигурировать приложение
 ●    тест не тестируется в изоляции от других классов
О пользе тестирования

  С чего все началось

  Началу эры тестирования положил Кент Бек в своей книге "Extreme
programming Explained", в которой он так же изложил первые принцыпы
Test-Driven Development (TDD) (разработка через тестирование).

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

  Набор рекомендаций по правилам unit-тестирования и составляет
основу методологии TDD.

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

 Задача TDD - достижение балланса между усилиями и результатом.
О пользе тестирования

  Итерация в TDD

                              Проектирование




Тестирование   Тестирование                    Тестирование




                               Реализация /
                               Рефакторинг
О пользе тестирования

                   Цена ошибок без unit-тестов


                    - кол-во багов       - траты на проект                                        - время на новую фичу
количество багов




                                                                       время на внедрение новой
                                                                                "фичи"

                           запрос на     запрос на        запрос на
                          изменение 1   изменение 2      изменение N

                                                  жизнь проекта                                                           жизнь проекта
О пользе тестирования

                                  Цена ошибок c unit-тестами


                                  - кол-во багов   - траты на проект     - unit-тесты                                  - время на новую фичу
количество багов и новых тестов




                                                                                            время на внедрение новой
                                                                                                     "фичи"

                                            запрос на       запрос на          запрос на
                                           изменение 1     изменение 2        изменение N

                                                                       жизнь проекта                                                           жизнь проекта
О пользе тестирования

Скорость разработки приложения


                                        - приект без unit-тестов   - проект с unit-тестами
время на внедрение нового функционала




                                                                                             жизнь проекта
О пользе тестирования

    Проблема модульного тестирования

●   Черезмерное покрытие тестами:
     ○ не стоит увлекаться в написании модульных тестов, достаточно что бы они покрывали,
         написанную Вами, бизнес логику приложения

●   Тесты должны быть простыми:
     ○ тесты, на написание которых у Вас уходит очень много времени - плохие, свозможно стоит их
         разбить на несколько тестов или убрать "лишний" функционал из, предварительно разработанного
         Вами дизайна модуля

●   Простота написания тестов зависит от архитектуры Вашего приложения
     ○ чем больше жестких зависимостей, тем хуже
Зависимости

 Откуда берутся зависимости

                      Приложение


                   уровень контроллеров




             уровень сервисов и моделей

               з а в и с и м о с т и

PHP extensions /       Массивы данных     Ваши классы
     Utils
Зависимости

   Зависимости это плохо ?

  Обычно, объекты зависят друг от друга, и это нормальная ситуация. В ООП благородным
делом считается избавление объектов от излишних зависимостей, в то же время вообще уйти
от них - невозможно! На фоне этого основной задачей разработчика становится контроль
зависимостей и их разумное уменьшение.


"Hard-coded dependencies are bad"
                                                                            Stephan Hachdörfer

  Создание жестких зависимостей в классах делает их (классы) не изолированными
(ортогональными) и, как следствие, приложение становится трудно-тестируемым.

  Тут на помощь приходит техника программирования - Inversion of Control.
Inversion of Control

   Определения

  Inversion of Control - это техника объектно-ориентированного программирования, которая
используется для устранение жестких зависимостей в коде, делая компоненты приложения
многоразовыми. Так же входит в состав SOLID-принцыпов, которые лежат в основе TDD.

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

  Существует несколько техник применения Инверсии зависимостей:
 ● Factory method pattern
 ● Service locator pattern
 ● Dependency injection pattern
     ○ инъекция в constructor
     ○ инъекция через setter method
     ○ инъекция через интерфейс
 ● контекстный поиск
Inversion of Control

    Service Locator Pattern

       Начальная ситуация                      Применение Шаблона Service Locator
●   что бы изменить зависимости - нужно       ●   декомпозиция класса
    изменить код                              ●   класс не должен ничего знать о сервисах
●   зависимости должны быть при компиляции    ●   класс можно протестировать в изоляции
●   трудно протестировать класс в изоляции    ●   нет логики управления зависимостями
●   повторяемый код на создание,                  внутри класса
    локализацию и управление зависимостями    ●   приложение становится модульным,
                                                  каждый модуль независим



          использует                                                         локализирует




                                                           использует
                              ServiceA                                                        ServiceA



     ClassA                                  ClassA                     Locator



          использует                                                         локализирует
                              ServiceB                                                        ServiceB




                                                                                    диаграмма взята из MSDN
Inversion of Control

    Factory Method Pattern

       Начальная ситуация                      Применение Шаблона Factory Method
●   что бы изменить зависимости - нужно       ●   декомпозиция класса
    изменить код                              ●   класс не должен ничего знать о сервисах
●   зависимости должны быть при компиляции    ●   класс можно протестировать в изоляции
●   трудно протестировать класс в изоляции    ●   нет логики управления зависимостями
●   повторяемый код на создание,                  внутри класса
    локализацию и управление зависимостями    ●   приложение становится модульным,
                                                  каждый модуль независим



          использует
                              ServiceA
                                                           использует
                                             ClassA                              Factory

     ClassA
                                                                                        фабричный метод

          использует
                              ServiceB

                                                                  ServiceA                  ServiceB
Inversion of Control

    Dependency Injection Pattern

       Начальная ситуация                            Применение Шаблона Factory Method
●   что бы изменить зависимости - нужно             ●     декомпозиция класса
    изменить код                                    ●     класс не должен ничего знать о сервисах
●   зависимости должны быть при компиляции          ●     класс можно протестировать в изоляции
●   трудно протестировать класс в изоляции          ●     нет логики управления зависимостями
●   повторяемый код на создание,                          внутри класса
    локализацию и управление зависимостями          ●     приложение становится модульным,
                                                          каждый модуль независим

                                                Пример использования интерфейсной
          использует                            инъекции с помощью Factory Method
                              ServiceA
                                                                       создает
                                                     ClassA                                Builder
     ClassA                                                             внедряет
                                             использует                                       инстанциирует

          использует
                              ServiceB
                                                    IServiceA                             ServiceA



                                                                                          диаграмма взята из MSDN
Inversion of Control

     Простейший пример Dependency Injection (Di)

Базовый класс                        Отрефакторен с использованием Di



class 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;
                                         }
                                     }
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/
Dependency Injection in frameworks

      ZendFramework 2 :: Martin Fawler's Movie & Lister
namespace 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;
                                                         }
Dependency Injection in frameworks

        Symfony 2

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

    // ...
}

Más contenido relacionado

La actualidad más candente

Sqa.days.2010.beskov.system.analyst.and.test.engineers.interaction
Sqa.days.2010.beskov.system.analyst.and.test.engineers.interactionSqa.days.2010.beskov.system.analyst.and.test.engineers.interaction
Sqa.days.2010.beskov.system.analyst.and.test.engineers.interaction
Alexei Lupan
 
Тестирование ПО
Тестирование ПОТестирование ПО
Тестирование ПО
seleznev_stas
 
Регулярное использование статического анализа кода в командной разработке
Регулярное использование статического анализа кода в командной разработкеРегулярное использование статического анализа кода в командной разработке
Регулярное использование статического анализа кода в командной разработке
Tatyanazaxarova
 
Михаил Павлов - is a tester responsible for quality
Михаил Павлов - is a tester responsible for qualityМихаил Павлов - is a tester responsible for quality
Михаил Павлов - is a tester responsible for quality
Alexei Lupan
 
Ptsp презентация
Ptsp презентацияPtsp презентация
Ptsp презентация
akmoldir
 

La actualidad más candente (18)

Проблемы тестирования 64-битных приложений
Проблемы тестирования 64-битных приложенийПроблемы тестирования 64-битных приложений
Проблемы тестирования 64-битных приложений
 
Sqa.days.2010.beskov.system.analyst.and.test.engineers.interaction
Sqa.days.2010.beskov.system.analyst.and.test.engineers.interactionSqa.days.2010.beskov.system.analyst.and.test.engineers.interaction
Sqa.days.2010.beskov.system.analyst.and.test.engineers.interaction
 
QAFest. Роль тестирования в Devops
QAFest. Роль тестирования в DevopsQAFest. Роль тестирования в Devops
QAFest. Роль тестирования в Devops
 
Методоллогии Agile
Методоллогии AgileМетодоллогии Agile
Методоллогии Agile
 
Поиск ловушек в Си/Си++ коде при переносе приложений под 64-битную версию Win...
Поиск ловушек в Си/Си++ коде при переносе приложений под 64-битную версию Win...Поиск ловушек в Си/Си++ коде при переносе приложений под 64-битную версию Win...
Поиск ловушек в Си/Си++ коде при переносе приложений под 64-битную версию Win...
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
Тестирование ПО
Тестирование ПОТестирование ПО
Тестирование ПО
 
BDD
BDDBDD
BDD
 
Ответственность за качество в разных ИТ-проектах
Ответственность за качество в разных ИТ-проектахОтветственность за качество в разных ИТ-проектах
Ответственность за качество в разных ИТ-проектах
 
Istqb lesson 3
Istqb lesson 3Istqb lesson 3
Istqb lesson 3
 
Mva stf module 6 - rus
Mva stf module 6 - rusMva stf module 6 - rus
Mva stf module 6 - rus
 
Istqb lesson 1
Istqb lesson 1Istqb lesson 1
Istqb lesson 1
 
Mva stf module 2 - rus
Mva stf module 2 - rusMva stf module 2 - rus
Mva stf module 2 - rus
 
Регулярное использование статического анализа кода в командной разработке
Регулярное использование статического анализа кода в командной разработкеРегулярное использование статического анализа кода в командной разработке
Регулярное использование статического анализа кода в командной разработке
 
Михаил Павлов - is a tester responsible for quality
Михаил Павлов - is a tester responsible for qualityМихаил Павлов - is a tester responsible for quality
Михаил Павлов - is a tester responsible for quality
 
Istqb lesson 2
Istqb lesson 2Istqb lesson 2
Istqb lesson 2
 
Ptsp презентация
Ptsp презентацияPtsp презентация
Ptsp презентация
 
ClubQA #2. Unit testing and TDD
ClubQA #2. Unit testing and TDDClubQA #2. Unit testing and TDD
ClubQA #2. Unit testing and TDD
 

Destacado

Destacado (10)

3 клас урок 4
3 клас урок 43 клас урок 4
3 клас урок 4
 
цветова палитра. избор на цвят 2012
цветова палитра. избор на цвят 2012цветова палитра. избор на цвят 2012
цветова палитра. избор на цвят 2012
 
Power point
Power pointPower point
Power point
 
3 клас_Урок 3
3 клас_Урок 33 клас_Урок 3
3 клас_Урок 3
 
3 клас_Урок 2
3 клас_Урок 23 клас_Урок 2
3 клас_Урок 2
 
Uroc3 5klas
Uroc3 5klasUroc3 5klas
Uroc3 5klas
 
Великден 1 е клас
Великден 1 е класВеликден 1 е клас
Великден 1 е клас
 
Muzikata
MuzikataMuzikata
Muzikata
 
Изразни средства в музиката
Изразни средства в музикатаИзразни средства в музиката
Изразни средства в музиката
 
Записване на музиката с ноти
Записване на музиката с нотиЗаписване на музиката с ноти
Записване на музиката с ноти
 

Similar a Benefits of unit-testing and inversion of controll

Test Driven Development in .NET Applications
Test Driven Development in .NET ApplicationsTest Driven Development in .NET Applications
Test Driven Development in .NET Applications
Anton Vidishchev
 
Марина Широчкина — «Тестирование»
Марина Широчкина — «Тестирование»Марина Широчкина — «Тестирование»
Марина Широчкина — «Тестирование»
Yandex
 
IT-шная история игрушек или feature-driven тестирование в действии
IT-шная история игрушек или feature-driven тестирование в действииIT-шная история игрушек или feature-driven тестирование в действии
IT-шная история игрушек или feature-driven тестирование в действии
Gleb Rybalko
 
Организация эффективной работы команды при разработке и поддержке сложной инф...
Организация эффективной работы команды при разработке и поддержке сложной инф...Организация эффективной работы команды при разработке и поддержке сложной инф...
Организация эффективной работы команды при разработке и поддержке сложной инф...
tabtabus
 
Стратегия тестирования крупного проекта в условиях Agile разработки v2
Стратегия тестирования крупного проекта в условиях Agile разработки v2Стратегия тестирования крупного проекта в условиях Agile разработки v2
Стратегия тестирования крупного проекта в условиях Agile разработки v2
Magneta AI
 
Роман Кокин «Организация тестирования в больших командах»
Роман Кокин «Организация тестирования в больших командах»Роман Кокин «Организация тестирования в больших командах»
Роман Кокин «Организация тестирования в больших командах»
DataArt
 
Тестирование крупного проекта командой из одного тестировщика
Тестирование крупного проекта командой из одного тестировщикаТестирование крупного проекта командой из одного тестировщика
Тестирование крупного проекта командой из одного тестировщика
Zestranec
 

Similar a Benefits of unit-testing and inversion of controll (20)

Test Driven Development in .NET Applications
Test Driven Development in .NET ApplicationsTest Driven Development in .NET Applications
Test Driven Development in .NET Applications
 
Марина Широчкина — «Тестирование»
Марина Широчкина — «Тестирование»Марина Широчкина — «Тестирование»
Марина Широчкина — «Тестирование»
 
IT-шная история игрушек или feature-driven тестирование в действии
IT-шная история игрушек или feature-driven тестирование в действииIT-шная история игрушек или feature-driven тестирование в действии
IT-шная история игрушек или feature-driven тестирование в действии
 
QA Fes 2016. Анастасия Асеева. Роль тестирования в Devops
QA Fes 2016. Анастасия Асеева. Роль тестирования в DevopsQA Fes 2016. Анастасия Асеева. Роль тестирования в Devops
QA Fes 2016. Анастасия Асеева. Роль тестирования в Devops
 
Организация эффективной работы команды при разработке и поддержке сложной инф...
Организация эффективной работы команды при разработке и поддержке сложной инф...Организация эффективной работы команды при разработке и поддержке сложной инф...
Организация эффективной работы команды при разработке и поддержке сложной инф...
 
Mva stf module 1 - rus
Mva stf module 1 - rusMva stf module 1 - rus
Mva stf module 1 - rus
 
Марина Широчкина - Тестирование
Марина Широчкина - ТестированиеМарина Широчкина - Тестирование
Марина Широчкина - Тестирование
 
Стратегия тестирования крупного проекта в условиях Agile разработки v2
Стратегия тестирования крупного проекта в условиях Agile разработки v2Стратегия тестирования крупного проекта в условиях Agile разработки v2
Стратегия тестирования крупного проекта в условиях Agile разработки v2
 
Роман Кокин «Организация тестирования в больших командах»
Роман Кокин «Организация тестирования в больших командах»Роман Кокин «Организация тестирования в больших командах»
Роман Кокин «Организация тестирования в больших командах»
 
Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
 Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва  Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
Как сейчас тесты в Android пишут, Денис Неклюдов, Google Dev Expert, Москва
 
DevOps guide for awesome quality assurance
DevOps guide for awesome quality assuranceDevOps guide for awesome quality assurance
DevOps guide for awesome quality assurance
 
Unit testing and TDD
Unit testing and TDDUnit testing and TDD
Unit testing and TDD
 
Возможна ли жизнь без тестировщика?
Возможна ли жизнь без тестировщика?Возможна ли жизнь без тестировщика?
Возможна ли жизнь без тестировщика?
 
Test Automation as a way of Natural Evolution of a Project
Test Automation as a way of Natural Evolution of a ProjectTest Automation as a way of Natural Evolution of a Project
Test Automation as a way of Natural Evolution of a Project
 
Лучшие практики на практике
Лучшие практики на практикеЛучшие практики на практике
Лучшие практики на практике
 
Enter: testing
Enter: testingEnter: testing
Enter: testing
 
Тестирование крупного проекта командой из одного тестировщика
Тестирование крупного проекта командой из одного тестировщикаТестирование крупного проекта командой из одного тестировщика
Тестирование крупного проекта командой из одного тестировщика
 
Тестирование крупных проектов командой из одного тестировщика
Тестирование крупных проектов командой из одного тестировщика Тестирование крупных проектов командой из одного тестировщика
Тестирование крупных проектов командой из одного тестировщика
 
Test driven development in net
Test driven development in netTest driven development in net
Test driven development in net
 
Использование html-прототипов для реверсивного анализа требований: ЗА и ПРОТИВ
Использование html-прототипов для реверсивного анализа требований: ЗА и ПРОТИВИспользование html-прототипов для реверсивного анализа требований: ЗА и ПРОТИВ
Использование html-прототипов для реверсивного анализа требований: ЗА и ПРОТИВ
 

Benefits of unit-testing and inversion of controll

  • 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. О пользе тестирования С чего все началось Началу эры тестирования положил Кент Бек в своей книге "Extreme programming 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) Базовый класс Отрефакторен с использованием Di class 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 Fawler's Movie & Lister namespace 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 2 class 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; } // ... }