Нет-нет. Статья не про отношение к написанию велосипедов на PHP, а именно о том, что PHP — велосипед сам по себе. И нет, автор не пытается примкнуть к тем неленивым, которые хотят PHP пнуть. Вернее будет сказать, что пнуть автор собирается не только PHP. Осторожно: статья крайне многословная.
PHP — достаточно уникальное явление современности. PHP обладает низким порогом вхождения, PHP хорош тем, что тра-ля-ля, тра-ля-ля. Вы и сами всё это знаете лучше меня. Именно на PHP крутится огромное количество сайтов и блогов, создатели которых не имеют порою совершенно никакого понятия о программировании. Joomla и WordPress тому яркое подтверждение. И я говорю именно о создателях таких сайтов, а не об авторах этих движков. Однако, без какого-либо сарказма, отмечу, что PHP действительно хорош во многом, и лично я не могу считать его абсолютным злом в байт-коде. Просто многие, ну очень-очень многие почему-то забывают, что PHP — всего лишь шаблонизатор.
Ну да. Просто это очень, очень продвинутый шаблонизатор. Настолько продвинутый, что в нём есть даже ООП, неймспейсы, и много всяких-разных полезных и удобных штук. И даже уже есть встроенный веб-сервер, говорят. Не знаю точно, лично не проверял, ибо уже не слежу.
Думаю, уместно будет попросить прощения у всех и каждого на случай, если какое-либо суждение покажется кому-то оскорбительным или неуважительным. Не было и в мыслях. Скорее, наоборот: я искренне преклоняюсь перед самоотверженно пишущими часто весьма и весьма хороший код людьми, и безмерно уважаю такой труд и таких людей. Простите великодушно и не судите строго. Просто смотрю на всё, что сегодня происходит в IT и, в частности, в WEB, и молчать становится всё сложнее. Поэтому статья представляет из себя полуфилософские размышления и соображения, и не содержит абсолютно никаких практических рекомендаций. Но, тем не менее, очень хочется надеться, что некоторый практический смысл мне, всё-таки, донести удастся. Навеян данный опус многочисленными публикациями на хабре и не только — про веб и про его закат, про HTML5/CSS/JS и не только, про шаблонизаторы, фреймворки и проектирование; а также комментариями ко всему этому.
Ну и, как водится, немного об авторе. Автор не тим-лид, не СЕО, не джуниор и не сеньор. И вообще, карьера автора в качестве программиста пока как-то не сложилась в силу разных причин, хотя предпосылки для этого были. В частности, в предсовершеннолетнем возрасте автор получал изрядное удовольствие от декомпиляции спектрушных игрушек и программирования в мнемонике Z80. Но, в дальнейшем, личностные перемены и отсутствие перспектив в том месте и в то время отодвинули всё это в разряд хобби, тому же сильно поспособствовала неудачная попытка осилить FoxPro 2.6 на незнакомой платформе с незнакомым, и совершенно непонятным, после ассемблера, ООП от MS. Но то, что в будущем стали называть громкой аббревиатурой IT, не отпускало, в результате много лет было прожито в небольшой госконторе в качестве сисадмина. Однако, мысли о программировании провели автора через различной степени погружение в VB/VBA/VBS, Delphi, MS VC++, ужасное и непонятое MFC, после чего автор на какое-то время обрёл покой с Borland C++ и его VCL. После чего пошла в ход литература уже по методикам программирования и проектированию систем и интерфейсов. Потом был PHP, ActionScript (который 3.0), Python и, разумеется, святая троица HTML/CSS/JS. Java долго не принимался в расчёт по идеологическим соображениям, но и это, как оказалось, не является неизменным. Повторюсь (это важно), все выше названные аббревиатуры и названия изучались и пробовались исключительно в качестве хобби; практические применения (в том числе и на коммерческой основе) случались нечасто, но всё же случались. Так что чукча, всё-таки, больше читатель, нежели писатель. На данный момент госконтора осталась в прошлом ввиду перехода автора на самообеспечение на поприще (дежа вю!) программирования, в том числе и web-ориентированного. И да, сваливать надо было раньше.
Также автора часто ругают друзья за игнорирование принципов JFDI (автор уважительно относится к народной мудрости из разряда «тише едешь» и «семь раз отмерь»), а также за крайнюю многословность.
И последнее: автор использует обращение к себе в третьем лице исключительно в контексте самоиронии, ибо всё вышеперечисленное видится ему весьма забавным (но и в чём-то грустным тоже). Но достаточно об этом.
Итак, шаблонизатор. Задумайтесь на минутку, а что же всё-таки делает штука, которую принято считать шаблонизатором? В большинстве случаев шаблонизатор, грубо говоря, на входе принимает шаблон (или, что чаще, ссылку на файл шаблона) и набор переменных, а выдаёт готовый текст в виде заполненного значениями переменных шаблона. Также нередко может использоваться шаблон «по умолчанию». В принципе, часто можно и переменные не передавать, тогда на выходе будет чистый шаблон. Также некоторые шаблонизаторы умеют сами запрашивать из базы данных какие-то данные и вставлять их в шаблон, однако, такая вольность многими считается недопустимой ввиду несоответствия концепциям MVC. Думаю, многие уже догадались, к чему я клоню.
Собственно, ничего нового я не сказал, ибо PHP и задумывался как шаблонизатор. Он и работает, как шаблонизатор: получил запрос — обработал — вернул ответ — спим (или конец работы). Я совершенно не против его такового использования. Но я совершенно против использования PHP как инструментария для создания шаблонизаторов. Также я против написания на PHP фреймворков и CMS, в особенности, с применением ООП (да ещё если иерархия классов разрастается до тысяч штук).
Однако, это всё всего лишь вступление. Сказка только начинается, ибо проблема здесь гораздо шире и глубже. Но давайте немного отвлечёмся и посмотрим на велосипеды. В буквальном смысле. Руль, педали да пара колёс. Как Вы думаете, каков мировой рекорд скорости езды на велосипеде? До недавнего момента я даже не догадывался. Однако, простейший поиск выводит на цифру 268 км/ч. Только вдумайтесь: оказывается, на велосипеде можно поехать со скоростью, на которую не всякий автомобиль способен! Конечно, и не на всякой дороге можно такую скорость развить, да и различные ухищрения потребуются.
Теперь посмотрим, кто же велосипедами пользуется:
- Спортсмены — с ними всё понятно, спорт — это спорт. Он такой, потому что так сложилось исторически.
- Дети — эти ещё не доросли либо до физиологической возможности управления автомобилем, либо до юридической. В общем, малы ещё. Только велосипеды и остаются.
- Люди, не имеющие финансовой возможности для приобретения автомобиля.
- Люди, идеологически приверженные данному виду транспорта по различным соображениям (экология, здоровье, опять же, деньги, но уже «из принципа»).
И в каких ситуациях:
- Велотреки/олимпийские трассы.
- Просто «погонять»/прокатиться.
- «Сгонять по-быстрому» куда-нибудь недалеко.
- При отсутствии альтернатив можно и подальше поехать, но это уже будет непросто.
- Ещё на нём можно привезти или прикатить что-нибудь слишком тяжёлое для ручной переноски.
Перечисленное выше может также комбинироваться в различных вариациях. Как видим, применение велосипеда в практическом плане в массах используется нечасто (большая часть Европы и Азии с этим не согласится, но на то есть причины). Оно и понятно — зачем, если можно комфортнее и быстрее? К тому же, поехать на велосипеде, скажем, на деловую встречу тоже не каждый может себе позволить. Потому что для этого нужна достаточная смелость и некоторое пренебрежение к комфорту (банально потеешь, когда педали крутишь). Да и человека в строгом костюме при галстуке с кейсом, и, при этом, на велосипеде, мне представить сложновато. Но опять же — оно не везде так, где-то это и нормально.
Итак, что мы имеем для сопоставления двух сущностей из разных миров:
- и заиметь, и поехать — просто и доступно
- но поехать недалеко и небыстро
- поехать можно и далеко, но это будет совсем небыстро и утомительно
- поехать можно и быстро, но недолго, и уже, в общем-то, недёшево, и ещё более утомительно. И, скорее всего, недалеко. Да и не везде этот фокус пройдёт.
Последний пункт наиболее нагляден. Применительно к PHP, пожалуй, можно исключить «недолго», а вот в остальном — практически полное идеологическое сопоставление. Нужен «колпак»/«воздушный коридор», который придётся организовывать специально для этого случая, и который, скорее всего, никогда больше не пригодится. Нужна гладкая дорога, которая есть не везде. Впрочем, гладкая дорога для любого наземного транспорта предпочтительна. И очень желательно, чтобы было «не в горку». Хотя, возможно, с «недолго» я поспешил. Большой или очень большой проект на PHP без принятия специальных мер по его стабильности всё равно рано или поздно рухнет. Не хватит либо железа, либо способностей программиста. Тут уж сами решайте, что на что похоже, но мне нравится такая аналогия:
- БД — это как дорога. Чем более плоская, тем лучше.
- WEB-сервер — как сопротивление воздуха. Чем меньше он тупит от хитов, тем лучше.
- Кэши различного рода — это «колпак» и сопровождающая его техника — без этого, конечно, можно, но с ней лучше.
В принципе, здесь автора можно упрекнуть в предвзятости — ведь веб-сервер нужен для любого сайта, написанного на любом языке! Этаа, онооо, канешна, эээ… да… — мнётся автор. Но. Автор ведь обещал пнуть не только PHP. Давайте посмотрим на процесс с другой стороны. Со стороны конечного пользователя (например, посетителя сайта) и его браузера. А так же на некоторые моменты из жизни HTTP. Можно посмотреть ещё со стороны заказчика сайта, но об этом мы не будем. Потому что заказчик если и будет выбирать, то только из того, что есть. Пока же допустим, что разработчик сайта — его же и хозяин. Такое тоже бывает.
В общем смысле, основная задача конечного пользователя сводится к получению нужной (а иногда и необходимой) информации. В частном — «тыцнуть в сцылку» (вбить руками/скопировать/вставить адрес в строку) и лицезреть вожделенное. И ему, в подавляющем большинстве случаев, совершенно пофигу, какое там железо, какой там софт. Ему даже на маршрут до сервера пофиг, и на весь HTTP вместе со всеми его ответами и состояниями. Он вообще не имеет представления, что там, зачем и почему. Из чего явно следует, что ни мускул, ни пых, ни даже нгинкс (я знаю, что оно не так произносится) ему не нужен. Ему нужна «инфа». И точка. И единственное, что видит пользователь — это картинки/текст/видео/звук. Кто-то ещё на дизайн/удобство обращает внимание, но не все. Кто-то ещё смотрит на скорость загрузки/реакции сайта, но, опять же, не все.
А на что же смотрит разработчик сайта? В наиболее полном смысле — на всё. Но для этого нужно иметь представление и о сисадминьстве, и о программизьме, и о вебь-дизайне («юзабилити» предлагаю включить в дизайн для простоты, хотя часто это не так). Таких не так уж и много, у нас в моде разделение труда. В результате иногда эти три ветви власти настолько независимы друг от друга, что просто диву даёшься, как оно вообще умудряется работать-то. Давайте просто перечислим в географически/временном порядке путь от запроса до страницы в том виде, в котором это существует на данный момент. Уверен, большинство тех, кто в теме, знает это лучше меня, и, если навру — поправят. Но я в общем смысле, чтобы оно предстало перед глазами во всей красе, так сказать. Итак:
- пользователь щёлкает по ссылке
- браузер выясняет адрес сервера (либо берёт из кэша, если не первый раз. Но первый раз это сделать всё равно придётся).
- браузер формирует GET|POST (реже иные HTTP) -запрос к web-серверу и осуществляет его.
- web-сервер:
- либо анализирует запрос (например, на предмет «статика/динамика») и, если статика, выдаёт файл
- либо просто вызывает скрипт
- скрипт разбирается, статика ли, динамика ли. Можно вообще файл на лету сгенерировать. И начинает собирать текст ответа. В стандартных случаях применительно к PHP эта процедура протекает как-то так:
- читается с диска (либо берётся из кэша файловой системы) скрипт, парсится, исполняется
- в зависимости от содержимого скрипта тут обычно начинают читаться (браться из кэша) конфиги, шаблоны, всё это начинает парситься, компилироваться (ну или браться из кэша PHP) и исполняться; осуществляются запросы к БД за данными, а порой и за шаблонами (по возможности здесь тоже кешируется)
- на основании всего прочтённого и исполненного формируется готовый текст ответа
- скрипт возвращает веб-серверу plain-текст ответа
- web-сервер (в общем случае) посылает браузеру заголовок и ответ скрипта
- браузер разбирает ответ сервера и решает что с ним делать:
- если HTMLсотоварищи — парсит и отображает/исполняет
- если медийная шняга, опять же, отображает/проигрывает, сам или с помощью плагинов
- profit! (если не 404 или ещё какая пакость, но не будем об этом; у нас ведь всё хорошо)
Весьма стандартная процедура, как видите. Ничего необычного, ничего фатального, всё в стандартных рамках. Я бы и сам не парился, но. Меня постоянно посещает такое ощущение, что «что-то здесь не так». Попробуем разобраться. Даже беглый осмотр выявляет одно часто употребляющееся выражение: «берётся из кэша». А если вы попробуете пробежаться по форумам, посвящённым повышению производительности сайта на PHP — Вас в этот самый кэш так натыкают, что Вы будете везде искать, чего бы ещё закэшить-то. А на Ваш вопрос «зачем кешить» Вам очень популярно объяснят, насколько это полезно. Приведу свои любимые формулировки:
— А как без кэша-то?
— Узкое место любого сайта — БД! Кэшируй всё что только можно!
— Мэмкэшд рулит!
И только самые сердобольные, тяжко вздохнув, в сотый или тысячный раз прочтут тебе краткую лекцию про то, что PHP — это интерпретатор, что оно компилируется каждый раз, но это можно закэшить, насколько медленна работа с БД и ваще, поставь nginx для static-proxy, а скрипты пусть apache крутит. А ещё юзай куки, сессии и локальные хранилища, потому что HTTP…
Приведу ещё один неприметный, на первый взгляд, списочек. Небольшой такой списочек технологий, которые нужны для того, чтобы легко и просто создать сайт (здесь я от PHP всё-таки отстану, ибо здесь уже начинается кроличья нора):
Серверная сторона:
- web-сервер, а то и несколько
- скриптовый (как правило, но не обязательно) язык
- сервер баз данных
Клиентская сторона:
- HTML
- CSS
- JS
- нередко и AS(Flash) и не только
Всё это так или иначе завязано на HTTP over TCP over IP over Ethernet (правда, внутри одного сервера могут использоваться сокеты межпроцессного взаимодействия). Семь (!!!) технологий для одного сайта! Нет, ну это правда нормально? Даже нет, не так. Для одного цикла запрос-ответ все они всё равно нужны и всё равно работают. Даже если это запрос к страничке типа «я и собака моя», которая меняться будет раз в полгода — семь разных технологий, которые сами себя постоянно парсят и кэшируют, это правда нормально? Конечно! — ответят профессионалы. И обоснуют свой ответ политиками и спецификой shared-хостингов и т.д. и т.п. И, кстати, будут правы. Применительно к сегодняшнему дню. Потому что на текущий день именно такая схема показала себя самой гибкой и живучей. Более того, в комментариях подкинут ещё пару-тройку, а то и больше. Я по любому что-то забыл или ещё хуже, не знал.
Но вот только лично мне это нормальным не представляется. И вот теперь я попробую свою позицию объяснить.
Лирическое отступление номер один. Около шести лет назад автор познакомился с веб-технологиями в виде сопровождения и дописывания сайтов, построенных на PHP/MySQL. Сначала, разумеется, это было весьма диковинно и ново, но очень быстро пришло осознание того факта, что смешанный в кучу HTML и JS, выводимый то через echo, то через print, то просто вне <?php ?> — это не так уж и весело. Параллельно с этим вдруг оказалось, что написать браузерную онлайн-игру — это не только круто и прибыльно, но ещё и чертовски легко! Знакомо? :) В результате состоялся запуск некоей браузерной онлайн игры, на якобы open-source движке, написанном (разумеется, не автором, а неизвестной третьей стороной) на PHP, после заглядывания внутрь кода которого шевелились волосы, а практика работы с БД в количестве порядка 180-ти запросов на каждый клик просто ужасала. И основная масса запросов реализовывала то, чего так не хватает в PHP over HTTP применительно к подобным проектам — текущее состояние игрока и игрового процесса. Здесь будет уместно поболезненней пнуть автора за никудышный выбор технологий, да и поделом ему. Разумеется, код переписывался, много чего было изменено в механике игры, но преодолеть главный недостаток движка мы тогда так и не смогли — требовалось его полное переписывание с нуля. Что и было задумано и начато. И самым большим нашим тогдашним желанием было организовать какого-нибудь «демона», который бы управлял БД и её содержимым с целью унифицировать и упростить механику движка. Примерно в то же время в мускуле появились хранимые процедуры и планировщик, и нам показалось, что это, наконец, решит все наши проблемы. Взять C или Python в то время у нас сначала не хватило смелости, потом — времени, а ещё через некоторое время стало ясно, что планируемое создание не будет приносить желаемого дохода ввиду своей специфики, и все лучшие мысли были отложены на чарующее «потом». Которое, пока что, ещё не наступило. Ключевой момент вышеописанного: именно отсутствие встроенных механизмов для работы с текущим состоянием и их костыльная реализация своими силами ускорили неизбежный крах того движка.
Лирическое отступление номер два. Автор — в некоторой степени идеалист, перфекционист и мечтатель. Автор любит с утра испить свежесваренного в турке кофе и немного помечтать. В том числе и о том, чтобы кофе варился как-нибудь сам. Но, поскольку данный конкретный образец мечтаний не носит совершенно никакого прикладного характера, автор любит пофантазировать на эту тему какую-нибудь очередную ахинею, в порядке бреда. Возможно, чтоб размять
ну, допустим, налить воды и засыпать кофе в турку можно и с вечера. Газовая плита с пьезоэлектроподжигом — им можно щёлкнуть по таймеру релюшкой, это несложно. Остаётся придумать простой способ поворачивать ручку крана конфорки, чтоб открывать и закрывать газ… И вот тут-то меня и осенило. Мы настолько привыкли к этому привычному процессу, что совершенно перестали замечать детали процесса, и мыслить стали скачками через проработанные когда-то давно ступеньки. Что нужно для того, что бы сварить кофе? Турка, вода, кофе, открыть газ, поджечь газ… Стоп! Причём тут вообще газ? Для того, чтобы нагреть воду. Так вот — нам шашечки или ехать? Нам нужен открытый газ или всё-таки нам нужна горячая вода?..
Вот, собственно, по этой схеме все мы обычно и рассуждаем. Устоявшиеся, отработанные, хорошие или просто удобные практики и алгоритмы мы оставляем для себя как образец успешного решения жизненных задач, и в аналогичных случаях пытаемся применить именно эти, зарекомендовавшие себя технологии. Это одно из основных оснований основ нашего
В своё время я с большим энтузиазмом наблюдал за эффектным шествием AS3, но пришёл мистер ай и всё испортил. Конечно, давайте обругаем древнюю технологию трёхлетней давности за её тормознутость и громоздкость, не будем пытаться её оптимизировать, договорившись и утряся технологические вопросы с парой десятков конечных производителей железа и софта, а вместо этого возьмём новенькие десятилетние наработки на основе плоского текста с поддержкой малоэффективной раскраски и суперскоростного интерпретируемого языка, который уже почти без проблем добавляет на наши и без того великолепные страницы капельку интерактива, если, конечно, воспользуетесь вот этим отличным фреймворком и поштучно обойдёте все ваши динамически видоизменяющиеся примитивы, и уже совсем скоро сделаем из всего этого конфетку, буквально пара лет осталась!.. Очень, очень сильно уважаю дядю Стива за много что, но конкретно в этом вопросе я с ним не согласен. Хотя, не исключаю, что он и в самом деле хотел как лучше. Но адобы то ли не так поняли, то ли просто повелись, и, в итоге, фактически, профукали веб…
Лирическое отступление номер три. На моей стене висит относительно новый телевизор с технологией Smart, встроенным браузером и поддержкой клавиатуры/мыши. Но попытки зайти на какой-нибудь видеохостинг в 90% случаев терпят неудачу. Для начала — сложно просто набрать адрес, если опечатался, ведь стрелки клавиатуры управляют курсором мыши(!!!). Но, даже если удастся успешно зайти на сайт — не факт, что доберётесь до просмотра фильма. Либо не удастся попасть курсором в фильм из-за сумасшедшего скроллинга, либо сдохнет браузер под тяжестью заботливо понатыканных владельцем сайта JS-скриптов, и всё придётся начинать сначала. Люди, разрабатывающие хвалёные Smart-приложения, похоже, ни разу не видели клавиатур, ибо символьная раскладка экранной клавиатуры почему-то, в большинстве случаев, алфавитная. Там даже иногда есть кнопка переключения языка ввода, но не работает ни одна устоявшаяся клавиатурная комбинация клавиш, для этого обычно используемая. Да что там язык — сама клавиатура в этих приложениях работает не всегда. И, вообще-то, тот факт, что там как раз и используется тот самый флэш — не значит ровным счётом ничего. Просто потому, что где-то работает так, как надо, а где-то — нет. И что, это — прогресс?
Когда я крутил тот самый AS3 — я, опять же, ужасался от того, что на нём пишут. Ибо самые известные игрушки-казуалки созданы на основе примеров из обучающих книг, а графика во многих хуже, чем «спектрушная» тридцатилетней (!!!) давности, про анимацию вообще молчу. Но это, к счастью, проблема не языка, а кривых рук. Потому что к моменту относительно широкого распространения различных движков качество местами улучшилось. В то время немалое количество талантливых ребят, в том числе и наших соотечественников, делали на AS3 шикарные вещи, в том числе реализовывали практически полноценное 3D и физику, потому что до десятой версии флэшплеера третьего измерения не было. В 10-й версии таки прикрутили координату Z, хотя и не всё было безоблачно, но важно не это. Важно то, что в Adobe осознали, что существует весьма явный и уже почти фатальный недостаток, и приняли меры по его устранению. К слову, вот вам простенький экзерсис двухлетней давности размером 4825 байт. Исходный код содержит около 250 строк кода; используются только встроенные классы, никаких сторонних движков. Орбиты эллиптические, положение планет рассчитывается по средней аномалии (движение ускоренное, по Кеплеру). Никаких оптимизаций ни по скорости исполнения, ни по размеру не проводилось. Вот и забацайте-ка мне что-нибудь аналогичное по размеру передаваемого клиенту кода и скорости исполнения на том же голом JS хоть с canvas'ом, хоть как. Или на CSS, гы-гы. Может, тогда я и признаю торжество HTML5&сотоварищи…
Теперь давайте коротко взглянем на эволюцию программиста и программирования на языках, отличных от PHP для платформ, отличных от HTML (этих мы рассмотрим чуть позже). Обычно путь развития программиста проходит через несколько ключевых для него этапов:
Шаг 00. Пишем «hello world». Ура! Я программист!
Шаг 10. Пишем Крутое Оконное Приложение.
Шаг 20. Чё-та как-то многа переменных, куча функций и переменных наклонирована копипастом. Исправлять в десяти местах уже надоело, надо что-то с этим делать.
Шаг 30. Ага! Надо использовать классы!
Шаг 40. Что-то классы у меня всё больше копипастятся, и править один фиг приходится в десяти местах.
Шаг 50. Ага! Шаблоны проектирования решат все мои проблемы!
Шаг 99. Блин, каким же я был идиотом… Вот же, всё же просто…
Шаг 100. Дзен.
Номера шагов и названия методик выбраны почти произвольно. Важны не они сами по себе, а факт смены программистом парадигм
Есть у меня одно беспокоящее меня наблюдение. В различных учебниках есть рекомендации не оглядываться в процессе проектирования программ на аппаратные возможности вычислительной техники, а также призывы не задумываться, почему это работает именно так, а просто использовать это. Мне это представляется в корне неверным для подготовки качественного программиста. И подтверждений этому я встречал множество — большинство действительно хороших программистов имеют неслабое представление о том, как работает «вообще это всё», иногда вплоть до ассемблера и уровня TCP. Но вот что примечательно: подобная рекомендация действительно ценна для воспитания monkeypatcher'а. Оно и понятно. Дрессировка животных обычно производится подобным способом: не важно, зачем и почему, важно сделать именно это и будет вкусно. И вот на этой неприятной ноте мы переходим к заветной парочке PHP/HTML.
Я лично склонен условно делить PHP'шников на две больших категории: тех, кто знает другие языки программирования (для таких, как правило, PHP не был первым языком, хотя и наоборот тоже бывает), и тех, кто не знает кроме PHP ничего. Первая категория часто развивается по предыдущему сценарию, и к ним у меня вопросов нет — они и на PHP обычно пишут хороший код и используют его грамотно и обоснованно. Но вот вторая категория — там всё иначе. Вообще всё. Потому что, проходя развитие по первому сценарию, люди часто изначально используют напрямую только одну-две непривязанных к конкретному языку технологии (например, консоль или WinAPI/X11), и причинно-следственные связи не рвутся: вот они, аргументы командной строки, а вот они и в коде, пользуемся. Чего никак нельзя сказать о второй категории.
Потому что люди, которые до PHP не программировали вообще — оказываются один на один с готовой, большой, уже работающей и очень непонятной системой. С одной стороны, вот тебе echo 'hello world' — браузер — F5 — вот оно, а с другой — не совсем ясно, как оно туда попало и почему не обновилось само. Нет, основные понятия типа «положить файл в корень вебсервера», конечно, усваивается, но вопросы «откуда у вебсервера корень?» и «как он выглядит вообще-то?» часто остаются без должных разъяснений с туманной надеждой на восполнение этого пробела в будущем. Со временем количество таких непонятных мест только растёт, туда добавляются всякие цээсэс/джээс/хэтэакцесс/оопэ/шаблоны/шрифты/жипеги, внутренности которых не особо понятны, но (и это очень важно) — всем этим, оказывается, определённо можно пользоваться вообще не задумываясь о том, что, почему и как. Со временем парадигма «не задумываться» иногда оказывается превалирующей, и тогда это совсем печально. Где-то когда-то какие-то психологи установили, что восприятие нового текста человеком прекращается на том месте, где он встретил непонятное слово. В таком случае самым правильным будет вернуться к этому слову, разъяснить его смысл, и продолжить. В случае с веб-технологиями (и чаще всего в вебе начинают именно с PHP) — непонятных слов очень много. Невероятно много, для некоторых — так почти все. Но: если начать объяснять всю цепочку от запроса до браузера через веб-сервер по тцпипу — до собственно программирования мы дойдём очень нескоро. И поэтому тут начинается враньё. Либо преподаватели (в широком смысле — это могут быть и старшие товарищи, и друзья-форумчане, и лекторы из видео-уроков) врут обучаемым, что потом всё станет ясно, либо сами ученики начинают врать себе и учителям (потому что признаться в непонимании стыдно): «Да лан, тут я всё понял». «Да нифига ты не понял», — машут рукой учителя и выдают следующую порцию обучения. Со временем обучаемые настолько свыкаются с состоянием «немного недопонял, но давай так», что в сознании накапливается полнейшая свалка из понятий, методов, форматов и всего, чего только можно.
На выходе мы можем получить «специалиста», который уже несколько лет программирует на PHP, но до сих не может внятно объяснить, как файл, залитый на один сервер, оказывается в браузере при запросе к другому серверу. Нет, в целом-то, он, канешна, панимает, но вот если попросить разъяснить — на выходе будет нечто среднее между «как-то так» и «да какая разница».
Дополнительная головная боль для PHP — это ООП в любом смысле и всякие иные плюшки времени исполнения. И эволюция PHP-программиста в итоге будет несколько отличаться от вышеописанных ста шагов до дзена. Потому что, с одной стороны, все пхпшники знают, что сценарий отработает, схлопнется и всё забудет, а с другой — пишут код так, как будто это софт, работающий непрерывно годами и веками. Тщательно продумывая структуру классов, статических методов, реализуя интерфейсы и даже (!!!) сигналы, они плодят километры кода. Апофеоз начинается с реализацией «ленивой загрузки» — ведь все же понимают, что этот код может оказаться и неисполненным, так чего его зазря инклудить? Подвоха не чувствуется ещё? Этот код, быть может, никогда и не исполнится, но он написан! И на его написание было потрачено время, силы, нередко и деньги…
И если для программиста на языке с длительным временем исполнения единожды проинициалированная переменная в доброй половине случаев может быть использована хоть через год работы программы, то в PHP это всё инициализируется, инстанцируется и композиционируется буквально в ответ на каждый чих от браузера пользователя, нередко и в ответ на ajax-запрос, после чего всё мгновенно рушится и забывается. Автор иногда немножко тормоз, и осознание этого факта для него однажды стало неслабым ударом по психике.
Разумеется, никакой Америки я снова не открыл, но почему я об этом говорю и почему считаю это важным. Потому что общая каша в головах многих программистов мешает им абстрагироваться от всего процесса и поразмыслить о сути бытия том, чего ради всё это нагорожено. И в ответ на попытки им это втемяшить они, привыкшие к тому, что «это всё равно так и этого не изменить», отказываются что-либо понимать. Иногда потому, что иного пути, кроме как браузер — веб-сервер — PHP — БД — PHP — веб-сервер — браузер просто не представляют. Ну а поскольку на выходе в любом случае всё равно HTML с плюшками, то и это переходит в разряд неизменных и непреложных истин, не подлежащих доказательству аксиом. И, поскольку PHP в наши дни в большинстве, и именно для него нужен именно отдельный_веб-сервер, то и программирующие на других языках начинают к отдельным_веб-серверам привязываться, ибо они всё равно установлены и настроены, да и зачем изобретать колесо? И правда, зачем? Всё же, вроде бы, и так прекрасно работает?
Чтобы всё-таки уже ответить на этот вопрос, коснёмся ещё одной темы. А именно: отдельный_веб-сервер. Что он делает обычно и с чего всё начиналось? Иными словами, зачем оно сделано именно так? Дело в том, что первый веб-сервер был создан очень давно. Оперативной памяти тогда было мало и она была дорогая. Файлы тогда тоже были маленькими, и графические элементы для оформления дизайна практически не использовались. Не было ни PHP, ни JS, ни CSS. Был только голый HTML. Браузер тогда был не средством утоления информационного голода, а новой программой, запустив которую, можно было некоторую информацию получить (при наличии подключения к интернету, который был тоже очень маленьким и медленным тогда). А веб-сайты были не способом выпендриться (хотяя… :)), а способом поделиться некоторым количеством информации. Дисковые массивы тоже не отличались большой ёмкостью, но всё-таки, были дешевле оперативки. Хранить файлы в оперативной памяти тогда просто считалось (да и на самом деле было) невозможным, даже если они использовались часто. К тому же скорость подключения тогда измерялась единицами и десятками килобит. Поэтому первые веб-серверы в ответ на запрос пользователя начинали по нескольку десятков байт в секунду считывать файл с жёсткого диска сервера и по кусочкам передавать его клиенту через сеть. И передача одного файла не всегда занимала меньше одной секунды. Да. С тех пор прошло чуть более двадцати лет. Всё изменилось. Любой тогдашний средний сервер обзавидовался бы, наверно, современному среднему смартфону по любому параметру, будь то ёмкость ОЗУ, частота ЦП, да и ёмкость ПЗУ, наверно, тоже. А то и разрешению экрана.
Но мы по-прежнему храним файлы на дисках, читаем их веб-серверами и скармливаем браузерам пачками. Только понапридумывали ещё кучу всяких красивостей и удобств вроде rich internet application со скриптовыми языками. И всё это поверх технологий двадцатилетней давности. Придумали не напрягать бедного пыха статическими файлами и раздавать их отдельно веб-сервером. Умные люди, уставшие от несовершенства CSS даже придумали LESS и SASS, а может, и ещё что-нибудь есть. И теперь дилемма — где и когда это компилировать? То ли на сервере, то ли на клиенте. То ли кэшировать, то ли перекомпилировать после каждого изменения и складывать в статику? Но почему-то никто не хочет посмотреть, а что же такое есть кэш по сути своей, и как веб-сервер статику раздаёт. Хотя каждый использует формулировки типа «файлы всё равно закэшатся системой и не будут перечитываться с диска каждый раз». Ну сделайте уже этот последний шаг! Ведь всем уже видно, что файлы, будучи закэшированными, по сути, хранятся не на диске, а в оперативной памяти! Зачем изобретать очередной тип кэша — просто загрузите эти файлы в память, и отдавайте их напрямую. Если это требует компиляции — скомпилируйте в итоговый вид и отдавайте, опять же, из оперативки. А уже то, что истинно переменно — подгружайте из БД или где Вы там это храните…
В этом месте кто-то должен ткнуть автора в бок бритвой Оккама, и возразить, мол, зачем нам лишние сущности, если всё и так работает? А зачем Вам автомобиль, если немногим более сотни лет назад большинству хватало лошади и своих двоих? Зачем человеку вообще персональный компьютер и графический интерфейс с браузёрами и тырнетами? Ведь именно это не так уж и давно утверждалось весьма авторитетно… Так вот, господа оккамисты. Проникающий На Всякий Уровень Проектирования Вездесущий Кэш, собственно и есть та самая лишняя сущность! Ведь всё будет работать и без него, не так ли? А если так, то зачем он нам? Давайте быть последовательными в суждениях. Но ведь нет, от кэша никто не спешит отказываться, лишний кэш никогда не бывает лишним. А почему? Потому что кэш, как нам говорят, ускоряет работу приложений. Но, господа, позвольте, ведь это же чушь! Как можно ускорить что-то, не разгоняя это? ЦП по-прежнему работает на той же частоте, частота работы оперативки та же, скорость обмена с дисковыми массивами тоже не увеличивается. Но, однако, с кэшем оно реально работает быстрее. Великая Священная Правда в том, что кэш ничего никогда не ускоряет — он всего лишь устраняет тормоза. То бишь, позволяет обойти медленно работающие участки при повторном по ним проходе, просто ненадолго запомнив их состояние. Ну а коли их всё-таки обходить приходится — значит, они есть. Но откуда они там взялись? Так мы же сами их там и нагородили, вообще-то…
Вот и вопрос — а зачем, во имя чего мы городим этот медленно работающий код? Почему мы его не делаем быстрым? Как правило, либо по незнанию, либо по неумению. Иногда по недоразумению. Но давайте посмотрим: среднестатистический современный не особо сложный сайт содержит от сотен килобайт до единиц мегабайт графического и прочего стилевого оформления. При современных ценах на оперативку — это ничто. С другой стороны — если оно будет в кэше неважно на каком уровне — оно всё равно эту оперативку займёт. Более того, оно может оказаться в кэшах разных уровней разных частей системы и может отъесть эту оперативку несколько раз. Причём не всегда оптимальным образом. Так зачем нам лишние слои, мы же ведь не Шрэк и не лук? Просто при старте системы загрузите их в память и используйте. И кэш получается, совсем не нужен. Но именно в этом месте и проявляется вся немощь PHP… Он так не может. Ничего не удастся выгадать, даже если сериализовать и сохранить — всё равно при следующем запросе придётся сначала инициализировать объектную иерархию и потом десериализовывать. Лишняя, никому не нужная, ничего не ускоряющая работа.
Лирическое отступление номер четыре. Знаете, почему ВАЗ2101 без доработки вряд ли удастся разогнать до скорости 200 км/ч? Даже не из-за двигателя. А потому, что уже на 130 км/ч бедную «копейку» начинает швырять из стороны в сторону так, что становится страшно ехать. Потому что 15-градусный люфт рулевого управления при 20 км/ч — это почти не заметно, а при 200 км/ч — можно запросто слететь с дороги буквально на ровном месте. Она просто не предназначена для таких скоростей. На велосипеде, кстати, быстро ехать тоже опасно. Нет амортизации, прямое рулевое… Одно неаккуратное движение может стоить немалых телесных потерь. Он тоже не рассчитан на большие скорости. Зато на большие скорости рассчитана прорва результатов современного автопрома. И знаете, чем отличается современный автомобиль от среднестатистического велосипеда пятнадцатилетней давности? Да, правильно. Всем. Но что в нём самое главное — все узлы в нём максимально подогнаны друг к другу профессиональными конструкторами так, что вам даже не нужно об этом задумываться. Вы просто садитесь в автомобиль, и едете. И когда для Вашей организации автомобиль вдруг становится необходимым, почему Вы не станете нанимать специально обученных автослесарей, которые до хрипоты будут спорить друг с другом на предмет количества устанавливаемых цилиндров, типа тормозов, конструкции шасси, чтобы сделать для Вас такой автомобиль, какой нужен именно Вам, и ни у кого такого больше не будет никогда? Да, кто-то и собирает автомобили для себя, но это либо хобби, либо промышленный заказ, и это всегда недёшево. Но даже в этом случае практически никто не станет для Вас рассчитывать параметры двигателя и проектировать его, а просто возьмёт подходящий по параметрам. Если, конечно, Вас интересует именно готовый автомобиль, а не процесс расчёта параметров двигателя. В этой аллегории важен момент, что рассчитанное специалистами в большинстве случаев лучше и надёжнее наколеночной сборки, а подчас и дешевле. Не без исключений, разумеется.
Тут мне скажут: так же ж автор же говорит про CMS или фреймворки! Как бы и да, и нет. Да, потому что и те и те призваны избавить программиста от лишней рутинной работы, и нет, потому что их работа всё равно выполняется на прикладном уровне. Иными словами, если проделать обратную аллегоризацию к автотранспорту — фреймворк или CMS, семантически подобны автомобилю, собранному из конструктора различной степени абстракционной детализации. Тоже, конечно, имеет право на жизнь, но как-то… Не в массовом применении, пожалуй. Но в программировании почему-то до сих пор так.
Во многих фреймворках на том же питоне, к примеру, а, с недавних пор и в PHP, есть встроенный веб-сервер для разработки, но на «продакшне» ими пользоваться не рекомендуется, ибо специализированные решения быстрее и надёжнее. Разработаны и расширения, и протоколы для работы с веб-серверами. Дальше. Хранение данных. Большинство языков имеют встроенные возможности для работы с файловой системой и различными способами хранения данных. Но в промышленных масштабах, опять же, рекомендуют пользоваться специализированными СУБД — ибо, опять же, надёжнее. Хотя уже не всегда проще. Хотя для многих проектов, признаться, SQLite-база, размещённая в оперативной памяти, вполне себе скоростное и надёжное решение. Другими словами, специализированное решение снова выигрывает. Теперь посмотрим на основную массу сегодняшних сайтов и попробуем выделить некоторые семантические признаки, общие для всех. Навскидку:
- Во-первых, принцип оформления. HTML/CSS/JS c с плюшками. Всё сплошь и рядом одинаково. Различаются, по сути, только гарнитуры/размеры/цвета шрифтов да размеры/стили/расположение блочных элементов дизайна.
- Во-вторых, принципы хранения и управления содержимым. Практически везде ведётся работа с пользователями, новостями, статьями, различными мультимедийными элементами (фото, фидео, аудио). Иными словами, структура большинства сайтов повторяется из раза в раз. Не стану говорить об игровых или сверхнагруженных проектах — это не мейнстрим в смысле создания — там каждый стремится делать всё по-своему в силу разных причин, но данные принципы в какой-то части могут быть применимы и к ним.
- В-третьих, принципы взаимодействия с пользователем на клиентской стороне. Браузер как специализированное средство взаимодействия с веб-сервером был предложен и реализован изначально, но с минимумом интерактива. Только просмотр страниц, запрошенных из адресной строки или по клику на гиперссылке, что для веб-сервера суть одно. С того момента интерактив неотвратимо, но невообразимо медленно пытается дотянуться по возможностям до десктопных приложений, заимствуя из них всё, что только можно — всплывающие и выпадающие по наведению элементы, виджеты и информеры, и мучительно пытается втиснуться в идеологически давным-давно устаревшую парадигму HTML+CSS+JS. Имеющие опыт построения интерфейсов для десктопа и для веба, думаю, легко со мной согласятся в том, что для десктопа это делать проще.
А что же в веб? Вот HTML5 — убийца флэша. Вот JS — убийца AS3. Прям народный фронт какой-то. Только кто с кем воюет-то? Война неандертальца с кроманьонцем, и поверженным, по каким-то непонятным причинам, оказывается кроманьонец. И это странно, и наводит на нехорошие мысли, что это может быть кому-то выгодно. Чем не угодил флэш как технология? Некрасивыми раздражающими баннерами? Так вопросы к изготовителям и размещателям, а не к технологам, вообще-то. А что, вырвиглазные перемигивающиеся дизайны HTML-сайтов начала 2000-х — это было лучше? Всё сияющее сверх меры рано или поздно уходит, и это бы ушло. Зачем нам флэш, у нас теперь есть canvas? Ню-ню. На месте adobe я бы вкрутил все методы для работы с нововведёнными элементами в очередную версию ActionScript, да и делов. Давно за ними не слежу, не знаю, может они уже так и сделали. Ибо в последнее время что-то флэшплеер пухнет как сдобное тесто. Так что, автор за флэш вместо HTML? Нет. Автор за разумный подход.
Лирическое отступление номер пять, последнее. Не так давно у автора началась вольная жизнь, среди прочего было решено вернуться к разработке сайтов по принципу «сляпаю по-быстрому на цмске за копейки, да и ладно» в качестве неосновного профиля деятельности. Но вот вопрос выбора CMS на PHP меня просто, можно сказать, убил. Была потрачена уйма времени, но серебряная пуля моей мечты так и осталась ненайденной. В тщетных попытках обрести дзен рассматривался даже Yii. Потрясный код, офигенные возможности, обширная, хоть и англоязычная, документация, как говорят, неплохое сообщество. Но ниасилил. Ну не могу я в качестве аргумента функции передавать массив массивов массивов, который, прям тут же и задаётся. Классный фреймворк, классно написанный код, но зачем??? И постоянные на форумах «Как сделать? — Иди в доку!». Но, чёрт побери, если возникают одни и те же вопросы раз за разом у разных людей в разное время, значит, что-то не так именно с этим местом! На всех форумах всех языков программирования постоянно одни и те же вопросы. Как сделать пользователя, как их хранить, чем хэшить, как написать запрос, а чё эта ваще такое, а почему так?.. И вот стотысячный программист тратит, наверное, уже стомиллиардный общемировой человеко-час, чтобы реализовать то_же_самое хранение пользователей, то_же_самое шифрование паролей, те_же_самые запросы к базе, в_тех_же_самых_местах подключает те_же_самые кэши, чтобы точно_так_же_не_тормозило… А как же хвалёное повторное использование кода? Примерно в то время произошла описанная выше ситуация с кофе, после чего я окончательно и бесповоротно решил послать отойти от PHP в сторону питона, на который заглядываюсь уже достаточно давно, а также написать эту статью.
Так чего же хочет автор, и к чему всё это словоблудие?
Самый мой нелюбимый ответ на заданный вопрос из разряда: «Почему это делается/происходит именно так?» — это «А как ты хотел?». Мне почему-то представляется очевидным, что я подразумевал что-нибудь иное, отличное от происходящего, потому, собственно, и спрашиваю. Так вот, ответьте, пожалуйста, на несколько вопросов:
- Зачем мы сплошь и рядом используем инструменты разработки, которые подразумевают различных степеней парсинг и синтаксический анализ на каждом этапе выполнения кода, сначала на серверной стороне, а потом и на клиентской?
- Во имя чего мы раз за разом мучаемся, приводя к какому-то общему знаменателю различные результаты этих самых парсингов и интерпретаций, созданных решениями разных производителей?
- Для чего нам сотни тонких настроек веб-серверов, если подавляющее большинство их комбинируется в две-три-пять-десять устоявшихся конфигураций и кочуют в виде FAQ'ов и рекомендаций с форума на форум, после чего успешно используются в конечных системах, совершенно неизменные?
- И на кой леший нам сотни реализаций совершенно однотипных операций типа CRUD, раз за разом борющихся с одними и теми же ограничениями идеологически неизменных на протяжении более десятка лет (и это IT-технологии, считающиеся едва ли не передовыми) серверов баз данных?
- Если парадигмы User/Password и Post/Comments настолько прочно обосновались в веб-технологиях — почему работа с ними, включая хранение, до сих пор не выведена на уровень стандарта языка или протоколов?
- Аналогично, если потребность в интерактиве сейчас совершенно очевидна, равно как и сложность её реализации на данный момент (а иначе для чего же нам самый_популярный_JS_фреймворк, нежели не для упрощения) — почему это до сих пор, вот уже 20 лет, не выведено в стандарты, спецификации и протоколы? В такие, которые действительно работают. В такие, при наличии которых нам не потребуется для каждой части MVC использовать свои отдельные, но, несомненно, лучшие фреймворки, а потом мужественно бороться с их несовместимостью и разнотипностью?
- И, кстати, если всё и так хорошо, то зачем нам фреймворки вообще?
- И, простите, какая, к чёрту, MVC, если на сегодняшний день парадигма всего веба строится на принципе запрос-ответ, и оба в виде плоского текста? Какие сигналы, какие события?
- И нафига нам вообще размазывать веб-приложение между всеми этими слоями? Почему бы не создать какой-нибудь RichWebDataServer, который будет включать в себя и web-сервер, и БД, и скомпиленное, тщательно вылизанное управление пользователями, постами с комментариями и новостями со статьями, а также оптимизированное именно под эти типы ресурсов хранение и управление, и всё это с открытым кодом? И пусть этот сервер выдаёт не плоский текст, а нормальное интерактивное пользовательское окно. И работает поверх какого-нибудь HTTP_2.0 с поддержкой состояний. При таком подходе можно будет поговорить и об MVC, и о сигналах, и о событиях. Признаюсь, большие надежды я возлагал в этом плане на ActionScript, но оно как-то не выстрелило, да и к тому же вся эта красота всё равно будет разбиваться о plain_text GET|POST. В общем, пора уже переходить к чему-нибудь наподобие X.Org или RDP, тем паче, что облака становятся всё ближе и доступнее, равно как и мобильные технологии.
Пора уже поблагодарить браузеры за службу ратную, долгую и верную, да и сдать их в музеи истории рядом с трафаретами и печатными машинками, достать из кармана какой-нибудь новомодный девайс, и насладиться подлинным интерактивом, построенном на торжестве современных технологий, а не на осколках технологий тридцатилетней давности. Шучу. :) А если серьёзно, то критически пересмотреть весь стек технологий существующего веба, на мой субъективный взгляд, действительно пора. А что касается PHP — то он никуда не денется. Не исключаю, что ему найдётся место и в новом вебе. Особенно, если энтузиасты перестанут пытаться сделать "более быструю лошадь". А старые добрые несложные сайты проработают на нём ещё очень-очень долго.
И ещё одно. В поставленных вопросах я умышленно местами перегибаю палку и вполне осознанно ожидаю закономерной критики. Как показывает практика, аргументированная критика хорошо вскрывает слабые места, а там, чего доброго, может и родится что-нибудь действительно полезное. Единственное, от чего бы я попросил воздержаться — так это от комментариев в духе «куда девать существующую прорву оборудования и армию обученных специалистов». Я не настолько наивен, чтобы ожидать взрывного эффекта с немедленной революцией. По правде говоря, я вообще не уверен, что в мире изменится хоть что-нибудь, но некоторая надежда на торжество разума расшевелить хоть кого-нибудь всё-таки имеется. Также хотелось бы предостеречь от самоутверждений типа «сразу видно, что автор не программист» — речь не о коде в рамках существующих технологий, а о целесообразности и удобстве самих технологий, как таковых. О зашоренности опытного взгляда, привыкшего именно к такому положению вещей. И о том, можно ли сделать мир лучше и чище, и что для этого нужно.
Благодарю всех за внимание и терпение при прочтении данного опуса. И прошу прощения за столь объёмное изложение. И нет, автор не шизофреник. Мы оба в этом абсолютно уверены — и я, и автор. :)
Автор: eternal_why