Как многие из посетителей Julik Live знают, последнее время я сильно углубился в Rails. Но записей тут не появлялось не поэтому. Все время с июля по октябрь было потрачено на поезда с 140 по 146, из которых я практически не вылезал. Во-вторых, огромное количество времени отнимает школа (на которую нужно пахать и пахать - и которая не предполагает ни блоггинга, ни вебдева как такового). Наконец-то нашлось полчаса, которые можно посвятить Rails, и это будет длинно и будет занимательно. Потому что просьбы товарищей надо выполнять. Дальше могут читать только люди причастные к веб-программированию (остальным будет неинтересно).

Technorati Tags: ,

Очень странная вещь Rails. Приводит к выводам, причем этих выводов я не ожидал.

Вывод 1. Если использование определенного инструмента подходит мне и подходит заказчику - в лес. Потому что мое удобство разработки (и качество продукции которую я своему заказчику могу предложить) в разы важнее чем чесучесть пяток у среднестатистического администратора среднестатистического русского хостинга.

Вывод 2. Я возненавидел PHP лютой ненавистью и надеюсь что больше ни одной строчки на нем мне написать не придется. Не потому что на нем нельзя делать рабочие и полезные решения - отнюдь. Потому что это моя работа и мне теперь неприятно делать ее на PHP. Rails в первую очередь дает мне наконец-то осознать что помимо PHP есть еще что-то - на чем сайты можно делать лучше, быстрее, элегантнее и с большим драйвом. Я знаю где я использую PHP - а именно как комплиментарную, используемую по нужде технологию-посредник (похожая схема применяется в MT).

Вывод 3. Дизайн существует и в языках программирования - и PHP определенно не тот язык, который этим понятием одарен. Идея в нем есть (быстро и грязно плеваться HTML в людей) но концепция отсутствует.

Ruby

Ruby - сказка. Это сложно обьяснить, но все аргументы “против”, встреченные мной (кроме претензий к скорости) мне кажутся совершенно абсурдными. Ruby is JavaScript done right.

А дело вот в чем. Ruby - язык креативного диктатора. Совершенно очевидно, что он сделан Конкретным Человеком с Конкретным Планом Действий - и каждая функция, каждая мелочь и каждая деталь сделаны настолько элегантно, что щеточка для сбора челюсти со стола требуется постоянно.

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

  • Все - объект
  • Класс - тоже объект
  • Класс класса - объект (ха!)
  • И строка, и число - объекты, равно как True и False.
  • Да, null тоже объект. Кстати, его класс - объект класса Класс.
  • Объекты отвечают на сообщения, причем сообщения сходной семантики в классах называются одинаково

Все. Этого достаточно.

Чтобы выяснить разницу двух массивов в PHP, нужно хорошенько прочитать про все 6478 функций set arithmetic. Чтобы сделать это в Ruby, нужно отнять один массив от другого знаком минус.

Чтобы выяснить включает ли массив элемент в PHP, или включает ли строка подстроку, нужно запомнить две разных функции (включая порядок их аргументов - которых много) и то, что одна возвразщает 1 а другая 0. В Ruby достаточно спросить содержащий объект

общее.include?(кусок) => false

И так во всем. В итоге количество глупостей, которые надо помнить, сокращается в разы - потому что кто-то подумал о том, что необязательно alias’ить С в скриптовый язык и можно поступить хитрее.

Более того, согласно официально “благословленному” principle of least surprise мало Ruby-разработчиков вставят в свой скрипт что-то, что таковой глупостью является. Я использовал уже как минимум десяток разных библиотек и только в одной был идиотский API. In contrast все используемые мной библиотеки на PHP (кроме ADODB и QuickForm) имели идиотский API изначально. И даже те которые я писал сам - тоже.

Принципиально почти устранена разница между методами класса и методами объекта (поскольку класс - объект этой проблемы просто не возникает).

some_var = Class
class_methods = some_var.methods

В итоге отпадает огромное количество костылей которые например авторам PHP пришлось передирать из Java - а именно всевозможные static, отдельный разделитель для вызова статических методов и так далее.

И блоки. О да - блоки это наше все. Грубо говоря - там где PHP нужно четыре функции для preg_replace_чтототам, Ruby обходится одной (gsub) - за счет того что она позволяет выполнить что-то еще внутри себя. Простейший пример блока - транзакция с базой. Переведенная на правильный Ruby она будет звучать так:

in_transaction do
  person1.deduct(100.bucks)
  person2.deposit(100.bucks)
end

Функция же in_transaction будет выглядеть так

 def in_transaction 
  Database::Driver.query "BEGIN"
  begin
   yield
   Database::Driver.query "COMMIT"
  rescue Database::UnicodeNotSupportedThisDatabaseSucks
  Database::Driver.query "ROLLBACK"
 end
