В статье будут освещены следующие проблемы разработки и поддержки проектов на базе php-фреймворка Yii:

  1. Главные достоинства и недостатки
  2. Тестирование
  3. Нюансы использования ActiveRecord
  4. Сервис-ориентированный подход
  5. Новшества языка
  6. Расширение фреймворка




Yii я использовал в четырёх коммерческих проектах разной степени сложности. Это были, следующие решения:

  1. Проект с нагрузкой порядка сотен тысяч хитов в сутки, с таргетингом, аналитикой по миллионам событий, обработкой мультимедиа и т. п. Рекламный сервис. Основные технологии:
    1. Yii1
    2. MySQL
    3. RabbitMQ
    4. Memcached

  2. Веб-интерфейс для одного из решений по управлению кампаниями на базе готового API аналитического сервиса. По сути простой web-GUI с некоторым кэшированием и минимальной серверной логикой. Основные технологии:
    1. Yii1
    2. SQLite
    3. bootstrap
    4. jQuery

  3. REST API на Yii2 для веб-приложения на AngularJS, и мобильных клиентов Android, iOS. Скидочная тематика, вся логика на сервере. Основные технологии:
    1. Yii2
    2. MySQL
    3. RabbitMQ

  4. Внутренняя система документооборота, узкоспециализированная под конкретную отрасль, но со множеством различных бизнес-процессов разных департаментов. Основные технологии:
    1. Yii1
    2. MySQL
    3. Клиентская часть была переписана на AngularJS 1 и отвязана от php.



Помимо этого я экспериментировал с этим фреймворком, обеих версий, в некоторых своих pet-проектах. В этой статье, я бы хотел осветить проблемы разработки и поддержки проектов разной степени сложности на Yii и дать ряд рекомендаций, основанных на собственном опыте.

Последний из перечисленных выше проектов (№4), разрабатывался около двух лет, к началу моего участия в нём. Ещё на собеседовании, когда я узнал о двухлетней разработке, без релиза, об использовании первой версии фреймворка (в начале 2015 года), я подумал что без проблем там не обойдётся. Но я согласился участвовать, чтобы принять challenge — взяться за то, что принято называть «унаследованный код». Да, тот самый, что вызывает самые разнообразные отрицательные чувства — отвращение, ненависть, отчаяние, страх — и следуя советам Фаулера, вооружившись тестами, сделать из долгостроя качественный, поддерживаемый, рабочий продукт. Год рефакторинга, смена архитектуры за несколько месяцев перед релизом и сам выход в продакшен проекта с подобной историей, заслуживают отдельной статьи — я получил бесценный опыт, которым хотел бы поделиться, если на то будет воля сообщества.

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


Yii о двух концах



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

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

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


Тестирование



Модульное тестирование в сообществе Yii-разработчиков не распространено повсеместно. Есть обзор тестирования в официальной документации (1, 2), многие из расширений создаваемых энтузиастами покрыты тестами. Но, оттого что в сообществе большой процент разработчиков с малым опытом, которые ещё не доросли до автоматического тестирования, начинать проект на Yii по TDD в целом, скорее не принято.

Дополнительную сложность для юнит-тестирования может представлять использование шаблона Active Record. Об этом я подробнее напишу ниже.

В упомянутом проекте проводилось только ручное приёмочное тестирование. Были не поддерживаемые тесты под Selenium, почему-то написанные на Java, но они выполнялись слишком долго, а запускались слишком сложно, и, как следствие редко, результат давали неоднозначный.

Одно из первых мероприятий, предпринятых мной было подключение PHPUnit и применение TDD при разработке новых фичей и рефекторинге существующего кода, обучение других членов команды методикам автоматического тестирования.

Позже был использован Codeception для приёмочного тестирования API. Позже был использован Codeception для приёмочного тестирования API. Были попытки использовать его и для функционального тестирования веб-интерфейса, но на фронтенде, начавшем к тому моменту активно использовать AngularJS были проблемы с поддержкой таких тестов, пришлось временно отказаться.

О себе я могу сказать — test infected. Чего и Вам желаю. Я не могу разрабатывать без тестов. Я не верю в работоспособность чьего-либо кода, если на него нет тестов. Я верю что любой код, на который нет авто-тестов будет отправлен на помойку. Он просто будет ломаться со временем и в какой-то момент окажется, что дешевле его переписать с нуля и с тестами, чем приводить в работоспособное состояние, путём отладки вручную.

