Как правильно работать с фасадами?

  • Автор темы Автор темы CoolKid
  • Дата начала Дата начала
Absinthe, моя мысль сводится к тому, что использование DI, вместо фасадов, или еще чего - также просто.
Я не уверен, что тот пример, который ты привел - это DI. Ты явно прописываешь, какой сервис берешь. Используя фасад, ты делаешь то же самое. И в чем разница?
 
Absinthe, 1) меньше зависимость (достаточно удалить комменты и use) от фреймворка 2) конструктор содержит явные зависимости (если таки инжектить не напрямую в свойство) 3) unit-тестрование самым естественным образом.

Плюс решение проблемы автокомплита для аннотаций, imho, проще: есть плагин для PhpStorm.

Но это меньшее из двух зол, как по мне. Так-то я аннотации не люблю и не понимаю что плохого в XML-конфигах, там ж автокомплит.
 
А, ну и кстати, ни о каком TDD с Service Locator и фасадами/синглтонами говорить не приходится: признайтесь, в таком случае тесты до реализации писать очень странно. Скорее всего вы будете по ходу реализации думать о том, что сейчас понадобится.
 
Господа, а вы можете на конкретных примерах показать как Вы бы правильно (академически или не очень) работали с классом в такой ситуации:
Есть класс FRegistry, который обеспечивает функционал хранилища времени выполнения.

PHP:
interface IStorage {
    function add($key,$data,$ttl=null);
    function hasKey($key);
    function delete($key);
    function flush();
    function get($key);
    function replace($key,$data,$ttl=null);
    function set($key,$data,$ttl=null);
}


PHP:
class FRegistry implements IStorage
{
    protected $storage=array();
    protected $args=array();

    public function __construct()
    {
        $args=func_get_args();
        $this->args=$args[0];
    }

    protected function makeKey($key)
    {
        return $key;
    }

    /** Is there a key in storage? */
    public function hasKey($key)
    {
        $_key=$this->makeKey($key);
        return array_key_exists($_key,$this->storage);
    }

    /** Writes data in runtime storage. TTL parameter is not in use. */
    public function set($key,$data,$ttl=null)
    {
      $_key=$this->makeKey($key);
      $this->storage[$_key]['data']=$data;
    }

    /** Adds data in runtime storage if key not exists. */
    public function add($key,$data,$ttl=null)
    {
        if(!$this->hasKey($key))
        {
          $this->set($key,$data);
          return true;
        }

        return false;
    }

    /** Replaces data in runtime storage if key exists. */
    public function replace($key,$data,$ttl=null)
    {
        if($this->hasKey($key))
        {
            $this->set($key,$data);
            return true;
        }

        return false;
    }

    /** Reads data from runtime storage */
    public function get($key,$default_value=null)
    {
        $_key=$this->makeKey($key);
        return $this->hasKey($key) ? $this->storage[$_key]['data'] : $default_value;
    }

    /** Returns all data in runtime storage */
    public function show()
    {
        return $this->storage;
    }

    /** Deletes data in storage by key*/
    public function delete($key)
    {
        $_key=$this->makeKey($key);
        unset($this->storage[$_key]);

    }
    
    /** Deletes all data in storage*/
    public function flush()
    {
      unset($this->storage);
      $this->storage=array();
    }
}

Собственно пример работы с классом:
PHP:
$registry=new FRegistry;
$registry->add('mykey',1111);
$registry->set('mykey',2222);
echo $registry->get('mykey');
var_dump($registry->show());
$registry->flush();

Как бы вы реализовали обертку над этим классом? Если можно пример с DI - было бы великолепно.
 
Ты путаешь тёплое с мягким, ди - это работа с зависимостями. допустим, у тебя есть функция, которая работает с этими классм.
PHP:
// вариант 1
function foo() {
    $r = new FRegistry();
    return $r->get('key');
}
foo();
// вариант 2
function foo(FRegistry $r) {
    return $r->get('key');
}
foo(new FRegistry());
foo(new FRegistryOther()); // мы получили лёгкую подмену зависимости
 
Absinthe, тот пример, что я привел - это самое простое использование DI. Фактически тот самый "говнокод во благо", который тут любят упоминать.
При возможности такого подхода существуют конфиги в yml/xml, которые писать не чуть не сложнее, но можно уже классы зависимостей конфигурировать как угодно, а умолчания прописывать с помощью параметров.
 
