Уточка говорит «кря-кря», коровка говорит «му-му», «Runn Me!» — говорит нам очередной фреймворк* на PHP. Часть 1

    «О нет!», воскликнет читатель, утомлённый разными мини-микро-слим-фреймворками и QueryBuilder-ами и будет прав.

    Нет ничего скучнее, чем очередной фреймворк на PHP. Разве что «принципиально новая» CMS или новый дейтинг.



    Так зачем же я с упорством, достойным лучшего применения, шагаю по неудобным подводным камням и выставляю на потеху публике суд товарищей своё творение? Заранее зная, что гнев критиков, как мощное цунами обрушится на этот пост и похоронит его на самом днище Хабра?

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

    Видимо и у программистов на PHP, к которым я вот уже 13 лет себя причисляю, есть такая же внутренняя потребность — выставлять свой код и зажмуривать глаза, ожидая реакции коллег.

    Что вас ждет под катом?

    • Открытый исходный код, лицензия LGPL
    • Код, полностью совместимый с PHP 7.0-7.2
    • 100% покрытие юнит-тестами
    • Библиотеки, проверенные временем в реальных проектах (и только проклятая прокрастинация мешала мне опубликовать их ранее!)

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

    * вообще говоря это пока еще не фреймворк, а просто набор библиотек, фреймворком он станет чуть позже



    Немного истории или Откуда взялась идея «написать еще один фреймворк?»


    Да, собственно говоря, ниоткуда. Она всегда была.

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

    Лет шесть назад руководство компании, в которой я тогда работал, поставило задачу: разработать свой собственный фреймворк. Сделать легковесный MVC-каркас, взяв только самое необходимое, добавить к нему специфичные библиотеки предметной области (поверьте — очень специфичные!) и собрать некое универсальное решение. Решение, надо отметить, получилось, но специфичность предметной области не позволила ему стать массовым — код не публиковался, продавались инсталляции на площадку клиента. А жаль. Некоторые вещи действительно опережали своё время: достаточно сказать, что пусть примитивное, но всё-таки довольно похожее подобие composer мы с командой сделали тогда совершенно самостоятельно и немного раньше, чем появился, собственно стабильный публичный composer :)

    Благодаря этому опыту мне довелось изучить практически все существовавшие тогда в экосистеме PHP фреймворки. Попутно произошло еще одно событие, очередной «переход количества в качество» — я стал преподавать программирование. Сначала в одной известной онлайн-школе, потом сосредоточился на развитии своего собственного сервиса. Стал «обрастать» методиками преподавания, учебными материалами и, конечно же, студентами. В этой тусовке и возникла идея некоего «учебного фреймворка», намеренно упрощенного для понимания начинающими, но при этом позволяющего всё-таки успешно разрабатывать несложные веб-приложения в соответствии с современными стандартами и тенденциями.

    Три года назад, как реализация этой идеи «учебного фреймворка», родился небольшой MVC-фреймворк под названием «T4»*. В названии нет ничего особенного, просто сокращение от «Технологический макет, версия 4». Думаю понятно, что предыдущие три версии вышли неудачными и только с четвертой попытки нам, вместе с тогдашними моими студентами, удалось создать что-то действительно интересное.

    * позже я узнал, что так в третьем рейхе называлась программа по стерилизации и умерщвлению неизлечимо больных людей… конечно же сразу встал вопрос о смене названия

    T4 благополучно развивался и рос, стал известным, как говорится, «в узких кругах» (очень узких), на нём был сделан ряд довольно крупных проектов, но росло и внутреннее недовольство этим решением.

    В начале этого года я окончательно созрел для переформатирования накопившегося кода. Вместе с группой единомышленников, которые тоже активно использовали T4, мы приняли ряд базовых принципов построения нового фреймворка:

    1. Делаем его слабосвязанным набором библиотек, так, чтобы каждую либу можно было подключить и использовать отдельно.
    2. Стараемся сохранять здоровый минимализм там, где это возможно
    3. Сам каркас для веб- и консольных приложений — тоже одна из библиотек, тем самым мы избегаем монолитности.
    4. Стараемся не изобретать велосипеды и максимально сохраняем те подходы и тот код, которые уже зарекомендовали себя в T4.
    5. Отказываемся от поддержки устаревших версий PHP, пишем код под самую актуальную версию.
    6. Стараемся делать код максимально гибким. Если можно — вместо классов и наследования используем интерфейсы, трейты и композицию кода, оставляя пользователям фреймворка возможность заменить эталонную реализацию любого компонента своей.
    7. Покрываем код тестами, добиваясь 100% покрытия.

    Так родился проект, который сначала назвали «Running.FM», а потом окончательно уже переименовали в «Runn Me!»

    Именно его я сегодня и представляю.

    Кстати, слово «runn» сконструировано искусственно: с одной стороны чтобы быть понятным всем и вызывать ассоциации с «run», с другой — чтобы не совпадало ни с одним из словарных слов. Мне вообще нравится буквосочетание «run»: я еще в RunCMS в своё время успел поучаствовать :)

    В данный момент проект «Runn Me!» находится в середине пути — какие-то библиотеки уже можно применять в продакшне, какие-то в процессе переноса из старых проектов и рефакторинга, а какие-то мы еще не начали переносить.

    В начале было Core


    Уместить в один пост рассказ о каждой библиотеке проекта «Runn Me!» невозможно: их много, хочется подробно поведать о каждой, ну и к тому же это живой проект, в котором всё изменяется к лучшему буквально ежедневно :)

    Поэтому я решил разбить рассказ о проекте на несколько постов. В сегодняшнем пойдет речь о базовой библиотеке, которая называется «Core».

    • Назначение: реализация базовых классов фреймворка
    • GitHub: github.com/RunnMe/Core
    • Composer: github.com/RunnMe/Core
    • Установка: командой composer require runn/core
    • Версии: как и в любой другой библиотеке проекта «Runn Me!», поддерживаются три версии, соответствующие предыдущей, актуальной и будущей версиям PHP:
      7.0.*, 7.1.* и 7.2.*

    Массив? Объект? Или всё вместе?


    Благодатная идея объекта, состоящего из произвольных свойств, которые можно создавать и удалять «на лету», как элементы в массиве, приходит в голову каждому программисту на PHP. И каждый второй эту идею реализует. Не стали исключением и я с моей командой: ваше знакомство с библиотекой Runn\Core я хочу начать с рассказа о концепции ObjectAsArray.

    Делай раз: определи интерфейс, который позволит тебе кастить твой объект к массиву и обратно: массив превращать в объект, не забыв в этом интерфейсе пару полезных методов (merge() для слияния объекта с внешними данными и рекурсивный кастинг к массиву)

    github.com/RunnMe/Core/blob/master/src/Core/ArrayCastingInterface.php
    namespace Runn\Core;
    
    interface ArrayCastingInterface
    {
        public function fromArray(iterable $data);
        public function merge(iterable $data);
        public function toArray(): array;
        public function toArrayRecursive(): array;
    }
    

    Делай два: собери мегаинтерфейс, который опишет поведение будущего объекта-как-массива максимально полно, заложив туда максимум полезного: сериализацию, итерацию, подсчет числа элементов, получение списка ключей и значений, поиск элемента в этом «объекте-массиве».

    github.com/RunnMe/Core/blob/master/src/Core/ObjectAsArrayInterface.php
    namespace Runn\Core;
    
    interface ObjectAsArrayInterface
      extends \ArrayAccess, \Countable, \Iterator, ArrayCastingInterface, HasInnerCastingInterface, \Serializable, \JsonSerializable
    {
      ...
    }
    

    Делай три: напиши трейт, который станет эталонной реализацией мегаинтерфейса. См. github.com/RunnMe/Core/blob/master/src/Core/ObjectAsArrayTrait.php

    В результате мы получили полноценную реализацию «объекта-как-массива». Использование интерфейса ObjectAsArrayInterface и трейта ObjectAsArrayTrait позволяет делать нам примерно так:

    class someObjAsArray implements \Runn\Core\ObjectAsArrayInterface 
    {
      use \Runn\Core\ObjectAsArrayTrait;
    }
    
    $obj = (new someObjAsArray)->fromArray([1 => 'foo', 2 => 'bar']);
    $obj[] = 'baz';
    $obj[4] = 'bla';
    
    assert(4 === count($obj));
    assert([1 => 'foo', 2 => 'bar', 3 => 'baz', 4 => 'bla'] === $obj->values());
    
    foreach ($obj as $key => $val) {
      // ...
    }
    
    assert('{"1":"foo","2":"bar","3":"baz","4":"bla"}' === json_encode($obj));
    

    Кроме базовых возможностей в ObjectAsArrayTrait реализована возможность перехвата присваивания и чтения «элементов объекта-массива» с помощью кастомных сеттеров-геттеров, этакий задел для будущих классов:

    class customObjAsArray implements \Runn\Core\ObjectAsArrayInterface 
    {
    
      use \Runn\Core\ObjectAsArrayTrait;
    
      protected function getFoo() 
      {
        return 42;
      }
    
      protected function setBar($value)
      {
        echo $value;
      }
    
    }
    
    $obj = new customObjAsArray;
    assert(42 === $obj['foo']);
    
    $obj['bar'] = 13; // выводит 13, присваивания не происходит
    

    Важно: null is set!


    Да, элемент объекта-массива, чье значение null, считается определенным.

    Это решение вызвало немало споров, но всё-таки было принято. Поверьте, на то есть серьезные причины, о которых будет рассказано дальше, в повествовании о библиотеке ORM:

    class someObjAsArray implements \Runn\Core\ObjectAsArrayInterface 
    {
      use \Runn\Core\ObjectAsArrayTrait;
    }
    
    $obj = new someObjAsArray;
    assert(false === isset($obj['foo']));
    assert(null === $obj['foo']);
    
    $obj['foo'] = null;
    assert(true === isset($obj['foo']));
    assert(null === $obj['foo']);
    

    И зачем это всё?


    Ну как же! Всё, о чем я рассказывал выше — это только начало. От интерфейса \Runn\Core\ObjectAsArrayInterface наследуются другие интерфейсы и имплементируют классы, дающие жизнь двум «веткам классов»: Collection и Std.

    Коллекции


    Коллекции в Runn Me! — это объекты-массивы, снабженные большим количеством дополнительных полезных методов:

    Тут можно увидеть их все
    namespace Runn\Core;
    
    interface CollectionInterface
        extends ObjectAsArrayInterface
    {
        public function add($value);
        public function prepend($value);
        public function append($value);
        public function slice(int $offset, int $length = null);
        public function first();
        public function last();
        public function existsElementByAttributes(iterable $attributes);
        public function findAllByAttributes(iterable $attributes);
        public function findByAttributes(iterable $attributes);
        public function asort();
        public function ksort();
        public function uasort(callable $callback);
        public function uksort(callable $callback);
        public function natsort();
        public function natcasesort();
        public function sort(callable $callback);
        public function reverse();
        public function map(callable $callback);
        public function filter(callable $callback);
        public function reduce($start, callable $callback);
        public function collect($what);
        public function group($by);
        public function __call(string $method, array $params = []);
    }
    


    Разумеется, сразу же в распоряжении разработчика имеется как эталонная реализация этого интерфейса в виде трейта CollectionTrait, так и готовый к использованию (или наследованию) класс \Runn\Core\Collection, добавляющий к реализации методов из трейта удобный конструктор.

    С использованием коллекций становится возможным писать примерно такой код:

    $collection = new Collection([1 => 'foo', 2 => 'bar', 3 => 'baz']);
    $collection->prepend('bla');
    
    $collection
      ->reverse()
      ->map(function ($x) { 
        return $x . '!'; 
      })
      ->group(function ($x) {
        return substr($x, 0, 1);
      });
    
    /*
    получится что-то вроде
    [
      'b' => new Collection([0 => 'baz!', 1 => 'bar!', 2 => 'bla!']),
      'f' => new Collection([0 => 'foo!'),
    ),
    ]
    */
    

    Что важно знать о коллекциях?

    1. Большинство методов не изменяют исходную коллекцию, а возвращают новую.
    2. Большинство методов не гарантирует сохранение ключей элементов.
    3. Наилучшее применение коллекций — хранение в них множеств однородных или подобных объектов.

    Типизированные коллекции


    Кроме «обычных» коллекций в библиотеку Runn\Core включен интересный инструмент, позволяющий полностью контролировать объекты, которые могут содержаться в коллекции. Это типизированные коллекции.

    Всё очень и очень просто:

    class UsersCollection extends \Runn\Core\TypedCollection 
    {
      public static function getType()
      {
        return User::class; // тут может быть и название скалярного типа, кстати
      }  
    }
    
    $collection = new UsersCollection;
    
    $collection[] = 42; // Exception: Typed collection type mismatch
    $collection->prepend(new stdClass); // Exception: Typed collection type mismatch
    
    $collection->append(new User); // Success!
    

    Std


    Вторая «ветка» кода, в чём-то противоположная коллекциям, называется «Стандартный объект». Строится он также пошагово:

    Делай раз: определи интерфейс для «магии».

    namespace Runn\Core;
    
    interface StdGetSetInterface
    {
        public function __isset($key);
        public function __unset($key);
        public function __get($key);
        public function __set($key, $val);
    }
    

    Делай два: добавь ему стандартную реализацию (см. github.com/RunnMe/Core/blob/master/src/Core/StdGetSetTrait.php )

    Делай три: собери из «запчастей» класс, опирающийся на StdGetSetInterface с множеством дополнительных возможностей. github.com/RunnMe/Core/blob/master/src/Core/Std.php

    В конце пути мы получаем с вами достаточно универсальный класс, пригодный для решения множества задач. Вот лишь несколько примеров:

    $obj = new Std(['foo' => 42, 'bar' => 'bla-bla', 'baz' => [1, 2, 3]]);
    assert(3 === count($obj));
    
    assert(42 === $obj->foo);
    assert(42 === $obj['foo']);
    
    assert(Std::class == get_class($obj->baz));
    assert([1, 2, 3] === $obj->baz->values());
    
    // о, да, реализация вот этой штуки весьма монструозна:
    $obj = new Std;
    $obj->foo->bar = 42;
    assert(Std::class === get_class($obj->foo));
    assert(42 === $obj->foo->bar);
    

    Разумеется, «умения» класса Std не исчерпываются chaining-ом, доступом к свойствам, как к элементам массива и наоборот, кастингом к самому классу. Он умеет гораздо больше: валидировать и очищать данные, отслеживать обязательные к заполнению свойства и т.д. Но об этом позже, в других статьях цикла.

    А дальше?


    Всё только начинается! Впереди нас ждут рассказы о:

    • Мультиисключениях
    • Валидаторах и санитайзерах
    • О хранилищах, сериализаторах и конфигах
    • О реализации Value Objects и Entities
    • Об HTML и представлении форм на стороне сервера
    • О собственной библиотеке DBAL, включая, конечно же, QueryBuilder!
    • Библиотека ORM
    • и как финал — MVC-каркас

    Но это всё в будущих статьях. А пока что с праздником, товарищи! Мир, труд, код! :)



    P.S. Детального плана со сроками у нас нет, как нет и желания успеть к какой-то очередной дате. Поэтому не спрашивайте «когда». По мере готовности отдельных библиотек будут выходить статьи о них.

    P.P.S. С благодарностью приму сведения об ошибках или опечатках в личные сообщения.

    ©


    КДПВ (с) Mart Virkus 2016
    Картинка в заключении статьи из гуглопоиска картинок
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 226

      –8
      Я тоже недавно пытаясь разобраться в Yii2 плюнул на это, и написал себе небольшой MVC с нуля.

      А еще ранее, когда только вышел ZF, произошло то же самое, но где тот первый движок — я уже и не помню :D

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

      Так что мысленно поддерживаю вашу инициативу!

      //И да, всегда с трепетным уважением смотрю на людей, сумевших разобраться в Symfony например. У них наверное какой-то особенно огромный мозг, или еще чего такое в этом же духе :)
        0
        А когда мастеришь только для себя, то постоянно приходится через несколько лет писать одно и то же заново.

        Откройте для себя Github ))

        Кстати, в чём-то я с вами согласен. Недовольство именно Yii, который пришлось несколько раз использовать, стало одним из поводов делать что-то своё. Мне просто стало интересно — сможем ли мы с ребятами сделать что-то вроде Yii 3, не таща за собой его фатальные архитектурные ошибки?

        Оказалось, что смогли :)
          +5
          Оказалось, что смогли :)

          Пруфы будут?)
            –6
            А как же. Статье к десятой. Имейте терпение!
              +6
              Мне кажется, что без пруфов до десятой статьи вряд ли кто-то дочитает.
                0
                Код открыт. Какие еще пруфы прямо сейчас вы хотели бы получить?
                  +1
                  Вам же уже писали: пруфы применения в сравнении с другими фреймворками, где ясно видно, что ваше решение лучше.
                    +3
                    Тот код, который открыт — антипруф. И ниже есть немало аргументов почему это так.
                      0
                      Я услышал ваше мнение, спасибо.
              +6
              Оказалось, что смогли :)

              Тут больше людей интересует каков был алгоритм. Такой:


              • Yii нам не подходит
              • Пишем свое

              или такой


              • Yii нам не подходит
              • Ресерчим существующие решения
              • пробуем на парочке понравившихся с идеологической точки зрения написать что-то свое
              • ничего не подходит, попробуем хотя бы из отдельных компонентов запилить
              • не, все грустно по таким-то причинам
              • Пишем свое

              Если все происходило по первому сценарию — в этом нет пользы. Если по второму — всех интересуют причины.

            +3
            «Недовольство именно Yii, который пришлось несколько раз использовать, стало одним из поводов делать что-то своё.»
            Допустим, я выбираю фреймворк, на котором реализовать проект. В чем преимущества Runn Me перед тем же Yii2?
              –5
              Сложно сейчас сформулировать преимущества, когда фреймворк еще в самой ранней стадии сборки. Я планировал раскрывать этот вопрос постепенно, по мере выхода статей и подготовки кода к публикации.

              Если кратко, то:
              — БОльшая архитектурная стройность, например у нас точно не будет никогда $this->breadcrumbs в контроллерах (!)
              — Возможность замены любой части, любого компонента на другой, имеющий аналогичный интерфейс. Например вы можете целиком заменить Renderer с нативного на другой, на базе Twig. Насколько я помню, в Yii это крайне сложно. Например конфиг можно сохранять в файл, в базу или в кэш, просто подставив нужную зависимость. Даже класс приложения (контейнера служб) можно вполне заменить на свой.
              — Нет тяжести поддержки старых версий, сразу ориентируемся на 7.1, поэтому нет таких вещей, как «поведения», которые в общем-то в современном PHP не нужны
              — Мы сразу закладываем возможность работать с несколькими БД, включая даже возможность строить в рамках ORM relations (разумеется lazy load) между разными базами данных

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

              Следите за публикациями!
                –1
                не будет $this->breadcrumbs в контроллерах (!)

                А хде?
                  +1
                  Разумеется в шаблонах :)

                  Зачем контроллеру вообще что-то знать о том, как будет отдан ответ пользователю? Контроллер готовит данные, представление — форматирует.
                    +1
                    Контроллер готовит данные

                    Так контроллер будет готовить breadcrumbs или нет? :)
                      0
                      Это вам решать в конечном счете. Но я бы не рекомендовал.
                      • UFO just landed and posted this here
                          –1
                          Отлично. :)
                          Хде их готовить? :)
                            0
                            В шаблонах страниц.
                              0
                              В шаблонах делать запросы к БД для получения всех родителей?
                              Дичь. :)
                                0
                                Не делайте. Зачем это вам?
                                Если модель является частью «дерева», то соответствующий метод у нее наверняка есть. А уж как он работает — делает один запрос или много — какая вам разница?
                                  0

                                  В шаблонах вы делаете вывод UI компонента который будет запрашивать модель самостоятельно а уже запросы в базу будут инкапсулированы на уровне модели.

                          0
                          Контроллер готовит данные, представление — форматирует.

                          Почему же его тогда называют "контроллер" а не "форматтер" или "презентер"?

                            +1
                            Кого именно?
                            Вы спрашиваете, почему «контроллер называют не форматтер или презентер»? Ну наверное потому, что контроллер ничего не форматирует и не показывает ))
                              0

                              Не проснулся с утра, кусок фразы пропустил. В моем варианте выходило "контроллер форматирует". Шэйм он ми.

                        –2
                        поэтому нет таких вещей, как «поведения», которые в общем-то в современном PHP не нужны

                        Как вы заменяете такую конструкцию?


                        [
                                'class' => TimestampBehavior::className(),
                                'attributes' => [
                                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                                    ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
                                ],
                                'value' => function () { return date('Y-m-d H:i:s'); },
                        ]
                          +4
                          Никак. Вам нужно срочно убрать это из ORM либо в триггер, либо, что лучше, в конкретный компонент бизнес-процесса.
                            –3

                            Причем здесь ORM? Это же просто пример. Поведениям можно задавать параметры, в отличие от трейтов, и это удобно. С трейтами можно сделать что-то похожее, но часть инициализации будет в конструкторе, и надо следить, чтобы конфликтов названий не было. С поведениями проще и нагляднее.

                              +3
                              Я отвечу вам подробно с примерами в одной из следующих частей. Если кратко: нет, поведений не будет. Как не будет вообще декларативного подхода и «автоматики». Это одно из самых неприятных впечатлений от Yii.

                              Явное лучше неявного. Код лучше массивов параметров.
                                +2
                                Явное лучше неявного. Код лучше массивов параметров.


                                Полностью согласен. Думаю в 10 грехов программирования, если их собрать, одним из первых будет конфигурирование вместо программирования. В этот грех впадают почти все
                                  –1

                                  Думаю, через год-другой в него окунуться с головой вообще все, учитывая что происходит у нас на тему DI-контейнеров.

                                    0
                                    Я имел в виду в широком смысле, когда программирование заменяется на сложное конфигурирование — примеров тому тьма тмущая.

                                    Про DI — я вот только что написал свой собственный DI (просмотрел кучу всяких либ — везде перегруженное гуано, ничто не устроило). Ну да к нему конфиг в виде карты классов, конфиг простой и понятный, нет головоломных DisabledOption = false;
                                      +2
                                      ну вот что вас не устроило в Symfony Container, к примеру?
                                        –2
                                        Кратко про контейнер симфони:

                                        1. использование аннотаций в рантайме — это чистое зло и никогда их использовать не буду. Что им мешает сделать генератор классов из аннотаций?
                                        2. 769Кб папка dependency-injection — это куда и зачем? Мне места на диске не жалко, мне жалко мусор, который за собой придется таскать. Сколько файлов подгружает при пустом контенйере? Писать сложно и непонятно я умею и этогоне хотел бы от других
                                        3. Dumper, Compiler, Extension, Loader — им действительно место в компоненте контейнера?
                                        4. безумное колво мутных интерфейсов для одного компонента, мне нужен только 1!!! интерфейс.

                                        В топку такие компоненты
                                          +2

                                          Вы не разобрались.


                                          Что им мешает сделать генератор классов из аннотаций

                                          Ничего не мешает. В рантайме будет один класс, в котором явно все прописано.

                                            +2
                                            1. Никакие аннотации в рантайме не используются
                                            2. В продакшене все это не грузится. Оно нужно для разработки.
                                            3. Это и не есть часть контейнера. Это независимые компоненты.
                                            4. Там только один и есть
                                              +2
                                              использование аннотаций в рантайме — это чистое зло и никогда их использовать не буду. Что им мешает сделать генератор классов из аннотаций?

                                              А где там аннотации в рантайме?


                                              769Кб папка dependency-injection — это куда и зачем?

                                              ну откройте и посмотрите. 420 килобайт тестов (можно иногда подсматривать как пример), куча лоадеров из разных форматов в котором вам приятнее держать параметры и дефинишены сервисов, средства отладки (в том числе возможность дамнуть весь граф зависимостей в виде dot файлика). Ну и конечно же кодогенерация, компиляция контейнера и т.д. Что-то вроде возможности проверять зависимости в компайл тайм.


                                              Сколько файлов подгружает при пустом контенйере?

                                              1. это не столь важно, есть же opcache
                                              2. в продакшене вы захотите использовать скомпилированный контейнер. На сегодняшний день симфоневый контейнер один из самых быстрых. Тогда в принципе количество подключаемых файлов будет сводиться к 3-4.

                                              1. Dumper, Compiler, Extension, Loader — им действительно место в компоненте контейнера?


                                              • Compiler — это то что делает контейнер быстрым и безопасным. А так же позволяет делать многие приятные вещи явно.
                                              • Dumper — это штуки которые нужны для экспорта контейнера в какой-либо формат, в основном для удобной отладки и разного рода средств автокомплита.
                                              • Extension — это что-то типа ServiceProvider-ов. Простой способ быстро подключить ваши компоненты а не лепить один гигантский конфиг.
                                              • Loader — ну надо же откуда-то загружать дефинишены сервисов.

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

                                              он у вас есть — ContainerInterface. Вам по сути больше ничего не нужно.

                                                –3
                                                Да, действительно, я не стал разбираться симфони, посмотрю еще раз. Ведь такая штука: бегло просматриваю базовые классы/интерфейсы, если мне не нравится стиль кодирования, вижу избыточнное количество методов с неочевидным назначением и т.д. Как правило отвергаю такую библиотеку.
                                            +1
                                            не смотрели https://github.com/auraphp/Aura.Di?
                                              0
                                              Да, конечно, все из топа выдачи гугла, у всех разное качество и к каждому я находил претензии. Больше всех мне понравился компонент di из codeception
                                                0
                                                компонент di из codeception

                                                Вы про это? Это не компонент, это просто надстройка для внутренних нужд Codeception. Он лишен основной фичи — нормальной декларации зависимостей, фабрик, возможности прокидывать параметры.

                                                  –1
                                                  Модуль (термин модуль — устроит вместо компонент?) из codeception я привел в пример того, что можно сделать автоматическую иньекцию малыми средствами, без зависимостей от других модулей. То, что вы назвали (чего нет) должны быть еще каждом своем одном модулле. Все. Если сверх того — это высокоуровневый говнокод.
                                                    0
                                                    сделать автоматическую иньекцию малыми средствами

                                                    Вот вам пример. Как вы организуете малыми средствами декорацию + автосвязывание? Или как вы организуете локальный бингдинг в пределах модуля.


                                                    Ну то есть оно и понятно что простые вещи можно делать просто. Более того, есть же pimple который хоть и не умеет автосвязывания, его можно допилить таким же стилем. Но суть компонентов типа auro.di или symfony/di — решить 95% юзкейсов возникающих в работе с контейнером зависимостей и предоставить возможность расширить поведение для решения остальных 5%.

                                                      0

                                                      Просто некоторые действуют по принципу «мне это не надо, значит это всё оверхед и куча мёртвого кода на много мегабайт» или «оно всё тормозит, а значит не нужно!!11». При этом пишут свои кривые поделки и считают себя дико умными. Соответственно либо не сталкиваются с задачами, где необходима «вся мощь», либо вообще не подозревают, что так можно, т.е. просто не в курсе, что такое DI, контейнеры, вот это всё...

                                                        –1
                                                        При этом пишут свои кривые поделки и считают себя дико умными.

                                                        А вот это уже не нужно обобщать :)
                                                          0

                                                          Очевидно, что вы — это http3. О ваших взглядах все уже в курсе)

                                                            +1

                                                            почему же, если брать в среднем то как раз таки про кривые поделки и идет речь. Я бы даже сказал подавляющее большинство.

                                                0
                                                Можете, пожалуйста, пояснить, что значит?
                                                программирование заменяется на сложное конфигурирование

                                                Буду очень благодарен, если можете привести простой пример кодом.
                                                  +2

                                                  Это когда вместо нескольких строк кода десятки строк XML. Погуглите по запросу code over configuration. Очень больная тема была во времена популярности grunt-ов всяких.


                                                  Как пример — опять же настройка пайплайна сборки билдов, сборки фронтэнда (grunt vs gulp, это сейчас вэбпаки всякие), например в assetic (интересно кто-то еще им пользуется?).


                                                  С DI контейнерами так же есть нюансы. Описывать зависимости в yaml или xml крайне неудобно.

                                                    0
                                                    Даже не знаю как продемонстрировать кодом — ведь конфигурация это как раз отсутствие кода, только данные. Без конфигов не обойтись и выходов может быть несколько:

                                                    — callback
                                                    — event
                                                    — перекрытие в наследнике метода
                                                    — возможность запросить и получить список не из жестко привязанного источника

                                                    Сами же можете придумать, как разрулить
                                                      0
                                                      Я могу привести пример, если позволите.

                                                      Плохо:
                                                      $rules = [
                                                        "deadline" => "required|numeric|after_timestamp:".$date
                                                      ];
                                                      


                                                      Хорошо:
                                                      if ( empty($this->deadline) ) {
                                                        yield new Exception('Empty column "deadline"');
                                                      }
                                                      if ( (new DateTime($this->deadline)) < (new DateTime($date)) ) {
                                                        yield new Exception('Invalid column "deadline"');
                                                      }
                                                      return true;
                                                      


                                                      Код условный, писал на калькуляторе.
                                                        0

                                                        «Плохо» смахивает на валидацию в Laravel)

                                                          0
                                                          Она и есть.
                                                          Ровно то, против чего я всегда выступал — использование конфигов и специфичных DSL вместо кода.

                                                          Пишите код, коллеги.
                                                          0
                                                          1. Второй код вполне может выполняться на основе первого.
                                                          2. Копипастить второй код в разные функции валидации плохо. Значит надо как-то обозначать, какие валидации из всех возможных нужны в этом объекте.
                                                            +2
                                                            Просто нужно перестать использовать примитивы и валидировать их на каждом шагу. Используйте объекты-значения и валидируйте данные в конструкторе такого объекта.
                                                            0

                                                            Правила валидации можно вынести в отдельный класс и реиспользовать столько сколько нужно. Такие валидаторы можно группировать из низкоуровневых правил в логические группы. Для этого очень хорошо подходит шаблон проектирования Спецификация.

                                                              0
                                                              Кто вам сказал про копи-паст? Напишите свой валидатор, инкапсулируйте в него все правила валидации и используйте. И никакого копи-паста.
                                                              +3
                                                              Тот случай, когда «плохо» очевидно лучше, чем «хорошо»
                                                                0
                                                                AlexLeonov, lavkasnov, Fesor cпасибо
                                                                  +1
                                                                  Хорошо:

                                                                  плохо потому что не скейлится. Нельзя делать композицию таких правил. Более того, невалидные данные — не исключительная ситуация. Во всяком случае с точки зрения компонента валидации. Для клиента, людей которые должны использовать ошибки валидации, важно не то что у них что-то не так а важно "что не так".

                                                                    –2
                                                                    Более того, невалидные данные — не исключительная ситуация

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

                                                                    Вы не обратили внимание разве на yield вместо throw перед тем, как повторять эту мантру? Условный валидатор генерирует последовательность ошибок валидации. И лишь вышестоящий код решает — (мульти-)исключение это или нет.

                                                                    Чтобы ему было проще, мы упаковываем ошибки в подходящий класс, реализующий Throwable. Захочет — бросит первую же ошибку, не захочет — соберет их все в мультиисключение и бросит все сразу, не захочет — обработает любым другим подходящим образом.

                                                                    Нельзя делать композицию таких правил

                                                                    Оу, как раз при таком подходе композиция элементарна. Что может быть проще, чем последовательно вызвать два-три-N генераторов?
                                                                      +1
                                                                      И никогда нет внятного обоснования — почему.

                                                                      У нас есть требуемое поведение — надо проверить валидны данные или нет, и если не валидны — где ошибки. Эта информация нужна клиенту что бы поправить данные.


                                                                      Соответсвенно с точки зрения объекта, который производит валидацию, его задача на самом деле не убедиться что данные валидны, а собрать ошибки. И данные будут считаться валидными только если ошибок нет, но это решение будет принимать уже пользователь валидатора.


                                                                      К примеру у меня был интересный случай. Есть запрос от пользователя который включает в себя какие-то данные по стоку (грубо говоря остаток на складе). Эти данные формируются на клиенте исходя из последних записанных результатов и того что вводит пользователь.


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


                                                                      В этом случае "ошибки" это такие же данные как и все остальные.


                                                                      Чем же исключения отличаются от "ошибок". Вопервых исключения это внутренний механизм языка. Их нужно использовать если вам важно:


                                                                      • обеспечить всплытие ошибок по стэку вызовов
                                                                      • сохранить точку где произошла ошибка (стэк трэйс)
                                                                      • неявный выход из функции (что есть сайд эффект)

                                                                      Нам же нужен объект который:


                                                                      • хранит информацию о том что не так с данными
                                                                      • хранит путь в массиве данных (где именно что-то не так)
                                                                      • желательно хранить список таких ошибок с сохранением иерархии. То есть дерево ошибок.

                                                                      Почему PHP разработчики так любят исключения? Потому что модель выполнения позволяет делать любой трэш и все всеравно будет хорошо. Незахэндленные исключения за них обработают фреймворки или просто дефолтный обработчик ошибок PHP.


                                                                      Если есть возможность избежать появления сайд эффектов, нужно этой возможностью пользоваться. Это очень сильно уменьшает сложность кода на всех уровнях.


                                                                      Захочет — бросит первую же ошибку, не захочет — соберет их все в мультиисключение и бросит все сразу

                                                                      продемонстрируйте.


                                                                      Оу, как раз при таком подходе композиция элементарна. Что может быть проще, чем последовательно вызвать два-три-N генераторов?

                                                                      приведите пример как вы будете делать что-то подобное:


                                                                      use Symfony\Component\Validator\Constraints\{
                                                                          NotBlank, Collection, Type, Optional
                                                                      };
                                                                      use App\Catalog\Constraints\{AvailableProduct};
                                                                      
                                                                      $productUpdateRules = new Collection([
                                                                         [
                                                                             'name' => [new NotBlank(), new Type('string')],
                                                                             'quantity' => new AvailableProduct(),
                                                                             'description' => new Optional([new NotBlank(), new Type('string')]),
                                                                         ]
                                                                      ]);

                                                                      что-то типа такого. А потом сравним по различным параметрам различные подходы.

                                                                        0
                                                                        продемонстрируйте

                                                                        См. следующую статью: https://habrahabr.ru/post/328080/

                                                                        Я уважаю ваше мнение и не буду с вами спорить. Но для себя реализовал другой подход и с удовольствием им пользуюсь.

                                                                        Попробуйте понять и альтернативную точку зрения. В ней нет ничего ужасного.
                                                          +1

                                                          В Питоне с этим переборщили, и используют всякие конвенции для private переменных. Причем в результате этот принцип нарушается, так как конвенции это неявная вещь, которая не прописана в коде. Так что везде нужна мера, и основная мера это удобство и понятность. Потому я и спросил, что предлагается взамен.

                                                            0
                                                            Предлагается писать код. Если вы хотите присвоить значение свойству, где-то должно быть написано $obj->prop = 'value'

                                                            Я не согласен с мифическим «удобством» в качестве меры качества кода. Код должен быть однозначным, читаемым, понятным, целесообразным, минимально необходимым и так далее. Но удобным? Нет, не думаю.
                                                              0
                                                              удобный — делающий что-либо приятным, легким в осуществлении чего-либо; уместный, подходящий для чего-либо

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

                                                                0
                                                                «удобством» в качестве меры качества кода

                                                                Когда речь идет о конвенции на уровне языка, это нормально так как все просто знают об этом. Это не какая-то выдумка на уровне фреймворка. Правда тут есть маленький нюанс — этот конвеншн никак не влияет на поведение. Это только для того что бы дать понять разработчику мол "вот эта штука — деталь реализации, а не часть публичного интерфейса".

                                                              +2

                                                              Пока что у вас в коде магии еще больше чем в Yii. get-, set-, validate-, sanitize- методы, которые объявляются в объекте, а вызываются магически при установке свойства. "Стандартный" класс объектов, который имеет и подсчет количества и сериализацию в JSON и много чего еще. Куча трейтов разной вложенности, которые мешают друг другу методами, которые все идут в результирующий объект. Какая-то магия с debug_backtrace при получении свойства. Как-то слишком много неявной автоматики.

                                                                0
                                                                Ваше мнение будет учтено в следующих версиях библиотеки. Спасибо.
                                                                +1
                                                                Иногда массивы параметров, обрабатываемые стандартным для фреймворка документированным кодом, гораздо лучше, чем 15 вариантов «явного кода», написанного 15ю разными разработчиками, в соответствии с 15ю разными жизненными философиями и стадиями ООП головного мозга.
                                                                Касаемо сложных систем, как только вы изобретете найдёте свой DI фреймворк и качественно выделите Composition root системы, не станет ровно никакой разницы, кодом вы инициализируете свои конструкторы или набором конфигурирующих параметров.
                                                                  +1
                                                                  DI — это просто один из вариантов композиции компонентов приложения. Фреймворк должен предоставить вам способ это сделать, конечно же. Но я не считаю, что DI — панацея, которая делает ваш код плохим.

                                                                  Код плохим делает нежелание писать код.
                                                                    +1
                                                                    Чорт, читать как «не считаю, что DI — панацея, которая делает код хорошим».

                                                                    Я буду 10 раз перечитывать комментарий перед отправкой!
                                                                      0
                                                                      Не панацея, но весьма удобный подход.
                                                                  +1
                                                                  Код лучше массивов параметров.

                                                                  Я б даже сказал, месива :)

                                                                    +1
                                                                    Код лучше массивов параметров.

                                                                    Нужно просто понимать, что обобщать, а что не обобщать. :)
                                                                    +1

                                                                    Жесть какая) А аргументы будут? У нас же тут обсуждение, разве нет?


                                                                    Я не предлагаю все трейты заменить на поведения. Но есть моменты, где поведения удобнее. Да, не в последнюю очередь это связано с архитектурой Yii, со всеми ее недостатками. Потому я и спросил, как аналогичный результат будет достигаться с учетом архитектуры этого фреймворка. И да, ответ "будет кодом, покажу потом" меня не устраивает. Потому что кодом можно написать по-разному, и объявление массива это тоже код.

                                                                      0
                                                                      Но есть моменты, где поведения удобнее

                                                                      «Удобство» в данном конкретном случае не есть критерий качества кода.

                                                                      ответ «будет кодом, покажу потом» меня не устраивает

                                                                      Я вам уже неоднократно ответил.

                                                                      Результат, аналогичный показанному вами поведению, достигается строчкой
                                                                      $model->updated = date('Y-m-d H:i:s')
                                                                      где-то в коде соответствующего процесса.
                                                                        +1

                                                                        Я не рассматривал какой-то конкретный случай. Удобство создания кода с заданным поведением и внесения в него изменений это один из главных критериев разработки. За исключением каких-то специализированных случаев типа оптимизации по производительности.


                                                                        где-то в коде соответствующего процесса

                                                                        Вот меня и интересует, где это "где-то" будет, с учетом методов организации кода и работы с БД, и насколько этим будет проще управлять. И повторю, вопрос касается не только ORM, а вообще добавления любой функциональности, которая отличается только параметрами.

                                                                          0
                                                                          Вот меня и интересует, где это «где-то» будет

                                                                          В коде бизнес-процесса.
                                                                          Контроллер принимает запрос (request) и видит параметры окружения, запускает соответствующий процесс или цепочку процессов, собирает ответ (response).
                                                                          Где-то в одном из ваших бизнес-процессов, Michael. Сложно сказать точнее.
                                                                            +1

                                                                            М? Ну так метод behaviors() это тоже часть бизнес-процесса. В чем разница?

                                                                              –2
                                                                              Разница в том, что поведение модели не есть часть БП.
                                                                                +1

                                                                                А чего это тогда часть? Инфраструктуры? Или стека TCP/IP?
                                                                                Поведение модели это часть бизнес-логики и бизнес-процессов в этой логике. И вопрос-то не в этом, а в повторном использовании кода. В контроллерах тоже есть повторяющийся код, который можно вынести в трейты или поведение. Но ок, я понял, что примеров пока не будет.

                                                                                  +3
                                                                                  В контроллерах тоже есть повторяющийся код, который можно вынести в трейты или поведение.

                                                                                  Перестаньте выносить повторяющийся код. Дублирование кода — это нормально. Особенно в контроллерах.


                                                                                  Когда мы говорим про DRY многие забывают про Try. Далеко не все дублирование нужно устранять. В целом мотивация этого действа весьма простая — если в коде будут баги и этот код дублируется — то надо править в нескольких местах. Однако с другой стороны, когда речь идет про такие вещи как контроллеры, которые декларируют последовательность действий, очень удобно когда весь флоу прописан последовательно и прочитать его можно без прыжков между файлами. А еще веселее становится после того, как через месяц после устранения дублирования вдруг оказывается что "некоторые штуки то оказывается были просто похожи но не являлись дублированием". И разворачивать всю эту штуку уже не так приятно. Та же история и с "поведениями" для Yii. Они конечно здорово и весело, но при определенном масштабе создают сложности для понимания кода.


                                                                                  Так что перед тем как устранять дублирование такими примитивными механизмами как трейты, следует задуматься:


                                                                                  • А не вытекла ли у меня логика случайно из какого-то объекта? Может она должна быть где-то инкапсулирована?
                                                                                  • А не проще ли мне вынести эту логику в какой-то отдельный объект, который будет медиатором между той и этой штукой (например между контроллером и моделью данных, или мидлвари, или еще чего).
                                                                                  • А как много дублирования? одно и то же в двух местах? не, пока рано что-то с этим делать. Добавлю пометку на будущее а если надо будет править буду уже думать.
                                                                                    +1

                                                                                    Ну вот мы подумали и решили вынести. И код везде одинаковый, за исключением какого-нибудь названия. Кстати, поведение это и есть отдельный объект) Просто композиция нестандартная.


                                                                                    Вы все правильно говорите, это надо различать. И хороший способ это представлять в динамике. Если я изменю тут, там надо будет синхронно менять или нет? Зависит ли это от сторонних условий? А если требования поменяются, все равно надо будет вместе менять?

                                                                                      0
                                                                                      поведение это и есть отдельный объект) Просто композиция нестандартная.

                                                                                      которая делает код не кохисив в случае имплементации в Yii.


                                                                                      А если требования поменяются, все равно надо будет вместе менять?

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

                                                                          +1
                                                                          Результат, аналогичный показанному вами поведению, достигается строчкой
                                                                          $model->updated = date('Y-m-d H:i:s')
                                                                          где-то в коде соответствующего процесса.


                                                                          Ну или в нескольких местах… наверное…
                                                                          0
                                                                          Но есть моменты, где поведения удобнее.

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

                                                                            0
                                                                            Ага.
                                                                            И делает фактически невозможной сколько-нибудь осмысленную отладку.
                                                                              +1

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

                                                                      +2

                                                                      Судя по перечню, вы находитесь под впечатлением yii1. Во второй версии хлебные крошки и другая презентационная обвеска к контроллеру отношения не имеют. Также есть возможность заменить все и вся, через DI контейнер и сервис-локатор. Базовый renderer меняется на twig одной строчкой в конфиге. Работа с несколькими БД, релейшены межу разными базами (например между mysql и монгой) уже есть, и с ленивой и с жадной загрузкой, как потребуется. Про поведения стоит понимать, что это, в первую очередь, обработчики событий объекта, связанные общей логикой одних бизнес-процессов, и собранные в один класс, который можно подключить через конфиг. И это трейтами не заменишь.

                                                                        +1
                                                                        у нас точно не будет никогда $this->breadcrumbs в контроллерах (!)

                                                                        В Yii они тоже не в контроллерах, если что...


                                                                        Например вы можете целиком заменить Renderer с нативного на другой, на базе Twig. Насколько я помню, в Yii это крайне сложно.

                                                                        Не верно. В Yii это в дизайне с самого начала. Более того, есть официальные реализации-примеры для Twig и Smarty.


                                                                        — Нет тяжести поддержки старых версий, сразу ориентируемся на 7.1, поэтому нет таких вещей, как «поведения», которые в общем-то в современном PHP не нужны

                                                                        7.1 никак с поведениями не связан. Альтернатива им — трейты. И то не полная. Есть плюсы и минусы.


                                                                        Мы сразу закладываем возможность работать с несколькими БД, включая даже возможность строить в рамках ORM relations (разумеется lazy load) между разными базами данных

                                                                        Есть в Yii и коробки.

                                                                      +2
                                                                      Ладно еще коллекции, но какой прок от объекта, которому динамически можно свойств накидывать? Чем вам тогда простой stdClass не подошел? Вы всеравно же не знаете какие в итоге свойства у итогового объекта.
                                                                        0
                                                                        Во-первых это chaining и то, что я называю innerCast. Обычный stdClass не умеет выстраивать цепочки свойств на лету и превращать «промежуточные» свойства в объекты этого же класса.

                                                                        Во-вторых управляемость. В базовом классе Std, например, можно задать список обязательных свойств и, если они будут отсутствовать при создании объекта — возникнет ошибка.

                                                                        Далее перехват присваивания, валидация и санитация данных, которые вы передаете в свойства. Умный конструктор и умный merge(), которые умеют собирать все ошибки валидации в коллекцию ошибок.

                                                                        Всё это проще сразу заложить в базовый класс. И потом расширять, при необходимости.

                                                                        P.S. Можете почитать код тестов, например https://github.com/RunnMe/Core/blob/master/tests/Core/StdTest.php и https://github.com/RunnMe/Core/blob/master/tests/Core/StdGetSetValidateSanitizeTraitTest.php — там многое написано понятнее, чем я рассказываю ))
                                                                          +1
                                                                          Под chaining вы понимаете fluent interface? Если так, то место ему в билдерах да коллекциях. И тащить наследование от базового класса только ради этого — глупо.
                                                                          Вы пишете что явное лучше неявного, но при этом под капотом у вас какая-то магия с innerCast.
                                                                          Ваш объект нарушает SRP, сочетая в себе и фабрику объектов, и сериалайзер, и валидатор.
                                                                            –2
                                                                            Фабрики объектов нет. Есть кастинг. Это раз.

                                                                            Валидации нет. Есть интерфейс для подключения валидаторов. Это два.

                                                                            Сериалайзер? Где? Вы про реализацию стандартного интерфейса из SPL? Для этого он и нужен, чтобы его реализовать.

                                                                            Следуя вашей логике и реализацию Countable можно признать нарушением принципа единой ответственности :)
                                                                              0
                                                                              Под chaining вы понимаете fluent interface?


                                                                              Не совсем. FI легко реализуется методами, которые заканчиваются на return $this;
                                                                              Я же имею в виду то, что в PHP штатными средствами легко сделать

                                                                              $arr = [];
                                                                              $arr['foo']['bar'] = 42;
                                                                              

                                                                              и это совершенно валидный код, но нельзя сделать:
                                                                              $obj = new SomeClass;
                                                                              $obj->foo->bar = 42;
                                                                              

                                                                              Мы этот недостаток в StdGetSetTrait исправляем. Коряво, но по-другому пока никак. Нужно готовить RFC для внесения в сам язык чего-то вроде нативного JSON, чтобы получить возможность создавать одной строкой объекты любой вложенности.
                                                                                0

                                                                                А чем плох вариант $obj->getBar()->setBaz($value)?


                                                                                Или же вы за полностью immutable подход? Если да, почему?

                                                                                  0
                                                                                  Или же вы за полностью immutable подход?

                                                                                  Нет. Не полностью. Я за такой подход там, где он оправдан. Например метод filter() в коллекции просто обязан возвращать новую коллекцию, иначе мы не сможем построить fluent interface.

                                                                                  А чем плох вариант $obj->getBar()->setBaz($value)?

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

                                                                                  Кстати, у вас в коде ошибка. Метод getBar() вернет значение свойства bar и дальше цепочка прервётся.
                                                                                    0

                                                                                    Нет, нет. Ошибки нет. Метод getBar() подразумевается, что вернёт объект, который содержит setBaz().
                                                                                    Это может как $this, так и this->propWithSomeBazSetterInterface


                                                                                    Надеюсь, смог донести до Вас свою мысль.

                                                                                      0
                                                                                      Я вас услышал. Для меня это ошибка. Ваш код нелогичен, метод $obj->getBar() должен возвращать нечто, что является 'bar' в составе $obj

                                                                                      Поэтому принять такое предложение не считаю возможным.
                                                                                        +1

                                                                                        А что здесь нелогичного? Классическая цепочка вызовов.
                                                                                        $obj имеет свойство bar которое содержит объект со своейством baz и сеттером для него.

                                                                                          0
                                                                                          $obj имеет свойство bar

                                                                                          Здесь нелогичность. В моем примере — не имеет. Оно создается на лету.
                                                                                            +1

                                                                                            В этом то и проблема что свойство создается на лету.
                                                                                            Классы не для того предназначены.

                                                                                              0
                                                                                              Вы можете не создавать. Я лишь даю вам такую возможность.
                                                                                      +3
                                                                                      Неплох.

                                                                                      Ну разве что мы нарушили закон Деметры и помохали ручкой инкапсуляции.

                                                                                    0
                                                                                    $arr['foo']['bar'] = 42;

                                                                                    $obj->foo->bar = 42;

                                                                                    Что люди не делают, лишь бы не использовать массивы. :)
                                                                                      0
                                                                                      Массивы не могут быть типизированы, к сожалению.
                                                                                        –1
                                                                                        Чтобы по пьяни не передать левую переменную? :)
                                                                                          0
                                                                                          Ну и чем тут поможет ваш аррай-лайк объект?
                                                                                          Вам всеравно нужно проверить, что свойство есть.
                                                                                          Да, вы можете указать реквайред свойства, но тчо мешает просто сделать обычный класс с передачей обязательных парамеров в конструктор?
                                                                                          0

                                                                                          Во славу type-safety и не такое сделаешь.

                                                                                  +2
                                                                                  Мне очень интересна ваша разработка, бегло просмотрел исходники. Какой стиль форматирования кода у вас? Зачем так много пустых строк? Ну это мелочи. Также почему не используете Psr\Container\ContainerInterface? В PSR мало интерфейсов, чтобы ими пренебрегать. А есть ли интерфейсы, которые вы хотели, чтобы они стали общепринятым стандарттом? Мне вот точно хотелось бы расширить PSR.

                                                                                  Что не увидел: DI, фабрики и как рулить их конфигами. Очень интересно было бы посмотреть ваш подход к этому. Насторожил синглетон в ядре.
                                                                                    –4
                                                                                    Контейнеры будут позже. А синглтона не бойтесь, в нем нет ничего страшного, просто дана эталонная реализация.
                                                                                      0
                                                                                      public function testDifferentInstances()
                                                                                          {
                                                                                              $obj1 = testClass1::instance();
                                                                                              $obj2 = testClass2::instance(1, -1);
                                                                                              $this->assertNotSame($obj1, $obj2);
                                                                                              $this->assertInstanceOf(testClass1::class, $obj1);
                                                                                              $this->assertInstanceOf(testClass2::class, $obj2);
                                                                                          }

                                                                                      Как вы тут скромно обошли проверку ->x и ->y, а ведь это самое интересное.
                                                                                      Вообще именно поэтому синглтон и считается анти-паттерном, что вызовы:


                                                                                      $obj1 = testClass1::instance(0, 0);
                                                                                      $obj2 = testClass2::instance(1, -1);
                                                                                      echo $obj2->x;


                                                                                      дадут нам совершенно неожиданный результат.


                                                                                      Мне кажется, что это нужно срочно отрефакторить и сингтон убрать.

                                                                                        –2
                                                                                        ну вот, первый ценный коммент на статью :))
                                                                                        спасибо!

                                                                                        P.S. я действительно тут скромно обошел, думаю, как лучше сделать. но вы, разумеется, правы.
                                                                                    +4
                                                                                    Благодатная идея объекта, состоящего из произвольных свойств, которые можно создавать и удалять «на лету», как элементы в массиве, приходит в голову каждому программисту на PHP.

                                                                                    Зачем? Пожалуйста, объясните зачем вы это делаете? Откуда в PHP эта «мода» делать из объекта массив?
                                                                                      0
                                                                                      Это наоборот: из массива объект. Мы любим массивы и хотим добавить к ним методы ))

                                                                                      На самом деле применений дальше будет множество.
                                                                                        +3
                                                                                        Мы любим массивы и хотим добавить к ним методы

                                                                                        т.е. сделать то, что и так уже есть в языке — объекты.
                                                                                        ArrayAccess входит в тройку самых ужасных для меня возможнойстей PHP: сразу за магическими __get, __set
                                                                                        и ReflectionProperty::setAccessible().
                                                                                        Код с применением указанных возможностей прекрасный способ усложнить себе и другим разработчикам жизнь.
                                                                                          0
                                                                                          В таком случае вы просто не любите PHP?
                                                                                            0
                                                                                            Я такого не говорил. Я говорил только о нескольких возможностях языка.
                                                                                            PHP начиная с версии 5.3 достаточно хорош, а с приходом 7.х еще лучше.
                                                                                              –1
                                                                                              Ну хорошо. А то уж я подумал вдруг ))
                                                                                      –1
                                                                                      начало выглядит неплохо, жду продолжения
                                                                                        +11
                                                                                        С таким уровнем магии более подходящим названием для фрейморка будет «Гарри Поттер». Вжух! И мы сделали из обьектов массив, теперь туда можно сваливать как в помойку любое количество данных создавая новые под-помойки на лету! Но через два часа программирования такими «обьектами» они превращаются в ружье и отстреливают фокуснику обе ноги.
                                                                                          +4
                                                                                          Посмотрел что у вас там дальше будет по циклу — веселье только начинается! Вот такая цепочка наследования…
                                                                                          SimpleValue implements \JsonSerializable
                                                                                          SimpleValueObject extends SimpleValue implements ValueObjectInterface
                                                                                          class IntValue extends SimpleValueObject
                                                                                          


                                                                                          чтобы реализовать Value Object который хранит одно число?

                                                                                          Я боюсь представить, сколько километров длинной будет цепочка наследования, когда дело дойдет до чего-то реально сложного.
                                                                                            –3
                                                                                            чтобы реализовать Value Object который хранит одно число?

                                                                                            Если в этом был единственный ваш вопрос, то ответ «да», именно так. Хранит в неизменном виде, позволяет создавать, валидировать при создании, не позволяет изменять ну и еще ряд полезных на практике возможностей.

                                                                                            А что?
                                                                                              +3
                                                                                              Класс сериализации… вы преподаете на этих примерах? Пожалуйста, скажите, что нет.

                                                                                              public function decode(string $data)
                                                                                                  {
                                                                                                      try {
                                                                                                          return eval('return ' . $data . ';');
                                                                                                      } catch (\ParseError $e) {
                                                                                                          throw new DecodeException($e->getMessage(), $e->getCode(), $e);
                                                                                                      }
                                                                                                  }
                                                                                              
                                                                                                0
                                                                                                Нет.
                                                                                                Это фактически заглушка, которая никогда не будет использоваться. Кроме как для зеленых тестов.

                                                                                                Если встретите где-то goto — сообщите сразу :)

                                                                                                Впрочем, как учебный пример — прекрасно. Сразу можно разобрать опасности такого подхода и показать на примере php-инъекцию.

                                                                                                P.S. Про библиотеку сериализации будет другая статья.
                                                                                                  +3
                                                                                                  Давайте дальше посмотрим, валидация…

                                                                                                  https://github.com/RunnMe/Validation/blob/master/src/Validation/Validators/IntValidator.php

                                                                                                  Зачем делать класс валидатор с состоянием, вынуждая создавать новый экземпляр на каждую валидацию?

                                                                                                  Почти все валидаторы можно выкинуть включив одну директиву strict types, которую я к своему удивлению не увидел ни в одном файле вашего фреймворка, заточенного строго под PHP 7.0+ и с таймпхинтингом повсюду.

                                                                                                  Правда очень странная ситуация, у вас есть большой опыт, преподаете, я хотел найти в коде что-то реально ценное, но вижу только сборник антипаттернов и непонятные тяжеловесные обертки над нативными возможностями языка, не добавляющие сверху ничего нового кроме дыр и хардкоженного подавления ошибок тут и там. От чего вы пытаетесь абстрагироваться таким образом? От самого PHP?
                                                                                                    –3
                                                                                                    Отвечаю на заданные вопросы.

                                                                                                    Зачем делать класс валидатор с состоянием, вынуждая создавать новый экземпляр на каждую валидацию?

                                                                                                    Состояние в данном случае — побочный эффект применения ООП и наследования. Расскажите, как сделать правильнее.

                                                                                                    От чего вы пытаетесь абстрагироваться таким образом? От самого PHP?

                                                                                                    Не сумел ответить. Ваш вопрос не содержит позитивного или негативного утверждения. Всё равно что спросить «а ваши родители знают, что вы гей?»
                                                                                                      +4
                                                                                                      Состояние в данном случае — побочный эффект применения ООП и наследования. Расскажите, как сделать правильнее.

                                                                                                      не использовать наследование?


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

                                                                                                    +2
                                                                                                    Сразу можно разобрать опасности такого подхода и показать на примере php-инъекцию.

                                                                                                    почему в ваших примерах нет ничего о IoC? Это одно из основных чему нужно учить студентов когда речь идет про архитектуру и фреймворки. Я вот студентам вот такую картинку показывал как противопоставление вот такой картине.


                                                                                                    Студентов не с php-инъекциями надо учить бороться, а объяснять им силу инкапсуляции и полиморфизма, проблемы связанности и преимущества зацепления… структурное программирование (и немного функциональное).

                                                                                                      0
                                                                                                      почему в ваших примерах нет ничего о IoC?

                                                                                                      Потому что статья не об этом.
                                                                                                      –1
                                                                                                      Если встретите где-то goto — сообщите сразу :)

                                                                                                      А что с ним не так?
                                                                                                        0
                                                                                                        Кто сказал «не так» кроме вас?
                                                                                                        Просто сообщите, пожалуйста. Это же очень интересно!
                                                                                                0
                                                                                                Но через два часа программирования такими «обьектами» они превращаются в ружье и отстреливают фокуснику обе ноги.

                                                                                                В ружье Чехова, которое выстрелит под конец — а именно на боевом сервере))
                                                                                                  0
                                                                                                  Если вы приведете мне конкретный пример — буду счастлив.
                                                                                                0
                                                                                                Это уже данность такая — любую статью про РНР начинать с нескольких абзацев извинений?
                                                                                                  0
                                                                                                  Мне показалось, что в праздничный вечер немного лирики не помешает. Вам помешало?
                                                                                                    0
                                                                                                    Хорошей лирики много не бывает!
                                                                                                  –13
                                                                                                  PHP хорош тем, что ему не нужен никакой фреймворк. То, для чего он предназначен, не требует фреймворков, потому что реализуется за день, без всяких ненужных абстракций.
                                                                                                  Теперь же php превратился в говнокод завернутый еще и в фреймоворк (который тоже часто состоит из говнокода), что только многократно все усложняет. Если в голове каша, никакой фреймворк не поможет. Поэтому и каждый берется за очередной «фреймворк», понимает что это пипец и… садится делать такой же пипец, только свой, из своей каши.
                                                                                                  Зачем все эти абстракции над и так уже хорошо работающими внутренними механизмами PHP?
                                                                                                  Самое печальное что теперь во все это верят и работодатели, подбирая людей под фреймворк, потом меняя фреймворк…
                                                                                                  Все мое личное имхо, и наблюдение, рад ошибаться
                                                                                                    +2
                                                                                                    Я думаю, что вы ошибаетесь.

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

                                                                                                    Другое дело, что пока что идеального фреймворка нет. Есть пара-тройка хороших да и только.

                                                                                                    А абстракции нужны затем, что так устроен наш, homo sapiens, способ мышления. Анализ, синтез, абстрагирование, обобщение, конкретизация…
                                                                                                      –9
                                                                                                      Адекватная точка зрения на хабре не приветствуется. :)
                                                                                                        +6

                                                                                                        Приветствуются адекватные доказательства своей точки зрения. Применительно к вашей точке зрения — код вашего фреймворка и проектов на нем написанных. А вам лень push на github сделать. Или стыдно, что более вероятно. Вот за бездоказательные утверждения сомнительных преимуществ вас и минусуют, как и комментатора выше, а не за саму точку зрения.

                                                                                                          –2
                                                                                                          Какие преимущества? :)
                                                                                                          О чем речь? :)
                                                                                                      0
                                                                                                      Благодатная идея объекта, состоящего из произвольных свойств, которые можно создавать и удалять «на лету», как элементы в массиве, приходит в голову каждому программисту на PHP. И каждый второй эту идею реализует.

                                                                                                      И что же это, каждый второй не может использовать конструкцию ;$result = (object) $array &
                                                                                                        0
                                                                                                        Не совсем ясно, где у вас "&" и что конкретно этот символ обозначает?
                                                                                                          0
                                                                                                          Извиняюсь, это был знак вопроса
                                                                                                        +6
                                                                                                        Оххх. И вот, опять, кто-то написал Фреймворк с ощущением, что всем не пофигу на него. Есть фреймоврки с большими сообществами, которые, как минимум могут нормально сформулировать свои конкурентные преимущества, сильные и слабые стороны. Фреймворк ради фреймворка это какая-то дичь, как по мне, если это не делалось в учебных целях(да, ваш делался и делается, но зачем каким-то широким массам показывать?). Нет у программиста качества хуже, чем изобретение велосипеда без видимых на то причин. Непонравился Yii2? Ну посмотрите Symfony, Zend, Laravel, Phalcon. НЕТ! ЗАЧЕМ? Будем городить еще кучу велосипедов.
                                                                                                        Я уж не говорю о том, что вы НЕ поняли разницу между Value Object и Entity судя по вашему же репозиторию ValueObjects. Особенно позабавило: `$object = $entity->toValueObject();`. Очень странная и неочевидная структура внутри ваших библиотек. Объекты, интерфейсы, исключения, люди, кони, львы! Все смешалось в одном namespace.

                                                                                                        Не поймите меня неправильно, я бы, наверное, написал бы куда более мягкий и воодушевляющий комментарий к вашему творению, если бы вы написали, так, мол и так, учебных целей для делаю свой Фреймворк, ищу помощи от сообщества, оцените, пожалуйста! Ну или что-то в таком духе. Но нет! Вы учите людей, заявляете, что это все проверено в «боевых проектах» и вообще все довольно шоколадно. Но я должен констатировать, что использование ваших подходов в крупных проектов приведет к скорому краху, поскольку у вас есть явное недопонимание тех вещей, которые вы пытаетесь использовать, либо внедрить.

                                                                                                        Вы говорите о каком-то там архитектурном превосходстве над каким-то из популярных фреймворков, хотя допускаете в своем ядре такие вот вещи:
                                                                                                        https://github.com/RunnMe/Core/blob/master/src/Core/Std.php

                                                                                                        В общем, вы сам все написали в начале, я просто оставлю этот комментарий здесь и надеюсь в ответ от вас услышать ответ на вопрос: «В чем разница между Entity и ValueObject и почему код, который я привел выше — абсурд?».
                                                                                                        Если вы с самого начала вместо бетона используете говно и палки и при этом заявляете, что ваше здание в архитектурном плане лучше, чем Empire State Building — какой реакции от сообщества Вы ждете?

                                                                                                        Все-таки, посмотрите на ядра Symfony, Zend, Laravel, Phalcon и как они устроены, а потом ответьте себе на вопрос: «Стоит ли использовать говно и палки для строительства, когда у вас есть бесплатные пеноблоки?». Меня очень смутил тот момент, что вы учите программировать… Где Pull-request? Come Review? Come Discussion? Project roadmap? Contribution guide? Architecture notes? Да банально описание проекта, или хотя бы понятные комментарии в коде?

                                                                                                        Еще раз прошу прощения, но не я написал эту статью.
                                                                                                          +1
                                                                                                          > Come Review? Come Discussion?

                                                                                                          Code само собой) Т9…
                                                                                                            –5
                                                                                                            НЕТ! ЗАЧЕМ?

                                                                                                            Это внутренняя потребность творить. Разве вам она не знакома?

                                                                                                            вы НЕ поняли разницу между Value Object и Entity

                                                                                                            В данной статье мы не обсуждаем библиотеку ValueObjects. Впрочем, если вам хочется — пожалуйста. Но конструктивное обсуждение будет в статье, посвященной именно ей.

                                                                                                            если бы вы написали, так, мол и так, учебных целей для делаю свой Фреймворк, ищу помощи от сообщества, оцените, пожалуйста!

                                                                                                            Я не ищу помощи. Я буду ей благодарен, но не ищу. Особенно я не ищу помощи от тех, кто пишет «фреймоврки», «Непонравился», «Come Review»

                                                                                                            Еще раз прошу прощения

                                                                                                            Вам не за что просить прощения. Вы просто высказали своё мнение. Спасибо. Любое мнение ценно.

                                                                                                            P.S. Зачем всё время «Фреймворк» с большой буквы? Это имеет какой-то смысл?
                                                                                                              +1
                                                                                                              P.S. Зачем всё время «Фреймворк» с большой буквы? Это имеет какой-то смысл?


                                                                                                              Т9, я сразу-же в ответе написал.

                                                                                                              Это внутренняя потребность творить. Разве вам она не знакома?


                                                                                                              Внутреннюю потребность творить лучше направить на что-то полезное не одному только Вам, Вы так не считаете?

                                                                                                              Я не ищу помощи. Я буду ей благодарен, но не ищу. Особенно я не ищу помощи от тех, кто пишет «фреймоврки», «Непонравился», «Come Review»


                                                                                                              То, что я пишу комментарии на Хабре с включенным Т9, который пока что работает совершенно непонятным для меня образом, никак не говорит обо мне, как о программисте, не так ли? Вы же тимлид, должны понимать что имеет значение, а что нет. А если для вас важно именно это, а не то, что я пытался донести в своем комментарии, то больше мне сказать нечего ;)

                                                                                                              Я не ищу помощи. Я буду ей благодарен, но не ищу.

                                                                                                              А какая цель публикации? Чего Вы хотели ей добиться?
                                                                                                                –7
                                                                                                                Внутреннюю потребность творить лучше направить на что-то полезное не одному только Вам, Вы так не считаете?

                                                                                                                Я именно так и считаю. Иначе бы не писал это статью.

                                                                                                                А какая цель публикации? Чего Вы хотели ей добиться?

                                                                                                                Чистое, незамутненное творчество. Чего пытался добиться Малевич, выставляя «Черный квадрат»? Я не знаю, но предполагаю, что однажды творчество превращается в потребность. У вас не так?

                                                                                                                То, что я пишу комментарии на Хабре с включенным Т9

                                                                                                                Где хоть вы его откопали? У вас реально что-то вроде Siemens S45?

                                                                                                                никак не говорит обо мне, как о программисте, не так ли?

                                                                                                                Хрен знает. Общее впечатление составляет. Неаккуратненько (с).

                                                                                                                больше мне сказать нечего

                                                                                                                Хорошо.
                                                                                                          +1
                                                                                                          Буханка троллейбус jpg
                                                                                                          :)
                                                                                                            +3
                                                                                                            Фабиену и Тейлору кто-то точно также говорил :)

                                                                                                            А уж что говорили Расмусу — я не могу написать по цензурным соображениям!
                                                                                                              +1
                                                                                                              Не слушайте никого, делайте что душа просит! :)
                                                                                                              Просто не понял зачем. Зачем делать «все массивами» и т.п. Любой фреймворк имеет право на существование. Буду следить за продолжением. :) Надо только еще понять, как это все применить. Надеюсь в следующих сериях картина прояснится.

                                                                                                                –1
                                                                                                                Просто не понял зачем

                                                                                                                Вы не поняли. Не поняли зачем.
                                                                                                                Честно — не знаю, что вам ответить. Ну ОК, постарайтесь понять :) Спросите, если что будет непонятно, хорошо?
                                                                                                                  +9

                                                                                                                  Постарайтесь объяснить какие именно характеристики фреймворка были вам важны когда вы принимали такие решения. Это всегда интересно.

                                                                                                                    +1
                                                                                                                    Ну ОК, постарайтесь понять :)


                                                                                                                    Так мы тут все это и пытаемся понять, а вы отвечаете только в духе «Захотелось». Ну, ок, но я же не пишу статью на хабре о том, что мне захотелось сегодня съесть борща. Пока что из Ваших же ответов следует, что вы делаете фреймворк ради того, чтобы сделать фреймворк. Понимаете, есть разница между «прыгнуть ради того, чтобы прыгнуть» и «прыгнуть, для того, чтобы запрыгнуть куда-то\перепрыгнуть что-то».
                                                                                                                      0
                                                                                                                      Так вы не задали ни одного вопроса же!
                                                                                                                      Если бы был вопрос — был бы ответ.
                                                                                                                        +3
                                                                                                                        Так вы просто игнорите вопросы) Давайте напомню:

                                                                                                                        Фреймворк ради фреймворка это какая-то дичь, как по мне, если это не делалось в учебных целях(да, ваш делался и делается, но зачем каким-то широким массам показывать?


                                                                                                                        Стоит ли использовать говно и палки для строительства, когда у вас есть бесплатные пеноблоки?


                                                                                                                        Постарайтесь объяснить какие именно характеристики фреймворка были вам важны когда вы принимали такие решения. Это всегда интересно.


                                                                                                                        Просто не понял зачем. Зачем делать «все массивами» и т.п.


                                                                                                                        Мне продолжить искать вопросы, оставшиеся без ответа в ветках, которые не являются прямыми соседями этой, или этого хватит?
                                                                                                                          –5
                                                                                                                          зачем каким-то широким массам показывать?

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

                                                                                                                          Стоит ли использовать говно и палки для строительства, когда у вас есть бесплатные пеноблоки?

                                                                                                                          «Ваши родители знают, что вы — гей?» Мы в детстве тоже баловались такими же «вопросами», ага ))

                                                                                                                          Постарайтесь объяснить какие именно характеристики фреймворка были вам важны когда вы принимали такие решения. Это всегда интересно.

                                                                                                                          Нет вопроса. Есть пожелание. Пожелание принимается — будет серия статей.

                                                                                                                          Просто не понял зачем. Зачем делать «все массивами» и т.п.

                                                                                                                          Нет вопроса. Есть констатация вашего непонимания.
                                                                                                                            +2
                                                                                                                            Вы считаете, что вопрос характеризуется исключительно знаком вопроса в конце предложения? Яснопонятно.

                                                                                                                            Ну тогда вот вам прямой вопрос, который задавлся выше:

                                                                                                                            ЗАЧЕМ?


                                                                                                                            Вы постоянно просто уходите от ответов, выкручиваетесь и юлите. Дело ваше, конечно, но конструктивную беседу таким образом не выстроить.
                                                                                                                              –3
                                                                                                                              ЗАЧЕМ?


                                                                                                                              Господь с вами, я вам уже раза три на этот вопрос ответил. Что же мне сделать, если вы прочесть ответ не можете?

                                                                                                                              Еще разик давайте, мне же не сложно: затем, что могу. Мне так захотелось. Не вижу причин не публиковать, ведь публикацией и обсуждением я не нанес никому ущерба, не так ли?
                                                                                                                                +3
                                                                                                                                У меня с мыслительными процессами сегодня туго, так что на всякий случай еще раз для себе уточню в последний раз, тем более, вам не сложно)

                                                                                                                                То есть мы имеем фреймворк, написанный ради того, чтобы написать фреймворк и статью, написанную ради того, чтобы написать статью. Я все правильно понял? Ничего не упустил?
                                                                                                                                  –1
                                                                                                                                  Неверно.

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

                                                                                                                                  Написана библиотека ради того, чтобы собрать в одном месте и в одном стиле ряд накопившихся за многие годы решения. И благодаря тому, что я могу и хочу это сделать.

                                                                                                                                  Статья написана для того, чтобы показать сообществу библиотеку. И опять же благодаря тому, что захотел написать.

                                                                                                                                  Если перефразировать так — то вы ничего не упустите.
                                                                                                                                    +1
                                                                                                                                    Как это коррелирует с Вашими предыдущими ответами на те же самые вопросы? Вы так гордо и высокомерно отвечали сначала одно, теперь говорите совершенно другое. Где же правда-то в итоге?
                                                                                                                                      0
                                                                                                                                      Не готов вам ответить на вопрос. Не думаю, что он вообще требует ответа.

                                                                                                                                      Вы находите какую-то «гордость» и «высокомерие» в каких-то совершенно технических текстах. Я не умею общаться в таком ключе, извините.

                                                                                                                                      Мне интереснее обсуждать код, а не те эмоции, которые у вас он вызывает.
                                                                                                                                        +1
                                                                                                                                        От обсуждение кода Вы точно так же уходите.
                                                                                                                                        Отбросьте из моего поста слова «так гордо и высокомерно» и ответьте, пожалуйста, на поставленный вопрос. Так-то он имеет прямое отношение к коду. А вы опять убегаете от ответа.

                                                                                                                                        Как это коррелирует с Вашими предыдущими ответами на те же самые вопросы? Вы отвечали сначала одно, теперь говорите совершенно другое. Где же правда-то в итоге?
                                                                                                                                          –1
                                                                                                                                          Оставлю вас в вашем собственном мире, где «гордость», «высокомерие», «убегают от ответов», а вы рыцарь на белом коне, несущий правду. А сам останусь в скучном мире программирования ))

                                                                                                                                          Однако с удовольствием отвечу вам на конкретные вопросе о коде данной библиотеки. Если я какие-то из них пропустил — не сочтите за труд повторить, пожалуйста.
                                                                                                                                +4
                                                                                                                                я вам уже раза три на этот вопрос ответил.

                                                                                                                                Вы сказали что вам "захотелось". Вы опубликовали. Только читателям тоже надо дать какую-то мотивацию разбираться в том что вы придумали. Вдруг у вас что-то интересное, а тем самым вы отбиваете у читателя желание разбираться. Зачем? Прост.

                                                                                                                          +2

                                                                                                                          Вы так и со студентами? Был задан вполне конкретный вопрос:


                                                                                                                          Зачем делать «все массивами» и т.п.

                                                                                                                          Ответили бы что мол "есть разница между массивами и коллекциями", что мол все ради type safety, что null-object-ы вместо неопределенностей… Вы же ответили "постарайтесь понять".

                                                                                                                +1
                                                                                                                Автору следует посмотреть сюда — https://github.com/auraphp потому что
                                                                                                                Делаем его слабосвязанным набором библиотек, так, чтобы каждую либу можно было подключить и использовать отдельно.
                                                                                                                Стараемся сохранять здоровый минимализм там, где это возможно
                                                                                                                Сам каркас для веб- и консольных приложений — тоже одна из библиотек, тем самым мы избегаем монолитности.
                                                                                                                Стараемся не изобретать велосипеды и максимально сохраняем те подходы и тот код, которые уже зарекомендовали себя в T4.
                                                                                                                Отказываемся от поддержки устаревших версий PHP, пишем код под самую актуальную версию.
                                                                                                                Стараемся делать код максимально гибким. Если можно — вместо классов и наследования используем интерфейсы, трейты и композицию кода, оставляя пользователям фреймворка возможность заменить эталонную реализацию любого компонента своей.
                                                                                                                Покрываем код тестами, добиваясь 100% покрытия.

                                                                                                                все там уже есть
                                                                                                                А чего нет — можно взять компоненты Symfony, Zend, Laravel и кучу нужных библиотек
                                                                                                                  0
                                                                                                                  Автор (и авторы) внимательно смотрели туда. Однако пока что ни один коммент на хабре не заставил их заплакать и отказаться от развития своих библиотек. Наверное, в этом что-то есть?
                                                                                                                    0
                                                                                                                    если какую-либо задачу ваши библиотеки позволят решить быстрее и эффективнее чем существующие инструменты — то почему бы и нет
                                                                                                                    правда пока что этого особо не видно — нет примеров реальных приложений, лично я пока не могу представить где ваши творения использовать
                                                                                                                      –2
                                                                                                                      лично я пока не могу представить

                                                                                                                      Остаётся только надеяться, что однажды сможете!
                                                                                                                  +1

                                                                                                                  Да, возможно написать свой framework хорошо, в данном случае для Вас.
                                                                                                                  Вы узнаете много нового, от коллег по цеху и с юмором будете вспоминать этот пост через месяц другой.


                                                                                                                  Но сейчас, из представленной статьи, мне кажется, что Ваш проект не столько сырой, сколько не полностью продуман в вопросе "зачем делать ТАК" и "какие уже существуют альтернативы и готовые решения"


                                                                                                                  В одном из комментариев Вы чуть-чуть наезжаете на Yii2. Скажу честно, что у меня самого в закромах есть статья которая сравнивает Yii2 и Symfony, причём не в пользу первого.
                                                                                                                  Я исправлял её уже очень много раз и изучал все моменты, и именно поэтому статья не опубликована и не никогда не будет. Это слишком разные проекты.
                                                                                                                  Да, мне не нравится ActiveRecord, но я стараюсь найти обходные пути или просто следовать best practices, т.к. это только часть фреймворка, так же как и поведения (мне они тоже не по душе).


                                                                                                                  Попробую посоветовать Вам поработать с разными языками: Java, Python, c++. У каждого свой подход, свои плюсы, минусы, ниши. Возможно, после code review от специалистов в этих языках Вы сможете более точно понять их назначение и область применения, равно как и PHP и ниши, на которые может быть нацелен Ваш Фреймворк.


                                                                                                                  В любом случае желаю Вам успеха и профессионального роста!


                                                                                                                  P.S. Прошу прощения за возможные грамматические и орфографические ошибки — пишу с телефона, перед сном, после кружки средства от простуды =)

                                                                                                                    –3
                                                                                                                    Не извиняйтесь за ошибки, все мы люди, все ошибаемся.

                                                                                                                    В одном из комментариев Вы чуть-чуть наезжаете на Yii2

                                                                                                                    Наезжаю? Вы шутите? Я считаю его примером анти-дизайна и анти-проектирования, и как подобный пример всегда подаю студентам.
                                                                                                                    Это настолько нелепая архитектурная конструкция, что даже не знаешь, с чего и начать его разбор :) Наверное с самого факта его существования :)
                                                                                                                    • UFO just landed and posted this here
                                                                                                                        0
                                                                                                                        нескольких крупных проектах

                                                                                                                        Мне просто для статистики, как вы "меряете" размеры проекта?

                                                                                                                          +1
                                                                                                                          Дело известное, берешь линейку, берешь свой проект, проект своего соседа и замеряешь. Бездуховно это только…
                                                                                                                    +13

                                                                                                                    Что отпугивает сразу:


                                                                                                                    • полное отсутствие вменяемой документации. Без этого можно забыть даже о каком-либо успехе.
                                                                                                                    • Ваши коллекции не скейлятся. Просто ненужные элиасы для массивов (вроде uksort) без возможности добавить новые методы, даже нет попыток как-то улучшить API на который так жалуются пользователи.
                                                                                                                    • Вы упомянули и не раз что Yii это пример анти-проектирования, однако в вашем коде практически везде поощряется расширение за счет наследования. Как по мне это самый жирный минус Yii (с остальными можно мириться) который перекочевал к вам.
                                                                                                                    • количество бесполезного кода зашкаливает. В частности в библиотеке с VO.
                                                                                                                    • компонент валидации содержит помимо валидации еще и санитайзинг. Причем это просто ненужная объектная обертка над filter_var. Она не дает никаких преимуществ, мы ни композиции правил построить толком не можем ни что-либо переопределить толком. Та же история и с валидаторами — выглядит неюзабельным.
                                                                                                                    • компонент для работы с файлами… не понятно почему File мутабелен. Опять нет четкого разделения ответственности. работа с файлами почему-то смешана с сериализацией, непонятно зачем. Забили на инкапсуляцию.

                                                                                                                    Словом вы выложили в опенсурс то что используете сами и пользуетесь только вы (если вообще используете). Работы над грамотным проектированием не производилось — на вид стихийное решение ваших прикладных проблем без оглядки и анализа существующих решений. Судя по состоянию репозиториев это что-то типа "ну мы тут с пивом собрались на выходных и решили запилить фреймворк".

                                                                                                                      0
                                                                                                                      Вот, наконец-то, официальный релиз )))
                                                                                                                        –3
                                                                                                                        После того как я открыл для себя Phalcon — на другие фреймворки даже не смотрю, фундаментально другой подход в компиляции сделал для меня погоду. Все фреймворки делают одно и тоже, зачем углубляться так глубоко в встроенные методы фреймворка, по сути нужен роутинг и структура для правильной организации кода. Чей фреймворк быстрее — тот я и использую со своими библиотеками.

                                                                                                                          +4
                                                                                                                          на другие фреймворки даже не смотрю

                                                                                                                          А зря. У разных проектов есть разные нужды, которые разные фреймворки удовлетворяют по-разному, понимаете о чем я? Бывает очень удобно настрочить очередную безумную идею на Laravel. Бывает, нужна гибкость Zend Framework, иногда фреймворк вообще ненужен.
                                                                                                                            0
                                                                                                                            Я понимаю о чем вы говорите, но я с вами не согалсен. Все относительно, я считаю, что большинство фреймворков имеют очень низкого качества встроенные методы и слишком универсальные.

                                                                                                                            Написать свой конструктор запросов займет — 2 дня с высокопроизводительными запросами. Например, мне нужно всего-лишь поменять названия функции $Sql->insert() на $Sql->insertInFile() и у меня будет вставка через LOAD FROM FILE csv (имею ввиду, что именно функция сама запишет массив данных в csv и загрузит его, вместо INSERT запросов), автоматическая, зачем мне фреймвокр и их непонятные 100-ые решения для CRUD

                                                                                                                            Фреймворк — это структура, если есть удобный Роутинг + Контроллер + Шаблон + Модель + Компонент — все, фреймворк можно использовать — любой.

                                                                                                                            Я выибарю Phalcon — потому что он скомпилирован как модуль к php, соотвественно не нужно комплировать php файлв фрейворка, что есть огромное преимущество для проектов, которые парятся о нагрузке.
                                                                                                                              0
                                                                                                                              Я себе еще сделал одно упрощение, которое тоже всем рекомендую. Все мои кастомные проекты API based. Даже если front-end на php шаблонировании. Сразу отпадает много вопросов выбора и появляются огромные возможности простейшого кеширования и ускорения.
                                                                                                                                +2
                                                                                                                                Написать свой конструктор запросов займет

                                                                                                                                А как вы будете разделять инфраструктуру от бизнес логики? Мне на самом деле интересно было бы послушать как люди организуют свой persistence layer. Используете ли вы DAO, мэпите ли результаты выборок на объекты для операций записи (на чтение пофигу, давайте только про выполнение бизнес-транзакций). Банальный пример. Есть у вас например необходимость сделать чатик на PHP (только запись и хранение истории сообщений), как бы вы организовывали следующую логику:


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

                                                                                                                                Желательно с хоть каким псевдокодом на gist. Реально интересно. Да, логика простая, но не хочу усложнять пример.


                                                                                                                                соотвественно не нужно комплировать php файлв фрейворка

                                                                                                                                А это простите зачем? Типа трюк с конкатенацией часто загружаемых файлов? Он не актуален с версии 7.0 при включенном opcache.

                                                                                                                                  0
                                                                                                                                  У меня это модель, где отдельная функция проверит связку пользователя и конверсейшена только по id через таблицу связей user_id conversation_id, после проверки — сообщение просто отпавлю в бд с данными после проверки прав. Вызываеть функции будет контроллер по очереди.

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

                                                                                                                                  0
                                                                                                                                  Вы серьезно сталкивались с проблемами производительности PHP на проектах с высокой нагрузкой? То есть вот прям именно не криворукий код, не работа с БД, не дебильные выборки и сортировки, а именно производительность PHP?

                                                                                                                                  Фреймворк — это структура


                                                                                                                                  Вы конечно правы, но у меня часто бывает так, что от фреймворка я беру отдельные компоненты, а вот структуру делаю свою. Ту, которая удовлетворяет потребностям проекта.

                                                                                                                                  В последнее время все чаще выбор падает на отказ от фреймворка вовсе. Благо, теже компоненты symfony прекрасно работают и без самого symfony)

                                                                                                                                  Но тем не менее, если завтра ко мне придут и скажут, что мне нужно сделать блоговый движок для нашей компании, то я лучше возьму и накидаю за пару часов что-то на Laravel. Если ко мне придут и скажут, что мне нужно напилить RESTFull API к существующей БД СРОЧНО, то наверное я возьму какой-нибудь Zend с Apigility и быстро решу поставленную задачу.

                                                                                                                                  Конечно, мои примеры высасаны из пальца, но это просто для удобства объяснения. И да, я работаю с проектами, которые довольно сильно парятся о нагрузке. И в тех местах, где это действительно важно на уровне языка программирования — мы просто не используем PHP, вот и все. Но в 99% случаев, проблемы с производительностью кроются вовсе не в PHP и какой-то там компиляции. Тем более, что есть opCache.
                                                                                                                                    –1
                                                                                                                                    Да, мои клиенты экономят сотни долларов на серверах, котому что они лажатся занчитель позже. У классических фреймворков такой же эфект как у Wordpres — серьезрый response delay под нагрузкой (у второго и без нагрузки) из-за огромног количества фреймворковских файлов. Есть бенчмарки, можете сравнить.

                                                                                                                                    — Вы абсолютно правы про криворукость запросов и именно такими их делают криворукие разработчики по документации того же Yii
                                                                                                                                      0
                                                                                                                                      У меня ваши поставленные задачи решены уже на одном фреймворке. Ведь эти сушности стары как мир, сколько можно под них подстраиваться, нужно ими управлять.

                                                                                                                                      Кстати php 7 очень быстрый, я тестировал на миллионом цикле с матиматикой и записью в массив. Проиграл 1-2 секунды C# и NodeJs и обошел Python на 30 секунд. (Тест конечно не супер лаборатоный), но меня порадовало, для меня больше важна скорость массивов и циклов.

                                                                                                                                      Ну я фанат универсальных решений и люблю php, у меня под php есть многоядерная библиотека на локальной машине так и по сети. Можно взять огромный массив и попросить обработать соседние сервера. Так что я немного больной в этом плане, потому я подгоняю все решения под «условную автоматику».
                                                                                                                                        0
                                                                                                                                        У меня ваши поставленные задачи решены уже на одном фреймворке. Ведь эти сушности стары как мир, сколько можно под них подстраиваться, нужно ими управлять.


                                                                                                                                        Я специально для вас сделал ремарку, что примеры высосаны из пальца. Само собой в реальности они совершенно другие, но я почему-то подумал, что вы сами сможете придумать себе пример. Если нет — дайте знать, выдам вам один из сотен «боевых» примеров.
                                                                                                                                        0
                                                                                                                                        Так разговор о фреймворке или криворукости разработчиков, не смешивайте теплое с мягким)

                                                                                                                                        экономят сотни долларов на серверах


                                                                                                                                        У меня есть очень большие сомнения в том, что вы когда-либо проводили тестирование вида: Ваше решение на Phalcon vs решение других ПРОФЕССИОНАЛОВ на любом другом фреймворке. Так что экономия тут — скорее ваша придумка, хотела и оправдание. Если уж говорить в таком ключе, то PHP вы вообще зря выбрали — не самый быстрый и надежный язык.
                                                                                                                                          0
                                                                                                                                          https://systemsarchitectdotnet.files.wordpress.com/2013/04/php-benchmark.png

                                                                                                                                          Быстро, чтобы не тратить время. Можно придиратья, но картина по дургим тестам такая же, то есть вы считаете, что такое количество запросов в секунду не на что не влияет и совершенно не помогает переживать те же DDOS, когда фильтры хостера бесполезны и вы фильтруете софтерно. Еще как.
                                                                                                                                            0

                                                                                                                                            Недостаток таких тестов в том, что они проводятся на hello world или на чем-то сильно примитивном.


                                                                                                                                            Do not trust benchmarks you didn't fake your self.

                                                                                                                                              0
                                                                                                                                              Вы считаете, что Hello word не достаточно? Это же первый вход — а дальше ваши кривые руки

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

                                                                                                                                              И вот вы все программисты и я не могу понять, почему вам не понятна разница самого факта, что Symfony — php, а Phalcon — C, то ест ьвы реально сравниваете доставку сервером php и скомпилированого C?
                                                                                                                                                +1
                                                                                                                                                Разговор был об экономии сотен нефти конечному заказчику. А из того, что вы скинули никак не следует то, что это позволяет хоть как-то экономить. Еще раз напомню про opcache. Более того, выше мы вроде как уже обсудили, что PHP редко бывает самым узким местом приложения.
                                                                                                                                                  +1
                                                                                                                                                  Мы так много времени на это потратили, хочу вернуться к работе.

                                                                                                                                                  У каждого из нас свой подход. Я считаю, что чем меньше звеньев в технологии — тем она стабильнее и надежнее.

                                                                                                                                                  Я очень скользко привел выше пример экономии.

                                                                                                                                                  Под DDOS атакой проект ложится намного позже. Часто просто продолжает медленно работать.

                                                                                                                                                  opcache — вариант конечно.

                                                                                                                                                  — Мое мнение, что разработчик должен решить две задачи:
                                                                                                                                                  1) Быстрое производство
                                                                                                                                                  2) Производительность

                                                                                                                                                  Остальные типа качества подразумеваются.

                                                                                                                                                  Phalcon более быстрая платформа из коробки, безусловно скорость фреймворка не решает насущих проблем производительности больших баз данных и больших обработчиков, но если мы говорим про емкие CRUD, где все и так оптимизирвоано и остается только роутинг, то только opcache вам в помощь и ничего плохого в этом нет, это ваш выбор )
                                                                                                                                                    +1
                                                                                                                                                    Соглашусь) Ушел работать недождавшись Вашего ответа даже.

                                                                                                                                                    Главное, что б денюжку платили и заказчики довольны были. А вот как именно это уже не так важно.
                                                                                                                                                      0
                                                                                                                                                      емкие CRUD

                                                                                                                                                      в доброй половине из этих проектов можно просто взять firebase и не возиться с php.

                                                                                                                                                    +2
                                                                                                                                                    а трудоемкость разработки на С и PHP не пробовали сравнить? Стоимость работы програмиста ща гораздо больше стоимости железа.
                                                                                                                                                      0
                                                                                                                                                      Если вы говорите про 50 долларов в месяц за Digital Ocean, то да )

                                                                                                                                                      Только я не понял вопрос про С и PHP, на Phalcon вы работает под PHP, сам фреймворк на C и его файлов нет в вашем проекте.
                                                                                                                                                        0
                                                                                                                                                        PS. Трудозатраты на разработку решения, которое работает быстро — очень преувеличены. По сути сейчас почти все мои решения «максимально быстры», покрайней мере на «мои мозги», может кто-то лучше программирует чем я. Но я сразу все библиотеки ориентирую под производительность.
                                                                                                                                                      0
                                                                                                                                                      Вы считаете, что Hello word не достаточно?

                                                                                                                                                      Ну тип того, да. Предположим разница между двумя фреймворками при таком тесте — фреймворк Б в 100 раз быстрее A. С другой стороны под фреймворк А в 50 раз больше разработчиков. Стоимость одного сервера за месяц составляет 1% от стоимости разработчика за тот же месяц. Так же предположим что на 10 разработчиков нам подходят 2 и 1 не пройдет испытательный срок (цифры с потолка и все зависит от проекта, на простых проектах цифры намного позитивнее).


                                                                                                                                                      Предположим что на реальном приложении мы упираемся уже не в CPU а в IOPS и сеть. И разница между фреймворками А и Б в плане RPS уменьшается до 2x. Для того чтобы добиться того же уровне RPS нам нужно 2.1x серверов (2.1 потому что резервирование железа и это не является 2.1x от всего кластера, это лишь php машинки). Так же не забываем что нам сложнее будет искать разработчиков. Искать людей которым плевать на чем писать и они все делают хорошо — это еще больше времени и денег. А далее уже надо смотреть на соотношение количества серверов к количеству разработчиков. И это мы еще делаем предположение что скорость разработки и инфраструктура у обоих фреймворков развита примерно одинаково.


                                                                                                                                                      tl;dr математика простая. Если у нас много серверов — мы получаем профит, но это должен быть реально большой кластер чтобы был профит. Потому хотелось бы знать заранее соотношение rps для более-менее реального проекта. А это уже сложно потому что надо делать.


                                                                                                                                                      p.s. hello world на php7 выдает на 30% больше RPS чем phalcon3.

                                                                                                                                                        0
                                                                                                                                                        С вашими словами согласен, но что делать если вся команда принимает проекты под ключ и делает их на Phalcon в рамках своего тех процесса и проводит обучение разработчиков по собственным наработкам — в таком случае ваш аргумент про найм сотрудников не имеет веса.

                                                                                                                                                        И я еще не видел сотрудников по php, которые бы не могли разобраться в любом фреймворке, сотрудников которых вы описали — это планка ниже 500$ в регионах. От 700$ в регионах — уже всеравно на чем писать, другой вопрос — общее качество на любом из фреймворков.
                                                                                                                                                          0
                                                                                                                                                          Вы тоже все описали слишком «лабораторно», в реальности, пока вы пишите код — ваш фреймворк все замедляется и замедляется. Не круто получать тяжеловесный шаблон например через 500ms или что еще хуже через секунду.
                                                                                                                                                          0
                                                                                                                                                          доставку сервером php и скомпилированого C?

                                                                                                                                                          Какая разница если 80% времени PHP тупо ждет блокирующих операций ввода/вывода?

                                                                                                                                                          0
                                                                                                                                                          Ну и безусловно иногда подразумевается, что при принятии подобных решений проводятся собственные субьективные тесты. Как выше мне говорили, что php медленный. Я думал, где мне обрабатывать 10 гигабайтный массив, в php,C или Node, провел тест php7 и в реальном испытании он показал отставание на секунду. Так же проводил тесты по нагрузке на сервера.