- PVSM.RU - https://www.pvsm.ru -

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Заключение

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

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

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

Автор: altgamer

Источник [20]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/php-2/187828

Ссылки в тексте:

[1] PHP: фрактал плохого дизайна: https://habrahabr.ru/post/142140/

[2] PHP Sadness: http://phpsadness.com/

[3] __halt_compiler: http://php.net/manual/ru/function.halt-compiler.php

[4] exit: http://php.net/manual/ru/function.exit.php

[5] отдельных: https://habrahabr.ru/post/269199/

[6] преобразования ключа: http://php.net/manual/ru/language.types.array.php

[7] зачем это нужно?: https://ru.wikipedia.org/wiki/ActiveRecord

[8] обработку сообщений объектами Smalltalk: https://ru.wikibooks.org/wiki/Smalltalk_%D0%B2_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D0%B0%D1%85/%D0%A1%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F

[9] PHP создан, чтобы умирать: https://habrahabr.ru/post/179399/

[10] «ударил-убежал»: https://ru.wikipedia.org/wiki/%D0%A3%D0%B4%D0%B0%D1%80%D0%B8%D0%BB-%D1%83%D0%B1%D0%B5%D0%B6%D0%B0%D0%BB

[11] расширения: https://habrahabr.ru/post/98862/

[12] dl: http://php.net/manual/ru/function.dl.php

[13] WordPress: https://ru.wikipedia.org/wiki/WordPress

[14] Doctrine: https://ru.wikipedia.org/wiki/Doctrine

[15] Twig: https://ru.wikipedia.org/wiki/Twig

[16] Phalcon: https://ru.wikipedia.org/wiki/Phalcon_PHP

[17] судя по тестам: https://habrahabr.ru/post/225851/

[18] VDS: https://www.reg.ru/?rlink=reflink-717

[19] на C писать: https://habrahabr.ru/post/154187/

[20] Источник: https://habrahabr.ru/post/310068/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox