Laravel 4: Фасад против DI (когда использовать)

Я понимаю, что фасад используется как альтернатива инъекции зависимостей. Пожалуйста, исправьте, если я ошибаюсь. Неясно, когда нужно использовать тот или иной.

Каковы преимущества/недостатки каждого подхода? Как определить, когда использовать тот или иной?

Наконец, почему бы не использовать оба? Я могу создать фасад, который ссылается на интерфейс. Кажется, Sentry 2 написан таким образом. Есть ли наилучшая практика?

Ответы

Ответ 1

ФАСАДЫ

Facades не являются альтернативой инъекции зависимостей.

Laravel Facade - это реализация шаблона Locator Service, создающего чистый и красивый способ доступа к объектам:

MyClass::doSomething();

Это синтаксис PHP для статических методов, но Laravel изменяет игру и делает их нестационарными за кулисами, предоставляя вам красивый, приятный и проверенный способ написания ваших приложений.

ВЗАИМОДЕЙСТВИЕ ЗАВИСИМОСТИ

Инъекция зависимостей - это, в основном, способ передачи параметров вашим конструкторам и методам, автоматически устанавливая их.

class MyClass {

    private $property;

    public function __construct(MyOtherClass $property)
    {
        /// Here you can use the magic of Dependency Injection

        $this->property = $property

        /// $property already is an object of MyOtherClass
    }

}

Лучшей конструкцией этого было бы использование интерфейсов на конструкторах Injected Dependency Injected:

class MyClass {

    private $property;

    public function __construct(MyInterface $property)
    {
        /// Here you can use the magic of Dependency Injection

        $this->property = $property

        /// $property will receive an object of a concrete class that implements MyInterface
        /// This class should be defined in Laravel elsewhere, but this is a way of also make 
        /// your application easy to maintain, because you can swap implementations of your interfaces
        /// easily
    }

}

Но обратите внимание, что в Laravel вы можете вводить классы и интерфейсы одинаково. Чтобы вводить интерфейсы, вам просто нужно сказать, что это будет так:

App::bind('MyInterface', 'MyOtherClass');

Это скажет Laravel, что каждый раз, когда одному из ваших методов нужен экземпляр MyInterface, он должен дать ему один из MyOtherClass.

Что здесь происходит, так это то, что этот constuctor имеет "зависимость": MyOtherClass, который будет автоматически вводиться Laravel с помощью контейнера IoC. Итак, создав экземпляр MyClass, Laravel автоматически создаст экземпляр MyOtherClass и поместит его в переменную $class.

Dependency Injection - это просто разработчик нечетного жаргона, созданный для того, чтобы сделать что-то простое, как "автоматическая генерация параметров".

ПРИ ИСПОЛЬЗОВАНИИ ОДНОГО ИЛИ ДРУГОГО?

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

Использовать Facades, чтобы облегчить запись кода. Например: хорошая практика создания пакетов для ваших модулей приложений, поэтому для создания Фасадов для этих пакетов также можно сделать их похожими на открытый класс Laravel и получить доступ к ним с использованием статического синтаксиса.

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

Ответ 2

Фасады, как отмечено, предназначены для упрощения потенциально сложного интерфейса.

Фасады по-прежнему проверяются

Реализация Laravel идет еще дальше и позволяет определить базовый класс, на который указывает "Фасад".

Это дает разработчику возможность "издеваться" над фасадом - путем переключения базового класса с помощью макетного объекта.

В этом смысле вы можете использовать их и иметь тестовый код. Здесь некоторая путаница лежит внутри сообщества PHP.

DI часто цитируется как проверяющий ваш код - они упрощают насмешливость классов. (Sidenote: Интерфейсы и DI имеют другие важные причины для существующих!)

Фасады, с другой стороны, часто цитируются как более сложные испытания, потому что вы не можете "просто вводить макет" в любой код, который вы тестируете. Однако, как уже отмечалось, вы можете на самом деле "высмеять" их.

Фасад против DI

Здесь люди путаются относительно того, являются ли Фасады альтернативой DI или нет.

В некотором смысле, они оба добавляют зависимость к вашему классу. Вы можете либо использовать DI, чтобы добавить зависимость, либо напрямую использовать фасад - FacadeName::method($param);. (Надеюсь, вы не создаете экземпляр какого-либо класса непосредственно внутри другого: D).

Это не делает Фасады альтернативой DI, но вместо этого в Laravel создает ситуацию, когда вы можете решить добавить зависимости класса одним из двух способов - либо с помощью DI, либо с помощью Facade. (Вы можете, конечно, использовать другие способы. Эти "2 пути" - это самый часто используемый "способ проверки" ).

Ответ 3

Laravel Facades - это реализация шаблона Locator Service, а не шаблон Facade.

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

http://martinfowler.com/articles/injection.html#UsingAServiceLocator

Ответ 4

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

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

Я думаю, это вопрос, какой метод вы предпочитаете использовать