Pull to refresh
9
0
Nikolay Stepanov @MaxZN

web developer

Send message
Чем объясняется повсеместное применение реализаций интерфейсов вместо наследования?

1. Строка public function __construct(Theme $theme); в интерфейсе, еще не повод ставить под сомнение повсеместное применение интерфейсов. Это все равно, если запретить спички, только потому, что один ребенок обжег ими палец. Или поставить под вопрос использование автомобилей, ведь за их рулем часто оказываются нетрезвые люди. Просто, нужно правильно использовать возможности языка, а не писать определение конструктора в интерфейсе, только лишь потому, что язык этого не запрещает.

2. Почему же их все-таки нужно использовать и желательно почаще?
Не будем далеко ходить и возьмем ваш пример. Мы имеем один абстрактный класс и два класса реализующие его. Допустим, у нас есть некий клиентский класс, который обращается к getContent().
class Client 
{
    private $page;

    /**
     * Client constructor.
     *
     * @param $page
     */
    public function __construct(AbstractWebPage $page)
    {
        $this->page = $page;
    }

    public function showPage()
    {
        return $this->page->getContent();
    }
}

Таким образом мы научили наш клиент работать только с AbstractWebPage. Что, если мы хотим добиться от клиента работы не только с AbstractWebPage типом но и другими похожими типами? Стоит отметить, клиенту важно только одно, это метод getContent(), все что он должен знать о типе AbstractWebPage.
Тут вспоминается пример из жизни, когда обезьянку научили приносить воду в ведре. Та ходила по искусственной дорожке, где в конце был небольшой резервуар с водой. Позже, к этим условиям добавили бассейн с водой, однако обезьянка продолжила ходить за водой по привычному маршруту, тогда как бассейн с водой был намного ближе.
Также и тут, в нашем примере, мы словно учим обезьяну. Мы говорим ей вместо «воды» «принести», «воооон там, есть дорога, ты должна пройти по ней и только по ней, а в конце дороги будет резервуар и из него набрать воды» «принести»

Возвращаясь к нашему примеру. С помощью интерфейса мы можем определить более абстрактно тип страницы PageInterface. И любой класс реализующий данный тип будет обязан описать логику для метода getContent()

3. Почему не использовать в нашем примере абстрактный класс вместо интерфейса? — это неправильный вопрос. Почему мы можем использовать их вместе? — а вот это уже правильный.
Если мы будем использовать и то и другое, то все сразу встанет на свои места. Интерфейс даст возможность определить корневой тип, суперабстракцию, а абстрактный класс сможет ее уточнить/конкретизировать до необходимой степени. Таким образом мы правильно распределим ответственность за степень абстракции между классами и сделаем более понятной их иерархию.

В итоге у нас может быть такое решение, когда типов страниц может быть больше одного, а клиент не хочет брать на себя ответственность за их обработку. Он знает только о getContent и что на входе у него уже есть какая то реализация типа PageInterface.
abstract class AbstractWebPage implements PageInterface
{
    protected $theme;

    public function __construct(WebTheme $theme)
    {
        $this->theme = $theme;
    }
}


class About extends AbstractWebPage
{
    public function getContent()
    {
        return "About page in ".$this->theme->getStyle();
    }
}

abstract class AbstractPdfPage implements PageInterface
{
    protected $theme;

    public function __construct(PdfTheme $theme)
    {
        $this->theme = $theme;
    }
}

class Cv extends AbstractPdfPage
{
    public function getContent()
    {
        return "Cv page in ".$this->theme->getStyle();
    }
}

class Client 
{
    private $page;

    /**
     * Client constructor.
     *
     * @param $page
     */
    public function __construct(PageInterface $page)
    {
        $this->page = $page;
    }

    /**
     * @return PageInterface
     */
    public function showPage(): PageInterface
    {
        return $this->page->getContent();
    }
}

