Удобная реализация фасада модуля

zuxel

Новичок
Как реализовать фасад модуля, чтобы:
1. не надо было создавать инстанс
2. можно было пользоваться автоподсказками ide основанными на структуре класса + phpdoc

Что-то вроде если все методы сделать статическими, но где-то видел, что это плохо. Это действительно так?
 

WMix

герр M:)ller
Партнер клуба
1. не надо было создавать инстанс
а если инстанс типо фасад типо модуль создать один раз и линковать его везде где его используешь один раз это будет очень страшно?
 

zuxel

Новичок
Создавать объект модуля в глобальной области видимости не хотелось бы. А если получать к нему доступ через какой-то единый для всего приложения сервис провайдер, то как в таком случае настроить иде чтобы она могла выводить подсказки по методам модуля?
 

WMix

герр M:)ller
Партнер клуба
а если создать не в глобальной области, а в некоемом методе, даже если при инициализации зависимостей рабочего модуля, или лучше при появлении события когда инициализация зависимости необходима?
 

fixxxer

К.О.
Партнер клуба
А зачем?

Модуль не должно волновать, сколько там где инстансов чего будет, это вопрос приложения. А на уровне приложения и так уже есть какой-то способ управления зависимостями.
 

zuxel

Новичок
а если создать не в глобальной области, а в некоемом методе, даже если при инициализации зависимостей рабочего модуля, или лучше при появлении события когда инициализация зависимости необходима?
но тогда нельзя будет динамически настраивать набор модулей приложения

Модуль не должно волновать, сколько там где инстансов чего будет, это вопрос приложения. А на уровне приложения и так уже есть какой-то способ управления зависимостями.
здесь зависит от логики модуля, некоторые требуют создания отдельного инстанса под каждый набор параметров,
некоторые надо использовать как синглтон, в вопросе я спрашивал про фасады-синглтоны

пока остановился на таком варианте:
PHP:
<?php

trait SingleInstanceModule 
{
    protected static $inst = [];
  /**
    *
    *  @return static
    */
    public static function facade(array $dependencies = [])
    {
        if ( ! isset(static::$inst[static])) {
            static::$inst[static] = new static($dependencies)
        }

        return static::$inst[static];
    }

    protected function __construct(array $dependencies = [])
    {
        foreach ($dependencies as $k => $v) {
            if (property_exists($this, $k)) {
                $this->{$k} = $v;
            }
        }
 

fixxxer

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

zuxel

Новичок
Если не может возникнуть нужды в двух инстансах в рамках одного процесса, то разработчику модуля логично будет запретить его неограниченное инстанцирование, чтобы,например, при использовании его другими разработчиками, избежать излишнего потребления памяти или параллельной обработки одних и тех же данных (плюс блокировки в этом случае).
 
Последнее редактирование:

WMix

герр M:)ller
Партнер клуба
пхп работает пошагово, взял обьектик поюзал убил, вот и нет утечки памяти
так к слову http://php-di.org/
 

zuxel

Новичок
Но могут быть еще другие разработчики, которые не разберуться и напорят делов
Да, и не надо забывать случаи, когда инстанс может быть не только один, но и состояние может его изменяться во время жизненного цикла приложения
 

whirlwind

TDD infected, paranoid
Если не может возникнуть нужды в двух инстансах в рамках одного процесса, то разработчику модуля логично будет запретить его неограниченное инстанцирование, чтобы,например, при использовании его другими разработчиками, избежать излишнего потребления памяти или параллельной обработки одних и тех же данных (плюс блокировки в этом случае).
Не нужно додумывать за пользователей класса. Это всегда приводит к плохому дизайну. Сегодня оправданием сингельтона может служить только одно: это обертка легаси кода, когда создание двух экземпляров _гарантировано_ приведет к программному сбою. Например, обертки старых dll библиотек, которые имеют только один сегмент данных на процесс и кривой дизайн, не позволяющий связывать функционал с объектами. Или использование устаревших технологий типа DDE, которые ограничены одним сервером на процесс и когда последовательный вызов этих функций для двух разных серверов приведет к несогласованному состоянию. Во всех остальных случаях за использование сингельтонов нужно отрывать руки. В 99.999% случаев сингельтоны это просто способ обхода DI со всеми вытекающими.
 

zuxel

Новичок
Или использование устаревших технологий типа DDE, которые ограничены одним сервером на процесс и когда последовательный вызов этих функций для двух разных серверов приведет к несогласованному состоянию
в этом случае только синглтоны не помогут
а что с обходом DI?
 

whirlwind

TDD infected, paranoid
а что с обходом DI?
DI какую задачу решает? Decoupling. То бишь понижение связанности за счет реализации взаимодействия на базе абстракций. Статика убивает наследование и полиморфизм. Ты уже не можешь оперировать абстракцией, потому что для доступа через статический метод нужно идентифицировать реализацию. Трейты вроде как не убивают наследование, но это другой продвинутый способ стрельнуть себе в ногу. В общем, твой вариант 1) повышает связанность кода 2) ограничивает область применения класса одним экземпляром. Ты передачей зависимостей пытаешься снизить связанность, а статическим акцессором тут же ее добавляшь. Ну вроде как сам себе по морде дал. При чем абсолютно ни за что.

PS. Перенеси запрос зависимостей через сервис-локатор в конструктор. Будут те же яйца, только без гемора для пользователя и с одной точкой высокой связанности - сервис-локатором.
 

zuxel

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

zuxel

Новичок
Набросал решение, которое хоть и опирается на свой инстанс, но открыто для переинициализации:

PHP:
<?php

interface DIPuttable
{
    public function getDIKey();
    public function getInstanceFromDI();

}

class TargetClass implements DIPuttable
{
    public static function getDIKey()
    {
        return 'targetClass';
    }

    /**
    *    @return static
    */
    public static function getInstanceFromDI()
    {
        if (null === ($i = \DIContainer::get(self::getDIKey)) {
            throw new \Exception('Seems class hasnt been initiated yet');
        }
        return $i;
    }

    public function __construct()
    {
        $this->dep1 = \DIContainer::get(OtherClass1::getDIKey());
        $this->dep2 = \DIContainer::get(OtherClass2::getDIKey());
    }
}


// ..... somewhere during bootstraping

$tClass = new TargetClass();
DIContainer::set($tClass->getDIKey(), $tClass);
буду рад конструктиву
здесь нет синглтона зато куча потенциальных проблем с тем, что, например, кто-то реинициализирует класс, но забудет его положить в DI
 
Сверху