Ответы пользователя по тегу ООП
  • Как использовать Di container?

    @Wentixon
    Рекомендую почитать книгу про паттерн или вот этот сайт посмотреть, в частности паттерны стратегия. Тогда думаю все станет намного понятнее, так как сейчас у вас даже вопросы неверные, а вообще без опыта в такие дебри лучше не лезть

    Если вкратце то:
    Вопрос1 - нужно ли всё равно передавать параметр в конструктор вызываемого контроллера или можно просто вызывать без параметров?

    У нас есть контейнер, в нем при запуске приложения мы регистрируем классы (сервисы). При регистрации мы связываем абстракцию (интерфейс) и реализацию (конкретный класс), а также впринципе говорим нашему приложению КАК создать конкретный объект. Потом же мы делаем просто так и получаем готовый объект
    // Получаем объект интерфейса из любой точки приложения
    $container->get(MyInterface::class);


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

    $container->register(MyInterface::class, function () {
      return new MyConcreteClass('какие то параметры');
    });


    Вопрос2 - где вообще надо делать $container->get('что-нибудь'); ? В самом контроллере как-то неправильно, наверное - ибо тогда всё равно зависимость. Где это делать?

    Во-первых, контроллер это обычный класс, во-вторых принцип DI заключается в том, чтобы у вас классы не зависили от конкретных реализаций и явно ЗАВИСИЛИ от АБСТРАКЦИЙ. Это самое важно что нужно понять. Отвечая на вопрос - брать напрямую из контейнера сервисы надо ЗА сервисами, то есть в сервис провайдере и выше

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

    Вот короче пример написал который впринципе все объясняет, если непонятно спрашивай

    interface CartRepository
    {
        public function add(CartItem $item);
        public function getAll();
    }
    
    class SessionCartRepository implements CartRepository
    {
        ...
    }
    
    class DbCartRepository implements CartRepository
    {
        ...
    }
    
    class Cart
    {
        public function __construct(CartRepository $repository) 
        {
            ...
        }
    
        public function getTotal()
        {
            ...
        }
    }
    
    // Service provider
    $container->register(CartRepository::class, function ($container) {
        if ($user = $container->get('auth')->getUser()) {
            $repository = new DbCartRepository($container->get('db'), $user->id)
        } else {
            $repository = new SessionCartRepository();
        }
    
        return $repository;
    });
    
    $container->register(Cart::class, function ($container) {
        return new Cart($container->get(CartRepository::class));
    });
    Ответ написан
    1 комментарий
  • Для чего бывает нужно подменять реализацию интерфейса?

    @Wentixon
    Все очень просто! Приведу пример на laravel, но фреймворк разумеется не имеет к этому никакого отношения.

    Например, в ларавеле есть пакет кэширования. Вот его интерфейс. Но разумеется, реализация кэширования может быть абсолютно разная, ты ее можешь настроить с помощью конфигурации. В одном проекте, ты можешь использовать какой нибудь redis, в другом memcached к примеру, а в тестах и вовсе массив. В каждом современном фреймворке есть сервис контейнер, который может отдать тебе нужную реализацию по запросу нужного интерфейса (привязывается реализация к интерфейсу в сервис провайдерах).

    А теперь представь, что ты делаешь сервис (класс) и ему нужно что то закэшировать. И сделаешь это вот так

    class RemoteApi {
        public function _construct(RedisCache $cache)
        ....
    }


    Я думаю сам видишь, в чем тут проблема. Этот класс будет работать только с редисом. А теперь представь, что таких классов очень много, которые использую кэш редиса. Потом при смене хранилища кэша придется все их менять и переделывать, так как интерфейсы у них, возможно, будут разные.
    Ответ написан
    Комментировать
  • Как использовать ооп на практике?

    @Wentixon
    ООП гораздо сложнее чем ты думаешь. Самый оптимальный способ изучить его это делать проекты на современных фреймворка и изучать сами эти фреймворки и разбираться, почему разработчики сделали именно так. Паттерны, solid поизучай. Это необходимо, иначе ты будешь делать не ооп а какую то пародию, которая скорее будет создавать проблемы, чем решать их
    Ответ написан
    1 комментарий
  • Как въехать в программирование (ООП, паттерны)?

    @Wentixon
    Шаблоны проектирования с человеческим лицом
    К сожалению, не успел к началу вопроса, многое уже посоветовали, но эту статейку вроде не успели еще кинуть. Недавно нашел ее и просто поразился как просто и доступно это изложено + с примерами кода на php. Просто шикарный перевод великолепной статьи!

    От себя же хочу сказать, что единственный способ понять паттерны - это столкнуться с проблемами которые они решают, ибо паттерны ни что иное как шаблоны решения каких то проблем (и предотвращения). Так что делаем вывод - нет проблем, не может быть и решений (конечно, вы просто не осознаете, что они есть, так как проект растет довольно медленно и чаще это какие то правки или добавление нового функционала, который не зависит от старого). Я очень долго пытался с ними разобраться, пробовал читать все перечисленные книги, но вроде читаешь такой и типа понимаешь, но с другой стороны какбы и нет. Вроде понятно, но где это применять хрен знает. Вообщем, как уже сказали, нужны реальные проблемы и тогда открываешь книгу с решениями этих проблем и думаешь какое решение выбрать. Это как с рецептами.. Хочешь что то приготовить, можешь как бы и сам, но не факт, что вкусно получится, тогда открываешь книгу проверенных рецептов и начинаешь применять все по шагам, опираясь при том на ингридиенты, которые у тебя имеются.

    Так что посоветую 2 варианта изучения.
    1) Тупо работаешь над сложные проектами, только действительно сложными, а не сайтиками на cms. И со временем ты начинаешь встречаться с проблемами. Тогда открываешь паттерны и тебе не придется даже как то их особо понимать, потому что это будет естевственно для тебя. Я думаю ты используешь ide вместо редактора кода. Но к примеру я помню тот момент, когда я пользовался саблаймом и знал, что есть ide, но я писал на тот момент простые вещи и когда мне говорили, почему я не юзаю ide, ведь в ней столько всего, я не понимал их потому что мне и саблайма за глаза хватало. Но пришло время, когда надо было то и се и саблайма стало мало. И тут открываю ide, а там уже есть все необходимое и думаешь в такие моменты, как я раньше этим не пользовался. А дело в том, что раньше и не надо было. Может неудачный пример, но вы поняли ) Конечно, этот вариант изучения не совсем реален, по скольку сложный проект еще найти надо, да еще попасть в команду, которая не говнокодит, так как и крупные проекты бывают достаточно плохо написаны. Но можно как вариант к примеру делать свою cms и применять в ней как можно больше паттернов.

    2) Тупо садитесь и изучаете паттерны (как и делал я). Но не просто изучаете, а к какждому паттерну придумываете как можно больше проблем, которые может у вас были или могут быть, так как паттерны в большинстве случаях любят описывать в метафорах, но чаще это получается слишком абстрактно, поэтому нужно чтобы вы придумали свои конкретные задачи, где бы вы попробовали применить этот паттерн. И второй этап - садитесь и пишите эти задачи. Тупо открываете свой яп и реализовываете паттерн. При чем несколько раз с разными проблемами.

    Также советую четко понять uml диаграммы. Таким образом, чтобы освежить паттерн вы не будете читать примеры, а просто посмотрите диаграмму и сразу вспомните, зачем он нужен и как его можно реализовать.
    Вот пожалуй и все
    Ответ написан
    1 комментарий