Пользователь
0,0
рейтинг
16 апреля 2012 в 08:58

Разработка → PHP: фрактал плохого дизайна перевод

Предисловие


Я капризный. Я жалуюсь о многих вещах. Многое в мире технологий мне не нравится и это предсказуемо: программирование — шумная молодая дисциплина, и никто из нас не имеет ни малейшего представления, что он делает. Учитывая закон Старджона, у нас достаточно вещей для постижения на всю жизнь.

Тут другое дело. PHP не просто неудобен в использовании, плохо мне подходит, субоптимален или не соответствует моим религиозным убеждениям. Я могу рассказать вам много хороших вещей о языках, которых я стараюсь избегать, и много плохих вещей о языках, которые мне нравятся. Вперёд, спрашивайте! Получаются интересные обсуждения.

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

PHP — препятствие, отрава моего ремесла. Я схожу с ума от того, насколько он сломан и насколько воспеваем каждым уполномоченным любителем нежелающим научиться чему-либо ещё. У него ничтожно мало оправдывающих положительных качеств и я бы хотел забыть, что он вообще существует.

Аналогия


Я только что выпалил это Мэл, чтобы описать своё расстройство и она настояла на том, чтобы я воспроизвёл это здесь:

Я даже не могу сказать, что не так с PHP, потому что… Окей. Представьте себе, эмм, коробку с инструментами. Набор инструментов. Выглядит нормально, инструменты как инструменты.

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

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

Берёте плоскогубцы, у которых нет зазубрин; они плоские и гладкие. Не так полезно, как могло бы быть, но ими всё ещё можно выкручивать болты.

И так далее. Все инструменты чем-то странные и вывернутые, но не настолько, чтобы быть совсем бесполезными. И во всём наборе нет конкретной проблемы; в нём есть все инструменты.

Теперь представьте себе миллионы плотников, использующих такой вот набор инструментов и говорящих вам: «А что не так с этими инструментами? Я никогда не использовал ничего другого и они отлично работают!». И плотники показывают вам, построенные ими дома с пятиугольными комнатами и крышей кверху ногами. Вы стучитесь в дверь, она просто падает внутрь и они орут на вас за то, что вы сломали их дверь.

Вот что не так с PHP.


Расстановка сил


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

  • Язык должен быть предсказуем. Язык — носитель для выражения человеческих идей и выполнения их на компьютере, поэтому человеческое понимание правильности программы критично.
  • Язык должен быть целостен. Похожие вещи должны быть похожи, разные должны различаться. Знание части языка должно помогать в изучении и понимании остальной части.
  • Язык должен быть краток. Новые языки существуют, чтобы уменьшить шаблонность присущую старым языкам. (Мы все могли бы программировать на машинных кодах.) Язык должен в тоже время избегать введения своих собственных шаблонов.
  • Язык должен быть надёжен. Языки — инструменты для решения задач; проблемы, которые они представляют сами по себе должны быть минимальны. Любые непонятные моменты вызывают смущение.
  • Язык должен быть отлаживаем. Если что-то идёт не так, программист обязан это починить, и нам нужна вся помощь, которую мы можем получить.


Моя позиция такова:

  • PHP полон сюрпризов: mysql_real_escape_string, E_ACTUALLY_ALL
  • PHP не целостен: strpos, str_rot13
  • PHP требует шаблонного кода: проверка ошибок вокруг «C API»-вызовов, ===
  • PHP чудной: ==, foreach ($foo as &$bar)
  • PHP непрозрачен: без стэктрэйсов по умолчанию и фатальных ошибок, сложный error reporting.


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

Не нужно следующих комментариев


Я участвовал во многих спорах о PHP. Слышал много общих контраргументов на самом деле предназначенных, чтобы закрыть тему. Пожалуйста воздержитесь от них :(

  • Не говорите мне, что «хорошие разработчики могут писать хороший код на любом языке», или что «плохие разработчики что-то там ещё». Это ничего не значит. Хороший плотник может забить гвоздь камнем или молотком, но где вы видели плотников забивающих что-либо камнями? Один из факторов, определяющих хорошего разработчика, это способность выбрать подходящие инструменты.
  • Не говорите мне, что разработчик обязан помнить тысячи странных исключений и неожиданных поведений. Да, это обязательно в любой системе, потому что компьтеры сосут. Только это не значит, что нет верхнего предела фигни в системе. В PHP нет ничего кроме исключений, и это не круто, если борьба с языком занимает больше усилий нежели написание самой программы. Мои инструменты не должны создавать мне не позитивную работу.
  • Не говорите мне, что «так работает C API». Какой вообще тогда смысл использовать высокоуровневый язык, если он даёт только строковые хэлперы и массу дословных C обёрток? Просто пишите на C! Смотрите, для него даже есть CGI-библиотека.
  • Не говорите мне: «Это тебе за то, что делаешь странные вещи». Если две фичи существуют, кто-нибудь когда-нибудь обязательно найдёт причину использовать их вместе. И снова, это не C: спецификации нет, как нет и надобности в «неопределённом поведении».
  • Не говорите мне, что Facebook или Wikipedia написаны на PHP. Я в курсе! Они так же могли бы быть написаны на Brainfuck'е, достаточно умные люди могут пересилить это всё. Всё, что мы знаем, это то, что время разработки могло быть ополовинено или удвоенно если бы эти продукты были написаны на каком-нибудь другом языке; только этот отдельный аргумент ничего не значит.
  • В идеале вы не должны говорить мне ничего! Это мой лучший выстрел; если он не изменит мнения о PHP, тогда его не изменит ничто, так что хорош уже спорить с каким-то чуваком в Интернете и иди уже сделай крутой сайт в рекордные сроки, чтобы доказать, что я не прав :)


Кстати: я обожаю Python. И с удовольствием прожужжу тебе уши, ноя о нём, если ты на самом деле этого хочешь. Я не утверждаю, что он идеален; я просто взвесил его преимущества и его проблемы и сделал вывод, что он лучше всего подходит для того, что я делаю.

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

PHP


Ядро языка


CPAN был назван «стандартной библиотекой Perl». Это не говорит много о стандартной библиотеке Perl, но указывает, что прочное ядро может построить замечательные вещи.

Философия


  • PHP изначально создавался для непрограммистов(и если читать между строк не для программ); он не смог уйти от своих корней. Вот из документации по PHP 2.0 цитата о том, как делался выбор относительно приведения типов для + и прочих:

    Отдельные операторы для каждого типа сильно усложняют язык, например, вы больше не сможете использовать '==' для строк(что?), вы теперь будете использовать 'eq'. Я не вижу в этом никакого смысла, особенно в таком языке как PHP, где большинство скриптов будут достаточно простыми и в большинстве случаев, написаны непрограммистами, которым нужен язык с простейшим логическим синтаксисом и низким порогом вхождения.
  • PHP построен, чтобы продолжать фурычить при любых обстоятельствах. Если есть выбор между тем, чтобы сделать непонятно что и упасть с ошибкой, он сделает непонятно что. Что-нибудь лучше, чем совсем ничего.
  • Дизайн не имеет определённой философии. Ранний PHP был вдохновлён Perl'ом; огромная std-библиотека с «out»-параметрами из C; ОО-часть сделана как в C++ и Java.
  • PHP обширно черпает вдохновение из других языков, при этом ему удаётся быть непонятным для тех, кто эти языки знает. (int) выглядит как C, но int не существует. Нэймспэйсы используют \. Новый синтаксис массивов получился уникальный среди всех языков с хэш-литералами: [key=>value].
  • Слабая типизация(всмысле, тихая автоматическая конверсия между строками/числами/всем остальным) настолько сложная, что она не стоит того, сколько бы усилий начинающего программиста она не сохраняла.
  • Новая функциональность реализуется как новый синтаксис, даже если она мала; большинство её делается с помощью функции или чего похожего на функции. Кроме поддержки классов, которая заслуживает множества новых операторов и ключевых слов.
  • Некоторые из проблем, описанных в этой статье на самом деле имеют первоклассное решение — если конечно вы хотите платить Zend'у за фиксы к их языку с открытыми исходниками.
  • Целая куча событий происходит за сценой. Взять хотя бы вот этот код, откуда-то из PHP-документации:
    @fopen('http://example.com/not-existing-file', 'r');
    

    Что он будет делать?

    • Если PHP скомпилирован с --disable-url-fopen-wrapper, он не будет работать. (Документация не говорит, что означает «не будет работать»; вернёт null, бросит исключение?) Заметьте, что этот флаг убрали в PHP 5.2.5.
    • Если allow_url_fopen выключен в php.ini, он тоже не будет работать. (Как не будет? Нет идей.)
    • Из-за @, предупреждение о несуществующем файле не будет выведено.
    • Но будет выведено, если scream.enabled установлен в php.ini.
    • Или если scream.enabled вручную установлен через ini_set.
    • Но не в том случае, если не установлен корректный error_reporting.
    • Если оно будет выведено, куда оно будет выведено зависит от display_errors, снова в php.ini. Или ini_set.


    Я не могу сказать как такой безобидный вызов функции будет себя вести без проверки флагов времени компиляции, глобальной конфигурации сервера и конфигурации в моей программе. И это всё встроенное поведение.
  • Этот язык полон глобального и неявного поведения. mbstring использует глобальную кодировку. func_get_arg и прочие вроде бы обычная функция, но оперирует над выполняемой в данный момент функцией. Обработка ошибок и исключений имеет глобальные умолчания. register_tick_function устанавливает глобальную функцию, которая выполняется каждый тик — чего?!
  • До сих пор нет поддержки потоков.(Неудивительно, учитывая вышеуказанное.) С отсутствием встроенного fork(упомянуто ниже), это очень усложняет парралельное программирование.
  • Некоторые части PHP практически созданы для производства глючного кода:

    • json_decode возвращает null для невалидного ввода, при том, что null — абсолютно верный объект для декодируемого JSON'а. Эта функция абсолютно ненадёжна, если вы конечно не вызываете json_last_errorкаждый раз при её использовании.
    • array_search, strpos и другие похожие функции возвращают 0, если находят вхождение на нулевой позиции, но false если не находят его вообще.


    Дайте-ка мне чуть расширить последний пункт.

    В C, такие функции как strpos возвращают -1, если элемент не был найден. Если вы не проверите этот вариант и попытаетесь использовать результат в качестве индекса, вы попадёте в мусорную память и ваша программа упадёт. (Скорее всего. Это же C. Хрен его знает. Я уверен, что для этого как минимум есть инструменты.)

    В Python'е например эквивалентные методы .index бросят исключение, если элемент не найден. Если вы не проверите этот случай, ваша программа упадёт.

    В PHP эти функции возвращают false. Если вы используете FALSE как индекс, или сделаете с ним почти всё что угодно кроме сравнения с помощью ===, PHP спокойно сконвертирует его в 0 за вас. Ваша программа не упадёт; она вместо этого будет работать неправильно без предупреждения, если конечно вы не забудете вставить нужный шаблонный код вокруг каждого места где вы используете strpos и некоторые другие функции.

    Это плохо! Языки программирования — это инструменты; я предполагаю, что они будут работать вместе со мной. Здесь же, PHP поставил для меня хитрую ловушку, и должен быть осторожен даже с такими повседневными вещами как операции над строками и сравнения на равенство. PHP — минное поле.


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

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

Окей, вернёмся к фактам.

Операторы


  • == бесполезен
    • Он не транзитивен. "foo" == TRUE, и "foo" == 0… но, конечно же TRUE != 0.
    • == конвертирует в число, если возможно. Далее конвертирует в float'ы, если возможно. Получается, что большие шестнадцатиричные строки(например, хеши паролей) могут неожиданно быть равными, когда они не равны.
    • По тем же причинам, "6" == " 6", "4.2" == "4.20" и "133" == "0133". Но прошу заметьте, что 133 != 0133, потому что 0133 восьмеричное.
    • === сравнивает значения и тип… но не для объектов, где === истинно если оба операнда один и тот же объект! Для объектов, == сравнивает оба значения(для каждого аттрибута) и типы, что === делает для всех остальных типов. Чего.
  • Не лучше и сравнение:
    • Оно даже не согласовано: NULL < -1, и NULL == 0. Сортировка не детерменирована; она зависит от порядка в котором, алгоритм будет сравнивать элементы.
    • Операторы сравнения пытаются сортировать массивы, двумя разными способами: сначала по длине, затем по элементам. Вторая сортировка происходит, если у массивов одинаковое количество элементов, но разный набор ключей. По хорошему, такие массивы вообще нельзя сравнивать.
    • Объекты при сравнении всегда больше всего остального… кроме других объектов, которые не больше и не меньше.
    • Для более типобезопасного ==, у нас есть ===. Для типобезопасного < у нас… нет ничего. "123" < "0124", всегда, что бы вы не делали.
  • Вопреки вышеописанном безумию и чёткому отрицанию Perl'овых пар строковых и числовых операторов, PHP не перегружает +, + всегда сложение, а . всегда конкатенация.
  • [] оператор индекса может также быть записан как {}.
  • [] может быть применён к любой переменной, не только к строкам и массивам. Он возвращает null и не выдаёт предупреждение.
  • [] не может слайсить; он только возвращает отдельные элементы.
  • foo()[0] — синтаксическая ошибка. (Пофикшено в PHP 5.4.)
  • В отличие от (почти) всех остальных языков с похожим оператором, ?: левоассоциативен. Поэтому следующий код:
    $arg = 'T';
    $vehicle = ( ( $arg == 'B' ) ? 'bus' :
                 ( $arg == 'A' ) ? 'airplane' :
                 ( $arg == 'T' ) ? 'train' :
                 ( $arg == 'C' ) ? 'car' :
                 ( $arg == 'H' ) ? 'horse' :
                 'feet' );
    echo $vehicle;
    

    выведет horse.


Переменные


  • Нет никакого способа объявить переменную. Переменные, которые не существуют создаются со значением null при первом использовании.
  • Глобальные переменные должны быть объявлены с ключевым словом global перед использованием. Это естественное последствие предыдущего пункта, кроме того, что глобальная переменная даже не может быть прочитана без явного объявления — вместо этого PHP просто создаёт локальную переменную с таким же именем. Я не знаю другого языка с такими же проблемами с контекстом.
  • Нет ссылок. То, что в PHP называется ссылками, это на самом деле псевдонимы; это шаг назад, прям как ссылки в Perl, не существует передачи через объект, как в Python.
  • «Ссылочность» поражает переменные больше всего остального в языке. PHP — динамически типизированный, поэтому у переменных в общем случае нет типа… кроме ссылок, которые украшают определения функций, синтаксис переменных и присваивания. Как только переменная становится ссылкой(что может случится где угодно), она связана с этой ссылкой. Невозможно определить, случилось это или нет и для разыменования ссылки нужно полностью уничтожить переменную.
  • Окей, я соврал. Есть "SPL-типы", которые тоже поражают переменные:

    Выполнение $x = new SplBool(true); $x = "foo"; завершится неудачей. Смотрите-ка, выглядит как статическая типизация.
  • Можно получить ссылку на несуществующий ключ внутри неопределённой переменной(которая становится массивом). Использование несуществующего массива обычно выводит notice, но не в этом случае.
  • Константы определяются с помощью вызова функции; до этого они не существуют. (Возможно, это копия Perl-поведения use constant.)
  • Имена переменных чувствительны к регистру. Имена функций и классов нет. Включая имена методов, что делает camelCase не лучшим выбором именования.


