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

Absinthe

жожо
Absinthe, моя мысль сводится к тому, что использование DI, вместо фасадов, или еще чего - также просто.
Я не уверен, что тот пример, который ты привел - это DI. Ты явно прописываешь, какой сервис берешь. Используя фасад, ты делаешь то же самое. И в чем разница?
 

Вурдалак

Продвинутый новичок
Absinthe, 1) меньше зависимость (достаточно удалить комменты и use) от фреймворка 2) конструктор содержит явные зависимости (если таки инжектить не напрямую в свойство) 3) unit-тестрование самым естественным образом.

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

Но это меньшее из двух зол, как по мне. Так-то я аннотации не люблю и не понимаю что плохого в XML-конфигах, там ж автокомплит.
 

Вурдалак

Продвинутый новичок
А, ну и кстати, ни о каком TDD с Service Locator и фасадами/синглтонами говорить не приходится: признайтесь, в таком случае тесты до реализации писать очень странно. Скорее всего вы будете по ходу реализации думать о том, что сейчас понадобится.
 

CoolKid

Новичок
Господа, а вы можете на конкретных примерах показать как Вы бы правильно (академически или не очень) работали с классом в такой ситуации:
Есть класс 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 - было бы великолепно.
 

AmdY

Пью пиво
Команда форума
Ты путаешь тёплое с мягким, ди - это работа с зависимостями. допустим, у тебя есть функция, которая работает с этими классм.
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()); // мы получили лёгкую подмену зависимости
 

hell0w0rd

Продвинутый новичок
Absinthe, тот пример, что я привел - это самое простое использование DI. Фактически тот самый "говнокод во благо", который тут любят упоминать.
При возможности такого подхода существуют конфиги в yml/xml, которые писать не чуть не сложнее, но можно уже классы зависимостей конфигурировать как угодно, а умолчания прописывать с помощью параметров.
 

fixxxer

К.О.
Партнер клуба
Absinthe, моя мысль сводится к тому, что использование DI, вместо фасадов, или еще чего - также просто. Когда мы пишем код проекта - мы можем свободно использовать приведенные мной аннотации и все будет работать, все будет красиво.
Моя мысль же в том, что когда мы делаем инъекцию напрямую в приватное поле - это ничем не отличается от фасадов: то же самое бесконтрольное использование любых зависимостей в любом месте. Если же честно описывать все интерфейсы/теги зависимостей в конструкторе, а нужные реализации - в конфигурации, это нифига не "так же просто" (но зато правильно).

В этом смысле выбор, скажем, между фасадами и DI через сервис-провайдеры в laravel монопенисуален выбору между инъекцией в private и честным DI через конструктор в Симфони. Меняется только синтаксис, суть та же.
 

CoolKid

Новичок
Если же честно описывать все интерфейсы/теги зависимостей в конструкторе, а нужные реализации - в конфигурации, это нифига не "так же просто" (но зато правильно).
А можно пример этого непростого, но правильного?
Или если не пример, то хотя бы где это можно посмотреть.
 

fixxxer

К.О.
Партнер клуба
Любой каноничный DI/IoC. Симфони-контейнеры такими являются, если использовать их правильно. IoC в Laravel, если выбросить фасады - тоже.
 

fixxxer

К.О.
Партнер клуба
А, ну и кстати, ни о каком TDD с Service Locator и фасадами/синглтонами говорить не приходится: признайтесь, в таком случае тесты до реализации писать очень странно. Скорее всего вы будете по ходу реализации думать о том, что сейчас понадобится.
А вот, кстати, очень хороший способ определить, уместно ли использовать фасады. :) Какой-нибудь контроллер или говнохелпер писать через TDD вряд ли будешь ведь.
 

AmdY

Пью пиво
Команда форума
Ай, гавно это всё. Заморачиваться зависимостями стоит только в местах, которые формируются рантайм на основе конфиго или условий, вдруг же случаях можно с чистым сердцем влепить new ClassName и спокойно спать, пока не понадобится менять, затем за 5 минут пройтись рефакторингом и прогнать тесты и дальше спасть спокойно, не страшно даже что тесты будут не везде юниты. Без религиозного фанатизма вокруг инъекций.
 

fixxxer

К.О.
Партнер клуба
не страшно даже что тесты будут не везде юниты.
то есть - ни разу разработка через тесты: "не везде юниты" ты же не пишешь перед тестируемым кодом? ;) Так а я о чем.
 
  • Like
Реакции: AmdY

keltanas

marty cats
Ну вот опять докатились до того, что разброд и шатание превалирует над бест практикалс ))
При чем ладно бы кто, ан нет, профессиональные программисты ))
И как мы после этого можем троллить битрикс?
 

AmdY

Пью пиво
Команда форума
keltanas, да уже наелись лазанью не меньше, чем спагетти. Бест практикс - это использовать мозг, а не из-за религию.

fixxxer, я с тобой согласен, другое дело, что есть ребята, которые свято верят, что код должен быть покрыт на 100% юнитами, да ещё в стиле before
 

fixxxer

К.О.
Партнер клуба
Ну вот опять докатились до того, что разброд и шатание превалирует над бест практикалс ))
Почему разброд и шатание? Наоборот, со временем приходит понимание, где надо бест практисес, а где можно и наговнокодить =)
 

Absinthe

жожо
Absinthe, 1) меньше зависимость (достаточно удалить комменты и use) от фреймворка
Это одно и то же.

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

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

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

Но это меньшее из двух зол, как по мне. Так-то я аннотации не люблю и не понимаю что плохого в XML-конфигах, там ж автокомплит.
Время не хочу так тратить.
 

Absinthe

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