<rmcreative>

RSS

Не HelloWorld на современных фреймворках

30 ноября 2012

Не думал, что у кого-то хватит на это терпения. Хватило. Jeff hush2 реализовал одно и то же приложение «Knowledge is Power» из книги Larry Ullman «Effortless E-commerce with PHP and MySQL» на CodeIgniter, Laravel, Yii и Zend Framework первой и второй версии.

CodeIgniter Демо Исходный код
Laravel Демо Исходный код
Yii Демо Исходный код
Zend Framework 1 Демо Исходный код
Zend Framework 2 Демо Исходный код

Комментарии RSS

  1. №7144
    PA
    PA 30.11.2012, 23:11:52

    И что ЭТО?? какой-то голимый сайт. почему "приложение"? Sam, почему это есть приложение, а не просто хомпага?

  2. №7145
    Maseo
    Maseo 30.11.2012, 23:31:33

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

  3. №7148
    WarGot
    WarGot 01.12.2012, 1:27:49

    Ссылка на исходник хелло ворлда под Zend Framework 1 битая, 404.

  4. №7149
    Sam
    Sam 01.12.2012, 1:33:51

    github слёг.

  5. №7151
    Wave
    Wave 01.12.2012, 12:59:12

    Так не интересно. Весь процесс создания приложения описывается двумя словами: First commit.

  6. №7152
    Sam
    Sam 01.12.2012, 14:19:05

    Интересно тут хотя-бы то, что это не Hello World. Можно посмотреть, на что похожи чуть более сложные приложения в исполнении на разных фреймворках.

  7. №7154
    vladimir.kalchenko
    vladimir.kalchenko 02.12.2012, 15:28:58

    Мда, ZF1 в сравнении со ZF2 еще няшка, а его монстром кличут... ИМХО ZF2 излишне многословен.

    Жаль в обзоре нет Symfony2 и Yii

  8. №7155
    vladimir.kalchenko
    vladimir.kalchenko 02.12.2012, 15:30:18

    опс, про Yii я опечатался... жаль нельзя комменты править

  9. №7158
    Александр
    Александр 02.12.2012, 18:02:33

    Мне ОЧЕНЬ интересно!

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

    Сегодня прочитал про инициативу предрождественской помощи - 24 коммита. На мой взгляд - отличная инициатива. Может наберусь смелости и сам приму в ней участие. А пока - спасибо за Ваш вклад!

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

    Даже при том, что я еще многого не знаю и не умею - Yii позволяет мне писать код, который успешно решает поставленные задачи!

    Еще раз спасибо, Вам, Александр и Jeff Hush.

    Извините, что немного эмоционально.

  10. №7160
    Oleg
    Oleg 03.12.2012, 5:21:37

    Молодец... Потратил время не зря. ZF2 не назовешь "скромным и лаконичным" :)

  11. №7161
    Wave
    Wave 03.12.2012, 16:02:36

    Было бы интересней, если можно было пошагово следить за созданием «не hello-world» приложением. Что и в какой последовательности делается и всё такое. Ну и чтоб быть уверенным, что ничего не пропустил. Сейчас мне, например, нужно скачать чистый релиз фреймворка соотв. версии и пофайлово сравнить, чтоб быть уверенным, что я нигде ничего не пропустил кроме моделей, контроллеров и вьюх. Мало ли, какие-то либы, какие-то конфиги и так далее. Ну и опять же, в какой последовательности это всё писалось (контроллер после модели, или модель после контроллера, и так далее) — х.з..

  12. №7163
    Александр
    Александр 03.12.2012, 16:37:08

    на самом деле в этом примере все очень лаконично.

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

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

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

  13. №7164
    Dr0ID
    Dr0ID 03.12.2012, 17:06:06

    После нового года буду переводить проект из-под Symfony2 на Yii - намного удобнее и приятнее работать.

    Простите, в чем приятность? Мне кажется вы что-то делаете не так :)

  14. №7166
    Александр
    Александр 03.12.2012, 17:22:18

    Попробую пояснить. Если требуется простая функциональность, то количество действий в Yii потребуется меньше, чем в Symfony.

    Тем не менее, я был в полном восторге от Симфони, когда переписал свой сайт с движка моей разработки на нее.

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

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

  15. №7168
    Dr0ID
    Dr0ID 03.12.2012, 18:04:46

    Согласен, главное, чтобы Вам было удобно.

    Для меня, например, ключевым является:

    1. POPO и persistence ignorance для доменной модели.
    2. Unit of Work.
    3. Service layer.
    4. IoC.

    Поэтому выбор фреймворка очевиден, однако на Yii просидел 2 года.

    ps все мы самоучки.

  16. №7172
    Sam
    Sam 03.12.2012, 21:41:09
    1. А можно раскрыть, что такое POPO и persistence ignorance (об этом очень смутно догадываюсь).
    2. Будет в Yii2.
    3. А это каким боком к фреймворку?
    4. IoC или IoC-контейнер?
  17. №7173
    resurtm
    resurtm 03.12.2012, 21:49:32

    POPO — это ведь тоже самое, что и POJO из Джавы.

    Persistence ignorance — тут хороший пример: docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html

    Все три модели по ссылке (Bug, Product и User) могут быть очень просто перенесены из MySQL, к примеру, в MongoDB вообще без изменения кода приложения и самих моделей.

    creocoder как-то даже делился мыслями по поводу того, что хотелось бы запилить DataMapper в виде экстеншна по всем канонам Yii. :-)

  18. №7174
    Dr0ID
    Dr0ID 03.12.2012, 21:50:01
    1. Чистые доменный объект, которые не знает где его хранят (тоже что и ru.wikipedia.org/wiki/POJO, только для PHP). Например, AR более чем полностью нарушает эти 2 принципа, что сказывается как минимум на тестировании, т.к. тяжко тестировать сугубо доменную логику в отрыве от БД.
    2. Естественно никак, писал за компанию.
    3. Контейнер.
  19. №7175
    resurtm
    resurtm 03.12.2012, 21:51:01

    Правильнее конечно не «перенесены модели из MySQL в MongoDB», а «данные для моделей перенесены из MySQL в MongoDB». :-)

  20. №7177
    resurtm
    resurtm 03.12.2012, 21:57:59

    Dr0ID:

    Например, AR более чем полностью нарушает эти 2 принципа, что сказывается как минимум на тестировании, т.к. тяжко тестировать сугубо доменную логику в отрыве от БД.

    Ну DataMapper (в виде Doctrine2) в отладке сложнее, и в целом медленнее, чем ActiveRecord (в виде Yii AR) и понимается сложнее. Так что минусы и у DM есть. :)

  21. №7181
    sowingsadness
    sowingsadness 05.12.2012, 17:28:54

    Dr0ID:

    Чистые доменный объект, которые не знает где его хранят (тоже > что и ru.wikipedia.org/wiki/POJO, только для PHP). Например, AR более чем полностью нарушает эти 2 принципа, что сказывается > как минимум на тестировании, т.к. тяжко тестировать сугубо доменную логику в отрыве от БД.

    Просто вы делаете это через ЖОПУ! Весь DataMapping - это большое дерьмо с огромным количеством ограничений. AR гораздо гибче в плане получения данных из БД. Можно вводить отдельные сервисы для части сущности.

    Теперь о том, как работать с AR в отрыве от БД. Делается это так(абстрактный фреймворк):

    class ActiveRecord { private $connection; public function __construct() { $this->connection = \App::getConnection(); } public funciton initConnection(\Connection $connection) { $this->connection = $connection; } }

  22. №7182
    sowingsadness
    sowingsadness 05.12.2012, 17:30:59
    class ActiveRecord
    {
        private $connection;
     
        public function __construct()
        {
            $this->connection = \App::getConnection();
        }
     
        public function initConnection(\Connection $connection)
        {
            $this->connection = $connection;
        }
    }
  23. №7183
    Dr0ID
    Dr0ID 05.12.2012, 21:18:16

    Весь DataMapping - это большое дерьмо с огромным количеством ограничений.

    Вот оно как, теперь все стало понятно!

    AR гораздо гибче в плане получения данных из БД.

    В случае AR доменный объект умеет ходить к хранилищу, в случае DM нет.

    Можно вводить отдельные сервисы для части сущности.

    Не понял.

    Теперь о том, как работать с AR в отрыве от БД. Делается это так(абстрактный фреймворк):

    Куда в вашем примере пропала БД? Вы просто сделали возможность заинжектить объект соединения к ней? Проблема от этого никуда не пропала.

    1. Если делать юнит-тест, то ваши тесты будут знать о деталях, вам придется делать моки которые будут знать о запросах генерируемых AR. Тесты будут хрупкие.
    2. Если делать интеграционный тест, то время выполнения будет высоким и надо делать кучу фикстур. Что в конечном итоге приведет опять же к хрупкости и излишней сложности тестов.
    3. Можно заюзать runkit для подмены find* методов. Но это вообще жесть.

    Итог: вы не можете просто так взять и заполнить AR сущность какими-то связными с ней данными, чтобы сделать именно юнит-тесты и тестировать чистую бизнес логику сущностей и их взаимодействие!

    Это подходы разных весовых категорий. Если у вас простая модель, мало связей, CRUD — AR подходит идеально. В противном случае, когда большая предметная область, не хочется получить монолитные комбайн-сущности, которые чуть менее, чем полностью нарушают SOLID (нарушается 4 из 5 принципов О_о). Наследуются от какого-то инфраструктурного класса. И самое главное, знают о хранилище.

    В случае с DM получается довольно гибкая инфраструктура (Specification, Repository, UoW). Можно начать разработку не с проектирования БД, а сосредоточиться сначала на бизнес логике (собственно это и есть главный плюс persistence ignorance) и прикрутить БД в последний момент (привет, code first). Да, определенная сложность, конечно, появляется, но она появляется на границе слоев.

    Кстати, Фаулер пророчит будущее за polyglot persistence, на AR это будет тяжко.

    Все вышесказанное имхо и не претендует на истину в последней инстанции.

  24. №7184
    Dr0ID
    Dr0ID 05.12.2012, 21:21:56

    И да, сорри за оффтоп :)

  25. №7185
    Александр
    Александр 05.12.2012, 21:48:54

    Коллеги - сам факт выживания каждой из обсуждаемых технологий говорит о ее жизнеспособности. В каждом из ваших доводов есть не просто рациональное зерно, а квинтэссенция вашего опыта (не подберу другого такого точного слова). Мир интересен именно благодяря различиям, так что в одном случае удобнее будет один подход, в другом будет удобнее другой. Каждый может найти себе инструмент, который ему удобен. Кто-то любит Vim, кто-то Coda - это дело вкуса. И фреймворки будут развиваться в соответствии с теми задачами, которые перед собой поставили разработчики именно этого фреймворка. Как показала практика - холивар редко становится источником развития, поэтому предлагаю сосредоточиться на конструктиве. Вопрос о тестировании и соответствии принципам ООП важен, но выбор сейчас есть среди тех фреймворков, которые уже написаны и мы выбираем их именно под наши задачи. Безусловно дискуссия была интересной и еще даст свои плоды (я надеюсь) так что я очень благодарен всем ее участникам, поскольку когда мы слышим мнения, отличные от своего - поневоле все же задумываемся - а не упустил ли я что-нибудь?

    И очень часто находим после этого новое качество.

    Удачи все и успехов!

  26. №7186
    SowingSadness
    SowingSadness 05.12.2012, 22:45:19

    Если делать юнит-тест, то ваши тесты будут знать о деталях, вам придется делать моки которые будут знать о запросах генерируемых AR. Тесты будут хрупкие. Если делать интеграционный тест, то время выполнения будет высоким и надо делать кучу фикстур. Что в конечном итоге приведет опять же к хрупкости и излишней сложности тестов. Можно заюзать runkit для подмены find* методов. Но это вообще жесть. Итог: вы не можете просто так взять и заполнить AR сущность какими-то связными с ней данными, чтобы сделать именно юнит-тесты и тестировать чистую бизнес логику сущностей и их взаимодействие!

    Что за ахенея?

    а) Если уж вы проводите интеграционное тестирование с БД, то вам как не крути придется загружать фикстуры.

    б) Если у вас юнит тестирование, то модель в AR НИЧЕМ не будет отличаться от подхода в DataMapping.

    Куда в вашем примере пропала БД? Вы просто сделали возможность заинжектить объект соединения к ней? Проблема от этого никуда не пропала.

    в) connection - это соединение с БД

    . В противном случае, когда большая предметная область, не хочется получить монолитные комбайн-сущности, которые чуть менее, чем полностью нарушают SOLID (нарушается 4 из 5 принципов О_о)

    г) С чего вдруг? Набор тезисов и неожиданный вывод о нарушении SOLID.

    В случае с DM получается довольно гибкая инфраструктура (Specification, Repository, UoW). Можно начать разработку не с проектирования БД, а сосредоточиться сначала на бизнес логике (собственно это и есть главный плюс persistence ignorance) и прикрутить БД в последний момент (привет, code first).

    д) Неожиданно это пропало у AR. Ау, в AR что мешает мне сначала сделать модели, а потом прикрутить БД? Я даже больше скажу, в DM как раз то и накладывается ограничение на архитектуру БД. Ибо объект получит все связи, без возможности задания среза получения данных. Простой пример: У нас есть пользователь, который имеет должность. С течением времени, наш пользователь может менять свою должность. При этом необходимо установленную дату показывать пользователя именно в должности той, которой он находится на тот момент. При этом, необходимо не забыть про то, что при сохранении этого пользователя, меняться должно предыдущее состояние, а не сбрасываться все связи. В AR реализуется элементарно. В DM - привет, хачим Repository, создаем дополнительную модель - срез Entity. И не забыть всю эту размазанную логику по репозиторию, Entity и срезу засунуть в тест.

  27. №7188
    Dr0ID
    Dr0ID 06.12.2012, 8:14:03

    Sam, таки сорри за оффтоп :)

    а) Если уж вы проводите интеграционное тестирование с БД, то вам как не крути придется загружать фикстуры.

    Интеграционными тестами буду тестировать сервисный слой. Соответственно, их будет меньше.

    б) Если у вас юнит тестирование, то модель в AR НИЧЕМ не будет отличаться от подхода в DataMapping.

    AR невозможно тестировать в полной изоляции от БД. Проблема в find методах.

    в) connection - это соединение с БД

    Я это и написал.

    г) С чего вдруг? Набор тезисов и неожиданный вывод о нарушении SOLID

    Это не вывод, а тезис.

    Неожиданно это пропало у AR. Ау, в AR что мешает мне сначала сделать модели, а потом прикрутить БД?

    Вряд ли получится сделать рабочее приложение без БД на AR.

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

    Это не накладывает абсолютно никаких ограничений. Абсолютно. Получения каких-то срезов и тд, которые нужны для presentation layer можно и нужно делать в сервисном слое. Т.к. домену это все не нужно.

    Простой пример

    Не совсем понял условие вашей задачи.

    Для rich model:

    class Employee
    {
        /**
         * DM мапит сюда позиции сотрудника
         * @var Positon[]
         */
        public $positions;
     
        public function getPositionAt(DateTime $date)
        {
            foreach ($this->positions AS $position) {
                if ($position->isAt($date)) {
                    return $position;
                }
            }
            return null;
        }
    }

    Для anemic model:

    class PositionService
    {
        public function getPositionAt(Employee $employee, DateTime $date)
        {
            $specification = 
                new PositionAtDateSpecification($employee, $date);
     
            return $this->positionRepository
                ->findBySpecification($specification);
        }
    }

    Оба подхода можно комбинировать, особенно, в случае с rich. Не нужно ничего хачить, вы просто не поняли идею DM. Более подробно все это раскрывается в DDD (domain driven design).

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

  28. №7189
    sowingsadness
    sowingsadness 06.12.2012, 9:32:58

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

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

    AR невозможно тестировать в полной изоляции от БД. Проблема в find методах.

    find находится в другом уровне абстракции, он никак не затрагивает тестирование логики сущности.

    Интеграционными тестами буду тестировать сервисный слой. Соответственно, их будет меньше.

    Вряд ли получится сделать рабочее приложение без БД на AR.

    Не совсем понял условие вашей задачи Для anemic model:

    Я тоже откланиваюсь, не буду заполнять сие пространство моей ненавистью к DM -))

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.