Конструкции


  • array() и пару дюжин других конструкций — не функции. Сама по себе конструкция array не означает ничего, $func = "array"; $func(); не работает.
  • Распаковка массивов может быть выполнена операцией list($a, $b) = .... list() — синтаксис похожий на функцию так же как array. Я не знаю почему для этого был выделен отдельный синтаксис или почему было выбрано такое смутное имя.
  • (int) очевидно создан, чтобы выглядеть как C, но это отдельный токен; в языке нет никакого int. Попробуйте: var_dump(int) не только не работает, но и выбрасывает parse error, потому что аргументы выглядит как оператор приведения типа.
  • (integer) — синоним (int). Ещё есть (bool)/(boolean) и (float)/(double)/(real).
  • Есть оператор (array) для приведения к массиву и оператор (object) для приведения к объекту. Звучит безумно, но у них есть применение: вы можете использовать (array) для создания функции с аргументом, который может списком либо одним его элементом, чтобы работать с ним одинаково. Кроме того, что вы не можете сделать это надёжно, потому что если кто-то передаст отдельный объект, приведение его к массиву выдаст массив состоящий из аттрибутов объекта. (Приведение к объекту выполняет обратную операцию.)
  • include() и прочие это просто C-шный #include: она дампит другой исходный файл в ваш. Нет системы модулей, даже для PHP-кода.
  • Вложенных классов и функций не существует. Только глобальные. include() файла дампит переменные из этого файла в текущий контекст функции (и даёт файлу доступ к вашим переменным), но классы и функции дампятся в глобальный контекст.
  • Добавление в массив выполняется $foo[] = $bar.
  • echo — выражение, а не функция.
  • empty($var) настолько не функция, что что угодно кроме переменной, как например empty($var || $var2) приводит к parse error'у. Почему вообще парсеру нужно что-то знать о empty?
  • Существует избыточный синтаксис для блоков: if (...): ... endif; и др.


