PHP: фрактал нецелевого использования

в 10:11, , рубрики: php

Мне кажется, критика PHP уже превратилась в самостоятельный жанр. Одной только статьи PHP: фрактал плохого дизайна достаточно, чтобы задуматься, стоит ли вообще его использовать хотя бы для странички заказа пиццы. А если у вас всё же остались сомнения, зайдите, например, на PHP Sadness.

Действительно ли PHP настолько плох? Не стану кривить душой — я знаю слишком много его недостатков. В моем личном списке на первом месте находится невменяемая система ссылок на переменные, которая:

а) делает клонирование объектов фактически бесполезным и

б) все равно не позволяет нормально пользоваться функцией call_user_func(_array) без хака, который описан в документации (sic!).

Второе место занимает совершенно сумасшедшая система ошибок. В PHP существует 2,5 разновидности ошибок и на момент 7 версии аж 2,5 класса базовых исключений, ни один из которых никак не связан с другими кроме реализации интерфейса Throwable… который есть только в PHP 7 и в более ранних версиях его использование само по себе вызывает ошибку. И это не считая функций __halt_compiler и exit.

В общем всё плохо. Но PHP не меньше вредит нецелевое использование языка на всех уровнях разработки — начиная от проектирования систем и заканчивая решением отдельных функциональных задач. И вот о чём я…

Гипертекстовый препроцессор

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

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

Отсутствующий type hinting для скалярных типов и типов элементов массива подразумевает, что функции принимают в качестве аргументов строки, массивы строк и объекты, а возвращают строки. В версии 5.4 аргументами могут быть ещё и функции, а чуть раньше, в 5.3, появились Closure, которые уже не строки, а вызываемые объекты. Таким образом есть строковые данные и инструменты для их обработки — можно сказать, что это PHP в миниатюре. В 7 версии скалярные типы таки появились, но выглядят скорее как отмазка, как и ООП «прям как в Java». Кстати, о нём.

Магические методы __get и __set, присутствующие в PHP вместо нормальных геттеров и сеттеров, на первый взгляд кажутся какой-то глупостью. Но на самом деле они являются очень мощным инструментом, позволяющим работать со свойствами динамически, без знания чёткой структуры объекта на этапе написания его кода. Казалось бы, зачем это нужно? Если рассматривать объекты сами по себе, то это выглядит бессмысленным нагромождением, вынуждающим писать boilerplate. Однако если рассматривать объект как интерфейс для какого-то внешнего инструмента (скажем, расширения или API), то такое решение обретает смысл. Как и __call, который, кстати, очень похож на обработку сообщений объектами Smalltalk (неожиданная аналогия с самым ОО языком — тема для целой отдельной статьи). Например, используя __get, __set и __call, можно написать очень удобный объектный менеджер базы данных, взаимодействие с которой осуществляется посредством вызова хранимых процедур и изменения настроек.

Не менее важной является возможность сохранять состояние объекта между вызовами скрипта с помощью магических методов __sleep, __wakeup и __set_state. Опять же, с точки зрения объекта как вещи в себе это катастрофа, в труху ломающая инкапсуляцию. Однако если объект — это интерфейс для чего-то, работающего вне скрипта, то это не менее логично, чем постоянное соединение с той же базой данных из примера выше. PHP создан, чтобы умирать, а другими словами — предназначен для написания сценариев, а не приложений.

Соколиный удар

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

PHP намного более силён в тактике, нежели в стратегии. Логика его работы похожа на хорошо известный приём борьбы с превосходящими силами под названием «ударил-убежал» (может быть, именно поэтому он и приходится по вкусу новичкам?). В вопросах функциональности он очень сильно полагается на расширения, которых у него в запасе огромное количество. Настолько, что обычно загружает их все при каждом вызове (хотя есть сомнительный dl). Последнее — спорная идея, но в PHP это как-то работает потому что в основном всё, что он загружает — это интерфейсы, а не сама функциональность. Это, впрочем, не мешает перерасходу ресурсов, частично устранив который исключением deprecated-функциональности PHP 7 значительно выиграл в скорости по сравнению с предыдущими версиями в том числе. Но как бы там ни было — то, что позволено Юпитеру, не позволено быку. А быки, в роли которых в данном случае выступают фрэймворки и CMS, следуют той же логике.

Для всех, кто имел дело с WordPress, очевидно, что эта CMS — не лучший пример. Но тем не менее это одна из самых популярных CMS, на которой работают аж 25% всех сайтов, если верить W3Techs. И вот что происходит на без малого четверти сайтов во всём мире. При каждом HTTP запросе, включая запросы к REST API (а иногда даже запросы к стилям и скриптам), происходит:

1) загрузка немаленького ядра самой CMS, содержащего массу инструментов на всякий случай, написанных на PHP,

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

И всё это для того, чтобы отдать HTML-страничку сомнительной художественной ценности. Это напоминает женщину, которая час красится, чтобы сходить за хлебом в соседний магазин. Остаётся только надеяться, что никто не заходит на эти 25% сайтов.

Я не знаю, сколько процентов сайтов во всём мире используют PHP, но совершенно точно подавляющее их большинство так же использует фрэймворки. Вы видели Doctrine? Нет, они на полном серьёзе написали парсер DQL. На PHP. Это уже не говоря про декораторы. Эти же ребята, кстати, написали Twig. И тоже на PHP. Я не спорю, что это отличные продукты, на которые были потрачены силы и время классных специалистов. Я ничего подобного не сделал (что ж, мне есть к чему стремиться). Я только не понимаю, причём здесь PHP. С тем же успехом можно было написать всё это на шелле.

С моими аргументами можно спорить, но есть же Phalcon, который, судя по тестам, разделывает всех под орех. Хотя это и всего лишь шаг в верном, на мой взгляд, направлении, но пример весьма наглядный. Почему не сделать сервер приложений на C и работать с ним из PHP как с той же СУБД, заодно используя FastCGI? Копеечные хостинги, на которых версию PHP-то не обновишь, не то чтобы установить расширение, могли быть причиной раньше. (И то сомнительной, если вы не делаете страничку класса «орлы 10А».) Но сейчас настроенный VDS стоит не сильно дороже.

Честное слово, иногда жалеешь о том, что PHP тьюринг-полный.

Заключение

Может возникнуть резонный вопрос — а зачем вообще тогда нужен PHP, если как полноценный язык программирования он откровенно слаб. Можно ведь и на C писать. Или на Java. Да на чём угодно. На мой взгляд, PHP позволяет сконцентрироваться на функциях собственно приложения, отделив его от гипертекстового интерфейса, который просто и удобно разрабатывать на PHP. Ведь логику базы данных удобно разрабатывать с использованием средств СУБД, а логику пользовательского интерфейса — на JS, TS, Java и так далее. Каждый инструмент хорош на своём месте и плох на всех остальных.

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

С другой стороны, PHP хоронят не первый год, однако пока он неплохо себя чувствует. Улучшается сам язык и для него появляются новые, более осмысленные инструменты. Правда чем больше нововведений происходит на потребу публики путём бездумного копирования из других языков, тем больше возникает и сомнений в пользе PHP при наличии этих самых других языков. Но может что и получится.

Автор: altgamer

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js