В Yii есть механизм для работы с фикстурами, который во многом компенсирует сложности тестирования Active Record. Поддержка Ваших фикстур — то о чём стоит задуматься с самого начала. Используйте для их организации способы, которые облегчат будущую поддержку:

  • можно использовать require для разбиения больших файлов по бизнес-процессам, ролям, ещё какой-то доменной логике
  • семантически осмысленные имена (aliases), указывающие в каких именно test cases эта запись используется, с какими другими моделями она связана (relation)
  • для меня было несколько неочевидных моментов в работе FixtureManager, пришлось читать исходники. Всегда стоит знать используемый инструмент
  • не забывайте явно очищать таблицы (tearDown / setUp), заполняемые в процессе теста, чтобы избежать побочных эффектов от разделяемого тестами состояния



Active Record



Active Record — это тоже один из плюсов и одновременно минусов фреймворка. Плюс в том, что при прототипировании database first подход, поощряемый кодогенерацией классов моделей по схеме, может существенно ускорить разработку, а также в том, что порой проще работать с моделью, в контексте которой можно делать и запросы и валидацию и вообще всё что с ней связано. Минусы начинаются, когда бизнес-логика слишком велика для того чтобы всю её помещать в модель, и нарушение принципа единственной ответственности даёт о себе знать — Active Record это же и Domain Model, и Repository, и Data Mapper, и Table и Row Gateways одновременно.

Если Вы видите, что предметная область сложнее сайта-визитки или банального блога — используйте альтернативные шаблоны проектирования, чтобы разгрузить ваши модели: в Yii есть разнообразные пути для этого:

  • можно использовать модели форм для валидации пользовательских данных, до того как передавать их в модель
  • валидаторы удобно оформлять отдельными классами
  • существуют поведения (bеhaviors для композиции вместо наследования!), которые помогают в организации различной переиспользуемой служебной функциональности
  • модель легко декомпозировать делегируя некоторые методы стратегиям — например, если вы кастомизируете во многих моделях метод search() — он наверняка становиться достаточно большим чтобы заслуживать подобный рефакторинг.


Такой подход проще в тестировании и позволяет моделям не заплыть «жиром».

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

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

  • всегда создавайте свой супер-класс уровня для моделей
  • не редактируете генерируемый код — наследуйте от его!
  • кастомизируйте шаблон и логику генератора для своих нужд — Yii позволяет делать это!
  • размещайте в ваших моделях только тот код, который находиться на уровне взаимодействия с базой данных — таблицы, имена колонок, условия запросов. Избегайте знания о структуре базы данных в других слоях приложения, хорошо если ваши классы Active Record будут самым низкоуровневыми в приложении
  • проверяйте результат работы gii: не все виды сложных связей генерируются корректно, иногда приходиться отступать от чистого реляционного проектирования или реализовывать вручную код, которые не удаётся сгенерировать.



Service Locator, services and singletons



По сути, экземпляр приложения, статически доступный как Yii::app() — есть сам себе singleton и сервис-локатор для компонентов приложения. Если без ООП фанатизма, это вполне рабочее решение, если вам не нужно иметь два разных экземпляра приложения в одном процессе.

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

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

Для автокомплита ваших компонентов воспользуйтесь рецептом от Александра Макарова.


Namespaces и другие новшества языка



Так как первая версия Yii была выпущена в конце 2008 года и поддерживает php 5.1 — в ней не используются пространства имён на уровне ядра. Но это не мешает Вам использовать их. В проектах на первой версии я успешно использовал их.

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

// «старый» подход
    'modules'=>array(
        'testmodule' => array(
            'class' => 'application.modules.testmodule.TestModuleModule',
        ),
    ),
// рекомендуемый в документации подход, для версий PHP >= 5.3
    'modules'=>array(
        'testmodule' => array(
            'class' => '\mynamespace\modules\testmodule\TestModuleModule',
        ),
    ),
// в 5.5 и выше это можно делать ещё удобнее
    'modules' => [
        'testmodule' => [
            'class' => \mynamespace\modules\testmodule\TestModuleModule::class,
        ],
    ],


И ещё пара улучшение для Вашего кода, о которых Вы возможно не знали, или забыли:

  • CgridView columns может принимать для value выражения не только в виде строки для eval'а но и анонимную функции.
  • Кастомизировав шаблон генератора можно использовать свои пространства имён, короткий синтаксис массивов, актуальное psr форматирование кода и всё что вашей душе угодно.
  • Yii1 можно подключить через composer.



Расширяйте фреймворк



Одним из недостающих классов в Yii1 для меня был web\Response, при том что существует Request. Написание простейшей реализации класса ответа, и добавление супер-класса для контроллеров, с обработкой оного в afterAction(), позволило модульно тестировать контроллеры, и в итоге избавить из от лишнего «жира».

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

А ещё, у сообщества есть полезные расширения, не только функциональные, но архитектурные. К примеру мы в проекте используем ObjectWatcher — реализация Identity Map — для того чтобы в разных контекстах работать иметь одни и те же экземпляры моделей, и NestedTransaction.

Не забывайте мудрые слова Стива МакКоннелла:

Программируйте с использованием языка, а не на языке.


Эта сентенция справедлива и для фреймворков: будьте Разработчиками, а не %framework_name%-программистами!

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


  1. Assada
    25.04.2016 16:04
    +1

    Хочу заметить что

    Быстрое прототипирование, может создавать у заказчика и менеджмента иллюзию

    это не проблема конкретного фреймворка, также как и низкий порог вхождения.


    1. samizdam
      25.04.2016 21:09
      +2

      Да, не только конкретно Yii.
      Но, на мой вкус, в сравнении с другими решениями, часто используемыми в стеке для аналогичных задач (Symfony, Zend) он лучше именно для быстрого прототипирования и легче для новичков.


    1. hudson
      25.04.2016 21:50

      У меня тут нарисовалось несколько legacy проектов на Yii, которые поддерживают подрядчики, а я… ну вероятно курирую их. Так вот, у меня создалось впечатление, что некоторые особенности Yii поощряют использование «слабых» сторон PHP, ну и вообще непопулярных практик.

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

      Повсеместное использование god object и его публичных статических полей типа \Yii::$app->{whatever}, и, как следствие на вопрос, а «где DI» — глаза как у Кота из Шрека — «нет, не видели...»

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


      1. M-A-XG
        27.04.2016 21:07

        >PHP шаблоны, которые буквально подначивают, чтобы в них всунули что-то не свойственное для представлений.

        Это каким таким образом?

        Такое можно везде наделать при желании :)


        1. hudson
          27.04.2016 21:17

          Ну в Twig надо приложить смекалку, чтобы такое провернуть =)


          1. M-A-XG
            27.04.2016 21:36
            -3

            Я вообще против дополнительных шаблонизаторов.
            PHP сам отличный шаблонизатор.

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


            1. hudson
              27.04.2016 22:44
              +1

              Не могу поддержать данную точку зрения (особенно в свете высказываний в стиле «не работал, но осуждаю»). Но если вас всё устраивает — пользуйтесь. Я не навязываю свою позицию.


            1. Fesor
              28.04.2016 00:26
              +3

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


              Поработайте, шутки ради. А заодно разберитесь как оно работает. На данный момент это лучшее решение для организации шаблонизации в PHP. Одно и самый главных преимущесвт — ограничения которые оно налагает на разработчиков. Для того что бы сделать что-то не правильное надо разбираться, и для многих это повод задуматься как же все же делать правильно. Новичкам нужна смирительная рубашка, и «снимать ограничения» нужно только по мере получения опыта и понимания того с чем работаешь.

              А извращения никогда не нужны. Если они нужны — значит вы где-то свернули нетуда. Хороший код должен быть скучным и предсказуемым.

              p.s. Смарти ужасная штука… лет так 10 назад было прикольно, сейчас не очень.


              1. M-A-XG
                28.04.2016 11:00

                >Новичкам нужна смирительная рубашка, и «снимать ограничения» нужно только по мере получения опыта и понимания того с чем работаешь.

                Новичкам не стоит сразу лезть на фреймворки…
                Целевая аудитория фреймворков — не новички ж? :)


                1. Fesor
                  28.04.2016 16:40
                  +1

                  Новичкам не стоит сразу лезть на фреймворки…


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

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

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

                  Целевая аудитория фреймворков — не новички ж? :)


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

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


              1. hudson
                28.04.2016 14:52
                +1

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


                1. Fesor
                  28.04.2016 16:41

                  я потому и сказал что лет 10 назад было прикольно (ну или сколько там, лет 6-7 назад еже даже)


  1. SamDark
    25.04.2016 16:11
    +1

    Были не поддерживаемые тесты под Selenium, почему-то написанные на Java

    Потому что раньше не было нормального драйвера под PHP. То, что было фейлило слишком часто.


    1. samizdam
      25.04.2016 21:18

      Сохранилось ещё такое предание, что писались они студентом-стажёром, которого занять чем-то надо было, а кроме Java он не владел ничем =)

      Как я предполагаю, год написания упомянутых тестов, вероятнее всего 2014.
      Я codeception уже использовал вместе с силениумом, примерно в это время, если ничего не путаю, не помню чтобы были большие проблемы. Но там не было потенциальных сложностей для тестирования, так что может просто повезло.


      1. hudson
        25.04.2016 21:56

        Селениум изначально Java-фреймворк. Лет 10 назад, когда вставал вопрос на чем писать тесты к API на Java мы проголосовали за Java, чтобы не париться с конвертациями. Но порог входа там конечно повыше чем в Yii, хотя традиционно (ошибочно) считается что тестировщик (в идеальном мире — инженер по качеству) должен быть не умнее программиста-джуниора.


      1. SamDark
        26.04.2016 02:14
        +3

        Не, ну в 2014 всё было уже нормально. Я про 2007—2009 где-то.


  1. aezhko
    25.04.2016 19:29
    -6

    Столкнулись на большом продукте с адовыми тормозами ActiveRecord и непрозрачностью DefaultScope'ов. Действительно, эти подходы годятся только для совсем маленьких сайтов.


    1. Assada
      25.04.2016 20:21
      +1

      А можно подробнее про тормоза ActiveRecord?


      1. AlexLeonov
        25.04.2016 21:40
        -2

        Вангую что тормоза не в самом ActiveRecord, а в чудовищном SQL-коде, который производят сложные relations в моделях Yii при неправильном их использовании.

        Но это не Yii виноват, разумеется, а DBA проекта.

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


        1. Miraage
          25.04.2016 22:04
          +1

          Не зная броду, не суйся в воду


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


          1. AlexLeonov
            26.04.2016 12:06
            +1

            Вы неправы. Опыта с Yii у меня достаточно. И я имею все основания не любить этот фреймворк.

            Интересно другое — что такого оскорбительного для себя вы нашли в моем комментарии, что немедленно пустились в ответные оскорбления? Какие ваши чувства задеты?


        1. aezhko
          26.04.2016 13:11
          -3

          Вы хотите сказать, что есть возможность спроектировать реляционную БД с миллионными табличками так, что производительность сильно нагруженного приложения, построенного с применением YII AR будет сопоставима с производительностью того же приложения, использующего для доступа к данным «простые запросы»?


          1. Alxdhere
            26.04.2016 13:28
            +3

            Если запросы из приложения на Yii будут возвращать десятки записей, т.е. фреймворку придется создавать только десятки AR, то вполне сопоставимы. Скажем так, конечный пользователь не заметит разницу.
            Но если вы имеете ввиду, что запросы будут возвращать 100500+ записей, то от AR надо отказаться.


            1. AlexLeonov
              26.04.2016 16:23
              +2

              если вы имеете ввиду, что запросы будут возвращать 100500+ записей, то от AR надо отказаться

              От запросов таких нужно отказаться. Нет никакой необходимости тащить на сторону PHP тысячи и более записей из БД. Если же такая необходимость возникает — пора заняться аудитом архитектуры. И зарплат разработчиков.


              1. Alxdhere
                26.04.2016 16:29

                Зачем же так категорично. Лично мне пришлось такую задачу решать. Банальный экспорт данных. Их может быть много и их надо тащить на сторону PHP.
                Сперва пробовал CActiveDataProvider, таскал по 100 записей. Получилось невыносимо медленно. Переделал на CArrayDataProvider и все зашевелилось.


                1. aezhko
                  26.04.2016 17:03

                  О подобных кейсах я во всей этой ветке и говорю.


              1. aezhko
                26.04.2016 16:52

                Вот прям сразу аудитом архитектуры? Даже если задача свормулирована как «отобразить 100500 записей»?)


                1. AlexLeonov
                  26.04.2016 17:04
                  +1

                  Вряд ли тот, кто ставил такую задачу, действительно хочет на одном экране видеть более 100 тысяч записей. Уточните задачу для начала ))


                  1. aezhko
                    26.04.2016 17:10

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

                    Конкретно в нашей команде, после названного Вами выше аудита архитектуры, мы внутри команды (не маленькой и не дешевой) пришли как-раз к тому, что от использования AR в пользовательской части системы имеет смысл отказаться, так как оверхед по ресурсам не стоит удобства, которое приносит использование данного шаблона.


                    1. AlexLeonov
                      28.04.2016 10:42

                      Я вас не понимаю.

                      Для меня ActiveRecord — это просто два метода save() и delete() у объекта. Какой оверхед по ресурсам вам создают эти два метода? Зачем нужно от них отказываться?

                      Поясните, пожалуйста.


          1. AlexLeonov
            26.04.2016 15:18

            А что такого экстраординарного в «миллионных табличках»?

            Даже для MySQL без всякого тюнинга таблицы на 10**6 — 10**7 записей не составляют никаких проблем. Я уж не говорю о более «взрослых» СУБД.

            И да. Я не знаю, что такое «сильно нагруженное приложение» в вашем комментарии. Вы в Badoo работаете? Или в Mamba? А может быть mail.ru? Нет? А откуда у вас тогда нагрузки? Ах, от собственной же архитектуры…


            1. aezhko
              26.04.2016 15:43

              При чем тут СУБД, если мы говорим о конкретной реализации конкретного шаблона проектирования, а если точнее о ее минусах? И при чем тут мое место работы, оно как-то влияет на эту эти минусы? Я всего лишь говорю, что данная реализация не подходит для нагруженной работы с крупными данными, и у меня есть примеры, когда в продакшене от этого было реально больно. Вы утверждаете, что дело в архитектуре БД/Приложения, возможно, вы сможете привести контрпример?)


              1. AlexLeonov
                26.04.2016 16:19
                +3

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

                Разговор бессмысленный.
                — не тащите на сторону PHP много данных из базы, берите только необходимое
                — используйте базу, как СУБД, а не как хранилище, переносите логику выборки на сторону базы
                — не используйте MySQL
                — не используйте без нужды сложные relations в Yii, без четкого понимания, какие именно запросы генерируются
                И будет вам счастье.

                А если вам вдруг мешает реализация ActiveRecord в Yii — подумайте, может в танцоре дело?


                1. aezhko
                  26.04.2016 16:37

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


                  1. AlexLeonov
                    26.04.2016 17:06
                    +2

                    Будьте точнее в формулировках — и не будет в ваш адрес очевидных постулатов.

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

                    Ну не всегда. И что? Никто и не утверждал, что «AR — всегда!»

                    А в целом я рад, что мы услышали друг друга.


                1. M-A-XG
                  27.04.2016 21:13
                  -2

                  >не используйте без нужды сложные relations в Yii

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

                  Кстати, Yii 1.1 не способен отобразить связанную модель связанной модели. :)


                  1. zelenin
                    27.04.2016 21:21

                    способен


                    1. M-A-XG
                      27.04.2016 21:47

                      И каким же образом можно обратиться к профилю автора в
                      $posts = Post::model()->with('author.profile')->findAll();
                      ?


                      1. zelenin
                        27.04.2016 22:24

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


                        1. M-A-XG
                          27.04.2016 23:56
                          -1

                          Что не ясно? :)
                          Как вытащить данные из profile?


                          1. zelenin
                            28.04.2016 00:01
                            +3

                            неясно то, что я написал комментом ранее — вы в разных комментах по разному сформулировали проблему.

                            $profile = $post->author->profile;


                            1. M-A-XG
                              28.04.2016 11:39
                              -1

                              $post->author->profile выводит только первичный ключ
                              Обратиться к
                              $post->author->profile->name уже не выходит,
                              Вышло так:
                              $post->author->getRelated('profile')->name

                              Не совсем в одном стиле :)
                              И в документации это почему-то не отражено.


                              1. zelenin
                                28.04.2016 16:25
                                +2

                                >>> $post->author->profile->name уже не выходит,

                                это чисто ваша какая-то проблема с описанием связи. Связи работают именно в едином стиле.


                              1. michael_vostrikov
                                28.04.2016 18:45
                                +3

                                Подозреваю, что у вас поле в БД тоже называется profile (а надо называть profile_id), и при обращении читается прямое значение атрибута, а не вызывается геттер для связи.


      1. aezhko
        26.04.2016 00:19

        Ну, разница в производительности выполнения одного и того же запроса, построенного через тот же command и те же criteria легко может составлять до десятка раз.


    1. Miraage
      25.04.2016 20:43
      -1

      1) DefaultScope / Lifecycle Callbacks (beforeSave, afterUpdate) — зло, не используйте их никогда
      2) ActiveRecord хорош до тех пор, пока вы не переборщите с магией. Как только появляются симптомы bottleneck в ActiveRecord — бежим к DataMapper/QueryBuilder


      1. samizdam
        27.04.2016 18:25

        1) Слишком категоричное утверждение. DefaultScope является хорошим решение для некоторых кейсов. before / after стоит использовать с осторожностью, но в некоторых случая они бывают полезны. Инструмент не зло, а помощник, если им владеть. В той же doctrine, event based hooks имеют место быть, у событий есть свои сценарии применения, полезности и сложности.
        2) С магией всегда стоит быть осторожным, на то она и магия) Я стараюсь избегать.


      1. M-A-XG
        27.04.2016 21:14

        Ага, запустили проект так, что-то изменили, а тут вдруг появились бутылочные горлышки.
        Нужно все переписывать.
        Это типа строили дом, а потом его нужно сломать и заново построить :)
        Шикарно.
        Архитектура на все 100.
        А, ну да, хоумпаджи с такими проблемами не столкнутся, что намекает на что расчитан AR.


    1. M-A-XG
      27.04.2016 21:08
      -2

      +100500 про маленькие сайты.

      Не знаю, почему минусуют :)


  1. vKreker
    25.04.2016 22:39
    +1

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

    У Yii есть три очень весомых преимущества — хорошая документация, качество фреймворка и большое сообщество. Первое и второе способствует привлечению новых программистов и познанию фреймворка. Третье — грамотным консультациям, разработке новых дополнений и переработке фреймворка. На выходе мы получаем хороший и популярный продукт.
    Здесь стоит кинуть палку в сторону Angular. Документация никакая, сообщество маленькое. Как результат имеем скверный фреймворк и малое количество специалистов.


    1. atc
      25.04.2016 23:45
      +1

      Но простите, репо angular1 48,787 звезд, yii2 7,957. Более того, angular распространен повсеместно, а yii2 большей частью на территории СНГ.

      Относительно минусов yii2, главным на мой взгляд минусом является гвоздями приколоченное ActiveRecord и отсутствие в документации инструкций по интеграции DataMapper, что влечет за собой непопулярность TDD\DI\DDD практик в сообществе.
      Так же к минусам (а возможно и к плюсам) следует отнести явную нацеленность фреймворка на прототипы, об этом говорит обилие странных виджетов, вроде Pjax\Modal\Nav\Carousel, полезных на этапе прототипа, но слишком сложных в кастомизации для продакшена.


      1. zelenin
        26.04.2016 03:57

        мне понравилась фраза автора статьи про «прототип выкидывать». Yii — RAD-фреймворк, и действительно хорош для прототипирования: набросали, нагенерили — работает. А дальше начинаем программировать с нуля на инструменте без навязанной архитектуры. Рядовой же член сообщества Yii уверен, что фреймворк популярен из-за своего качества и удобства и подходит для любых задач, ничего не знает о техническом долге, и ничего не слышал о ddd/solid/tdd. И продолжает набивать в модель следующую тысячу строк: «ну не еще же один класс создавать»/«сервис? это сложно!».


        1. M-A-XG
          27.04.2016 21:18

          Строили, строили дом, а потом взяли, передумали, развалили и начали строить заново :)


          1. zelenin
            27.04.2016 21:19

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


            1. M-A-XG
              27.04.2016 21:49

              То есть Yii таки говно?

              И это какой-то странный подход к разработке. :)


              1. zelenin
                27.04.2016 22:27

                я про yii не писал.
                Это не подход к разработке, а способ быстро набросать концепт например для показа инвестору.


    1. zelenin
      26.04.2016 03:46
      +1

      немного понимать ООП и научиться тыкать кнопки — это и есть низкий порог входа. Знать некоторые паттерны для yii не надо.
      Именно этот низкий порог и способствует наряду с хорошей документацией привлечению новых программистов, но ни в коем случае не качество. Если фреймворк и работает, то уровень 99% сторонних расширений ниже плинтуса. И все это опять же следствие низкого порога. Низкий порог => большое сообщество программистов низкого уровня. Популярность всегда напрямую коррелирует с уровнем. Это просто данность.


      1. vKreker
        26.04.2016 13:32
        +1

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

        Yii подходит для большинства задач. Ведь в большинстве своем сайты достаточно просты (визитки, корп-порталы, простые crm).
        Если система достаточно сложна, естественно, используют другие решения. Да и уровень задействованных программистов гораздо выше.


    1. zhigalin
      26.04.2016 22:47

      >знать некоторые паттерны, научиться генерировать модели
      Можно поподробнее?


    1. M-A-XG
      27.04.2016 21:17

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


  1. bardex
    26.04.2016 15:46

    А как вы видите перспективы фреймворка Yii (пока второй версии) в будущем? В беседах с коллегами по цеху, всплывает тема, что это умирающий фреймворк, имеет ли смысл начинать учить его сейчас?


    1. zelenin
      26.04.2016 16:08
      +2

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


      1. bardex
        26.04.2016 18:24

        а если не джуниор, но проекты небольшие и тащить симфони нет смысла?


        1. zelenin
          26.04.2016 19:18

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


  1. Serega67
    26.04.2016 22:47

    Добрый вечер!
    Интересная статья, понравилась.

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


    1. samizdam
      26.04.2016 22:56

      Скорее всего, если код писался на протяжении года без тестов, с ним в нагрузку идёт существенный технический долг, и он будет сопротивляться тестированию. Учитывайте, что одно из главных преимуществ unit-тестирования, не в верификации правильности программы (этим QA-инженеры должны заниматься или профессиональные тестировщики), а в том, что тесты улучшают архитектуру приложения на уровне кода. Иными словами, чтобы код был тестируемым, Вы будете вынуждены делать его более модульным, менее связанным и простым.
      Покрывать тестами существующий код, без хорошего опыта в тестировании и существенного рефакторинга, может оказаться невыполнимой задачей.
      Возможно, на первом этапе, будет проще попробовать новый функционал писать через тесты: сперва тесты — потом код.
      Рекомендую так же, если ещё не читали, почитать книгу Кента Бека: очень доходчивая методичка о разработке через тестирование на простых и очевидных примерах.


    1. M-A-XG
      27.04.2016 21:20

      Очевидно же, с того, что чаще всего используется… :)


  1. M-A-XG
    27.04.2016 17:55

    Так дело в том, что Yii рекомендует жирные модели:
    www.yiiframework.com/doc/guide/1.1/ru/basics.best-practices#sec-2
    :)


    1. samizdam
      27.04.2016 17:59

      Вы лукавите, выдёргивая один тезис из контекста. Там же написано:

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

      Далее идёт пример разделения ожиревшей модели при помощи наследования. Но, как я писал и статье, композиция предпочтительнее наследования, хотя и несколько сложнее в реализации.


      1. M-A-XG
        27.04.2016 21:02

        Я в курсе о наследовании. Но это уже ООП головного мозга.
        Про это есть в статье: http://blog.kpitv.net/article/frameworks-1/

        Да и все апологеты фреймворков за жирные модели почему-то.
        Аж странно.


        1. zelenin
          27.04.2016 21:27

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


  1. M-A-XG
    27.04.2016 21:04
    -2

    В стате почему-то смешаны лучшие практики с личным опытом, не совсем касающимся этих практик :)


  1. M-A-XG
    27.04.2016 21:23

    >Программируйте с использованием языка, а не на языке.

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


  1. Alxdhere
    28.04.2016 06:17

    Из всех критикующих комментариев складывается впечатление, как будто Yii всей своей сущностью и натурой заставляет программиста писать неэффективный/буксующий код, а все остальные фреймворки — нет. По-моему все зависит от программиста, его компетенции в PHP в целом и в Yii в частности!
    Как говорится, нечего на зеркало кивать, коли рожей не вышел.


    1. Fesor
      28.04.2016 10:36
      +2

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

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


    1. M-A-XG
      28.04.2016 15:57
      -1

      Все фреймворки заставляют писать буксующий код :)