Обработка ошибок


  • Ещё один уникальный оператор PHP @(на самом деле взятый из DOS) заглушает ошибки.
  • У ошибок PHP нет стэктрэйсов. Вы должны установить обработчик, чтобы их генерировать. (Но вы не можете для fatal error'ов — см. ниже.)
  • Parse error'ы PHP часто просто выплёвывают состояние парсера и больше ничего, жутко усложняя отладку, если вы где-то забыли кавычку.
  • Парсер PHP внутри ссылается на :: как на T_PAAMAYIM_NEKUDOTAYIM, и на << как на T_SL. Я сказал «внутри», но как указано выше это то, что показывается программисту, когда :: или << встречается в неверном месте.
  • Большая часть обработки ошибок состоит в выводе строчки в лог сервера, который никто не читает и не интересуется.
  • Уровень E_STRICT как раз то, что нужно, но похоже он на самом деле предотвращает немногое и нет документации, что он на самом деле делает.
  • E_ALL включает все категории ошибок — кроме E_STRICT.
  • Жутко много противоречий о том, что разрешено, а что нет. Я не знаю, как E_STRICT к этому применяется, но следующее делать можно:
    • пытаться получить доступ к несуществующему свойству объекта, типа $foo->x.(warning)
    • использовать переменной как имени функции, или имени переменной, или имени класса.(без сообщений)
    • пытаться использовать неопределённую константу.(notice)
    • пытаться получить доступ свойство чего-нибудь, не являющегося объектом.(notice)
    • пытаться использовать имя переменной, которая не существует.(notice)
    • 2 < "foo" (без сообщений)
    • foreach (2 as $foo); (warning)

    А это нельзя:
    • пытаться получить доступ к несуществующей константе класса, типа $foo::x. (fatal error)
    • использовать константной строки как имени функции, имени переменной или имени класса. (parse error)
    • пытаться вызвать неопределённую функцию. (fatal error)
    • оставлять точку с запятой в конце блока или файла. (parse error)
    • использовать list и разные другие квазиконструкции как названия методов. (parse error)
    • индексировать возвращаемое функцией значение, типа foo()[0]. (parse error, пофикшено в 5.4, см. выше)


    Во всём этом списке есть ещё несколько хороших примеров странных parse error'ов.
  • Метод __toString не может бросать исключения. Если вы попробуете PHP… эм, бросит исключение. (На самом деле fatal error, который снова в отличие от всех остальных можно передавать.)
  • PHP-ошибки и PHP-исключения абсолютно разные существа. Они, похоже, не могут взаимодействовать никак.
    • PHP-ошибки (внутренние и вызванные через trigger_error) не могут быть словлены блоком try/catch.
    • Точно так же, исключения не приводят к вызову обработчиков установленных через set_error_handler.
    • Вместо этого, есть отдельная функция set_exception_handler которая обрабатывает не пойманные исключения, потому что обернуть входную точку вашей программы в блок try невозможно в модели mod_php.
    • Fatal error'ы (типа new ClassDoesntExist()) не могут быть пойманы ничем. Многие вполне невинные вещи бросают fatal error'ы, принудительно завершая вашу программу по сомнительным причинам. Shutdown-функции всё ещё вызываются, но они не могу получить стэктрэйс (потому что выполняются на верхнем уровне), и в них не так просто определить завершилась ли ваша программа с ошибкой или выполнилась до конца.
  • Нет конструкции finally, создание wrapper-кода(установил обработчик, выполнил код, убрал обработчик; манкипатч, проверил, разманкипатчил) утомительно и сложно для написания. Несмотря на то, что объектная модель и исключения в многом скопированы из Java, это было сделано намеренно, потому что finally «не имеет большого смысла в контексте PHP». Да ну?


Функции


  • Вызовы функций явно достаточно дорогие.
  • Некоторые встроенные функции взаимодействуют с функциями возвращающими ссылки, скажем так, странно.
  • Как я замечал ранее, некоторые вещи, похожие на функции или похожие на то, что должно быть функцией на самом деле конструкции языка, поэтому всё, что работает с функциями не будет работать с ними.
  • Аргументы функций могут иметь «type hint'ы», это попросту статическая типизация. Но вы не можете требовать от аргумента быть int или string или object или другим примитивным типом, хотя каждая встроенная функция использует эти типы, наверное потому что int в PHP не существует.(про (int) см. выше) Вы также не можете использовать специальные псевдо-типы используемые повсеместно во встроенных функциях mixed, number или callback.
    • В результате, следующий код:
      function foo(string $s) {}          
      foo("hello world");
      

      Выводит ошибку:
      PHP Catchable fatal error:  Argument 1 passed to foo() must be an instance of string, string given, called in...
      
    • Вы можете заметить, что указанного «type hint'а» не должно здесь быть. В этой программе нет класса string. Если вы воспользуетесь ReflectionParameter::getClass(), чтобы исследовать type hint динамически, он упрётся в несуществующий класс, делая невозможным получение имени класса.
    • Type hint не может быть применён к возвращаемому функцией значению.
  • Передача аргументов функции в другую функцию(dispatch, не такая уж и редкость) делается через call_user_func_array('другая функция', func_get_args()). Но func_get_args выбрасывает fatal error в рантайме, жалуясь, чтом func_get_args не может быть параметром функции. Как и почему такая ошибка вообще существует? (Пофикшено в PHP 5.3.)
  • Замыкания требует явного указания всех замыкаемых переменных. Почему интерпретатор сам не может это определить? Калечит всю фичу. (Окей, потому что любое использование переменной переменной, абсолютно любое, создаёт её, если обратное явно не указано.)
  • Замыкаемые переменные «передаются» с той же семантикой как остальные аргументы функции. Вот так, массивы, строки и пр. будут переданы по значению. Если не используете &.
  • Т.к. замыкаемые переменные фактически автоматически передаваемые аргументы и нет вложенных контекстов, замыкание не может использовать private-методы, даже если оно определено внутри класса. (Возможно пофикшено в 5.4? Не уверен.)
  • Нет именованных параметров функций. На самом деле явно отклонено разработчиками, потому что «ведёт к беспорядочному коду».
  • Аргументы со значениями по умолчанию могут быть перед аргументами без них, не смотря на то, что в документации указано, что это странно и бесполезно. (Зачем тогда это позволять?)
  • Лишние аргументы игнорируются(кроме лишних аргументов встроенных функций, они вызывают ошибку). Недостающие аргументы предполагаются равными null.
  • Функции с переменным числом аргументов требуют возни с func_num_args, func_get_arg и func_get_args. Для этого нет синтаксиса.


ООП


  • Функциональные части PHP сделаны как в C, а объектные как в Java. Даже не могу сказать, как меня это раздражает. Я не нашёл ни одной глобальной функции с заглавной буквой в имени, в то время как важные встроенные классы используют camelCase для имён методов и аксессоры getFoo в Java-стиле. Это динамический язык, верно? Perl, Python и Ruby: у каждого из этих языков есть какуя-либо концепция доступа к «свойству» из кода; у PHP же только неуклюжий __get и прочие. Система классов создана вокруг более низкоуровневого языка Java, который естественно и намеренно более ограничен, чем языки-современники PHP, я сбит с толку.
  • Классы не объекты. Любой метакод вынужден ссылаться на них по имени, как в случае с функциями.
  • Встроенные типы не объекты и (не как в Perl) никоим образом не могут быть представлены ввиде объектов.
  • instanceof оператор, несмотря на то, что классы были добавлены достаточно поздно и что большая часть языка построена на функциях и функционном синтаксисе. Влияние Java? Классы не first-class объекты?
    • Но существует функция is_a. С необязательным аргументом указывающим разрешать ли объекту быть строкой, содержащей имя класса.
    • get_class тоже функция; нет оператора typeof. Также как и оператора is_subclass_of.
    • Тем не менее, instanceof не работает для встроенных типов (снова, int не существует). Для этого случая вам нужен is_int и пр.
    • И ещё правая часть должна быть переменной или литеральной строкой; не может быть выражением. Это приводит к… parse error'у.
  • clone — оператор?!
  • ООП-дизайн представляет из себя жуткую мешанину Java и Perl.
  • Синтаксис аттрибутов объектов $obj->foo, а аттрибутов классов $obj::foo. Я не в курсе есть ли другой язык в котором сделано так же или какую пользу это приносит.
  • Также метод экземпляра может быть вызван статически (Class::method). Такой вызов сделать в другом методе(пер. или даже другом классе) трактуется как обычный вызов метода в текущем $this.
  • new, private, public, protected, static и пр. Хотели привлечь Java-разработчиков? Я в курсе, что это дело вкуса, но я не понимаю зачем это обязательно в динамическом языке — это нужно в C++ в основном для компиляции и разрешения имён во время компиляции.
  • Подклассы не могут перегружать private-методы. Перегруженные публичные методы подкласса даже не видят private-методы, кроме того, что не могут вызывать. Создаёт проблемы, например, при написании тест-моков.
  • Методы не могут называться, например «list», потому что list() — специальный синтаксис(не функция) и парсер начинает путаться. Для такой неоднозначности нет никакой причины, и всё работает при динамической модификации(пер. monkeypatching).($foo->list() не приводит к ошибке синтаксиса.)
  • Если при вычислении аргументов конструктора бросается исключение(например new Foo(bar()) и bar() бросает исключение), конструктор не будет вызван, а деструктор будет.(Пофикшено в PHP 5.3.)
  • Исключения в __autoload и деструкторах вызывают fatal error.
  • Нет никаких конструкторов и деструкторов. __construct — это инициализатор, как __init__ в Python. Нет метода при вызове, которого выделится память и будет создан объект.
  • Нет инициализатора по умолчанию. Если суперкласс не определяет собственный __construct, Вызов parent::__construct() приводит к fatal error'у.
  • ООП также вводит интерфейс итераторов, который учитывают некоторые части языка(типа for...as), но ни одна встроенная сущность(такая как массивы) этот интерфейс на самом деле не реализует. Если вам нужен итератор массива, вам приходится оборачивать его в ArrayIterator. Нет встроенной поддержки сцепления, slice'инга и чего-либо ещё для работы с итераторами, как «first class»-объектами.
  • Классы могут перегрузить то, как они конвертируются в строки и как они ведут себя будучи вызванными, но не как они конвертируется в числа и другие встроенные типы.
  • Есть конверсия в строки для Строк, чисел и массивов; язык на это очень полагается. Функции и классы тоже строки. Тем не менее конверсия встроенного или определённого пользователем объекта(и даже замыкания) в строку вызывает ошибку, если объект не определяет __toString. Даже echo становится потенциально склонен к ошибке.
  • Нет перегрузки сравнения и последовательности(пер. ordering).
  • Статические переменные внутри методов экземпляра глобальны; одно значение на все экземпляры класса.


Стандартная библиотека


Философия стандартной библиотеки Perl «some assembly required»(пер. возможный перевод «понадобится некоторая сборка»), Python — «батарейки в комплекте», PHP — «раковина, но канадская с подписью C на обоих кранах».

Общие замечания


  • Нет системы модулей. Вы можете компилировать расширения PHP, но какие из них загружать указывается в php.ini, и у вас только две опции: расширение существует(и вносит своё содержимое в глобальное пространство имён) или нет.
  • Стандартная библиотека не разбита на namespace'ы, поскольку они были добавлены недавно. В глобальном пространстве имён тысячи функций.
  • Части библиотеки дико противоречат друг другу:
    • Подчеркивание против его отсутствия: strpos/str_rot13, php_uname/phpversion, base64_encode/urlencode, gettype/get_class
    • «to» против 2: ascii2ebcdic, bin2hex, deg2rad, strtolower, strtotime
    • объект+действие против действие+объект: base64_decode, str_shuffle, var_dump versus create_function, recode_string
    • Порядок аргументов: array_filter($input, $callback) против array_map($callback, $input), strpos($haystack, $needle) против array_search($needle, $haystack)
    • Путаница с префиксами: usleep против microtime
    • Варьируется положение i в именах функций, нечуствительных к регистру
    • Около половины имен функций работы с массивами начинаются с array_. Другая половина нет.
  • Раковина. Библиотека включает:
    • Байндинги для ImageMagick, байндинги для GraphicsMagick(это форк ImageMagick), и пригорошню функций для чтения EXIF-данных(что и так умеет делать ImageMagick).
    • Функции для парсинга bbcode'а, специального маркапа используемого горсткой некоторых форумных пакетов.
    • Слишком много разных XML-пакетов. DOM(объектно-ориентированный), DOM XML(не объектно-ориентированный), libxml, SimpleXML, «XML Parser», XMLReader/XMLWriter и ещё полдюжины акронимов, которые я не могу разобрать. Между ними точно есть какая-то разница, идите и узнайте её сами.
    • Байндинги для двух отдельных процессоров кредитных карт: SPPLUS и MCVE. Зачем?
    • Три способа доступа к базе MySQL: mysql, mysqli и абстракция PDO.


Влияние C


Оно заслуживает отдельного пункта в этом списке, потому что оно настолько абсурдно и при этом пронизывает язык вдоль и поперёк. PHP — высоко-уровневый, динамически-типизированный язык. В то же время большая часть стандартной библиотеки представляет из себя тонкую обёртку вокруг C API, со следующими результатами:

  • «Выходные» параметры, не смотря на то, что PHP вполне способен возвращать специальные хэши или несколько аргументов без особых усилий.
  • Как минимумум дюжина функций для получения последней ошибки определённой подсистемы(см. ниже), хотя исключения существуют в PHP уже восемь лет.
  • Бородавки типа mysql_real_escape_string, несмотря на то, что у неё такие же аргументы как и у сломанной mysql_escape_string, просто потому что это часть MySQL C API.
  • Глобальное поведение для неглобального функционала (например MySQL). Использование нескольких подключений MySQL требует передачи дескриптора подключения в каждый вызов функции.
  • Врапперы очень, очень и очень тонкие. Например вызов dba_nextkey без вызова dba_firstkey упадёт с segfault'ом.
  • Набор функций ctype_*(типа ctype_alnum) называется в соответствии C-функциям определения класса символа с похожими именами, вместо того, чтобы называться, например isupper.


Обобщения


Нет никаких обобщений. Если вдруг функции нужно делать две немного разные вещи, в PHP для этого две функции.

Как сортировать в обратном порядке? В Perl, вы можете сделать sort {$b <=> $a}. В Python .sort(reverse=True). В PHP, это отдельная функция rsort().

  • Функции получения C-ошибки: curl_error, json_last_error, openssl_error_string, imap_errors, mysql_error, xml_get_error_code, bzerror, date_get_last_errors и другие.
  • Функции сортировки: array_multisort, arsort, ksort, krsort, natsort, natcasesort, sort, rsort, uasort, uksort, usort
  • Функции для текстового поиска: ereg, eregi, mb_ereg, mb_eregi, preg_match, strstr, strchr, stristr, strrchr, srcpos, stripos, strrpos, strripos, mb_strpos, mb_strrpos плюс вариации, выполняющие подстановки.
  • К тому же куча бесполезных псевдонимов: strstr/strchr, is_int/is_integer/is_long, is_float/is_double, pos/current, sizeof/count, chop/rtrim, implode/join, die/exit, trigger_error/user_error...
  • scandir возврщает список файлов в текущей директории. Вместо того, чтобы возвращать сначала директории(что могло бы быть полезно), функция возращает их в алфавитном порядке. Необязательный аргумент позволяет получить их в обратном алфавитном порядке. Очевидно, функций сортировки было недостаточно.
  • str_split разбивает строку на равные по длине части. chunk_split разбивает строку на части одинаковой длины и объединяет их через разделитель.
  • Для каждого формата архивов используется отдельный набор функций. Всего шесть груп таких функций, с разным API, для bzip2, LZF, phar, rar, zip и gzip/zlib.
  • Т.к. вызов функции с массивом аргументов настолько неудобен(call_user_func_array), есть несколько пар функций типа printf/vprintf и sprintf/vsprintf. Они делают одно и то же только одна принимает аргументы, а другая массив аргументов.


Текст


  • preg_replace с флагом /e(eval) выполняет подстановку соответствий на строку подстановки, затем eval'ит эту строку.
  • strtok очевидно создана по образу C-функции, которая считается неудачной по разным причинам. Неважно, что PHP мог бы легко возвращать массив(в C это не так просто), и что хак, используемый strtok(3)(модификация строки на месте) в PHP не используется.
  • parse_str парсит строку GET-запроса, не указывая этого в имени. Также она ведёт себя как register_globals и дампит запрос в виде переменных в локальный контекст, если вы не передадите ей массив для наполнения. (Она, конечно, ничего не возвращает.)
  • explode отказывается разбивать с пустым разделителем. Любая другая реализация разбиения строки где угодно воспринимает это как разбиение посимвольно; в PHP для этого отдельная функция, непонятно названная str_split и описанная как «конвертирующая строку в массив».
  • Для форматирования дат, используется strftime, которая ведётся себя как C API и учитывает локаль. Ещё есть date с абсолютно другим синтаксисом и работающая только с английским.
  • "gzgetss — Получить строку из указателя на gz-файл и вырезать HTML-тэги." До смерти хочу узнать какие обстоятельства привели к концепции этой функции.
  • mbstring
    • Всё дело о «много-байтовости», в то время как проблема в кодировках.
    • Работает с обычными строками. Использует одну глобальную кодировку «по умолчанию». Некоторые функции позволяют указание кодировки, но она применяется ко всем аргументам и возвращаемому значению.
    • Предоставляет функции ereg_*, но они устарели. Функциям preg_* не повезло, тем не менее они могут понимать UTF-8, если скормить им кое-какие специфические флаги PCRE.


Система и reflection


  • Вообще целая куча функций стирает грань между текстом и переменными. compact и extract — только вершина айсберга.
  • Существует несколько способов для динамики в PHP, и с первого взгляда нет никакой заметной разницы или опредёлнных приемуществ. classkit позволяет модифицировать ползовательские классы, runkit заменяет classkit и позволяет модифицироет что угодно пользовательское; Reflection*-классы позволяет инспектировать большинство частей языка; очень много функций для работы со свойствами функций и классов. Эти подсистемы независимы, связаны, избыточны?
  • get_class($obj) возвращает имя класса объекта. get_class() возвращает имя класса, в котором вызвана функция. Принимая это во внимание, функция делает две абсолютно разные вещи: get_class(null)… ведёт себя так же, как get_class(). Поэтому вы не можете доверять ей при передаче произвольного объекта. Сюрприз!
  • Классы stream_* позволяют реализовывать пользовательские потоковые объекты и прочие встроенные файловые сущности. «tell» не может быть реализован по внутренним причинам. (К тому же в эту систему вовлечена цела ГОРА функций.)
  • register_tick_function принимает объект замыкания. unregister_tick_function нет; вместо этого она бросает ошибку, жалуясь, что замыкание не может быть сконвертировано в строку.
  • php_uname сообщает о текущей OC. Не в том случае, если PHP не может сказать, где он выполняется; тогда он сообщает на какой ОС он был собран. Произошло ли это не сообщается.
  • fork и exec не встроены. Они идут с расширением pcntl, но оно не включено по умолчанию. popen не предоствляет pid.
  • session_decode читает произвольную строку сессии, но работает только если уже есть активная сессия. И дампит результат в $_SESSION, вместо того, чтобы его возвращать.


Разное


  • curl_multi_exec не изменяет curl_errno в случае ошибки, но изменяет curl_error.
  • Аргументы mktime идут в следующем порядке: час, минута, секунда, месяц, день, год.


Манипуляция данными


Программы ничто иное кроме как большие машины поглощающие данные и выплёвывающие больше данных. Очень много языков созданы вокруг типов данных, которыми они манипулируют, от awk до Prolog и C. Если язык не может обрабатывать данные, он не может ничего.

Числа


  • Целые — знаковые и 32-битные на 32-битных платформах. В отличие от современников PHP, в нём нет автоматической конверсии в большое целое. Так что ваша математика может работать по разному в зависимости от архитектуры процессора. Единственная альтернатива использовать функции обёртки GMP или BC. (Разработчики предложили добавить новый отдельный 64-битный тип. С ума сошли.)
  • PHP поддерживает восьмеричный синтаксис с ведущим 0, так что 012 будет числом десять. Однако, 08 будет числом ноль. 8(или 9) и остальные следующие цифры исчезают. 01c ошибка синтаксиса.
  • pi — функция. А ещё есть константа, M_PI.
  • Нет оператора возведения в степень, только функция pow.


Текст


  • Нет поддержики юникода. Надёжно работает только ASCII, честно. Есть вышеупомянутое расширение mbstring, но оно как бы не работает.
  • Это означает, что использование встроенных строковых функций с UTF-8-текстом создаёт риск их порчи.
  • Точно также нет концепции типа сравнения регистра вне ASCII. Несмотря на распространённость нечуствительных к регистру версий функций, ни одна из них не считает é равным É.
  • Ключи нельзя квотировать при интерполяции переменных, например "$foo['key']" — ошибка синтаксиса. Вы может не квотировать ключи(будет сгенерировано предупреждение) или использовать ${...}/{$...}.
  • "${foo[0]}" работает. "${foo[0][0]}" — синтаксическая ошибка. Работает, если внести $ внутрь фигурных скобок. Плохо скопированный синтаксис Perl(с абсолютно другой семантикой)?


Массивы


Ё моё.
  • Этот тип данных ведёт себя как список, упорядоченный хэш, упорядоченный набор, разреженный список и время от времени как их странные комбинации. Какая его эффективность? Каков будет расход памяти?(пер. анализ расхода памяти для массивов) Кто знает? У меня всё равно нет других вариантов.
  • => — не оператор. Это специальная конструкция, существующая только внутри конструкций array(...) и foreach.
  • Отрицательные индексы не работают, т.к. -1 точно такой же валидный ключ как и 0.
  • Несмотря на то, что это единственная структура данных языка, для неё нет короткого синтаксиса; array(...)это короткий синтаксис. (PHP 5.4 вводит «литералы», [...].)
  • Конструкция => базируется на Perl, который позвляет foo => 1 без квотирования(вот почему конструкция существует Perl; иначе вы можете просто использовать запятую.) В PHP вы не можете так сделать не получив предупреждение; PHP — единственный язык в своей нише, в котором нет проверенного способа создать хэш без квотирования строковых ключей.
  • Функции работы с массивами часто ведут себя смутно и противоречиво, потому что вынуждены оперировать списками, хэшами или возможно их комбинацией. Взять хотя бы array_diff, «вычисляющий разность массивов».
    $first  = array("foo" => 123, "bar" => 456);
    $second = array("foo" => 456, "bar" => 123);
    echo var_dump(array_diff($first, $second));
    

    Что будет делать этот код? Если array_diff воспринимает аргументы, как хэши тогда очевидно они разные; одинаковые ключи с разные значения. Если аргументы воспринимаются как списки, тогда они всё равно разные; значения идут в разном порядке.

    Фактически array_diff признаёт массивы равными, потому что он воспринимает их как наборы; она сравнивает только значения и игнорирует порядок.
  • В той же мере array_rand странно ведёт себя выбирая случайные ключи, что не так полезно в общем случае выбора из списка вариантов.
  • Несмотря на то, как сильно PHP-код полагается на сохранение порядка ключей:
    array("foo", "bar") != array("bar", "foo")
    array("foo" => 1, "bar" => 2) == array("bar" => 2, "foo" => 1)
    

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


Немассивы


  • Стандартная библиотека включает «Quickhash», ООП-реализацию «специфических строго-типизированных классов» для создание хэшей. И на самом деле предоставляет четыре класса, каждый для работы с различными комбинациями типов ключей и значений. Непонятно, почему встроенная реализация массивов не может быть оптимизирована для этих очень частых случаев, и какова относительная эффективность «Quickhash».
  • Класс ArrayObject(реализующий пять различных интерфейсов) может оборачивать массив и позволяет ему вести себя как объект. Пользовательские классы могут реализовывать те же интерфейсы. Беда в том, что у класса жалкая горстка методов, половина которых не похожа на встроенные функции, к тому же встроенные функции не умеют оперировать ArrayObject'ом или другим похожим на массив классом.


Функции


  • Функции — не данные. Замыкания всё-таки объекты, но обычные функции нет. Вы даже не можете ссылаться на них по их прямым именам; var_dump(strstr) вызывает предупреждение и предполагает, что вы имели ввиду строковый литерал, "strstr". Нельзя отличить произвольную строку от «ссылки» на функцию.
  • create_function просто обёртка вокруг eval. Она создаёт функцию с обычным именем и устанавливает её глобально(поэтому эта функция никогда будет собрана сборщиком мусора — не используйте в цикле!). Она на самом деле ничего не знает а текущем контексте, поэтому это не замыкание. Имя содержит NUL-байт, поэтому такая функция никогда не конфликтует с обычными функциями(потому что PHP-парсер отказывает, если где угодно в файле есть NUL).
  • Если определить функцию __lambda_func, create_function сломается — на самом деле реализация создаёт через eval функцию с именем __lambda_func, затем внутренними методами переименовывает её. Если __lambda_func уже существует, первая часть процесса бросит fatal error.


Прочее


  • Инкремент (++) NULL'а выдаёт 1. Декремент (--) NULL'а выдаёт NULL. Более того декремент строки оставляет её неизменной.
  • Нет генераторов.


Web-фрэймворк


Выполнение


  • Один общий файл, php.ini контролирует огромную часть функционала PHP и вводит сложные правила относительно того, что и когда перегружается. PHP-приложение которое предполагает внедрение на произвольных машинах вынужден в любом случае заменять настройки, чтобы нормализовать окружение, в любом случая уничтожая полезность такой механики как php.ini.
  • По существу PHP выполняется как CGI. При каждой загрузке PHP-страницы всё приложение перекомпилируется и выполняется. Даже дев серверы для игрушечных Python-фрэймворков так себя не ведут.

    Это создало целый рынок «PHP-акселераторов», выполняющий компиляцию единожды, ускоряя PHP до уровня любого другого языка. Zend, компания, стоящая за PHP, сделала это частью своей бизнес-модели.
  • Достаточно долгое время PHP-ошибки по умолчанию шли на клиент — думаю, чтобы для помощи при разработке. Не думаю, что это до сих пор верно, но я всё ещё время от времени вижу mysql-ошибки, выпадающие наверху страницы.
  • PHP всё ещё полон странных «пасхальных яиц» типа выдачи логотипа PHP при передаче соответствующего аргумента в запросе.
    Кроме того, что это никак не связано с построением вашего приложения, это ещё и позволяет определить используете ли вы PHP(и возможно грубо определить какую версию), в не зависимости от того как много конфигурации в ваших mod_rewrite, FastCGI, обратном проксировании или Server:.
  • Пробелы вне тэгов <?php ... ?>, даже в библиотеках, считаются текстом и включаются в ответ(или приводят к ошибкам «headers already sent»). Популярный фикс — не указывать закрывающий ?>; PHP не жалуется и у вас нет завершающей новой строки в конце файла.


Внедрение


Внедрение часто упоминается как наибольшее преимущество PHP; сбросьте несколько файлов и всё. В самом деле это проще, чем выполнение целого процесса, как вы делали бы в Python, Ruby или Perl. Но PHP не даёт много другое.

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

  • PHP естественно связан с Apache. Выполнение его по отдельности или с другим Web-сервером требует точно такой же(если не больше) возни как и в других языках.
  • php.ini применяется ко всем PHP-приложениям, выполняющимся на машине. Есть только один файл php.ini и он применяется глобально; если вы на shared-сервере и вам нужно его изменить, или вам нужно выполнять два приложения с различными настройками, тогда вам не повезло; вы должны применять набор всех нужных настроек из самого приложения через ini_set, конфигурационный файл Apache или .htaccess. Если можете. Вау, нужно проверить много мест, чтобы определить как же настройка получает своё значение.
  • Подобным образом нет простого способа «отделить» PHP-приложение и его зависимости от остальной системы. Выполняете два приложения, требующие разных версий библиотеки или даже самого PHP? Начните со сборки второй копии Apache.
  • Подход «сбрось несколько файлов» между прочим делает routing жуткой болью в заднице, также это значит что вы должны осторожно разрешать и запрещать доступ, потому что ваша иерархия URL'ов, также весь ваш код. Конфигурационные файлы и другие «partial'ы» требуют защитных проверок как в C, чтобы избежать их прямой загрузки. Шум контроля версий (типа .svn) должен быть также защищён. С mod_php всё в вашей файловой системе потенциальная входная точка; с сервером приложений, у вас одна входная точка, и только URL контролирует вызывается ли она.
  • Вы не можете бесшовно обновить несколько файлов выполняемых как CGI, если вы не хотите падений и неопределенных поведений, когда пользователи пинают ваш наполовину обновлённый сайт.
  • Не смотря на то, как просто настроить Apache для выполнения PHP, даже здесь вас поджидает несколько коварных ловушек. В то время, как документация PHP советует использовать SetHandler для запуска .php-файлов как PHP, AddHandler работает так же хорошо, и на самом деле Google выдаёт мне в два раза больше результатов для AddHandler. Собственно проблема.

    Когда вы используете AddHandler, вы указываете Apache, что «выполнение следующего как php» — один из возможных способов обработки .php-файлов. Но! Apache не одного и того же мнения о расширениях файлов, как каждый человек на планете. В нём есть поддержка, например, index.html.en, распознаваемого как HTML-файла на английском. Для Apache файл может иметь сколько угодно расширений одновременно.

    Представьте, что у вас есть форма загрузки файлов, которая выгружает файлы в публичную директорию. Чтобы быть уверенными, что никто не загрузит PHP-файл, вы просто проверяете, что расширение файлов не .php. Всё, что атакующий должен сделать это загрузить файл с именем foo.php.txt; загрузчик не увидит никаких проблем, но Apache будет распознавать файл как PHP, и он выполнится.

    Проблема не в том, что «используется исходное имя файла» или «надо было лучше валидировать»; проблема в том, что ваш Web-сервер, настроен выполнять любой старый код, на который он может наткнутся — именно это свойство делает PHP «простым для внедрения». CGI требовал +x, это хотя бы что-то, но PHP не требует даже этого. И это не теоретическая проблема; я нашёл несколько сайтов с этой проблемой.


Чего не хватает


Я предполагаю следующее с различными уровнями критичности для построения Web-приложения. Имело бы смысл в PHP, как языке, продаваемом как «Web-язык», реализовать что-нибудь из нижеуказанного.

  • Нет системы шаблонов. Есть сам PHP, не нет ничего что бы работало как большой интерполятор, вместо того, чтобы работать как программа.
  • Нет XSS-фильтра. Нет, «используй htmlspecialchars» — не XSS-фильтр. Вот это XSS-фильтр.
  • Нет CSRF-защиты. Вы должны делать её сами.
  • Нет обобщённого стандартного API для баз данных. Штуки, типа PDO, вынуждены оборачивать отдельные API для абстракции.
  • Нет routing'а. Ваш сайт выглядит так же как ваша файловая система. Многие разработчики обмануты, думая, что mod_rewrite (и весь остальной .htaccess) подходящая замена.
  • Нет аутентификации или авторизации.
  • Нет дев сервера.
  • Нет интерактивной отладки.
  • Нет явного механизма внедрения; только «скопируйте вот эти файлы на сервер».


Безопасность


В рамках языка


Плохая репутация безопасности PHP в основном связана с тем, что он принимает произвольные данные из одного языка и выдаёт их в другой. Это плохая мысль. "<script>" ничего не значит в SQL, но точно значит в HTML.

Ещё хуже становится от крика об «очистке входных данных». Это полностью неверно; нет в природе волшебной палочки, взмахнув которой вы делаете кусочек данных «чистым». Что нужно делать так это говорить на нужном языке: использовать placeholder'ы в SQL, использовать списки аргументов при создании процессов и пр.

  • PHP открыто поощряет «очистку»(пер. sanitizing): для этого есть целое расширение для фильтрации данных.
  • Все эти addslashes, stripslashes и прочая слэш-фигня — отвлекающий манёвр, который ничего не даёт.
  • Как я знаю, нет способа безопасно создать процесс. Можно ТОЛЬКО выполнить строку через шэл. Вы можете экранировать как сумасшедший и надеяться, что шэл по умолчанию использует верное экранирование; либо вручную делать pcntl_fork и pcntl_exec.
  • Две функции escapeshellcmd и escapeshellarg имеют почти одинаковые описания. Заметьте, что для Windows, escapeshellarg не работает (т.к. предполагает семантику Bourne shell), а escapeshellcmd просто заменяет пачку пунктуаций на пробелы, потому что никто не может понять экранирование Windows cmd (который может тихо упасть вне зависимости от того, что вы пытаетесь сделать).
  • Оригинальные встроенный MySQL-байндинги, до сих пор широко используемые, не могут создавать prepared statement'ы.


По сей день PHP-документация по SQL-инъекциям рекомендует сумасшедшие практики типа проверки типов, используя sprintf и is_numeric, везде вручную используя mysql_real_escape_string, или везде вручную используя addslashes (которая «может быть полезна»!). PDO или параметризация даже не упоминаются, кроме как в пользовательских комментариях. Я пожаловался на это конкретное место разработчикам PHP минимум два года назад. Да, разработчики были встревожены… страница не обновлена до сих пор.

Небезопасны по умолчанию


  • register_globals. Его выключили по умолчанию достаточно давно, и он пропал в PHP 5.4. Мне пофигу. Это помеха.
  • include разрешает HTTP URL'ы. Туда же.
  • Magic quotes. Так близки к безопасности по умолчанию, и всё же слишком далеки от правильного понимания самой концепции.


Ядро


Интерпретатор PHP сам по себе содержал просто очаровательные проблемы безопасности.

  • В 2007 в интерпретаторе была уязвимость переполнения целого. Фикс начался с if (size > INT_MAX) return NULL; и покатился по наклонной. (Для тех, кто не в курсе C: INT_MAX самое большое целое, которое может уместится в переменную, вообще. Я думаю, дальше вы поняли.)
  • Чуть позже, в PHP 5.3.7 умудрились включить функцию crypt(), которая фактически позволяла зайти кому угодно с каким угодно паролем.
  • PHP 5.4 уязвим к отказу в обслуживании, т.к. он берёт заголовок Content-Length (который кто угодно может установить в любое значение) и пытается создать массив переданного размера. Это плохая мысль.


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

Заключение


Некоторые комментаторы справедливо указали, что у меня нет заключения. И да, у меня нет заключения. Если вы до сюда дочитали, я предполагаю, вы были согласны со мной с самого начала :)