Спасибо за статью. Проще, чем описаны паттерны тут refactoring.guru еще не видел. К тому же, примеры на псевдокоде + диаграммы, на русском.
Отличный дайджест, много интересного, спасибо!)
В частности из материалов по Laravel вынес для себя гору ценной информации.

Релиз Phpstorm 2017.1 новостью не был, на неделе читал на официальном сайте о нем. Сложилось такое впечатление, что ребята просто взяли, то что и так уже можно было установить плагинами и добавили в IDE. Смысла переходить на новую версию для себя не увидел, буду ждать следующих релизов.
Stacker обновился до первой стабильной версии. Вы уже пробовали ставить на винду? Интересен ваш опыт в этом плане, так как на macos и linux работает все превосходно, а обратной связи от обладателей win еще не поступало.

В планах переписать ролики с вычиткой, ждем пока микрофон с али придет.

А вообще, касаемо статьи, у нас таже боль была, привлекаемые периодически товарищи верстальщики и фронтендеры некоторые даже понятия не имели, как наше окружение ставить. Плюс те кто постоянно работали уже утомились от периодических реплик, вроде: — А у меня локально все работает…
Все сошлись во мнении, что у команды должно стоять идентичное окружение и это окружение не должно бадаться с тем, что уже стоит(это больше для привлекаемых на время сотрудников) Только на винду не ставили пока ни разу, как то не довелось. Поэтому, отпишитесь плиз, очень интересует, как проходит установка и насколько сложно.
На здоровье!) Ролики, только нужно переписать будет, на скорость делал, с первого раза — гомно конечно.
Огромное спасибо за дайджесты и отдельное спасибо за наш stacker — не забыли, приятно.
Да, и это еще один жирный плюс докеру, не стал это упоминать показалось отступлением всторону. Так как разговор сейчас о среде для локальной разработки. Тут, должно быть понятно, что это не про деплой ни одним местом.
Да и в целом, прод это уже за локусом так сказать, там сервер, а за сервер должны отвечать админы. Конечно, если разработчик может полноценно совмещать еще и обязанности админа — это замечательно. Но это больше из разряда легенд о единороге. Пока еще не видел не одного сильного разработчика, что бы он еще при этом был и сильным админом.
Вы докером пользовались? Какие сложности у вас возникали при сборке образа?
Почему приводите в пример vagrаnt? Vagrant и Docker это разные технологии.

Зачем нужен Docker, если есть тот же Vagrant? Главным образом, просто потому что виртуализация в Docker дешевле. Используя Vagrant, вы эмулируете работу целой операционной системы, тогда как Docker позволяет изолировать просто один процесс. Соответственно, используя одно и то же железо, с помощью Docker вы можете создать больше виртуальных окружений, чем при помощи Vagrant. Более того, LXC контейнеры запускаются (и останавливаются тоже) практически моментально, так как в них не происходит загрузка отдельной ОС. К тому же, Docker использует «слоеную» файловую систему AuFS, благодаря которой контейнеры могут совместно использовать одинаковые части файловой системы, доступные только на чтение. Если образ файловой системы занимает 5 Гб и вы запускаете 100 виртуальных окружений, то Vagrant потребуется 500 Гб места, а Docker — на порядок меньше.
Для новичка вообще все вызывает вопросы)
На мой взгляд идея универсального образа не плоха, те же денверы и лампы построены на ней и довольно удобны. Но мне нравится ход ваших мыслей, в сторону «использовать нужное, но не больше». Допускаю, самым простым было бы отключение не нужного, а не добавление нужного. Отключить проще, чем добавлять. С первым нужно знать что нужно, таким образом уже знаешь, что отключить. Чтобы добавить, нужно знать довольно много и всякие надстройки тут не спасут, а только будут дублировать, то что и так уже делает докер это раз, плюс еще добавят сложности это два, так как все равно нужно будет изучать и доку докера и доку этой надстройки.