Absinthe, моя мысль сводится к тому, что использование DI, вместо фасадов, или еще чего - также просто. Когда мы пишем код проекта - мы можем свободно использовать приведенные мной аннотации и все будет работать, все будет красиво.
Моя мысль же в том, что когда мы делаем инъекцию напрямую в приватное поле - это ничем не отличается от фасадов: то же самое бесконтрольное использование любых зависимостей в любом месте. Если же честно описывать все интерфейсы/теги зависимостей в конструкторе, а нужные реализации - в конфигурации, это нифига не "так же просто" (но зато правильно).

В этом смысле выбор, скажем, между фасадами и DI через сервис-провайдеры в laravel монопенисуален выбору между инъекцией в private и честным DI через конструктор в Симфони. Меняется только синтаксис, суть та же.
 
Если же честно описывать все интерфейсы/теги зависимостей в конструкторе, а нужные реализации - в конфигурации, это нифига не "так же просто" (но зато правильно).
А можно пример этого непростого, но правильного?
Или если не пример, то хотя бы где это можно посмотреть.
 
Любой каноничный DI/IoC. Симфони-контейнеры такими являются, если использовать их правильно. IoC в Laravel, если выбросить фасады - тоже.
 
А, ну и кстати, ни о каком TDD с Service Locator и фасадами/синглтонами говорить не приходится: признайтесь, в таком случае тесты до реализации писать очень странно. Скорее всего вы будете по ходу реализации думать о том, что сейчас понадобится.

А вот, кстати, очень хороший способ определить, уместно ли использовать фасады. :) Какой-нибудь контроллер или говнохелпер писать через TDD вряд ли будешь ведь.
 
Ай, гавно это всё. Заморачиваться зависимостями стоит только в местах, которые формируются рантайм на основе конфиго или условий, вдруг же случаях можно с чистым сердцем влепить new ClassName и спокойно спать, пока не понадобится менять, затем за 5 минут пройтись рефакторингом и прогнать тесты и дальше спасть спокойно, не страшно даже что тесты будут не везде юниты. Без религиозного фанатизма вокруг инъекций.
 
не страшно даже что тесты будут не везде юниты.
то есть - ни разу разработка через тесты: "не везде юниты" ты же не пишешь перед тестируемым кодом? ;) Так а я о чем.
 
  • Like
Реакции: AmdY
Ну вот опять докатились до того, что разброд и шатание превалирует над бест практикалс ))
При чем ладно бы кто, ан нет, профессиональные программисты ))
И как мы после этого можем троллить битрикс?
 
keltanas, да уже наелись лазанью не меньше, чем спагетти. Бест практикс - это использовать мозг, а не из-за религию.

fixxxer, я с тобой согласен, другое дело, что есть ребята, которые свято верят, что код должен быть покрыт на 100% юнитами, да ещё в стиле before
 
Ну вот опять докатились до того, что разброд и шатание превалирует над бест практикалс ))
Почему разброд и шатание? Наоборот, со временем приходит понимание, где надо бест практисес, а где можно и наговнокодить =)
 
Absinthe, 1) меньше зависимость (достаточно удалить комменты и use) от фреймворка
Это одно и то же.

2) конструктор содержит явные зависимости (если таки инжектить не напрямую в свойство)
Дергай фасады только в конструкторе.

3) unit-тестрование самым естественным образом.
Нет особой разницы.

Плюс решение проблемы автокомплита для аннотаций, imho, проще: есть плагин для PhpStorm.
ide-helper. Но штормовый плагин мне больше нравится, хоть он и немного деревянный (многие классы в нем намертво прописаны, и с их наследниками он не работает)

Но это меньшее из двух зол, как по мне. Так-то я аннотации не люблю и не понимаю что плохого в XML-конфигах, там ж автокомплит.
Время не хочу так тратить.
 
Absinthe, тот пример, что я привел - это самое простое использование DI. Фактически тот самый "говнокод во благо", который тут любят упоминать.
При возможности такого подхода существуют конфиги в yml/xml, которые писать не чуть не сложнее, но можно уже классы зависимостей конфигурировать как угодно, а умолчания прописывать с помощью параметров.
Я еще раз повторю, что данный пример ни разу не DI, а обычный Service Locator, реализованный через аннотации.
Этот пример аналогичен использованию фасадов.
 
Сверху