Если вы знаете только PHP и вам любопытно научиться чему-то ещё, гляньте учебник по Python и попробуйте Flask для Web'а. (Я не большой фанат их языка шаблонов, но он делает своё дело.) Он разделяет части вашего приложения, но это всё ещё те же самые исходные части и они должны быть похожи на то, что вы видели до этого. Я, возможно, напишу настоящий пост об нём; ураганное введение в целый язык и web-стек — тема для другой статьи.

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

Если вы не разработчик, но всё равно читаете это по какой-либо причине, я не успокоюсь, пока все не планете не прочитают Learn Python The Hard Way.

Я не пробовал Ruby on Rails и его соперников, у Perl с его Catalyst'ом вроде есть ещё порох в пороховницах. Читайте, учитесь, создавайте, жгите.

Ссылки


Спасибо за вдохновение:

Перевод: Eevee
Артем Ольшевский @siasia
карма
124,7
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

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

  • –27
    Какой ужасный перевод.
    • +89
      Статья огромная. Слэнговая. Я считаю оно в любом случае того стоило :)
      • +20
        Однозначно стоило. Хотя бы для того, чтобы разместить на Хабре. Автору мегареспект.
        • 0
          И начать очередной холивар…
    • +5
      Перевод неплохо. Просто, видимо, у автора не так много переводческого опыта и он спешил.
      • +18
        Переводческого опыта определённо нет. И да, признаюсь, спешил, боялся перегореть и забить.
      • 0
        При переводе очень больших статей (особенно со сленгом) привыкаешь к середине и странные языковые конструкции становятся привычными. Так что скорее просто недостаток опыта.
    • +5
      Можете перевести сами: translated.by/you/php-a-fractal-of-bad-design/into-ru/trans/
  • –34
    Сколько пафоса…
    • +41
      Сколько пафоса…
      • +10
        Понять и простить…
        • –1
          Я один не понял что произошло в этой ветке? :))
          • –1
            вы не одиноки
  • +10
    Я конечно ждал, что эта нетленка будет переведена на Хабрахабре… Но не в таком виде.

    Тут нужен адаптивный перевод с сохранением юмора, а не этот прогон через первокурсника-филолога, ну. Текст заслуживает хорошего перевода.
    • +2
      Извините, я не филолог. Поможете довести до ума?
      • –6
        Я такие вещи читаю только на языке оригинала.

        Тащемта, кому интересно, есть неплохой ответ на статью: blog.ircmaxell.com/2012/04/php-sucks-but-i-like-it.html
        • +1
          Но она мне нравится, пусть и не красавица…
        • +6
          • +1
            Спасибо.
        • 0
          Перевести что ли…
          • 0
            Опоздал :)
            • +1
              Ничего, можете вычитать и помочь переводчику, например :)
              • +2
                Короче оригинал — меньше ошибок в переводе :)
              • 0
                Ему это не помешает, хочу заметить.
      • –1
        И да, я тоже не филолог :)
      • +9
        Для того, чтобы делать хорошие переводы, не надо быть филологом, надо хорошо знать язык, на который вы переводите (и неплохо — тот, с которого).
      • +1
        Кстати, почему бы и не довести её до ума, раз уж начали.

        Кидайте мне в почту (sergey.sega.vasilenko → gmail.com) вариант с маркапом. Сегодня-завтра причешу.
        • 0
          Вам, что больше нравиться? Хабрамаркап или маркдаун?
          • 0
            Давайте md.
  • +26
    читал и плакал
    • +10
      читал и смеялся :)
  • –8
    Хотел написать много всего, но решил ограничиться следующим:

    1. Надеюсь, автору оригинала и переводчику значительно лучше спится после такой полезной и оригинальной статьи.

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

    «Я пожаловался на это конкретное место разработчикам PHP минимум два года назад, разработчик был встревожен и страница не был с тех пор обновлена»

    И такого пол текста.

    3. Всегда думал, что если что-то не нравится, то не бери и не пользуйся. Ощущение, будто автора пытали программированием на PHP несколько лет и в сыром подвале. Потом его спасла полиция и вся эта статья — исповедь перед журналистами. Для чего потрачено столько времени?
    • +3
      Вы знаете. Не промтом. Вручную. Над процитированным предложением долго бился, а вот с родом и правда промахнулся. Ща поправим.
      • –24
        Не обижайтесь, но по-моему, здесь тот случай, когда проще «сделать заново», нежели исправить.
        • +17
          siasia пожимает плечами.
          • +54
            Забейте на всех этих умников — они просто завидуют, что Вы смогли сделать такой здоровенный кусок работы, а они нет. Я прочитал с удовольствием, спасибо за перевод.
            • –9
              Да бросьте вы.
              Сделать много работы и сделать много работы хорошо — разные вещи. Не понимаю, чего все так переводчика защищают. Или вам плевать, что вам предлагают к прочтению? Как можно «с удовольствием читать» несогласованные предложения, где смысл не всегда понятен?
              • +10
                Нам не плевать. Вот мы вместо того, чтобы судачить об этом скидываем в личку переводчику багованые места. И по-тиху статья становится лучше.
                • –25
                  Мне не наплевать на то, что я читаю. Если взялся переводить, то делай это хорошо. Лично я не вижу никаких подов исправлять чужой перевод. По-моему, в наше время, можно любой текст перевести без проблем, при этом владея только тем языком, на который осуществляется перевод.

                  В общем ладно, продолжайте хвалить другу друга и заниматься обоюдным вытиранием соплей. В нашей стране так принято — человека стоит хвалить за одно только желание что-то делать. Качество результата второстепенно. Толерантность и кармодрочество хабра возводят все это в степень.
                  • +9
                    У нас тут вообще-то сообщество. Если нашел ошибку или неточность — сообщи автору в лс. Никто никому ничего не обязан. Ишь ты, не нравится ему перевод.
                    • –18
                      Да, простите. Я забыл, что быть нем-то недовольным запрещено. Нужно всем широко улыбаться и говорить спасибо даже за то, что в принципе внимания не достойно.
                      • +13
                        Есть такой принцип в мире opensource: «Открывать рот может только тот, кто что-то сделал». Если бы у Вас в профиле висел десяток грамотных переводов и значок «Переводчика» — Ваши замечания были бы приняты и имели бы смысл. Заявления «Надо делать хорошо! Я вот ничего не сделал, но если бы сделал — это было бы сделано ужасно круто» — Вы сами слышите как звучат.
                        • –13
                          Перевод статьи из разряда «Язык программирования @name@ — говно» — это opensource? Выходить, всем известное слово из трех букв, написанное на заборе — тоже opensource и не дай Бог кому-нибудь возмутиться на этот счет…

                          За сим откланяюсь.
                          • +9
                            opensource был упомянут просто как источник хорошего принципа. Удачи Вам.
              • +3
                > Как можно «с удовольствием читать» несогласованные предложения, где смысл не всегда понятен?
                У меня в голове встроенная автозамена, которая согласует слова в предложении, тогда становится понятен смысл, так что все нормально.
                Но, немного соглашусь, что перевод местами кривой.
              • +4
                На английском я бы столько не прочитал. Хотя читаю более менее свободно.

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

                А за перевод респект. Хоть я и не пишу на ПХП после того, как провел две почти бессонные недели вычищая код наших аффилированных субподрядчиков. Потому что с их срокам реакции на замечания — так было проще.

                По сути статьи меня бесит еще вот что: пхп позаимсвовал у перла много библиотек (с теми же именами), поэтому когда гуглишь что-то перловое… натыкаешься на кучу к делу не относящегося.
      • +2
        И над «нитями» вместо «потоков» бились наверное?
        • +3
          О, блин, точно :) Бывает забудешь слово и клещами его не достать.
    • –10
      Поддержу про перевод. Прежде чем переводить с английского, неплохо бы выучить русский. Глядишь и проблем с переводами меньше будет.
    • +20
      > 3
      Вот мне тоже интересно, как он собрал такую огромную подборку. Это надо быть или коллекционером, или мазохистом.

      Пока работаешь на php половины из этого не замечаешь, ко второй привыкаешь и это не так беспокоит. Проблемы видно со стороны. После Питона, например.
    • +6
      Я хотел автору оригинала нечто подобное написать (это я про пункт 3) и даже пытался адаптировать наше «мыши плкали, кололись, но продолжали жрать кактус» для инглиш-спикеров, но вспомнил картинку «в интернете кто-то не прав» и решил, что оно того не стоит — у каждого свои заморочки.
      Пусть ruby, java, python, erlang программисты тужатся, обсирая PHP, мне как-то пофиг — для меня PHP — инструмент, так же, как Python и Java.
    • +3
      Для чего потрачено столько времени?
      Быть может, для того, чтобы его не тратили другие, выбирая себе инструмент для работы?
  • +15
    Много честно, но много и гипертрофированно. Аналогия с кривыми инструментами не верна, там скорее о кривых руках и незнакомых инструментах надо было писать.
    Как php-developer подписываюсь под бОльшей частью претензий, но менять язык не собираюсь, знакомые болячки на уровне разработки как рутина обрабатываются, а новых болячек новых языков никакой устоявшийся проект не утерпит
    • +6
      Я думаю что эта статья больше для новичков, чтобы лишний раз задумывались перед выбором инструментов.
  • +58
    Любители php обиделись и вымещают злость на переводчике. Чем выкобениваться, лучше помогите ему, указав на слабые места перевода и предложив свой вариант. Почему-то, ни у кого из прокомментировавших «ужасный перевод», я не обнаружил в профиле десятка отлично переведенный статей. А с виду казались такими умными, начитанными ребятами.

    Переводчику спасибо. Представляю каково было переводить эту простыню.
  • +18
    Перевод нормальный, спасибо переводчику.

    Что касается автора данного «труда» — очевидно что он просто теоретик.
    Да, он много знает, но все это теория. Все эти доводы актуальны только когда речь идет о «программировании ради программирования». Но автор забывает что программирование — это работа, которая делается для того чтобы (о, боже!) получать деньги. А когда мы начинаем говорить о деньгах на первый план выходят совсем другие вопросы:
    — скорость развертывания;
    — количество специалистов на рынке;
    — стоимость обучения;
    — размер сообщества;
    — количество аутсорсных компаний;
    и т.д.

    Да какая мне, черт побери, разница что python имеет более правильный синтаксис массивов, если python-разработчика я буду искать полгода, а php — две недели?
    • +27
      Потому что каждый раз когда вам надо что-то поменять — вы снова будете искать 2 недели еще одного разработчика на PHP, еще неделю он будет переписывать все, т.к. ему просто не понятно что там накалякал предыдущий…

      Главные свойства любой системы, которая должна проработать дольше недели — стабильность, поддерживаемость, повторяемость\предсказуемость результата. Если вы пишете код который выбрасываете через неделю — я вам сочувствую, имхо вы проживаете свою жизнь зря, тратя ее на такой бессмысленный труд.
      Жизнь слишком коротка чтобы заниматься говенной работой.
      • +2
        Вдогонку — это не касается конкретного языка — я не пишу на PHP или Python (хотя последний порывался попробовать\изучить), это именно фундаментальные принципы, которые должны соблюдаться продуктом для надежности его функционирования.
        Прочитав статью до половины и сломав мозг на некоторых вещах, типа левоассоциативного ?: (ну почему Horse-то ?8-\?), я понял что обрисованная картина довольно печальная. Хорошо что я ушел из PHP очень рано.
        • 0
          Кстати про horse тоже не понял, хотя php не знаю, но логика-то должна быть хоть какая-то :)
          • +8
            ( $arg == 'B' ) ? 'bus' :
                         ( $arg == 'A' ) ? 'airplane' :
                         ( $arg == 'T' ) ? 'train' :
                         ( $arg == 'C' ) ? 'car' :
                         ( $arg == 'H' ) ? 'horse' :
                         'feet' )
            

            Раз вернулся horse, значит
            ( $arg == 'B' ) ? 'bus' :
                         ( $arg == 'A' ) ? 'airplane' :
                         ( $arg == 'T' ) ? 'train' :
                         ( $arg == 'C' ) ? 'car' :
                         ( $arg == 'H' )
            

            вернул 'car'. bool('car') -> True А 'car' он вернул потому что
            ( $arg == 'B' ) ? 'bus' :
                         ( $arg == 'A' ) ? 'airplane' :
                         ( $arg == 'T' ) ? 'train' :
                         ( $arg == 'C' )
            

            вeрнул 'train'. А 'train' он вернул потому что
            ( $arg == 'B' ) ? 'bus' :
                         ( $arg == 'A' ) ? 'airplane' :
                         ( $arg == 'T' )
            

            вернул true. Потому что $arg == 'T" и
            ( $arg == 'B' ) ? 'bus' :
                         ( $arg == 'A' )
            

            вернул false, потому что $arg != 'B' и $arg != 'A"
            • 0
              Ужас, а не код. Пионеры прочитают и будут так делать, ох.

              $arg = 'A';
              $items = array('A' => 'airplane', 'B' => 'bus' ...);
              if (in_array($arg, array_keys($items) ))
              {
              echo $items[$arg];
              }
              • 0
                приведённый выше пример решает, конечно, не совсем ту задачу, скорее это пример упрощения.

                С кучей вариантов if-elseif-else/switch-case всегда лучше для последующего использования, чем инлайн-условие, использованное не по делу.
                • 0
                  «инлайн условие» лучше тем, что не заставляет повторять n раз одно и то же.
              • 0
                в php нет функции с параметром который возвратится если ключа нет массиве?
                В python это было бы так:

                {'B':'bus', 'A' : 'airplane', 'T': 'train', 'C':'car', 'H': 'horse'}.get(args, 'feet')
                
                • 0
                  Если элемент не false или null, то можно так:

                  $items[$arg] ?: 'feet';
                  • 0
                    Вот за что я люблю перл, что там все определенно (ну если знать как работают умолчания, конечно)

                    exists $items{$arg} && defined $items{$arg} ? $item{$args} :  'default'
                    
                    • 0
                      Всё это великолепие можно (да и НУЖНО) написать как:

                      $item{$arg} // 'default'
                      • 0
                        Нет, так писать нельзя, проверка $items{$arg} = '0'

                        Я же не указал в условиях задачи, что является валидным вводом ;)
                        • 0
                          ок =)
                          • 0
                            Хотя для большинства случаев вы правы — но я хотел продемонстрироать именно проверку разных состояний exists и defined
                    • 0
                      Полный аналог этой строки в PHP, видимо:

                      array_key_exists($arg, $items) && isset($items[$arg])? $item[$args]: 'default';
                      • 0
                        ну значит не всё так страшно. единственное, что действительно имена функций не очевидные согласованые, хотя код вполне читаем
                      • 0
                        Кстати, вы ошибку скопипастили. В перл она нестрашная, ибо сразу вылезет exception при use strict (а тех, кто не пишет первой строчкой use strict, на работу не берут, ибо диагноз)
                        • 0
                          PHP тоже выдаст два предупреждения (Notice) в этом случае (в логи или прямо на странице, смотря как настроено). Исключение не выбросит, но в случае PHP его и не должно быть, я считаю.
                          • 0
                            Имелась ввиду ошибка компиляции. Имхо — это более правильно, чем предупреждение в логах — кто их читает пока не припрёт? ;)
                        • +1
                          я пишу use strict четвертой строчкой. пора увольняться? :)

                          #!/usr/bin/perl
                          
                          use warnings;
                          use strict;
                          
                          • 0
                            ох уж эта перловая свобода выбора решения)

                            уели )
                      • 0
                        правильней будет просто:

                        isset($items[$arg])? $items[$arg]: 'default';
                  • 0
                    упс опечатко, но в первой строчке все равно написано use strict;
      • 0
        каждый раз когда вам надо что-то поменять — вы снова будете искать 2 недели еще одного разработчика


        Если вы пишете код который выбрасываете через неделю


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

        • +6
          Данные утверждения основаны на том, что вы ставите во главу угла количество специалистов на рынке, скорость развертывания и пр. Это все важно, но определенные фичи достижимы при любой платформе, специалисты — вам нужна малая часть, вы же не собираетесь скупить всех свободных пхп прораммистов для реализации своей задачи, а дешевизна — ну о качестве она говорит обычно довольно внятно.

          Но при этом вы упускаете из виду фундаментальные свойства, от которых зависит качество работы и сопровождения системы. Вы же не будете развертывать ее каждый день по новой, заказывать аутсорсинг или обращаться к коммунити. Один раз развернутая система должна работать. А создавать систему на «слабопредсказуемом» языке ( дао horse из текста я еще пока не постиг) — довольно опрометчиво.

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

          Я знаю (видел) что и на ПХП тоже можно писать качественные и сложные системы, но как правильно замечено в статье — талантливый программист перепишет любое решение хоть на brainfuck'е. Но зачем? Зачем делать что-то правильно когда сам язык мешает это делать, когда его поведение нелогичное, когда оно непредсказуемо и зависит от 2-3-5 параметров исходной системы, настроек компиляции или локали установленной при развертывании.
          Создавать продукты для такого окружения — тратить время своей жизни на борьбу с ветрянными мельницами — можно, но бесполезно. Хотя это ваше время и вам выбирать на что вы его потратите.
          • +1
            Ну я понял. PHP это зло по определению и любые его плюсы — всего лишь заблуждение.
            Миллионы людей пользуются им лишь потому что он прост, а питон невероятно сложен, ок.
            • +4
              Ну какие у него плюсы как у языка программирования?

              P.S. PHP просто только для непосвящённого человека, чтобы примеры для новичков выглядели симпатично, на самом деле надо писать МНОГО неудобного и некрасивого кода и единственный выход для какой-никакой гибкости — это уход в жёсткое ООП, что для новичков не особо-то радостная новость.
              • –2
                Я все написал в первом комментарии этой ветки.
                Проблема в том, что спорят со мной программисты — то есть те люди, который видят лишь одну сторону медали — написание кода. Думать о том что этот код нужно будет потом продать — не их работа.
                • +9
                  На самом деле в веб программировании клиенты не очень часто выставляют предпочтения на чём для них писать и как писать. Их больше интересует скорость, дешевизна и чтобы продвижение было дешёвое. Потому предлагать им можно что угодно, самое главное оправдывать данные обещания.
                  Да и можно переубедить при желании.
                  А большинство пишут на PHP не из-за каких-то сложных мыслей и забот, а потому что не знают что есть что-то иное и более лучшее.
                  • +2
                    Пару-тройку лет назад ещё большим доводом в пользу php была огромная проблема с хостингами для ruby/python.
                    А вот сейчас, если не считать хостеров с сервисом 'всё за пять копеек', то этой неприятности уже нет.
                    • +2
                      Ну как сказать, я пару месяцев назад так и не нашел хостинга с актуальной версией руби и рельс. Пришлось брать VPS. И неделю его мучать в попытках поставить весь набор.
                      • 0
                        Неделю? Что же вы делали неделю, интересно? Когда мне понадобился хостинг для работы django, я просто купил первый попавшийся VPS и настроил все за два часа.
                        • +2
                          Приложения на рельсах, джанге, куче других языков (Java, Scala, Clojure, Erlang, Node.js, PHP, etc) можно очень быстро задеплоить на Heroku.
                          • 0
                            Ну, тем более — если это ускорит процесс еще больше (сам не пробовал пока, но спасибо за наводку), то о какой неделе настройки говорить вообще? :))
                            • +1
                              Фактически деплой приложения на Heroku сводится к

                              $ heroku create --stack cedar
                              $ git push heroku master
                              


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

                              И кстати, на хероку можно запускать не только веб-приложения. Это могут быть и всякие background worker'ы, и боты.

                              Масшабировать приложения тоже не тяжело:

                              $ heroku scale web=10 worker=20 # будет 10 веб dyno и 20 воркеров
                              


                              Ну и легкая установка аддонов:

                              $ heroku addons:add sendgrid:starter # smtp
                              $ heroku addons:add mongolab:starter # mongodb
                              


                              По своим возможностям, IMO, Хероку является очень гибким и простым решением.
                  • +2
                    В том то и дело, что предлагать «все что угодно» можно далеко не всегда.

                    Для сравнения два варианта для предложения клиенту:

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

                    2. Мы сделаем все на Django, но вам потребуется VDS и сисадмин который все это развернет и настроит. Если хостинг разонравится — вам нужно будет повторить операцию на новом VDS. Для доработок вам нужен будет специалист по Django, которого трудно найти и он дорого стоит.

                    Какой вариант выберет клиент?

                    Я согласен что PHP имеет кучу проблем. Не спорю с этим, это очевидно.
                    Но продавать решения на нем — легче. Потому что он популярен.
                    Так что надо быть объективнее и не делать крайних утверждений.
                    • +4
                      Давно уже это неверно, как минимум с выхода PHP 5.3, ибо на многих хостингах стоит PHP 5.2 и так запросто всё не заработает (если замыкания используются и.т.п.). Да и клиенты сами с хостинга на хостинг на моей памяти не переезжали, всегда за отдельную плату, либо на основании каких-то договорённостей просили наших специалистов перенести им сайт.

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

                      Далее, обычно продавая сайт продают ещё и целый пакет услуг в которые входит и поддержка и доработка творения, потому выбор языка важен только если веб-студия разругалась с клиентом и/или не доделала всё в полной мере, такое бывает не часто и таким веб-студиям выбор ЯП не поможет =)

                      Я работал в веб студии которая имела собственный хостинг, потому это было совсем не проблемой. Да и за деньги мы подыскивали для клиентов хостинги и переносили их сайты (даже без собственной доработки).

                      Клиент выберет тех кому доверяет (а тут очень сильно влияют портфолио компании и обаяние менеджера), независимо от платформ и ЯП, ибо он (клиент) обычно не разбирается в этом.

                      P.S. опять же клиенту можно и про говнокодеров на PHP рассказать каждый последующий из которых за его деньги будет переписывать ему один и тот же код =)
                      P.P.S. сам сейчас поддерживаю достаточно посещаемый проект, после последнего говнокодера сайт просто перестал работать. Сейчас на том же железе производительность подняли в 6 раз и, думаю, ещё столько же выдержим. Так вот, эти сторонние фрилансеры-разработчики ни о какой безопасности вообще не задумывались, сайт был дырявый как дуршлаг. Про индексы для БД они тоже не слышали и о том что профилировать запросы можно тоже не знали. Кеширование — тоже какое то непонятное слово, при том что платили им от 1500/час. Вот тебе и PHP фрилансеры нанятые человеком не разбирающимся в вопросе.
                      • +1
                        Ну клиент будет сравнивать именно 2 предложения. И первое выглядит заманчивее. А что бы второе стало интереснее вам пришлось написать 6 абзацев текста.
                        • 0
                          Предложения выставлены однобоко и не особо-то и приближены к истинному положению вещей, о чём я и написал. Для того чтобы доносить такое и большее количество информации до клиентов есть менеджеры и они с этим, надеюсь, справятся.
                • +9
                  Все ваши плюсы не относятся к языку программирования, а к сложившейся на рынке ситуации. И, как мне кажется, автор оригинальной статьи исходит гневом именно по той причине, что наибольшее инфраструктурное преимущество имеет язык с одним из худших дизайнов. Это… огорчает.
                  • 0
                    Однако авторы подобных статей — не конструктивны. На тему того, что PHP плох — вылито уже прилично помоев. Но ещё никто не придумал, как внедрить в инфраструктуру веб лучший язык. А без этого все подобные статьи — неуместный троллинг и пережёвывание одного и того же. Впрочем, именно эта статья наверно должна была быть написана, переведена и прочитана каждым — титанический труд собрать всё это вместе и систематизировать. Надеюсь это поможет как-то изменить ситуацию со временем — то ли в сторону развития PHP как языка, то ли в сторону популяризации Ruby или Python'а.
                    • 0
                      Авторы подобных статей конструктивны в том смысле, что до сих пор встречаю фанбоев PHP, пытающихся рассказать о его достоинствах именно как языка. Можно не тратить время на призывы к здравому смыслу, а просто давать линк на статью.
                      Удобно.

                      А насчёт придумки — пфф, тут и думать нечего. Просто используйте другой язык. Вот так просто. Впрочем, в российских реалиях можно ещё попытаться нарисовать законодательный запрет на PHP с уголовной ответственностью :)
                      • –1
                        Вот так просто

                        И что в этом простого? Если я для своего проекта выберу другой язык — популяризации этого языка это поспособствует мало, а вот я огребу все недостатки низкой популярности этого языка — отвратная документация, отсутствие вменяемого сообщества, отсутствие соответствующего предложения на рынке труда. Хорошо, если проект — крупный и расчёт изначально идёт на то, что труд высококлассного программиста на порядки дешевле затрат на железо, всё окупится. Крупные проекты, собственно, так и поступают. Но если проект небольшой, специалисты на него нужны недорогие, то простотой здесь не пахнет ну никак. Небольших проектов значительно больше, чем крупных. Энтузиастов, готовых облагораживать за свой счёт индустрию — не много.
                        По моему скромному мнению, PHP вообще развивается быстрее, чем альтернативные языки откусывают долю от рынка.
                        • 0
                          > По моему скромному мнению, PHP вообще развивается быстрее, чем альтернативные языки откусывают долю от рынка.

                          Интересно как вы сравнили килограммы с минутами? (а точнее «фича/сек» с «процент/сек»)
                          • 0
                            По проекции на выгоду или потери от внедрения. Чем не показатель?
            • 0
              Вы или не читаете что я пишу или явно троллите. Я пытаюсь пояснить, почему предсказуемость поведения, защита от незнания секретных ключей\констант, (по сути все это — повторяемость результата) для языка важнее, чем доступность, массовость и дешевизна кодеров.

              Банальный пример:
              трудозатраты на реализацию решения с использованием языка «Х» — это сумма «5хS». Для доработки или для повторения решения (сделать и развернуть еще 1-2-100 копий) необходимы затраты «K».

              Трудозатраты на реализацию решения с использованием языка Y — это сумма S, сумму вы смогли уменьшить за счет массовой конкуренции на рынке программистов на Y. Но с большой вероятностью вы получили некачественное или сложноподдерживаемое решение. Если вас это устраивает — все ОК, одноразовые вещи должны делаться как можно дешевле.
              Если вам необходимо сопровождать\повторять это решение для каждого заказчика — стоимость сопровождения будет не K, а например 3хК. Очевидно что деньги сэкономленные в S против 5xS, вы потратите при доработках.

              А т.к. жизненный цикл нормального приложения довольно длинный — доработок будет больше чем разработок с нуля. В итоге в длительной перспективе — решение на языке Х дешевле чем на Y, хотя начальные вложения были больше.
              Вроде прописные истины, а вы обвиняете что я что-то называю злом по определению.
              Выбор платформы должен происходить на основе всего жизненного цикла приложения — короткая жизнь, одноразовый код — берите Y, доработки, сопровождение, надежность — берите X.

              Да, вместо X и Y могут быть любые другие языки, не обязательно упомянутые ;).

              • 0
                Да нет, троллите скорее вы.
                Сначала вы говорите что писать на PHP это «тратить время своей жизни на борьбу с ветряными мельницами», а теперь выясняется что все таки выбор зависит от задачи. Так это же очевидно, об этом я и говорил в своем первом комментарии.

                PS: и я до сих пор не понял почему мне нужно будет искать нового разработчика каждый раз, как я захочу что-либо поменять в PHP-коде.
          • +3
            Меня в институте бесил Access. Почти вся группа, из которой, если говорить честно, задатки программистов были у двух трех человек, на Access сделала вполне приемлемые приложения. Я же, «звездочка», с трудом сделал троечную работу, за которую мне поставили 4ку практически за старые заслуги.

            Я просто не мог понять, как это работает. А нужно было не пытаться понять, а просто потыкать мышкой. И написать пару строчек кода в в месте обозначенном на лекциях (на которые я, ессно, не ходил). Потом, уже после интститута мне приходилось чинить чужие аксесовские прилады… Практически методом тыка.

            Так что пхп на этом фоне логичен, в конце концов не всё заимствованное с перла (который, как не удивительно, весьма логичен) «упрощено для лучшего понимания».

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

            Если уж брать что-то что ты непонимаешь, как работает (к чему зачастую приходят вполне логичные и понятные проекты, начинающиеся с легкого фреймворка вне зависимости от языка), то лучше брать то у чего болшеекомьюнити… И менее заносчивое комьюнити, кстати.
            • 0
              Да-да, такая же история с Access. Я просто переключал окно в режим прямого редактирования SQL и писал запрос руками. И писал обработку событий на формах тоже руками. Как народ умудрялся что-то там нащёлкивать для меня до сих пор остаётся загадкой.
              • 0
                Вот это и удивительно — как майрософт ухитрился сделать среду разработки, интуитивно понятную новичкам и «убивающую» спецов, привыкших «копать глубже».

                Формы, кстати фигня, — вот система функций там отдельная песня. Как их можно так назвать и организовать, что поиск нужного выливался в квест? Наверно шаманы работали.
      • –3
        Хнык. Хнык.
        *ушел дальше заниматься говенной работой*…

        А где я тут в долбаном захолустье найду вакансию javascript или ruby или чего там еще ТруЪ?
        • 0
          За рубежом, разумеется. Интернеты есть? Весь мир открыт.
          • –2
            Ну да, ну да. Звучит правильно и красиво. Ну а как иначе можно выразиться на таком уважаемом ресурсе. Только вот мне надо пару лет переучиваться, менять подходы, искоренять php из головы, сказать на это время семье и детям — счас мы будем пару лет жить хуже, потому что в интернете дядя мне сказал что на пхп работать низя, и чтобы постичь дзен нужно кодить на питоне…

            А, ну да, еще сказать директору той работы на которой работаю — говно эта твоя работа, тут на пхп всё написано, и плевать что мы первые в рунете и снг по нашей тематике. Этож не тру.
            • +2
              Только вот мне надо пару лет переучиваться

              Пару лет? Это же не обучение программированию с нуля. Шаблоны проектирования и прочие MVC они и на питоне работают. База Данных и там и там.
              Раз вы хороший специалист, то вы, вероятно, выделяете время для обучения, и, скорей всего, вы программируете не только на PHP. А значит можете изучать тот же питон параллельно работе.
              • +1
                Ну вот смотрите. я представляю что такое mod_php, fcgid, fastcgi, fpm и примерно как их нужно варить и сколько солить; каковы особенности работы с тяжелыми данными на php, как разруливать и делать достаточно нетривиальные конфигурации. Знаю как расширять некоторые cms, их косяки, вижу сразу «индусский код», знаю что мне ждать от xcache а что от других опкешеров, как защитить те или иные вещи и овер 9000 остального. На любой вопрос я почти сразу знаю ответ как это сделать правильно, безопасно, быстро.

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

                Для того, чтобы делать что-то интересное например на питоне, мне нужно знать его историю, знать его косяки, знать на нем как минимум пару различных *MS, архитектуру ядра хотябы в первом приближении, около 50 разных библиотек…

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

                Так что развлекайтесь с вашими питонами как душе угодно, но работы на PHP больше раз в 100500. И реалии таковы, что если сразу не начал с этого лет 5 назад, то свободно все бросить можно только при наличии тыла, свободного времени, и уверенности что это еще кому то нужно…
            • +1
              Вы это всё к чему вообще? Вы спросили — где найти вакансию. Вам ответили — работать с зарубежными заказчиками. Какое отношение к этому имеют рыдания по поводу «переучиваться»?
          • +1
            У нас один программист работал. «У нас» == крупный богатый интегратор. В котором, сотрудников не считали. Посему там можно было не работать (при некоторой пофигистичности и фрондерстве). Ибо з/п одного специалиста ни на что не влияла, а количество спецов влияло — на престиж отдела. Т.е. никого увольнять за профнепригодность там даже и не пытались, просто игнорировали.

            А вот этого товарища уволить собирались. Ибо косячил… Везде. eval «action_$USER_INPUT» — это просто мелочи, рабочие моменты.

            Но не успели уволить, сам исчез. Объявился в Канаде, либом с приличной зарплатой. Оттуда продолжал по аське задавать дурацкие вопросы, в основном по ПХП. Гуглящиеся на раз-два.

            Так что и с ПХП можно уехать и устроиться… Главное чтобы руки язык из нужного места рос.
        • +5
          Вы можете стать профессионалом и в PHP, более того — зная все тонкости, описанные в статье, вы будете очень, очень ценным кадром, т.к. вы сможете своим «участием» в проекте на PHP придать языку качества, которыми он «не обладает в стандартной поставке».
          Но только надо тогда уж становиться профессионалом, а не убеждать себя в стиле «буду работать как все и на массовом рынке» (возможно вы таким и становитесь, я не знаю).

          Есть просто одна проблема работы на массовом рынке — люди стареют и качественно делать одну и ту же работу — невозможно. молодые обойдут на поворотах, срежут углы за счет 3 бессонных ночей, подрежут на хаках, которые вы себе не позволяете. Поэтому надо сдвигаться всегда в сторону «штучности».
          В «массе» очень трудно жить, ну если только вы не пасете всю эту массу =)
    • +8
      «Работа, чтобы получать деньги»… нет, не слышал. Я-то всегда думал, что это занятие, к которому лежишь всей душой, от которого получаешь удовольствие, ну и, как побочный эффект, за это ещё и хорошо платят. Какой смысл разрабатывать на чем-то, что не нравится концептуально, идеологически или просто неудобно, не радует эстетически, в конце концов? К чему эдакий мазохизм? Но если «работа» от слова «раб», то ок ;-)

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

      Количество «специалистов», особенно на школьных каникулах — зашкаливает, а вот найти человека, который правда умеет нормально писать на PHP иногда посложнее, чем для, скажем, конкурирующих языков. Низкий порог вхождения и то, что PHP позволяет писать плохо — делают своё грязное дело, т.е. насыщают этот самый рынок говнокодерами, в то время, как некие другие языки просто не позволяют писать плохой код, что, в купе с другими факторами, предотвращают распространение заразы. Что лучше, 100 человек, из которых только 6 действительно специалисты, или 20, из которых все или, хотя бы, 19 более, чем достойны?

      Стоимость обучения… специалистов обучать не надо вообщем-то, они и сами отлично обучаются. Это только «специалистов» надо доучивать или переучивать. На эту тему — предыдущий абзац. Остальные случаи «обучения» тоже эквивалентны вполне, хотя бы, исходя из «затраты/польза».

      С сообществом всё тоже самое, что и со «специалистами», — можно иметь орду «индусов», из которых лишь процент — идеологические спецы, или же сообщество поменьше, но где каждый самоценен.

      Даже если исходить из денежных соображений, что само по себе, концептуально, «рукалицо» и «провал», то куда больше рисков и потенциальных трат именно на стороне сабжа.

      IMHO.
      • +1
        Вопрос не в том, что нравится именно вам и от чего вы получаете удовольствие.
        Это может быть что угодно, без проблем.
        Вопрос в экономической эффективности того или иного инструмента.
        И в этом плане на сегодня у PHP нет конкурентов, как ни крути.

        Да, есть риски. Но в случае чего я найду фрилансера который все исправит за полчаса.
        Пусть это будет «говнокод», окей. Но кому какое дело, по сути? В реальном мире всем важно чтобы «это работало» а не «как это работает».

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

        Я не отрицаю что у PHP есть проблемы, более того, согласен почти со всеми утверждениями автора.
        Просто я считаю что нельзя так однобоко судить и делать крайние утверждения.
        • +2
          Вопрос в экономической эффективности стоит перед бизнесменами, а программистам должно быть важнее удобство инструментов и скорость проектирования и/или рефакторинга ПО.
          • –8
            Программист — это наемный работник, который пишет то что ему скажут на чем ему скажут.
            Если программист сам выбирает инструмент — значит он либо уже на половину «бизнесмен» (хотя я бы предпочел слово «менеджер») и ему это позволено, либо для компании где он работает производство софта — не профильное занятие.
            • +2
              Программист — это софтверный инженер, специализирующийся на каких-то технологиях. Как и других инженеров, его привлекают для решения специфических задач по его специализации.
        • +4
          Пусть это будет «говнокод», окей. Но кому какое дело, по сути? В реальном мире всем важно чтобы «это работало» а не «как это работает».

          Подход « лишь бы это работало» приводит только к дополнительным затратам. На поддержку, на оборудование, чтобы «лищь-бы-работало-код» не тормозил.

          Если вы или ваша компания может позволить себе тратить время на такой код — то замечательно!
          • 0
            Вы утрируете. Думаю всем понятно что я имел в виду.
            • +2
              Да, не перевелись еще эффективные менеджеры типа «главное побыстрее сбагрить лоху-клиету, экономя на всем». А что, торговать обносками на базаре — тоже бизнес.
              • 0
                Конечно, лучше пусть клиент ждет три года, он же никуда не торопится.
                Я ведь не о корпорации со штатом в 1000 программистов говорю.
                • 0
                  Никто не спорит что делать сайты-визитки на PHP легко и выгодно. Я говорил именно о написании веб-приложений.

                  На питоне можно написать ничуть не медленнее. Можете посмотреть на примеры экстремального программирования, когда делали сервис на Django за 2 суток. На выходе читаемый код, быстро вносить изменения и тд. Берите толковых студентов (питон изучить — ничего сложного), платите нормальную для студента зарплату и делайте качественные продукты. Так нет ведь, столько менеджеров думает что «говнокод» и «говнодизайн» — это такие прихоти программистов.
                  • +1
                    В итоге мы пришли к тому, с чего все началось.
                    А именно — к мысли «каждый инструмент хорош для своих задач».
                    Моя претензия к автору изначально не в том что он ругает PHP, а в том что он умалчивает о возможности его эффективного применения там, где это уместно.
                    • 0
                      О том, чем PHP хорош и так кричат на каждом углу.

                      Возможно автора, как и многих, задолбало именно засилье евангелистов-недоучек, которые выучили php и пытаются написать на нем все, начиная от приложения для распределенных вычислений, кончая обработкой изображений.
                      • –4
                        О, у пехепешников баттхерт =) Давай, ставь мне минус и ты перестанешь писать свой фреймворк за еду =)
          • 0
            Подход « лишь бы это работало» приводит только к дополнительным затратам. На поддержку, на оборудование, чтобы «лищь-бы-работало-код» не тормозил.

            Если вы или ваша компания может позволить себе тратить время на такой код — то замечательно!

            вот этот вопрос на самом деле заслуживает простыни раз в 10 подлиннее, чем сама статья.
            Перманентных выгод может быть гораздо больше, но те заторы, которые могут случиться в дальнейшем, в критическое время — могут убить все начинания. Тонкая грань, нить, на которой висит выбор умного управленца — это найти такой баланс между инструментом, далекоидущими планами, исполнителями и средствами, которые можно на это направить — талант нужен тот еще…
        • +1
          Пусть это будет «говнокод», окей. Но кому какое дело, по сути?

          Тем продажникам, которых потом сожрут разъярённые клиенты из-за потери данных?
          xkcd.com/327/
          • +3
            да.
            В моей практике был клиент, который раньше нанимал индусов.
            Ну что же, всего 2$/hour, вся деревня к вашим услугам.

            Всё было ок, да.

            Перестал, когда слили базу клиентов, из-за кода что-то вроде
            «select * from users where login=$_GET['login']»…
            Причем это всё было приколочено к вебмагазину на кейке, вопреки всем заветам MVC, вообще игнорируя все концепции.
          • 0
            Всегда при упоминании трудов программиста идёт речь об аутсорсинге. Я разрабатываю софт для внутреннего использования в компании, и тут выгода полного ООП, канонов программировани и прочих академических штук очивидна. Иногда давят на «надо быстрее запустить», ошибки в процессе попрявятся.
    • +2
      А когда мы начинаем говорить о деньгах на первый план выходят совсем другие вопросы:
      — скорость развертывания;
      — количество специалистов на рынке;
      — стоимость обучения;
      — размер сообщества;
      — количество аутсорсных компаний;


      Серьезный бизнес! И что это мы тут какие-то тупые .Net и Java изучаем. Весь топовый бизнес давно на пхп!
      • 0
        В мире есть не только топовый бизнес.
    • +2
      — скорость развертывания;
      Со всеми имеющимися жопами с безопасностью, капризами интерпретатора и т.д? Лол.
      — количество специалистов на рынке;
      Нормальный PHP разработчик (подчеркнуто) зверь редкий, стоит от 100к
      — стоимость обучения;
      = время обучения. Опять же нормальный, разработчик — это много лет разбирательства в муторной экосреде и мелких костылях и нюансах.
      — размер сообщества;
      А качество информации не? Хотя за 10 лет оно действительно не могло не разрастись.
      • +1
        >Нормальный PHP разработчик (подчеркнуто) зверь редкий, стоит от 100к

        Это же каким упрямством нужно обладать, чтобы в процессе обучения программированию не спрыгнуть с него на более интересные языки и доучиться до мастера!
        • +1
          Ну, в конце 90-х это была просто прекрасная альтернатива перлу, а питон с руби начали набирать силу как веб-платформы только в середине 2000-х, как раз на этот момент пришелся пик качественных PHP профи.

          Сейчас клепатель модулей под битрикс может иметь весьма достойную зарплату, так как всю эту заваренную кашу надо как-то поддерживать.
      • +1
        Согласен. Имел опыт найма Django и JS разработчиков, и видел со стороны как ищут качественного РНР.
        Меньше всего сейчас качественных JS.
        Качественных РНР и Django — примерно на рынке одинаково тяжело найти.
        Вот если нужен уровень хуже — тут у РНР плюс несомненный.
        • +2
          С JS, несмотря на популярность, кучу документации, либ и полную монополию на клиенте есть одна проблема — он очень сложный. Конечно не в плане лексики, а требовательности к разработчику, функционалка схожая с лиспом, куча асинхронных сопель, динамическая типизация, стремный скоп, среда браузера на клиенте, глючная нода на сервере и т.д. Ну и он просто не предназначался для того, для чего его используют сейчас. (Впрочем, как и PHP, который проложил свой путь из области шаблонизаторов)

          Так что перспективы по количеству специалистов мне кажутся умеренными.
          • +1
            Не забывайте еще тот момент, что JS как самостоятельный язык (в том ключе что для него стали нанимать отдельно программистов) выделился совсем недавно, ибо раньше он шел довеском к серверсайду. Отсюда идет следствие что большинство JS гуру так-же отлично знают Ruby/Python/PHP. А это еще + окладу.
            • 0
              Я бы не сказал, что скиллы в резюме нужно просто суммировать в оклад. Да иельзя знать серверсайд совсем не зная клиентской стороны и наоборот.

              Если нужен программист, работающий под RoR то его навыки работы с Plone могут быть огромными, но бесполезными — куча локальных скиллов, которые при смене платформы меняют актуальность. Платить JS кодеру за то, что он идеально знает 1С, да нафига, когда поискав можно найти того же, кто его не знает и не захочет этот бонус, который бессмысленен для работодателя.

              Имхо, основной плюс к окладу — это насколько сотрудник способен создавать работающие штуки. На js их создавать и тестировать достаточно сложно.
              • 0
                А я и не говорю что если человек может получать 80 за серверсайд, и 70 за JS то в сумме он будет иметь 150. Это показывает общий уровень, не более.

                Вы же в свою очередь утрируете приводя пример разработчика на RoR со знанием Plone, которые по сути в одной компании редко используются, а еще реже и в одном проекте. Или вообще абстрактный пример с 1С и JS.
                • 0
                  Да, я перегнул немного, пытаясь сделать акцент сильнее, хотя зоопарки всякие попадались.

                  1C и JS вполне могут ужиться, если ищут кодера-эникейщика на поддержку всякого из низшей касты. Чем выше каста (тупо зарплатная), тем важнее, чтобы специалист ровно решал задачи в рамках весьма определенной области. Писать прекрасные клиенты вообще не вникая что там на заднике это совершенно нормальное явление. Есть описание интерфейса I/O + Т.З. и зашибись.
              • +1
                Платить JS кодеру за то, что он идеально знает 1С

                Интеграция сервера на NodeJS с 1С? :)
          • 0
            Непонятно каким боком тезис о сложности языка подтверждается аргументом «схожая с лиспом». Проще лиспа сложно что-то придумать.
            • 0
              а проще программы на лиспе?
              • 0
                не понял вопроса
                • 0
                  сложно ли придумать что-то проще программы на лиспе? например программу на hackel?
                  • 0
                    я, видимо, сегодня невероятно тупой, но я всё еще не понимаю вопроса. прости.
    • 0
      Там была правильная мысль, что многие талантливые разработчики тикают с php в сторону того же python'а. Да и за две недели хорошего разработчика не найти, а если получится — то не благодаря php, а вопреки.
      Лично я ушёл от php после написанного на нём крупного проекта. Вспоминаю как страшный сон, и более не хочу.
  • +12
    Спасибо за такую большую статью. Буду ждать пост про Python.
    • 0
      Затянувшаяся миграция с 2-й ветки на 3-ю, юникод, локи интерпретатора, экспрешены, динамическая типизация… Уфф, все равно лучше пока не нашел.
      • 0
        руби? )
        • 0
          Затянувшаяся миграция с 1.8 на 1.9, GIL…

          не знаю, о чем именно речь шла в пунктах «юникод» и «экспрешены», динамическая типизация меня не напрягает)
          • 0
            А я вот руби копаю — питон у меня в основном как калькулятор, после того как запостил им ошибку в стандартном пакете «с батарейками», они скинули мне ссылку на более изящный патч, чем мой… который у них уже три месяца пылиться. Правильно — не фиг использовать питон под виндой, да ещё и с не английской кодировкой по умолчанию.

            Хотя тут думаю — комплекс профессионала — проблемы питона я знаю и подсознательно боюсь, что повылезают, а об руби я ничего страшного пока не знаю.
            • 0
              Я на руби пишу как раз.

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

              То есть хороший язык, но не мой =)

              И на руби под виндой тоже писать не стоит, насколько мне известно (сам я никогда даже не пробовал).
              • 0
                Я слишком ленив. чтобы настраивать виртуалку там, где можно обойтись без оной. Но пока на грабли особо не натыкался.
  • –1
    Хабр дебил. По Enter отправляет пост в черновики. И убивает все комментарии. Уж извините.
    • +11
      Упс, ложная тревога.
  • +3
    Переводчику спасибо за труд. Одного не могу понять, зачем переводить очередной батхерд на тему PHP. Все эти вопросы разбирались уже не раз. Те кто давно и профессионально работает с PHP знает про особенности и подводные камни, кому не по нраву перешли на другой язык. Мне сложно представить человека — фаната профи PHP, который писал бы каверзные статьи на темы других языков. Так что это за попытка? Поднять бурление на изъезженную тему или очередная контрпропаганда? Зачем …?
    • +1
      Что ж? Выражу своё мнение. Просто уж очень часто натыкаюсь на древний софт(который нужно поддерживать или переписать), написаный на PHP и испытываю точно такой же батхёрт. Ужасно устал от самопальных фрэймворков на нём же.
      • +4
        Делов то, смените работу и будете натыкаться на оверинжинирнг в джаве или ещё какую-нибудь беду в другом ЯП.
        • 0
          Речь в статье идёт о серьёзных архитектурных проблемах языка, в других ЯП не так всё запущено. Опять же это влияет и на рост языка и на качество кода.
          • +1
            Ну и что это значит то? В чем смысл этого опуса? Всем надо резко перейти на другие языки? Новички не должны учить php или что?
            • +1
              Именно :)
              • +1
                Статья проплачена конкурентами!
                • 0
                  Если не секрет, кто они? О_о
                  • 0
                    В данном случае они — заказчики.
              • +1
                Ну давайте, переходите, отдайте мне на поддержку всех своих старых клиентов с проектами на php и забудьте про баттхёрт. Ну это так, ради смеха.

                PHP объективно занимает свою нишу на рынке, т.е. отвечает его требованиям. Поэтому все резко никуда не перейдут. Со временем конечно php уступит свое место, но когда это будет… Да и в таком случае, автору и переводчику лучше бы сосредоточиться не на баттхёрте от пхп, а направить свою энергию на развитие питона, руби или от чего они там фанатеют — было бы больше толку и для всех.

                Что касается новичков — так это порог вхождения и опять же спрос на пхпбыдлокодеров.
              • 0
                Вот как люди тонко избавляются от конкуренции )))
            • +1
              Я считаю что новички должны знать что есть ещё языки на которых удобно и приятно программировать, ибо большинство людей тупо учит PHP потому что это «модно» и везде пишут что сайты надо разрабатывать только на PHP, а потом не понимают что же они так несчастливы от рутинного написания говнокода. Язык в этом случае тоже имеет значение.
              • +6
                Я согласен, но для этого лучше писать статьи типа «Питон за шесть часов» или «RoR for dummies» и уж никак не «ПХП ЕСТ ДЕТЕЙ».

                Сами подумайте, ну прочитает новичок эту простыню по диагонали и что? Да ничего, он все так же пойдет и скачает какой-нибудь вордпресс или друпал и начнет потихоньку делать свой первый говносайт. Среда не располагает к изучению других языков, хоть пять статей напиши.
                • –1
                  Не надо фатализма. Всё будет хорошо.
                  • +3
                    Уже всё хорошо.
                • 0
                  Зависит от новичка. Почему не начать с питона?
                  • 0
                    Начинайте с чего угодно. Речь о среде и о том, что вероятней всего новичок в первую очередь наткнется на PHP со всеми вытекающими, такова правда жизни. В таком контексте статья выглядит абсолютно бестолково.
                  • 0
                    Потому что вордпресс или друпал можно просто залить на шаред-хостинг за пару баксов, да и на вдске не проблема поднять, не говоря о денвере? И можно «хелловорд» во «все интернеты» выложить без проблем?
                    • 0
                      Да, а здесь настроить хостинг очень сложно!
                      И вообще ДЕНВЕР поставить гораздо легче чем какой-то тупой wamp.
                      • 0
                        Исключение, подтверждающее правило :)
                • 0
                  Лол, по питону обычно рекомендуют не «питон за шесть часов», а «Dive in the python» и PEP-ы.
                  А за 6 часов лучше действительно PHP изучить для галочки и забыть.
                  • 0
                    Я в курсе, вы просто не уловили мысль.
              • 0
                По-моему как раз наоборот, везде пишут, что НЕ надо разрабатывать на PHP, что Python/Ruby/NodeJS это модно и круто, но дешёвый хостинг и огромное количество готового кода берёт своё.
    • +2
      Я считаю этот текст достаточно ценным хотя-бы в качестве назидания людям, которые сейчас выбирают язык программирования.
    • –2
      как зачем? зависть =) и жадность =)
    • 0
      Мне кажется, это просто страдание человека, не безразличного к вопросу дизайна языков о том, что ЭТО смогло стать лидером рынка.
  • +14
    Это же как надо ненавидеть PHP, чтобы столько написать :-D
    • +21
      Я гналась за вами три километра, чтобы сказать, как вы мне безразличны! © не знаю откуда
      • +14
        Принцесса
        Три дня я гналась за вами. Только в бурю потеряла ваш след, встретила охотника и пошла к нему в ученики.

        Медведь
        Вы три дня гнались за мной?

        Принцесса
        Да! Чтобы сказать, как вы мне безразличны.

        Шварц, «Обыкновенное чудо»
      • 0
        «Обыкновенное чудо».

        «Я бежала за вами три дня и три ночи, чтобы сказать вам как вы мне безразличны». Цитата на память, могу чуть исказить.
  • 0
    А мне ссылочки понравились, полистаю на досуге: )
  • +20
    Пришла мысль, она может быть не в тему, но выскажу.

    Наверняка, можно написать такую же статью про русский язык.
    • множество заимствований из других языков (бордюр, компьютер ...);
    • множество исключений (оловянный, деревянный и т.п.);
    • множество слов, в которых нельзя проверить согласные ударением;
    • существуют слова, которые нельзя поставить в определённую форму(победю, пылесосу ...);
    • … ;

    • 0
      а чем «пылесошу» плохо?
      • +3
        Вот, не желающие выучить новый язык подтянулись! ;D
        • 0
          вам на заметку — в основном сейчас работаю с Java.
          Я просто к тому, что пример неудачный — если с победю действительно проблема, то с пылесосением проблемы такой не стоит.
          • +3
            Это всего-навсего была шутка в контексте первого комментария, о языках разговорных, не принимайте близко к сердцу!
            • 0
              извините, неправильно понял :)
    • +8
      Понимаете ли, естественные языки развиваются эволюционно. И только по этой причине имеют столько исключений. В то время как искусственный язык проектируется. Хотя мне иногда, что в случае PHP это не совсем верно :)
      • 0
        * мне иногда кажется
      • +10
        Я думаю, что тут можно с уверенностью сказать, что PHP изначально не проектировался вообще.
        • +2
          Ну тогда у нас нет тысяч лет для эволюционного развития чего-то качественного нового из PHP, что может позволить себе природа.
        • +3
          Да уж, после программирования на Python, PHP выглядит как набор костылей из глобальных переменных, операторов вместо функций и ООП заимствований отовсюду.
          «Пипл хавает» (с).
      • +2
        В те годы, когда проектировали PHP, ещё никто не думал о большинстве описанных в статье глобальных проблем. PHP создавался, чтобы решить конкретную вполне простую задачу — обработку форм и внедрение простейшей логики в веб-страницы. Он её решил. Если требуется решить другие задачи, то для них есть другие инструменты. Тем не менее, не стоит забывать, что огромному количеству сайтов не нужно ничего, кроме обработки веб-форм и простейшей логики и пытаться туда прикручивать какой-нибудь node.js это ещё большая глупость. А таких примеров немало :)

        Ну и про эволюцию. С переходом между Питоном 2 и 3 там тоже есть нюансы, знаете ли. 2to3 и прочие инструменты передают привет.
      • +1
        Не стоит рассматривать естественные языки как нечто совершенное.
        Почитайте хотя бы юридические тексты — имхо, неплохая аналогия «программированию» на естественном языке.
        • +1
          Я этого и не утверждаю, даже наоборот эволюционное развитие очень медленно и склонно к падению в локальный минимум.
    • 0
      И ещё, многие любят русский язык за его исключительность…: )
    • 0
      Это можно написать про любой естественный язык. Во всех есть странности, несогласованности и различные недостатки…
      • 0
        Аналогчично и в ЯП
      • 0
        Опс, попутал ветку.
    • 0
      Да уж, это вам не эсперанто, но почему-то мало желающих его изучать, парадокс человеческой психики.
  • +6
    Автор маньяк. Да и переводчик
  • –1
    Кто может объяснить заголовок статьи? Хотел перевести эту статью просто так, для себя. Но сдался на заголовке. Дословно переводить не хотелось.
    Фрактал — самоподобная фигура, то есть PHP — плох по дизайну весь так же, как плоха по дизайну каждая его составляющая?
    • 0
      В статье же написано, почему. Ну, или лень читать, слово «фрактал» поищите по тексту.
      • 0
        Я читал статью в оригинале(вроде даже дважды) и прекрасно понимаю смысл статьи, и намёк в заголовке. Мне интересно как литературно перевести заголовок.
        • 0
          фрактал — бесконечно (теоретически) самоповторяющаяся фигура => php бесконечно самоповторяющийся на глюках язык
          примерно такая аналогия получается…
    • 0
      Нет, он имел в виду, что чем глубже закапываешься, тем больше ошибок вылазит
      • 0
        Понятно, что лучший перевод — дословный
        • +1
          да, кстати, как я проморгал, аббревиатура PHP же содержит в себе смаоповторение, видимо этот момент был обыгран
    • +5
      тут больше имеется ввиду такого рода фракталы:

      image

      Намек на то, что весь дизайн языка — одна сплошная дырка.
      • +4
        Спасибо, протестировал монитор на муар
  • –5
    Берем статью, делаем выдержки, и… задаем вопросы на собеседовании ;)
    даже на таких граблях
    "foo" == TRUE, и "foo" == 0… но, конечно же TRUE != 0.
    сколько раз падали. Вопросы мот по круче патернов программирования будут, и многая специфика языка открывается.
    • +2
      О нет, да это же универсальное оружие :)
    • 0
      «foo» == 0? Разве?
      • 0
        при приведения строки к int что по вашему должно быть?
        • 0
          Да, что называется смотреть и не видеть. Я сразу же подумал, что «foo» = TRUE = 1.
    • +8
      Я не пойду работать в контору, где на собеседовании дают такие вопросы.
      А старые сишные привычки не позволяют попадать в 90% ситуаций с невнятным поведением.
      По этой же причине я без понятия что даст, например []+{} в javascript.
      • +4
        Здесь в начале третьей минуты есть ответ… WAT?
        • +3
          Ага, на этот ролик я и ссылался. Он забавный, но за годы я не помню, чтобы нарывался на похожие ситуации.
      • +1
        Правильно: зачем знать, что будет при сравнении строки с числом, если никогда не станешь сравнивать строку с числом?
  • +4
    Не так давно, я всерьез собрался менять php в сторону python'a. Остановило меня знакомство с php-фреймворками и конкретно с Yii. Я получил огромный набор инструментов из коробки, которые большую часть описанных в статье недостатков исправляют.

    Статья слишком далека от реальности.
    В реальных проектах с этими проблемами не сталкиваешься.

    >Поэтому следующий код:
    >
    >$arg = 'T';
    >$vehicle = ( ( $arg == 'B' )? 'bus':
    > ( $arg == 'A' )? 'airplane':
    > ( $arg == 'T' )? 'train':
    > ( $arg == 'C' )? 'car':
    > ( $arg == 'H' )? 'horse':
    > 'feet' );
    >echo $vehicle;
    >выведет horse.
    Вот за такой код в реальном проекте нужно руки отрывать. В реальном проекте будет использован switch-case.
    • 0
      Ну двойная вложенность-то может быть? И проблема имеет место быть. А пример выполнен как гипербола, но смысл проблемы он не искажает.
    • 0
      Видите ли, должный уровень профессионализма накладывает свой отпечаток на видение языка. Вы наступили на грабли 5 лет назад, и сегодня вам кажется, что их нет. Но грабли никуда не делись. Более того, их в принципе не должно было быть.

      В качестве доказательства ошибочности вашего мнения «статья слишком далека от реальности», предлагаю вам заглянуть на любой популярный сервис вопросо и ответов (например, ВиО Google), и посмотреть, о чем там спрашивают, и какой код публикуют. Чего стоят только конструкции вида:

      $query = "SELECT * FROM users WHERE login='$login';"
      

      Которые приводятся в 99.9% вопросов про PHP в связке с MySQL.

      Это реальность. И это косяки языка программирования (ну и говноучебников по его изучению).
      • 0
        т.е. использование старого нерекомендуемого модуля (mysql) или неверное использование новых инструментов (mysqli, pdo etc) новичками — это вина языка?
        • –1
          Этот «старый нерекомендованный модуль» — этакое спецсредство для стрельбы по ногам. Вина языка уже в том, что он в нем вообще появился. И еще большая вина в том, что все еще существует и поддерживается.
          • +8
            Хорошо так говорить, когда другие языки могут учиться на чужих ошибках. Данный модуль создавался давно и расчитан был на старый функционал и защиту скриптов самим программистом.
            В данном случае модулем до сих пор пользуются огромное количество программистов, либо новичков, либо тех, кто ведет старые проекты. PHP не может взять и выкинуть модуль. Разработчики плавно отучают пользователей от него (первый этап — только обновления безопасности и обновление документации, дальше — больше).
            Поэтому 1) вина в появлении — может быть, но такое есть во всех языках — программист может выстрелить в ногу тысячами способов.
            2) PHP не поддерживает больше данный модуль, только обновления безопасности
            Поэтому в целом я все равно считаю, что подобные вопросы от новичков — не вина языка.
            • 0
              Уважаю ваше мнение, но остаюсь при своем. :)
            • +5
              Хорошо так говорить, когда другие языки могут учиться на чужих ошибках.
              Я ни с кем ни о чём не спорю, однако отмечу, что Пайтон появился в 1991, Руби и PHP в 1995.
              • 0
                >>Хорошо так говорить, когда другие языки могут учиться на чужих ошибках.
                … а некоторые — не могут
                • 0
                  Так предположим, что какие-то языки появились недавно и учились у PHP (C#, Io, Scala, Clojure, ага).
                  Но ведь в контексте предыдущей дискусии, я предпологаю, сравнивается PHP с его ближайшими «соперниками», а не какими-то абстрактными новыми языками.
              • +1
                Если быть точным, истоки Python Гвидо создал на новогодних каникулах '89 :)
        • +1
          Автор указывает, что документация тоже не сахар :)
      • –1
        Ну это спорный вопрос, если человек даже не задумывается над безопасностью своего кода… Такое можно написать на любом языке, вот вам на руби:

        @user = User.find_by_username("#{params[:username]}")
        

        • +1
          Я не знаю Ruby. Хотите сказать, что если в usename будет содержаться «1'; TRUNCATE TABLE users;» — это приведет к очистке таблицы?
          • –1
            Да, правильней написать можно например так:

            User.where("username = ?", params[:username])
            

            Тогда переменная не летит напрямую в БД, как в первом варианте. Говнокод — всегда говнокод.
            • –1
              Согласен. Только некоторые языки больше располагают к его написанию, а некоторые меньше.

              Думаю, вы согласитесь со мной, что в творениях новичков Ruby говнокода будет существенно меньше, чем в коде новичков PHP. А почему? Потому что первый меньше располагает к стрельбе по ногам.
              • +3
                Не могу судить про новичков в руби, сам такой) Но по личному впечатлению, само комьюнити как-то подталкивает искать верные и красивые решения, покрывать код тестами.
              • 0
                в творениях на Руби говнокода ещё побольше будет. Но не потому, что язык плохой, а потому, что есть 100500 способов сделать одно и то же действие. И новичку нужно время, чтобы попробовать их все и придти к своему стилю.
                • +4
                  Когда мне демонстрировали «гибкость» Ruby, я офигел от некоторых показанных конструкций и тоже была мысль, что это вроде как преимущество языка можно легко превратить в недостаток.

                  Всё никак не соберусь погрузиться в Ruby основательно. Python после PHP вызвал у меня культурный шок, интересно, как оно будет с Ruby. :)
                  • –1
                    Собирайтесь, и не верьте про «говнокода еще побольше будет». Такого как во внутренностях джумлы вы там не встретите никогда :)
                    • +8
                      Joomla в качестве аргумента против PHP — это уже перебор. Слишком жестоко и несправедливо. )
                      • 0
                        «Не бейте меня по яйцам — я сам себе в ногу выстрелю» :-)
                    • 0
                      …удар ниже пояса, так сказать.
                  • 0
                    Если вы кодите на Python, то непонятно зачем вам вообще Руби.
                    • +2
                      Исключительно для расширения кругозора. После знакомства с Python/Django, если бы мне пришлось вернуться к PHP, я бы достаточно интенсивно юзал подсмотренные в Django вещи. Думаю, в RoR тоже можно «подсмотреть» много вкусного. Как-то так…
                      • 0
                        Для расширения кругозора — поддерживаю, это хорошее начинание.
                • –1
                  Частично соглашусь, увлёкшись метапрограммированием можно страшного наворотить :)
                  А вот обилие вариантов делания одного и того же на самом деле огромнейший плюс, позволяющий писать DSL'и и в конкретных ситуациях получать очень компактный выразительный код.
                  Взять тот же RSpec или что-то подобное Person.where { (name =~ 'Ernie%') & (salary < 50000) | (salary > 100000) }
              • +3
                Языки? Посадите новичка писать «сайт» на чистом руби без фреймворков — он вам и не такого напишет. Ну или давайте сравнивать честно и поставить на сторону PHP какой-нибудь приличный фреймворк.
                • –2
                  Не напишет, потому что это не так тривиально, как в PHP. :) Практически любой другой язык, кроме PHP, очень быстро отбивает охоту к велосипедописанию. Даже(!) если задаться вопросом написания велосипеда на том же Ruby или Python — обстоятельства будут подталкивать к переизобретению какого-то подобия MVC.
            • +2
              Первый вариант тоже правильный и не приводит к SQL injection.

              Приводит вот это:

              User.where(«username = '#{params[:username]}'»)
              • –2
                Да, только что проверил. Но суть не в том как конкретно работают методы find_by_* или where AR'a, а в том что плохой код можно написать на любом ЯПе, что и было замечено.
                • 0
                  Конечно, с этим полностью согласен.

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

                  И если в Ruby/Python человека изначально окружают в целом хорошие решения, то он скорее всего будет использовать подобные хорошие решения, потому что они рядом.

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

                  Кроме того, я смутно помню, что когда я еще работал с PHP, то делать сколько-то больой проект хорошо там было просто неудобно. С переходом на руби стало на порядок легче. Но при этом делать на RoR одну форму отправки письма — это оверкилл, тут PHP как раз идеален, наверное.

                  То есть, по всей видимости, некоторые особенности языка/фреймворков хорошо работают в своей нише, а в другой приводят к хаосу.

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

                  Originally used for tracking visits to his online resume, he named the suite of scripts «Personal Home Page Tools,» more frequently referenced as «PHP Tools.»


                  Если несколько утрировать: есть замечательный язык ЛОГО, но это не значит, что на нем нужно писать интерфейсы к БД.
                  • +3
                    Но при этом делать на RoR одну форму отправки письма — это оверкилл

                    Для этого есть синатра
                    • +2
                      Ну лично я бы для этой конкретной задачи сделал бы обработчик на голом Rack, имхо тут и Синатра и не нужна.

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

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

                      Основное отличие в настройке сервера и деплое. Для PHP вы можете поставить апач из пакета, mod_php (если ничего еще не поменялось) и кинуть файл в нужную директорию.

                      В руби — поднять аппсервер, настроить проксирование, мониторить этот аппсервер.

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

                      Ну и наличие шаредхостингов с нормальной поддержкой руби пока не очень радует.

                      Но даже если эти проблемы будут решены, я сомневаюсь, что в этой нише (маленьких задач на 1-2 страницы) Ruby будет более простым решением чем PHP. Равным — вполне возможно.
                      • 0
                        Во многих дистрибутивах модуль passenger для апача есть в репах. Какая разница, что указывать после aptitude install — mod_php или passenger? С nginx ситуация сложнее, но там для php вообще придётся какой-нибудь php-fpm ставить.
                        С шаред хостингами всё верно. Но если заказчик не может раскошелиться на VPS или хотя бы heroku, я бы поостерёгся с ним работать.
                        Хотя если речь не о заказе проекта для ведения бизнеса, а для personal home page — возможно, абстрактному разработчику будет проще. Я бы всё равно выбрал синатру, просто в целях унификации основных проектов с личными.
        • +3
          Кто-то явно не в теме

          pry(main)> User.find_by_nickname(«test'\»")
          User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`nickname` = 'test\'\"' LIMIT 1
          • +2
            парсер кавычки побил
            User.find_by_nickname("test'\"")
            
          • –2
            Отрицаете SQL injections в AR?

            [22] pry(#<#<Class:0x9c59118>>)> User.where("username = 'user2' OR '1'='1'").first
            => #<User id: 17, username: "admin", email: nil, crypted_password: "$2a$10$mAeQyVoi8.8FlKiTWPH0yOJvSVZlqrKQKBgAVcUFaC2c...", salt: "dGYtwAFYA2f2q9ipXGXE", created_at: "2012-04-07 12:49:51", updated_at: "2012-04-07 12:49:51", remember_me_token: nil, remember_me_token_expires_at: nil, role: "admin">
            [23] pry(#<#<Class:0x9c59118>>)> 
            
            
            • 0
              Ну так и писали бы сразу нормальный рабочий пример вместо кода, где инъекции нет.
              В местах, намеренно предназначенных для вставки голого sql, конечно же ничего само не будет экранироваться.
              А в дефолтных ситуациях с User.where(:username => params[:username]) или с выражениями на синтаксисе metawhere/squeel отстрелить себе ногу не выйдет.
              • +1
                Да, конкретно с find_by_* я протупил что-то, спасибо за поправку.
  • +14
    Интересно что он скажет про JavaScript :)
    • –3
      JS неплохой объектный язык, я не понимаю вашего сарказма.
      • 0
        А что тут непонятного? В нем тоже есть неочевидное поведение в некоторых моментах.
        • 0
          Про любой язык так сказать можно. Есть неочевидное уникальное поведение.
        • –1
          У него куда более лаконичный синтаксис, код читать куда приятнее, да и работает он в пару раз быстрее.
          • 0
            Это вы с V8 сравнивает? :)
      • +4
        wtfjs.com/ — вот целая куча всякого, типа того, что описано в этом топике про ПХП
        • +8
          Ну надо же — значит, NodeJS не спасёт мир? Но как же так?
      • +2
        Начнем с того, что он не объектный…
        • +2
          давайте на этом и закончим! :) о терминах можно спорить ещё дольше и жарче чем о PHP
    • –4
      В JS нет таких ярких проблем с архитектурой.
      Неочевидное поведение документировано. А все удивления «как это оно так работает» и «почему у меня везде последнее значение несмотря на цикл» от малого опыта работы с ФП.
      • +9
        В JS ярчайшие проблемы с архитектурой.
        Имеющие, кстати, теже самые корни, что и у PHP — делали изначально одно, а потом периодически поверх накручивали совершенно другое.
      • +2
        Да ладно… взять ту же область видимости переменных ограничиваемой функциями — я потерял много часов жизни пока с этим не разобрался. Бредовая идея вообще.
        Неоднозначность strict синтаксиса, то есть он вроде бы есть, но им мало кто знает как пользоватся.
        ООП непривычное, причём до такой степени что многие эмулируют привычное ООП создавая тормоза и путанницу.
        Постоянные заботы об преждевременной оптимизации, что портит нас как программистов. Ибо в firefox — unshift невероятно медленный, а в других браузерах всё ок, вот и тратишь время на всякую чепуху…
        Однопоточный интерпретатор, что не является таким уж и большим благом.
        да можно ещё продолжать, просто время тратить неохота… не в тему распыляться…