Идея в простоте, и если мы хотим ее предоставить, то нужно требовать, как можно меньше в плане знаний от пользователя. В принципе запилить sh для отключения не нужного не долго, просто параметрами передавать нужные образы для docker-compose и готово.

Так и хочется спросить: — «Почему?»
Если, это не что-то личное. В этом случае вопросов нет.
По поводу упростить, можете поподробнее, что вы предлагаете?

Формировать контейнеры под себя можно и сейчас, это довольно простой процесс. Редактируете Dockerfile по своему вкусу, далее запускате:

$ stacker build && stacker down && stacker up && stacker ps 

это тоже самое что и:

$ cd /path/to/stacker
$ docker-compose build
$ docker-compose up -d
$ docker-compose ps

Данный процесс ничем не отличается от описанного в документации по докеру.

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

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

опять же. У вас должен быть один образ с приложением, в нем composer (чтобы иметь возможность запускать composer скрипты). А для разных вещей (запуск приложения или запуск тестов или запуск bin/console) мы просто используем разные контейнера. Но образ и Dockerfile один и тот же.


У нас образ для прода так и готовится, изначально идея докера в доставке и быстром запуске. По аналогии с контейнерами в порту, вы запаковываете в контейнер нужный вам груз и транспортируете куда вам нужно. Однако, и я наверное повторюсь, но скажу еще раз, stacker для локальной разработки, а не для транспортировки, его задачи в другом, вы просто подсовываете папку с проектами(больше одного) и запускаете их.
Также, мы хотели проявить немного заботы и о новичке, чтоб переход на наше окружение не был чем то сложным и пугающим. Напротив, чтобы все проходило плавно и безболезненно, с возможностью вернуться к прежнему окружению, когда будет нужно. В итоге:
— ему не нужно перемещать файлы и папки это раз
— не нужно сносить старый LEMP или то, что у него там стояло
— не нужно сносить базы(порты смещены на единицу для DB).

Когда нужно транспортировать на прод, то вы можете запаковать надлежащим образом проект в образ, файлы файлами, пакуйте и везите)
— «различия в окружениях должны разруливаться» — даже, если окружение всегда одно, локальное?
— тут несколько с другой стороны заход, докер использовали в качестве альтернативы LAMP и тд. чтобы локальное окружение у всех было одинаковое и чтобы можно было легко перепрыгнуть со своего текущего окружения на наше. А чтоб ничего там не доустанавливать, решили установить максимальный пулл экстенженов для php сразу. Выглядит страшновато и избыточно, обсудим, спасибо за обратную связь.

— образ php7console для консольных утилит, вроде composera. Да, Вы правы cli уже есть в другой сущности, но мы решили отделить таким образом xDebug и php от консоли с npm, composer, и тд. чтобы не держать все это на хостовой машине, но php тут тоже нужен. Например для запуска консольных команд Sf2 и других фреймворков.

— элиасы, да, нужды в них нет, надо вычистить

В целом, нам бы не помешали грамотные контрибьюторы вроде вас, делайте форк, шлите pullrequest. Будем рады.
Печалька с виндузом. К сожалению не смогу помочь. Тут бы пригодилось мнение админа, как вам маунты грамотно в винде настроить или если дело не в них, то ткнуть носом и сказать, что нужно делать.
Полгода прошло, а чего не поделились с остальными своим решением? )
Можете показать, как у вас логер настроен? По умолчанию конфигурация идет упоротая. Все подряд пишет, да еще и в один файл.
Сидим под MacOS и Ubuntu, такой проблемы пока не наблюдаем. Возможно вам поможет создание отдельного контейнера под логи с Elastic. Не уверен, что вам это подойдет, просто где-то видел такое решение на github.
xdebug.remote_autostart=On — так тормозить же будет, на моей железке падение производительности наблюдал в сотни раз
xdebug.remote_host=<ip хостовой машины> — если вы один работаете в компании или с одного хоста все сидят, а так удобнее ставить xdebug.remote_autostart=0 тогда xdebag будет коннектить к каждому сам

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity