Симфония самоподдува
Иногда, несмотря на все недостатки, технология выстреливает. Все эти проблемы видят, ругаются, удивляются, но ничего сделать не могут. Уже выстрелило, а значит придется пользоваться, неожиданно, конечно, но раз в год и палка стреляет. Хотя стремительное появление новых технологий в сфере веб-разработки скорее напоминает работу многоствольного деревянного пулемета, изрыгающего фекалии. Переходя от метафор к конкретике, предположу, что PHP-фреймворк Symfony, на мой взгляд, является ярким представителем таких технологий. И о проблемах этого фреймворка я бы и хотел поговорить. Среди тех, кто пишет на Symfony встречается много людей, которые его искренне любят. А среди тех, кто его не любит встречается много людей, которые тем не менее этим фреймворком зарабатывают. Так что все написанное ниже не более, чем психотерапия для последних, а также удобная ссылка для троллирования первых фанатами, например, Yii.
Введение Когда 4 года я впервые начал работать с этим фреймворком, мне показалось, что он переусложнен. В коммьюнити мне объяснили, что я нуб, который опробовал не так много других веб-фреймворков, чтобы делать выводы. Это объяснение меня удволетоврило. 3 года назад мне посчастливилось работать в паре с человеком, фанатом Symfony, который все хотел делать правильно и согласно идеологии, из-за чего мы безбожно срывали сроки. Коллега объяснил мне это тем, что говнокод клепать не надо. Это объяснение было из области идеологии и я предпочел не спорить. 2 года назад я сделал несколько типовых проектов сам, используя так мало компонентов Symfony как только возможно, и был приятно удивлен этим фреймворком. Коммьюнити сказало мне, что у меня низкий уровень интеллекта из-за чего я не способен эффективно оперировать сложными абстракциями. Это объяснение не то что бы меня удволетворило, но худо бедно объясняло происходящее. Год назад мне на поддержку попался проект, владелец которого был недоволен высокой стоимостью поддержки и малой скоростью разработки. Проект писали серьезные ребята, все было сделано по книжке, идеальный код. Было задействовано все: фильтры ассетика, все фичи форм, активно использовались события, были использованы лучшие популярные бандлы где была хоть малейшая возможность не писать свой код, в общем код был редким эталоном, который и в опенсорсе нечасто увидишь. Я списал произошедшее на то, что «звезды» устали заниматься рутинной поддержкой и стали работать спустя рукава. Ну, а что мне еще оставалось думать, если бандлы к фреймворку множились, а сам фреймворк мало того что получил грант, так еще и всюду считался верхом совершенства? И вот наконец месяц назад, я был вынужден оставить и этот проект, передав его другому программисту. Начав искать себе замену, я столкнулся с тем фактом, что все вопросы по Symfony, которые я мог придумать на собеседование, так или иначе упирались в знание справочной информации, что, учитывая ее обилие, было неудивительно, но неудобно. Стратегия поиска «просто вменяемого программиста» была бы провальной — нужен был человек, который бы сразу въехал в проект, не тратя свое время на борьбу с премудростями фреймворка, уже набивший шишки. Тем более сам проект был обыкновенным CRUD-ом, пусть и объемным. В итоге я просто составил примерный список основных вещей с которыми должен столкнуться каждый программист, чтобы проверить правда столкнулся ли с ними кандидат перед тем как столкнуться со мной. Но такой подход заставил меня задуматься.
По результатам нескольких проведенных собеседований я пришел к некоторым выводам. Во-первых Symfony толком не знает практически никто, за исключением людей, которые не просто с ней работают, но, простите, пердолятся в нее. Во-вторых даже те люди, которые знают многие компоненты Symfony, ругаются на их переусложненность и в результате не используют их. Все это окончательно убедило меня в том, что с этим фреймворком что-то не так.
Немного истории Сейчас Symfony около 5 лет, но это так называемая Symfony 2 — вторая ветка фреймворка, совместимая с первой на уровне названия почти полностью (не считая двойки в конце). В остальном это разные фреймворки, и первая ветка уже благополучно всеми забыта, поэтому речь пойдет о фреймворке Symfony 2, первые коммиты в github репозиторий которого были сделаны в январе 2010. С самого начала фреймворк позиционировался как сборище всего самого нового, лучшего и продвинутого в веб-разработке на PHP, и это были первые плиточки на дороге, ведущей в ад. Сейчас это уже четырехполосное шоссе. Корпоративность из фреймворка перла до такой степени, что создатель предлагал обучающие курсы с сертификацией еще в то время, когда фреймворк был несколько далек от готовности к промышленному использованию. А может это просто был способ монетизации, и если так, то он удался. Само наличие таких курсов уже говорило о том, что фреймворк был не для слабых духом и вообще предназначался для произведения впечатления на серьезных дяденек, которые привыкли видеть стойкую корреляцию между сертификатом и профпригодностью обладателя сертификата. И ведь правда, там была калька со многих вещей из уютного java-мирка: и dependency injection, когда даже родную мать можно объявить сервисом, была бы пустая строчка в конфиге, и ORM по сложности сравнимый с Hibernate, и аннотации, которые были больше чем аннотации, и, в качестве завершающего штриха, сверхмодульная структура, дико дробленая на файлы и пытающаяся выжать все из возможностей ООП в PHP.
Все это настолько соответствовало духу высокого штиля в программировании, что однажды создатель фреймворка получил грант на развитие своего детища в размере 7 млн. долларов. Серьезный фреймворк для серьезных задач получил не только аргументы в рамках действующей идеологии совершенного кода, но еще и аргумент понятный всем программистам, даже совершенно не связанным с совершенным кодом, и более того, не связанных с программированием.
Сперва фреймворк распиарили, и, несмотря на его адову кривизну в 2011 году, все только и говорили какой он замечательный. Что характерно, многие, в том числе я, повелись на это и решили выбрать этот фреймворк как способ профориентации. Некоторые молчали, некоторые плевались, за счет демагогии и активной подмены понятий (компоненты симфонии используются много где == симфония используется много где) проблемы в значительной мере замалчивались, а популярность фреймворка росла. А после получения гранта можно было заткнуть любого скептика. Круг самоподдува замкнулся.
Коротко о главном Фреймворк переусложнен, причем без видимых на то причин. И все это прибито ментальными гвоздями. В попытках сделать архитектуру фреймворка максимально гибкой была нагорожена тонна абстракций, требующих бойлерплейта и времени на то, чтобы заставить полезный код работать в рамках этих абстракций. Чтобы все было как в Java, но только в PHP. Избавиться от этого нет никакой возможности — отход от стандартной идеологии крайне не одобряем сообществом. Нельзя просто взять и отказаться от использования компонента, который вам стал поперек проекта. Это повлечет сильные репутационные издержки для того несчастного, который предложит, например, не использовать стандартный ACL или формы. Если вы захотите выкинуть Doctrine из своего проекта, то вам придется потом долго и нудно объяснять каждому встречному, почему вы это сделали под укоризненное качание головы. Сами по себе компоненты Symfony очень хороши (из-за этого у многих сторонних разработчиков складывается впечатление, что весь фреймворк так же хорош), но когда они собираются вместе, начинается страшное.
Хоть прошло и порядочно времени со времен создания PHP, а многие стереотипы потеряли актуальность, очень часто в области веб-разработки до сих пор творится трэш. В мелких проектах никто не пишет тесты, никто не работает над хорошей архитектурой, никто не думает о том, как это потом поддерживать. Да чего греха таить, в средних и крупных все это начинает происходить уже после того как проект «выжил». Это плохо, но это норма жизни. По моим ощущениями, то что пишут на хабре про то, как правильно разрабатывать программы, соблюдается дай бог 20–30% разработчиков. В остальных случаях это трэш, в котором совершенный код — подойдет только в качестве эпитафии на могилу проекта. Тут применение Symfony по всем стандартам качества — не просто метание бисера перед свиньями, это заливание скотины таким количеством бисера, чтобы она хрипела и дохла, захлебываясь им.
Symfony дает колоссально извилистую кривую обучения, на вершине которой вас ждет не эффективность разработки выше чем на других фреймворках, а умение бороться с самой Symfony. Порой это тот фреймворк, где проще все переписать самому, чем следовать его гайдлайнам. Я думал что я идиот не способный понять симфонию ровно до тех пор пока не встретил код от человека, выступающего по конференциям по Symfony, и поддерживающим собственный форк этого фреймворка. Этот код реализовывал собственный механизм ACL. В комментариях к коду была заметка — собственный ACL писался из-за сложности стандартного ACL в Symfony. Возможно он тоже идиот, тут не угадаешь, но есть над чем задуматься, а в целом вырисовывается забавная картина.
Symfony-only developer Сложность фреймворка такова, что я ловлю себя на мысли, что если пару недель активно не работаю над проектом на Symfony, то мне потом приходится въезжать не только в сам проект, но и во фреймворк. Возможно у меня плохая память, но сможет ли более памятливый читатель, считающий что такой сложности нет, сходу вспомнить и написать без гугла и копипаста как: сделать наследование таблиц в доктрине, типичное действие для нескольких групп пользователей добавить новую роль в стандартный ACL добавить хелпер в Twig добавить аннотацию для для VARCHAR и TEXT в модели добавить репозиторий добавить новую группу валидации в форму добавить трансформер в форму объявить нечто как сервис, возможно с несколькими аргументами, возможно написать фабрику для этого сервиса реализовать загрузку файла, привязанного к Entity добавить в доктрину поддержку очередной агрегатной функции SQL написать консольную команду Если вы таки помните все это наизусть, то поздравляю — у вас феноменальная память. К сожалению я не могу это запомнить, потому что каждый из этих пунктов обычно приходится реализовывать не чаще чем раз в неделю. Поэтому Symfony стала для меня первой технологией, для которой я завел справочник, который регулярно пополняется. Поэтому у среднего программиста вроде меня есть два пути. Послать к чертовой матери большую часть возможностей Symfony и краснеть каждый раз, когда кто-то видит ваш код. Или же завести себе справочник, потому что для постоянного гугления всех нюансов у вас должно быть терпение, дарованное не каждому среднему программисту. Есть еще и особый третий путь, исконно русский, он заключается в том, что вы устраиваетесь работать в низкопробную веб-студию, которая клепает сайты по шаблону, а значит вы будете по 10 раз на дню повторять одни и те же немногочисленные операции, что даст возможность их запомнить. И даст стойкую иллюзию того, что вы таки знаете Symfony. Хотя если вы достаточно пытливы, то вы ее узнаете. Только зачем?
К сожалению, я не нашел способа как отвечать всем требованиям современного программиста на Symfony, не словив при этом симфонию головного мозга. Если вы, дорогой читатель, обнаружили таковой, и он не является выигрышем в генетическую лотерею, то поделитесь им в комментариях.
Конструктор Когда я мельком прочитал о том, что Drupal с версии 8 имеет много общего с Symfony, неудивлению моему не было предела. Ведь оба продукта по сути конструкторы сайтов, несмотря на то, что в одном случае мы имеем CMS, а в другом — фреймворк общего назначения. Возможно, что концепция конструктора для большей части современного web — это та концепция, которая позволит сэкономить время, повысить безопасность за счет использования многократно протестированных компонентов. Там еще есть всякие рюшечки, которые смотрятся очень красиво, а старой веб-макаке, не знающей слов дизайна, для самостоятельной реализации недоступны. А заказчики это любят. Рюшечки, а не старых веб-макак. Но есть некий баланс между тем, сколько времени вы потратите на допиливание готового блока, чтобы он работал в вашем проекте, и тем, сколько времени лично вы потратите на то, чтобы самому написать этот функционал. Этот выбор очень неоднозначен в случае Symfony — сложность самого фреймворка, насаждение сложной для восприятия архитектуры бандлов, кривизна самих бандлов, порой ломающихся при минорном обновлении, все это делает использование готовых блоков не таким уж очевидным выбором. Пусть даже готовый бандл сэкономит вам много часов в будущем, если вы не выкатите новый функционал сегодня, будущего может и не быть. А вы можете и не выкатить, если будете разбираться с бандлом — не все они заводятся с полоборота. Бывали случаи когда я выкидывал после нескольких часов мучений бандл-обертку вокруг популярной библиотеки и в итоге использовал свою обвязку или же прямой доступ к библиотеке. Symfony сейчас популярна, а значит туда лезет толпа самопиарщиков, жаждущих получить сотню-другую звездочек на гитхабе. К сожалению после первых нескольких звездочек энтузиазм таких программистов угасает и багфиксы вы можете делать собственноручно.
Идея же крупного сайта-конструктора часто критикуется из-за того, что такой подход несет сложности в поддержке и поиске тех, кто сможет это поддерживать. Вы не можете найти человека сходу под те технологии, что у вас есть. В Perl-мире это даже одна из самых распространенных проблем — от веб-фреймворка остается только название, под капотом может скрываться все что угодно. И это приводит к поиску «просто хорошего программиста» и даче ему времени, чтобы въехать в проект. Для PHP, где очень значительная часть проектов — мелочь, бюджеты для которых малы, а на рынке труда куча посредственных кадров, поддержка сайта-конструктора вообще вызывает серьезные вопросы.
Ни туда ни сюда Symfony, в том виде в каком она есть сейчас, занимает непонятную нишу. Выше было написано, что лучше всего она подходит для массового поклепа сайтов на базе фреймворков на ее базе. Но это донышко веб-разработки, особенно с точки зрения квалификации программистов, которые оседают на таком донышке, вкалывая по 10 часов. Но Symfony подразумевает огромные времязатраты на обучение, есть вполне официальная занудная книга по ней, которая раскрывает тонкости чуть менее, чем никак. Есть курсы по ней же. Вроде как рассчитано на крупные серьезные проекты? Хорошо, допустим. У нас вроде есть все архитектурные изыски требуемые в больших проектах. И дробленость, удобная для тестирования, и события в ядре фреймворка, и DI, а файлы конфигурации подвластны корпоративному божеству Ксамаэлю, и все такое прочее.
При ближайшем рассмотрении все это — не более, чем реализация многих паттернов, которые сами рождаются в любом крупном проекте. Но только если они нужны. Symfony однозначно говорит, что они нужны. И именно в том виде, в котором они реализованы в Symfony. Хотя применение ORM такого как Doctrine в корпоративных проектах вообще крайне сомнительно — длинные запросы на DQL по десяткам таблиц это то, что не приснится даже в самых худших кошмарах. ACL, которое будет завязано на LDAP и черт еще знает что, и которое нужно будет писать почти с нуля, пытаясь подстроиться под стандартный ACL Symfony. А глядя на иные архитектурные изыски диву даешься — компонент для дампа рекурсивных структур данных (а таковыми являются почти вещи которые вы захотите дампить) появился только в версии 2.6, уже после выпуска первой LTS ветки. Понадобилось около 4 лет, чтобы подобная элементарная фича появилась во фреймворке.
Для штучных маленьких проектов Symfony хороша за счет огромного количества бандлов. Но плоха за счет сложности обучения и… решения проблем вызванных самим фреймворком — все это отнимает время. С другой стороны на базе Symfony можно легко построить свой фреймворк, отвечающий специфике вашей работы. С третьей стороны сколько я себя помню, веб-студии и так всегда создавали для себя фреймворки на базе чего угодно для типовых сайтов. И что характерно, сложности при замене программиста те же, что в случае форка Symfony, что в случае самописного проекта.
Для современных сайтов Symfony хороша за счет… того что застряла на уровне веб 2.00, вернее первых его ревизий. Symfony Forms — это отменная вещь до тех пор пока вам не приходится делать полудинамические или динамические формы. Для круда Symfony Forms божественны, для CRUD с парой-тройкой динамический полей они терпимы, для сколько-то серьезной клиентской логики форму проще выкинуть и спроектировать заново. Валидацию и сохранение данных переделать придется тоже. Т.е. сами формы вещь отличная, но вот переход от простого фронтенда к сложному не продуман. То же касается и Assetic. Хотя во всем остальном Symfony пропагандирует самый передовой (или стереотипно-правильный?) подход во всем.
Для корпоративных проектов Symfony подходит тем, что имеет LTS и официальную поддержку, курсы с сертификацией, но плоха тем…, а впрочем программное обеспечение для корпораций независимо от фреймворка и языка всегда получается монструозным и трудным в поддержке.
Проблема изоляции компонентов Даже для незначительных изменений приходится ворошить кучу файлов. Например, если вы добавляете в форму поле, для этого нужно: добавить поле в FormType добавить рендеринг в шаблон если для нового поля нужны какие-то зависимости (например получение извне данных для listbox), то нужно сделать изменения в services.yml, конструктор формтайпа если поле привязано к какому-то полю модели, но не может быть прямо сохранено в базу, то вам нужно внести изменения в трансформер формы если это поле — файл, то возможно придется править код контроллера, если вы не хотите уродовать модель процедурой сохранения файлов если у вас правила валидации в модели (а в 90% проектов они либо там, либо в отдельном yml, но никак не в формтайпе), то добавить аннотации в модель Скорее всего вы либо полезете в справочник либо будете копипастить из соседних файлов. Изоляция компонентов по файлам и указание зависимостей одних компонентов от других тоже со временем превращается в головную боль. Вы не можете просто дернуть ядро фреймворка через global, это неправильно! Вместо этого когда вам внутри Entity понадобится сделать что-то сложное, но все-таки связанное с этим Entity, то вы можете или сделать проброс нужных зависимостей в Entity, или отрефакторить наверх всю цепочку вызовов, убедившись, что вместе с сохранением Entity происходят нужные действия.
В обоих случаях это сложно и требует высокой концентрации — вам нужно поправить конструктор Entity или его репозитория, убедившись, что нужные зависимости пробрасываются. Потом сделать изменения в services.yml. Звучит просто, но даже с IDE это требует времени. Рефакторинг с пробросом наверх действий, которые требуют зависимостей, тоже вызывает понятные сложности. Вы фактически вываливаетесь из процесса написания бизнес-логики и погружаетесь в процесс ее подгонки под фреймворк. Это примерно как отвлечься на телефонный звонок в процессе написания кода.
Для компонентов максимальная изоляция это хорошо. Для бизнес-логики это, на мой взгляд, вызывает излишние сложности. Во всяком случае в том виде, в котором это преподносится Symfony.
Сообщество Как только вы объявили нечто самым лучшим и активно это распиарили, у вас почти гарантировано появится аудитория, которая захочет приобщиться к этому новому и лучшему. Эта аудитория оправдает любые огрехи и недостатки технологии, а вас, несогласных, … не оправдает. Symfony неявно (или таки явно?) подразумевает под собой самые передовые решения, самые правильные подходы, что косвенно означает, что если ты не с Symfony то твое место в ПТУ, а твоя участь — поклеп сайтов на джумле. Старое доброе «кто не с нами, тот дурак». Ладно, допустим вы адаптировались к такому раскладу, и научились строить нужную мину при обсуждении данного фреймворка. Теперь вы сталкиваетесь с другой проблемой — передовые решения зачастую сырые, их часто забрасывают после пары месяцев активности на гитхабе сами авторы. Но вам будут их советовать, особенно сами авторы. Вы будете получать в наследство бандлы которые не заработают под 2.3 или 2.7, фиксы к которым вам придется искать по многочисленным форкам. И качество, качество… На словах вся правильность порой оборачивается соблюдением PSR и хорошей настройкой IDE. Благодаря этому тонны бойлерплейта дают ложно представление о нормальном качестве кода. Сообщество Symfony является почти идеальным примером иллюстрирующим проблему ученого дурака — знания показушны, поверхностны, истинного понимания как все это работает у многих нет, зато есть демагогия позволяющая оправдать все проблемы и непробиваемая самоуверенность.
Самое печальное, что эти люди как правило не знают весь фреймворк в совершенстве, но часто знают отдельные его куски, костыли и прочие козьи тропы. В результате когда кто-то не знает того, что знают они, они раз за разом отказываются замечать сложность фреймворка и огромное количество справочной информации, которую невозможно держать в голове. Они обитают в тесном кругу задач, где все обходные пути уже найдены, а до других частей фреймворка им дела нет.
Сообщество является главным и единственным катализатором того бедлама, который творится с Symfony. Не будь его, можно было бы выкинуть Assetic, Forms, Doctrine, а также Good Practices и использовать как Symfony как нормальный микрофреймворк из коробки.
Неужели все так плохо? Symfony не сильно хуже всех остальных фреймворков, но идеология и негласные правила, которые идут вкупе с фреймворком, делают его использование неэффективным. В случае пересмотра того, что можно, а что богопротивно делать с этим фреймворком, с ним можно будет комфортно работать даже несмотря на сложность. В рамках такой политики будет полезна и ревизия Symfony Book так чтобы она отвечала на конкретные технические вопросы, а не учила правильному стилю программирования. Из-за сложности Symfony есть и положительная сторона, не для заказчика, но для программиста — оплата труда несколько выше, чем на других фреймворках. Даже больше! На этом фреймворке вы сможете создать такую причудливую архитектуру, которая не будет понятна никому, но по всем формальным признакам будет идеальной. Это усложнит поиск вашей замены. Ну и если вы потратите пару неделю и соберете на базе Symfony свой фреймворк, то вам будет относительно весело на фрилансе.
В заключении Я намеренно не приводил иллюстраций конкретных проблем типа реализации аггрегатных функций на Doctrine, медленной работы Assetic, ограничений в темизации форм, примеров бойлерплейта и т.п. Для тех, кто искренне любит фреймворк, это не проблемы. А всех остальных, также считающих, что Symfony — замечательный способ делать простые вещи через тридесятую задницу, я искренне поздравляю — вы не одиноки. Добро пожаловать снова.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.