«О нет!», воскликнет читатель, утомлённый разными мини-микро-слим-фреймворками и 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
Картинка в заключении статьи из гуглопоиска картинок
Поделиться с друзьями
-->

Комментарии (226)


  1. procode
    01.05.2017 15:37
    -8

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

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

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

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

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


    1. AlexLeonov
      01.05.2017 15:40

      А когда мастеришь только для себя, то постоянно приходится через несколько лет писать одно и то же заново.

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

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

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


      1. hlogeon
        02.05.2017 13:09
        +5

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

        Пруфы будут?)


        1. AlexLeonov
          02.05.2017 13:12
          -6

          А как же. Статье к десятой. Имейте терпение!


          1. skobkin
            02.05.2017 13:34
            +6

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


            1. AlexLeonov
              02.05.2017 14:02

              Код открыт. Какие еще пруфы прямо сейчас вы хотели бы получить?


              1. skobkin
                02.05.2017 14:24
                +1

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


              1. hlogeon
                02.05.2017 14:54
                +3

                Тот код, который открыт — антипруф. И ниже есть немало аргументов почему это так.


                1. AlexLeonov
                  02.05.2017 15:56

                  Я услышал ваше мнение, спасибо.


      1. Fesor
        02.05.2017 14:27
        +6

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

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


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

        или такой


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

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


  1. higgsbison
    01.05.2017 16:21
    +3

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


    1. AlexLeonov
      01.05.2017 16:26
      -5

      Сложно сейчас сформулировать преимущества, когда фреймворк еще в самой ранней стадии сборки. Я планировал раскрывать этот вопрос постепенно, по мере выхода статей и подготовки кода к публикации.

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

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

      Следите за публикациями!


      1. http2
        01.05.2017 17:15
        -1

        не будет $this->breadcrumbs в контроллерах (!)

        А хде?


        1. AlexLeonov
          01.05.2017 17:17
          +1

          Разумеется в шаблонах :)

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


          1. http2
            01.05.2017 19:37
            +1

            Контроллер готовит данные

            Так контроллер будет готовить breadcrumbs или нет? :)


            1. AlexLeonov
              01.05.2017 19:42

              Это вам решать в конечном счете. Но я бы не рекомендовал.


            1. webcote
              02.05.2017 02:15
              +3

              Я считаю, что breadcrumbs вы должны готовить сами :) Это не та задача, которую фреймворк должен уметь делать «из коробки».


              1. http2
                02.05.2017 11:42
                -1

                Отлично. :)
                Хде их готовить? :)


                1. AlexLeonov
                  02.05.2017 12:24

                  В шаблонах страниц.


                  1. http2
                    02.05.2017 12:26

                    В шаблонах делать запросы к БД для получения всех родителей?
                    Дичь. :)


                    1. AlexLeonov
                      02.05.2017 12:28

                      Не делайте. Зачем это вам?
                      Если модель является частью «дерева», то соответствующий метод у нее наверняка есть. А уж как он работает — делает один запрос или много — какая вам разница?


                    1. Fesor
                      02.05.2017 12:37

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


          1. Fesor
            02.05.2017 08:29

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

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


            1. AlexLeonov
              02.05.2017 10:59
              +1

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


              1. Fesor
                02.05.2017 12:37

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


      1. michael_vostrikov
        01.05.2017 17:29
        -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'); },
        ]


        1. AlexLeonov
          01.05.2017 17:34
          +4

          Никак. Вам нужно срочно убрать это из ORM либо в триггер, либо, что лучше, в конкретный компонент бизнес-процесса.


          1. michael_vostrikov
            01.05.2017 17:53
            -3

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


            1. AlexLeonov
              01.05.2017 18:06
              +3

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

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


              1. lavkasnov
                01.05.2017 18:19
                +2

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


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


                1. SamDark
                  02.05.2017 22:20
                  -1

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


                  1. lavkasnov
                    02.05.2017 23:24

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

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


                    1. oxidmod
                      02.05.2017 23:27
                      +2

                      ну вот что вас не устроило в Symfony Container, к примеру?


                      1. lavkasnov
                        03.05.2017 00:02
                        -2

                        Кратко про контейнер симфони:

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

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


                        1. velvetcat
                          03.05.2017 00:33
                          +2

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


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

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


                        1. oxidmod
                          03.05.2017 00:43
                          +2

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


                        1. Fesor
                          03.05.2017 01:58
                          +2

                          использование аннотаций в рантайме — это чистое зло и никогда их использовать не буду. Что им мешает сделать генератор классов из аннотаций?

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


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

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


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

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

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


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

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

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


                          1. lavkasnov
                            03.05.2017 07:43
                            -3

                            Да, действительно, я не стал разбираться симфони, посмотрю еще раз. Ведь такая штука: бегло просматриваю базовые классы/интерфейсы, если мне не нравится стиль кодирования, вижу избыточнное количество методов с неочевидным назначением и т.д. Как правило отвергаю такую библиотеку.


                    1. MetaDone
                      03.05.2017 00:05
                      +1

                      не смотрели https://github.com/auraphp/Aura.Di?


                      1. lavkasnov
                        03.05.2017 07:29

                        Да, конечно, все из топа выдачи гугла, у всех разное качество и к каждому я находил претензии. Больше всех мне понравился компонент di из codeception


                        1. Fesor
                          03.05.2017 12:10

                          компонент di из codeception

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


                          1. lavkasnov
                            03.05.2017 12:41
                            -1

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


                            1. Fesor
                              03.05.2017 18:25

                              сделать автоматическую иньекцию малыми средствами

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


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


                              1. franzose
                                04.05.2017 06:27

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


                                1. http2
                                  04.05.2017 08:31
                                  -1

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

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


                                  1. franzose
                                    04.05.2017 08:42

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


                                  1. Fesor
                                    04.05.2017 10:14
                                    +1

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


                    1. Hellek
                      04.05.2017 20:01

                      Можете, пожалуйста, пояснить, что значит?

                      программирование заменяется на сложное конфигурирование

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


                      1. Fesor
                        04.05.2017 20:13
                        +2

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


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


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


                      1. lavkasnov
                        04.05.2017 22:05

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

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

                        Сами же можете придумать, как разрулить


                      1. AlexLeonov
                        04.05.2017 23:30

                        Я могу привести пример, если позволите.

                        Плохо:

                        $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;
                        


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


                        1. franzose
                          05.05.2017 01:31

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


                          1. AlexLeonov
                            05.05.2017 09:57

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

                            Пишите код, коллеги.


                        1. michael_vostrikov
                          05.05.2017 07:13

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


                          1. oxidmod
                            05.05.2017 08:19
                            +2

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


                            1. AlexLeonov
                              05.05.2017 09:58

                              +1


                          1. ghost404
                            05.05.2017 09:56

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


                          1. AlexLeonov
                            05.05.2017 09:58

                            Кто вам сказал про копи-паст? Напишите свой валидатор, инкапсулируйте в него все правила валидации и используйте. И никакого копи-паста.


                        1. fukkit
                          05.05.2017 09:53
                          +3

                          Тот случай, когда «плохо» очевидно лучше, чем «хорошо»


                        1. Hellek
                          05.05.2017 12:21

                          AlexLeonov, lavkasnov, Fesor cпасибо


                        1. Fesor
                          05.05.2017 12:41
                          +1

                          Хорошо:

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


                          1. AlexLeonov
                            05.05.2017 13:36
                            -2

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

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

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

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

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

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


                            1. Fesor
                              05.05.2017 16:02
                              +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')]),
                                 ]
                              ]);

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


                              1. AlexLeonov
                                05.05.2017 17:40

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

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

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

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


              1. michael_vostrikov
                01.05.2017 18:32
                +1

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


                1. AlexLeonov
                  01.05.2017 18:40

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

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


                  1. michael_vostrikov
                    02.05.2017 09:10

                    удобный — делающий что-либо приятным, легким в осуществлении чего-либо; уместный, подходящий для чего-либо

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


                  1. Fesor
                    02.05.2017 09:33

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

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


              1. michael_vostrikov
                01.05.2017 20:50
                +2

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


                1. AlexLeonov
                  01.05.2017 20:52

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


              1. fukkit
                01.05.2017 22:24
                +1

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


                1. AlexLeonov
                  01.05.2017 22:25
                  +1

                  DI — это просто один из вариантов композиции компонентов приложения. Фреймворк должен предоставить вам способ это сделать, конечно же. Но я не считаю, что DI — панацея, которая делает ваш код плохим.

                  Код плохим делает нежелание писать код.


                  1. AlexLeonov
                    01.05.2017 22:34
                    +1

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

                    Я буду 10 раз перечитывать комментарий перед отправкой!


                    1. fukkit
                      02.05.2017 10:47

                      Не панацея, но весьма удобный подход.


              1. franzose
                02.05.2017 09:57
                +1

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

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


              1. http2
                02.05.2017 11:49
                +1

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

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


            1. michael_vostrikov
              02.05.2017 06:38
              +1

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


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


              1. AlexLeonov
                02.05.2017 11:02

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

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

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

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

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


                1. michael_vostrikov
                  02.05.2017 11:58
                  +1

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


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

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


                  1. AlexLeonov
                    02.05.2017 12:27

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

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


                    1. michael_vostrikov
                      02.05.2017 13:20
                      +1

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


                      1. AlexLeonov
                        02.05.2017 13:36
                        -2

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


                        1. michael_vostrikov
                          02.05.2017 14:12
                          +1

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


                          1. Fesor
                            02.05.2017 14:39
                            +3

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

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


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


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


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


                            1. michael_vostrikov
                              02.05.2017 15:56
                              +1

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


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


                              1. Fesor
                                02.05.2017 17:00

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

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


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

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


                1. Nelin
                  02.05.2017 12:24
                  +1

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


                  Ну или в нескольких местах… наверное…


              1. Fesor
                02.05.2017 12:40

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

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


                1. AlexLeonov
                  02.05.2017 12:44

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


                1. michael_vostrikov
                  02.05.2017 13:22
                  +1

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


      1. Zhuravljov
        02.05.2017 03:45
        +2

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


      1. SamDark
        02.05.2017 22:18
        +1

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

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


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

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


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

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


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

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


  1. oxidmod
    01.05.2017 16:43
    +2

    Ладно еще коллекции, но какой прок от объекта, которому динамически можно свойств накидывать? Чем вам тогда простой stdClass не подошел? Вы всеравно же не знаете какие в итоге свойства у итогового объекта.


    1. AlexLeonov
      01.05.2017 16:49

      Во-первых это 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. oxidmod
        01.05.2017 18:48
        +1

        Под chaining вы понимаете fluent interface? Если так, то место ему в билдерах да коллекциях. И тащить наследование от базового класса только ради этого — глупо.
        Вы пишете что явное лучше неявного, но при этом под капотом у вас какая-то магия с innerCast.
        Ваш объект нарушает SRP, сочетая в себе и фабрику объектов, и сериалайзер, и валидатор.


        1. AlexLeonov
          01.05.2017 18:53
          -2

          Фабрики объектов нет. Есть кастинг. Это раз.

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

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

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


        1. AlexLeonov
          01.05.2017 22:37

          Под chaining вы понимаете fluent interface?


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

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

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

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


          1. artem90
            01.05.2017 23:33

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


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


            1. AlexLeonov
              01.05.2017 23:47

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

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

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

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

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


              1. artem90
                02.05.2017 00:02

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


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


                1. AlexLeonov
                  02.05.2017 00:34

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

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


                  1. ghost404
                    02.05.2017 10:39
                    +1

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


                    1. AlexLeonov
                      02.05.2017 11:03

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

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


                      1. ghost404
                        02.05.2017 12:01
                        +1

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


                        1. AlexLeonov
                          02.05.2017 12:28

                          Вы можете не создавать. Я лишь даю вам такую возможность.


              1. Fesor
                02.05.2017 12:41
                +3

                Неплох.

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


          1. http2
            02.05.2017 11:56

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

            $obj->foo->bar = 42;

            Что люди не делают, лишь бы не использовать массивы. :)


            1. AlexLeonov
              02.05.2017 12:28

              Массивы не могут быть типизированы, к сожалению.


              1. http2
                03.05.2017 12:20
                -1

                Чтобы по пьяни не передать левую переменную? :)


              1. oxidmod
                03.05.2017 12:29

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


            1. Fesor
              02.05.2017 12:42

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


  1. lavkasnov
    01.05.2017 18:07
    +2

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

    Что не увидел: DI, фабрики и как рулить их конфигами. Очень интересно было бы посмотреть ваш подход к этому. Насторожил синглетон в ядре.


    1. AlexLeonov
      01.05.2017 18:10
      -4

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


      1. Yeah
        02.05.2017 00:02

        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;


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


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


        1. AlexLeonov
          02.05.2017 00:35
          -2

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

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


  1. zloyusr
    01.05.2017 20:40
    +4

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

    Зачем? Пожалуйста, объясните зачем вы это делаете? Откуда в PHP эта «мода» делать из объекта массив?


    1. AlexLeonov
      01.05.2017 20:46

      Это наоборот: из массива объект. Мы любим массивы и хотим добавить к ним методы ))

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


      1. zloyusr
        01.05.2017 21:51
        +3

        Мы любим массивы и хотим добавить к ним методы

        т.е. сделать то, что и так уже есть в языке — объекты.
        ArrayAccess входит в тройку самых ужасных для меня возможнойстей PHP: сразу за магическими __get, __set
        и ReflectionProperty::setAccessible().
        Код с применением указанных возможностей прекрасный способ усложнить себе и другим разработчикам жизнь.


        1. AlexLeonov
          01.05.2017 21:53

          В таком случае вы просто не любите PHP?


          1. zloyusr
            01.05.2017 21:59

            Я такого не говорил. Я говорил только о нескольких возможностях языка.
            PHP начиная с версии 5.3 достаточно хорош, а с приходом 7.х еще лучше.


            1. AlexLeonov
              01.05.2017 22:03
              -1

              Ну хорошо. А то уж я подумал вдруг ))


  1. akirsanov
    01.05.2017 20:51
    -1

    начало выглядит неплохо, жду продолжения


  1. sspat
    01.05.2017 21:41
    +11

    С таким уровнем магии более подходящим названием для фрейморка будет «Гарри Поттер». Вжух! И мы сделали из обьектов массив, теперь туда можно сваливать как в помойку любое количество данных создавая новые под-помойки на лету! Но через два часа программирования такими «обьектами» они превращаются в ружье и отстреливают фокуснику обе ноги.


    1. sspat
      01.05.2017 21:49
      +4

      Посмотрел что у вас там дальше будет по циклу — веселье только начинается! Вот такая цепочка наследования…

      SimpleValue implements \JsonSerializable
      SimpleValueObject extends SimpleValue implements ValueObjectInterface
      class IntValue extends SimpleValueObject
      


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

      Я боюсь представить, сколько километров длинной будет цепочка наследования, когда дело дойдет до чего-то реально сложного.


      1. AlexLeonov
        01.05.2017 22:30
        -3

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

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

        А что?


        1. sspat
          01.05.2017 22:34
          +3

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

          public function decode(string $data)
              {
                  try {
                      return eval('return ' . $data . ';');
                  } catch (\ParseError $e) {
                      throw new DecodeException($e->getMessage(), $e->getCode(), $e);
                  }
              }
          


          1. AlexLeonov
            01.05.2017 22:38

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

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

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

            P.S. Про библиотеку сериализации будет другая статья.


            1. sspat
              01.05.2017 22:56
              +3

              Давайте дальше посмотрим, валидация…

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

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

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

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


              1. AlexLeonov
                01.05.2017 23:02
                -3

                Отвечаю на заданные вопросы.

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

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

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

                Не сумел ответить. Ваш вопрос не содержит позитивного или негативного утверждения. Всё равно что спросить «а ваши родители знают, что вы гей?»


                1. Fesor
                  02.05.2017 02:04
                  +4

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

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


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


            1. Fesor
              02.05.2017 02:08
              +2

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

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


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


              1. AlexLeonov
                02.05.2017 11:04

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

                Потому что статья не об этом.


            1. http2
              02.05.2017 12:08
              -1

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

              А что с ним не так?


              1. AlexLeonov
                02.05.2017 12:29

                Кто сказал «не так» кроме вас?
                Просто сообщите, пожалуйста. Это же очень интересно!


    1. TheShock
      01.05.2017 22:41

      Но через два часа программирования такими «обьектами» они превращаются в ружье и отстреливают фокуснику обе ноги.

      В ружье Чехова, которое выстрелит под конец — а именно на боевом сервере))


      1. AlexLeonov
        01.05.2017 22:42

        Если вы приведете мне конкретный пример — буду счастлив.


  1. vladiman
    01.05.2017 22:25

    Это уже данность такая — любую статью про РНР начинать с нескольких абзацев извинений?


    1. AlexLeonov
      01.05.2017 22:29

      Мне показалось, что в праздничный вечер немного лирики не помешает. Вам помешало?


      1. vladiman
        01.05.2017 23:05

        Хорошей лирики много не бывает!


  1. joker2k1
    01.05.2017 22:25
    -13

    PHP хорош тем, что ему не нужен никакой фреймворк. То, для чего он предназначен, не требует фреймворков, потому что реализуется за день, без всяких ненужных абстракций.
    Теперь же php превратился в говнокод завернутый еще и в фреймоворк (который тоже часто состоит из говнокода), что только многократно все усложняет. Если в голове каша, никакой фреймворк не поможет. Поэтому и каждый берется за очередной «фреймворк», понимает что это пипец и… садится делать такой же пипец, только свой, из своей каши.
    Зачем все эти абстракции над и так уже хорошо работающими внутренними механизмами PHP?
    Самое печальное что теперь во все это верят и работодатели, подбирая людей под фреймворк, потом меняя фреймворк…
    Все мое личное имхо, и наблюдение, рад ошибаться


    1. AlexLeonov
      01.05.2017 22:28
      +2

      Я думаю, что вы ошибаетесь.

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

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

      А абстракции нужны затем, что так устроен наш, homo sapiens, способ мышления. Анализ, синтез, абстрагирование, обобщение, конкретизация…


    1. http2
      02.05.2017 12:17
      -9

      Адекватная точка зрения на хабре не приветствуется. :)


      1. michael_vostrikov
        02.05.2017 12:34
        +6

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


        1. http2
          02.05.2017 15:57
          -2

          Какие преимущества? :)
          О чем речь? :)


  1. Movimento5Litri
    01.05.2017 22:25

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

    И что же это, каждый второй не может использовать конструкцию ;$result = (object) $array &


    1. AlexLeonov
      01.05.2017 22:26

      Не совсем ясно, где у вас "&" и что конкретно этот символ обозначает?


      1. Movimento5Litri
        02.05.2017 09:30

        Извиняюсь, это был знак вопроса


  1. hlogeon
    01.05.2017 23:10
    +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. hlogeon
      01.05.2017 23:14
      +1

      > Come Review? Come Discussion?

      Code само собой) Т9…


    1. AlexLeonov
      01.05.2017 23:15
      -5

      НЕТ! ЗАЧЕМ?

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

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

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

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

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

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

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

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


      1. hlogeon
        01.05.2017 23:46
        +1

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


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

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


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

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


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

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

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


        1. AlexLeonov
          01.05.2017 23:53
          -7

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

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

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

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

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

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

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

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

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

          Хорошо.


          1. ghost404
            02.05.2017 10:11

            Рекомендую почитать про Чёрный квадрат Малевича.


  1. thecoder
    01.05.2017 23:30
    +1

    Буханка троллейбус jpg
    :)


    1. AlexLeonov
      01.05.2017 23:33
      +3

      Фабиену и Тейлору кто-то точно также говорил :)

      А уж что говорили Расмусу — я не могу написать по цензурным соображениям!


      1. thecoder
        02.05.2017 00:01
        +1

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


        1. AlexLeonov
          02.05.2017 00:40
          -1

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

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


          1. Fesor
            02.05.2017 01:42
            +9

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


          1. hlogeon
            02.05.2017 11:39
            +1

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


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


            1. AlexLeonov
              02.05.2017 12:30

              Так вы не задали ни одного вопроса же!
              Если бы был вопрос — был бы ответ.


              1. hlogeon
                02.05.2017 12:51
                +3

                Так вы просто игнорите вопросы) Давайте напомню:

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


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


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


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


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


                1. AlexLeonov
                  02.05.2017 12:58
                  -5

                  зачем каким-то широким массам показывать?

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

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

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

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

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

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

                  Нет вопроса. Есть констатация вашего непонимания.


                  1. hlogeon
                    02.05.2017 13:01
                    +2

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

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

                    ЗАЧЕМ?


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


                    1. AlexLeonov
                      02.05.2017 13:13
                      -3

                      ЗАЧЕМ?


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

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


                      1. hlogeon
                        02.05.2017 13:17
                        +3

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

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


                        1. AlexLeonov
                          02.05.2017 17:27
                          -1

                          Неверно.

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

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

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

                          Если перефразировать так — то вы ничего не упустите.


                          1. hlogeon
                            02.05.2017 17:29
                            +1

                            Как это коррелирует с Вашими предыдущими ответами на те же самые вопросы? Вы так гордо и высокомерно отвечали сначала одно, теперь говорите совершенно другое. Где же правда-то в итоге?


                            1. AlexLeonov
                              02.05.2017 17:33

                              Не готов вам ответить на вопрос. Не думаю, что он вообще требует ответа.

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

                              Мне интереснее обсуждать код, а не те эмоции, которые у вас он вызывает.


                              1. hlogeon
                                02.05.2017 17:36
                                +1

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

                                Как это коррелирует с Вашими предыдущими ответами на те же самые вопросы? Вы отвечали сначала одно, теперь говорите совершенно другое. Где же правда-то в итоге?


                                1. AlexLeonov
                                  02.05.2017 17:44
                                  -1

                                  Оставлю вас в вашем собственном мире, где «гордость», «высокомерие», «убегают от ответов», а вы рыцарь на белом коне, несущий правду. А сам останусь в скучном мире программирования ))

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


                                  1. hlogeon
                                    02.05.2017 17:45

                                    ч.т.д


                      1. Fesor
                        02.05.2017 13:19
                        +4

                        я вам уже раза три на этот вопрос ответил.

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


              1. Fesor
                02.05.2017 13:17
                +2

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


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

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


  1. MetaDone
    01.05.2017 23:48
    +1

    Автору следует посмотреть сюда — https://github.com/auraphp потому что

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

    все там уже есть
    А чего нет — можно взять компоненты Symfony, Zend, Laravel и кучу нужных библиотек


    1. AlexLeonov
      01.05.2017 23:49

      Автор (и авторы) внимательно смотрели туда. Однако пока что ни один коммент на хабре не заставил их заплакать и отказаться от развития своих библиотек. Наверное, в этом что-то есть?


      1. MetaDone
        01.05.2017 23:58

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


        1. AlexLeonov
          02.05.2017 00:41
          -2

          лично я пока не могу представить

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


  1. artem90
    01.05.2017 23:58
    +1

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


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


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


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


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


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


    1. AlexLeonov
      02.05.2017 00:39
      -3

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

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

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


      1. DeLuxis
        02.05.2017 08:17
        +3

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

        Конструктивно, хотя бы штук пять.

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


        1. Fesor
          02.05.2017 08:34

          нескольких крупных проектах

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


          1. hlogeon
            02.05.2017 11:21
            +1

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


  1. Fesor
    02.05.2017 02:01
    +13

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


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

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


  1. drakulitka
    02.05.2017 10:52

    Вот, наконец-то, официальный релиз )))


  1. Dimash2
    02.05.2017 10:52
    -3

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


    1. hlogeon
      02.05.2017 11:34
      +4

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

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


      1. Dimash2
        02.05.2017 13:30

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

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

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

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


        1. Dimash2
          02.05.2017 13:33

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


        1. Fesor
          02.05.2017 13:38
          +2

          Написать свой конструктор запросов займет

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


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

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


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

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


          1. Dimash2
            02.05.2017 14:44

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

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


        1. hlogeon
          02.05.2017 13:39

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

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


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

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

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

          Конечно, мои примеры высасаны из пальца, но это просто для удобства объяснения. И да, я работаю с проектами, которые довольно сильно парятся о нагрузке. И в тех местах, где это действительно важно на уровне языка программирования — мы просто не используем PHP, вот и все. Но в 99% случаев, проблемы с производительностью кроются вовсе не в PHP и какой-то там компиляции. Тем более, что есть opCache.


          1. Dimash2
            02.05.2017 13:41
            -1

            Да, мои клиенты экономят сотни долларов на серверах, котому что они лажатся занчитель позже. У классических фреймворков такой же эфект как у Wordpres — серьезрый response delay под нагрузкой (у второго и без нагрузки) из-за огромног количества фреймворковских файлов. Есть бенчмарки, можете сравнить.

            — Вы абсолютно правы про криворукость запросов и именно такими их делают криворукие разработчики по документации того же Yii


            1. Dimash2
              02.05.2017 13:46

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

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

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


              1. hlogeon
                02.05.2017 13:51

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


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


            1. hlogeon
              02.05.2017 13:47

              Так разговор о фреймворке или криворукости разработчиков, не смешивайте теплое с мягким)

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


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


              1. Dimash2
                02.05.2017 13:55

                https://systemsarchitectdotnet.files.wordpress.com/2013/04/php-benchmark.png

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


                1. Fesor
                  02.05.2017 13:57

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


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


                  1. Dimash2
                    02.05.2017 13:59

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

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

                    И вот вы все программисты и я не могу понять, почему вам не понятна разница самого факта, что Symfony — php, а Phalcon — C, то ест ьвы реально сравниваете доставку сервером php и скомпилированого C?


                    1. hlogeon
                      02.05.2017 14:09
                      +1

                      Разговор был об экономии сотен нефти конечному заказчику. А из того, что вы скинули никак не следует то, что это позволяет хоть как-то экономить. Еще раз напомню про opcache. Более того, выше мы вроде как уже обсудили, что PHP редко бывает самым узким местом приложения.


                      1. Dimash2
                        02.05.2017 14:27
                        +1

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

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

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

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

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

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

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

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


                        1. hlogeon
                          02.05.2017 15:04
                          +1

                          Соглашусь) Ушел работать недождавшись Вашего ответа даже.

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


                        1. Fesor
                          02.05.2017 15:14

                          емкие CRUD

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


                    1. caballero
                      02.05.2017 14:28
                      +2

                      а трудоемкость разработки на С и PHP не пробовали сравнить? Стоимость работы програмиста ща гораздо больше стоимости железа.


                      1. Dimash2
                        02.05.2017 14:30

                        Если вы говорите про 50 долларов в месяц за Digital Ocean, то да )

                        Только я не понял вопрос про С и PHP, на Phalcon вы работает под PHP, сам фреймворк на C и его файлов нет в вашем проекте.


                        1. Dimash2
                          02.05.2017 14:32

                          PS. Трудозатраты на разработку решения, которое работает быстро — очень преувеличены. По сути сейчас почти все мои решения «максимально быстры», покрайней мере на «мои мозги», может кто-то лучше программирует чем я. Но я сразу все библиотеки ориентирую под производительность.


                    1. Fesor
                      02.05.2017 14:55

                      Вы считаете, что 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.


                      1. Dimash2
                        02.05.2017 15:01

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

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


                      1. Dimash2
                        02.05.2017 15:05

                        Вы тоже все описали слишком «лабораторно», в реальности, пока вы пишите код — ваш фреймворк все замедляется и замедляется. Не круто получать тяжеловесный шаблон например через 500ms или что еще хуже через секунду.


                    1. Fesor
                      02.05.2017 17:05

                      доставку сервером php и скомпилированого C?

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


                  1. Dimash2
                    02.05.2017 14:04

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

                    Один из тестов попал и Wordpress, он тоже попал под жесткую оптимизацию и вам советую, если делаете на WP сайты напишите в index.php перехватчик буфера вывода и кешируйте его в БД, получится скорость сайта из 1 php файла и одного запроса — полностью отрубаете WP компиляцию


            1. redfs
              02.05.2017 14:26

              серьезрый response delay под нагрузкой (у второго и без нагрузки) из-за огромног количества фреймворковских файлов
              Почему то вы игнорируете все упомининия ваших оппонентов про opcache. Данные, которыми вы оперируете, устарели на несколько лет.


              1. Dimash2
                02.05.2017 14:31

                Вы правы, но эти споры — развлечения, по сути ниже правильно написали. Фреймворк быстрый, минималистичный и он меня устраивает.


            1. SamDark
              02.05.2017 22:55

              А что именно не так в документации Yii по запросам?


    1. Fesor
      02.05.2017 13:33
      +2

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

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


      фундаментально другой подход в компиляции

      Это как простите? подход то тот же абсолютно.


      так глубоко в встроенные методы фреймворка

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


      структура для правильной организации кода

      В бородатых 70-х придумали такие штуки как coupling и cohesion для грамотной декомпозиции проекта на модули. А когда фреймворк заставляет меня ложить все в сontroller и model я грущу.


      К слову может будет интересно. Тут есть прекрасно поданный материал на тему структурирования кода. Правда в контексте Java но это не столь принципиально.


      1. Dimash2
        02.05.2017 13:37

        Спасибо.

        Да, вы меня правильно поняли, чем не устраивает универсальный и самый производительный подход, разве не это вам позволяет делать фреймворк?

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

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

        Вот не могу себе представить, где лучше будет Ember чем Angular и наоборот — только мои предпочтения.


        1. Fesor
          02.05.2017 13:50

          разве не это вас позволяет делать фреймворк?

          Я использую Symfony, он позволяет мне не использовать то что мне не нужно. Так что я в целом доволен. А сам по себе фреймворк не является в моем случае узким местом, тут скорее инициализация контейнера зависимостей уже больше будет влиять. А вообще у меня тут есть маленький пет-проджект, надо бы все же попробовать его реализовать на phalcon. Уже года 2 собирался потыкать этот фреймворк тупо для расширения кругозора, да все небыло интереса. А так хоть нагрузочные тесты можно будет погонять что бы посмотреть стоит ли овчинка выделки.


          что фреймворки — это пища для развития.

          Я именно о таких штуках как "а не попробовать ли мне SPA делать заместо обычного WEB, вдруг устраню кучу проблем". Или "в symfony/flex замутили удобный скаффолдинг проектов, любопытно, сворую для фалькона".


          1. Dimash2
            02.05.2017 13:59

            Ну вот и вы написали, что все на ваших предпочтениях ) и все задачи по сути вы на Симфони и решаете (в целом если творчество не загорится)


            1. Fesor
              02.05.2017 14:57

              вы на Симфони и решаете

              типовые проекты — на своей сборке, некоторые специфичные задачи — на отдельных компонентах и не только на симфони компонентах.


          1. caballero
            02.05.2017 14:34

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

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


            1. Fesor
              02.05.2017 14:59

              неважно какие проблемы он решает,

              для меня важно. Мы таким образом сильно упростили бэкэнды, а UI логика на SPA ложится просто прекрасно.


              какие еще большие проблемы создает

              незначительные на фоне профита на самом деле. Ну это если знать что делаешь. Вот тут могут быть проблемы.


              пофиг SPA там или древний CGI,

              Это влияет на UX причем неслабо, и уж поверьте рядовому пользователю разница тут будет огромна.


              1. caballero
                02.05.2017 15:30
                +1

                Мы таким образом сильно упростили бэкэнды,

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


    1. caballero
      02.05.2017 14:23

      Все фреймворки делают одно и тоже,

      Все языки программирования делают одно и тоже.
      Все компьютеры делают одно и тоже.

      На самом деле фреймворк важен не тем что он делает а тем насколько упрощает програмисту решение конечно задачи.
      Другое дело что 9 из 10 фреймворков — архитектурные MVC-близнецы и поэтому их сложно разложить по направлениям решения (точнее имплементации задач).


      1. Dimash2
        02.05.2017 14:28

        Я с вами согласен )


  1. Therebro
    02.05.2017 17:11
    +2

    Очередной велосипед…


  1. velvetcat
    03.05.2017 00:46
    +3

    Заглянул на Гитхаб...


    Репозиторий Core. Core чего, фреймворка? Но он же слабосвязанный? И что во фреймворке такого, центрального, без чего фреймворк — не фреймворк?


    О нет, это ядро всего приложения… Фреймворк не должен быть ядром приложения, ядро должно быть независимым ни от чего. Чисто практически — кто будет использовать интерфейсы или наследовать свои классы от никому не известной 3d-party библиотеки?


    Storages/KeyValueStorage. Финт с null-овым именем для вызова мощного деструктивного поведения когда-нибудь дорого обойдется. Явное лучше неявного, почему бы не сделать методы loadAll/saveAll()?


    Load data from external storage into this object by specified...? То ли впопыхах вкоряченный и забытый костыль, то ли тотальное непонимание ООП. От KeyValue клиентам нужно только одно — положить данные, а потом их забрать, им глубоко фиолетово, что там где-то за KeyValue есть еще одно external storage. Хинт: попробуйте реализовать этот интерфейс на базе memcached.


    /**
     * Stores the value by specified key in this object
     * @param int|string|null $key
     * @param mixed $value
     */
    public function set($key, $value);

    Ключи "1" и 1 — будут считаться за один и тот же ключ или за разные? Укажите string, стандартного приведения типов достаточно.


    Зачем Вам XxxStorageAwareInterface? Здесь не проглядывается ни одной причины для его использования. Выглядит особенно странно с учетом Вашего прохладного отношения к DI. Кстати, аннотации противоречат сигнатурам методов.


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


    SingletonTraitTest. Проверять рефлекшеном, что конструктор непубличный — это, пардон, днище. Класс нельзя инстанцировать через new — вот что надо проверять, не больше и не меньше. И дайте тестовым методам нормальные имена хотя бы.


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


    1. AlexLeonov
      03.05.2017 09:54

      Большое спасибо за столь подробный комментарий.

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

      А если серьезно, то любые отзывы всегда на пользу. Положительные дают силы продолжать дальше. Отрицательные — возможность задуматься и вовремя что-то изменить. Большое спасибо, что пишете их!