end

В итоге получается что не надо думать о закрытии файла после чтения из него. И не надо думать о вставке фрагментов текста обратно после обработки этого текста. И вообще не надо думать о том что после операций X и Y обазана следовать операция Z - потому что операция Z всегда завязана на операцию X и там где их может быть две их не должно быть три.

Ну и конечно dereferencing, но его слава богу заставили работать и в PHP. Что в контексте Rails (благодаря расширениям базовых классов) дает совершенно прелестные конструкции (не имеющие ничего общего с Perl)

40.days.from_now + 2.hours => Thu Jan 05 05:14:59 CET 2006 

Или (в контексте RuTils)

10.rublej => "десять рублей"

Еще 19 функций из головы вон, включая непрерывную конверсию из секунд от epoch в строку и обратно.

И так во всем - работа с Ruby это как бесконечный яблочный пирог.

Rails

А теперь собственно про Rails. Поскольку мало кто таки собирается и ставит его себе на машину, а уж тем более - пишет на нем приложение, краткий рассказ - что оно такое есть.

Rails - это framework (набор библиотек, к которому надо приписать минимум кода для создания готового веб-приложения), сделанный для создания веб-сайтов с базами данных “с нуля”. Это важно - именно “с нуля”, для “напяливания” сайта на 1С оно не подойдет совершенно.

Здесь следует сказать о разнице между framework и библиотекой. Разница сложнообъяснимая но очень четкая - framework использует IOC, то есть вместо явного вызова вами кода библиотеки код библиотеки вызывает ваш.

Rails хорош только и исключительно с Ruby. Бесконечные попытки (в том числе мои собственные) передрать и переплюнуть Rails выглядят настолько никчемно, что хочется дать им Ruby-хостинг из жалости. Проблема их всех в том что огромное количество вещей, которые Rails использует (например - дополнение и расширение функциональности всех классов и модулей “на ходу”) невозможно в PHP - и даже с приложением всех сил PHP-сообщества (с целью “быстро и дешево пере***ь и запустить на пятидолларовом хостинге”) эту проблему нельзя решить - это fundamental flaw PHP, будучи динамичным он вполне мог бы это позволять. Более того, даже со всеми усилиями PHP-код никогда не будет таким элегантным (просто потому что дизайн отсутствует).

Далее. Rails - это по сути воплощение всех традиционных паттернов создания веб-приложений, только с минимумом ненужных костылей. Actions сокращены до методов, ActiveRecord заменяет Mapper и так далее - то есть сознательно уменьшена гибкость за счет увеличения скорости разработки (и того самого “запуска с нуля”). К сожалению, Rails не содержит того заряда новизны который есть в Seaside например (и которые Ruby вполне в состоянии предоставить) - но с этим можно свыкнуться. Более того, поскольку Rails изначально сделан с мыслью о “дизайне” (да, фанатам PHP надо видимо кричать это слово прямо в левое ухо - потому что оно таки есть) его компоненты достаточно разумно разделены, и я думаю не так уж тяжело будет надеть фасад из Wee на уже существующую модель из ActiveRecord.

Есть вещи которые Rails делает плоховато. Например, использование простейших (и быстрых) SQL-запросов становится несколько сложным потому что они все время норовят вылезти за границы возможностей ORM. Штука скользкая - но седлаемая - никто не мешает спуститься до уровня базы данных и отправлять запросы напрямую. Другое дело, что огромное количество вещей которые в принципе хороши (например буферизация результатов запроса к базе) с ORM становятся крайне тяжелы.

В этом плане Rails - инструмент реалиста. Например - при загрузке 10 записей из базы у них будут загружены все поля. Включая тот самый blob в котором лежит 100-мегабайтный видеофайл, именно так. Только во многих ли приложениях бывают 100-мегабайтные файлы в базе?

То есть соблюдена основная мантра 37signals - “простые вещи просты, сложные - возможны”. При минимуме кнопок.


Но все вышесказанное нужно попробовать. По крайней мере по тому что в области архитектуры сейчас Rails - культовая система, а через год будет baseline-решением (а место Rails займут Seaside и ему подобные). Даже если работать с Rails и Ruby претит принципиально рекомендуется наконец-то высунуть голову из PHP-болотца (как жаль что я это сделал так поздно) и оглядеться вокруг.


Ну а оприхтер? PHP я больше не использую. Проект уже запущен, и не один, а на подходе еще несколько. Пользователи счастливы, тесты написаны - а разработка ускорилась раза в три. Да и субпродукт не так плох.

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