Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
чтобы использовать полный рабочий день разработчиков
P.S.: Стоимость поддержки drupal доходит до 200$ в час, если бы эффективно было использовать другую технологию, то цены не доходили бы до таких высот.
Программисту всегда интереснее (а потом уже проще и удобнее), написать свой велосипед нежели изучать документацию чужого (хоть и распространенного) продукта.
Я написал десятки модулей разной сложности для десятков сайтов. Бывают модули с чёткой и понятной функциональностью, а бывают и вот такие:
…
Это весь модуль.
Для этой же view в template.php +15 строчек, чтобы просто добавить class к table.
И еще много строчек, чтобы URL сделать ссылкой в таблице (не ставя для этого модуль на сотни строк кода).
Но факт, что тех кто понял Друпал очень мало. Их сложно найти и они дорого стоят. И еще и не хотят работать в офисе)
В итоге все равно получаем, что использовать Друпал в больших кастомных проектах просто не выгодно.
Расскажите мне кто-нибудь, как вообще это можно использовать? Сколько кода надо написать, что бы полноценно анализировать Sql-запросы и тем более править их на лету?
Ну и туда же идут такие же кривые хуки типа form_alter (парни, в нормальном фреймворке вы либо расширяете объект с формой, либо если речь о внешнем виде, то наследуете/переписываете шаблон этой формы, а не ковыряетесь в пяти мерном массиве). Что касается хуков типа js_alter/css_alter — опять же, умные ребята просто делают систему шаблонов/виджетов и про сборке страницы автоматически учитывают все зависимости. Ну или хотя бы берут уже готовый XSLT — через него можно шаблоны хоть наизнанку выворачивать.
API Друпала — отдельная кривая вещь. Хотите получить ноду по id? В руководстве АПИ прямо написано, что для этого лучше использовать прямые запросы, так как метод АПИ выбирает много данных и медленно работает.
SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context AND s.textgroup = 'default'
(запрос из locale.module, видимо для перевода строк). Для незнакомых с MySQL объясняю — при переводе строки мало того, что Друпал делает запрос в БД (да еще и с джойном, чтобы не отпимизировался), так еще и с поиском по текстовому (до 65536 символов) полю source. Любой человек, кто прочел хотя бы полглавы мануала по MySQL будет за такое бить монитором по голове. Gettext герои-друпаловцы решили побрезговать, что нам стоит каждую строчку из БД выдергивать.
// Refresh database stored cache of translations for given language.
// We only store short strings used in current version, to improve
// performance and consume less memory.
$result = db_query("SELECT s.source, s.context, t.translation, t.language FROM {locales_source} s
LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = 'default'
AND s.version = :version AND LENGTH(s.source) < :length", array(':language' => $langcode,
':version' => VERSION, ':length' => variable_get('locale_cache_length', 75)));
foreach ($result as $data) {
$locale_t[$langcode][$data->context][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
}
cache_set('locale:' . $langcode, $locale_t[$langcode]);
Я уж молчу, что в нем нет ни моделек, ни ORM, ни валидаторов, ни нормальной работы с формами, ни системы views/widgets, ни наследуемых шаблонов, ни контроллеров, ни MVC, вообще ничего, чем все прогрессивное человечество пользуется в последние 10 лет.
Ок, насчет alter_query я ошибся — он работает с разбитым в массив запросом. Это, однако, не делает его более осмысленным, так как трудно представить себе, сколько возможно труднообнаружимых багов, когда ты делаешь запрос, а какой-то модуль тихонько его переписывает на другой.
Насчет перевода — gettext выгоднее. В случае Apache например, бинарный файл с переводом загружается в память один раз и повторно используется при обработке следующих запросов, а его структура обеспечивает более компактное хранение данных и поиск строк.
Не говоря о том, что gettext — это открытая и повсеместно используемая бибилиотека.
Если уж так надо переводить строки через админку (вы вообще уверены, что это удобно? учитывая скорость работы друпала?...
… и наличие специального софта для работы с переводами) — можно было хранить строки в БД, но генерировать по ней .po -файл для gettext.
Насчет ORM — «в Друпале он есть, только свой» — где там ORM? Там есть система хранения сущностей, которые должны быть основаны на нодах, но ORM — в том виде, как например, это сделано в Hibernate, Doctrine — там нет (замечу, что я считаю саму Doctrine неудачной реализцией ORM — но она в разы лучше того, что в Друпале). Как всегда, какой-то свой криво, тормозной, неудобный велосипед.
Насчет расширения системы через хуки. Многие вещи, типа регистрации действий в системе, добавления пунктов меню, свойств в ноды, валидация, сделаны через хуки (=костыли).
Вы говорите, а как еще сделать это, когда у вас 20 разных модулей. Отвечаю. Модули должны при установке (а не при каждом запросе) регистрировать в системе новые пункты меню и свойства
class SomeModule {
public static function afterInstall() {
$drupal->menu()->addEntry(...)
$drupal->schema()->addContentType(...)
$drupal->schema()->addProperty(...)
$drupal->schema()->addValidator(...)
}
}
А когда у вас в ходе выполнения запроса происходят сотни вызовов разных модулей, они могут на ходу что-то подправить (а могут и не подправить) — это каша в коде, каша в голове разработчиков, снижение производительности, источник трудновоспроизводимых багов.
И идея разнести базовую функциональность на 20 модулей тоже, на мой взгляд, не самая лучшая.
Про архитектуру. Архитектуры там нет.
Возьмем, например, пример из мануала по Друпалу, описание хука node_validate():
if (что-то неправильно) {
form_set_error(....);
}
Какое отношение валидация сущности имеет к форме?
студенты, которые придумали этот хук, не в курсе, что сущности могут создаваться без участия формы
связанность — отдельная тема, в Друпале как и в этом примере, все связано намертво
То, что вы пишите про event-driven архитектуру — да нет там никакой архитектуры
Что еще ждать от людей, которые программируют на функциях и глобальных переменных.
Эм, а зачем? Как я понимаю процесс разработки сайта, дизайнер рисует макеты, верстальщик из них нарезает шаблоны, а зачем «модулям влиять на рендеринг целых классов элементов страницы вне зависимости от даже используемой темы»? Чтобы сломать чьим-то модулем готовый дизайн?
А, еще вспомнил про систему шаблонов: допустим, мы выводим на отдельной странице список разделов (используя модуль View). Каждый раздел мы хотим вывести большой красивой картинкой, а потом, внизу, еще сделать текстовый список разделов. Сделать это — нельзя! Потому что мы имеем 2 шаблона, для вывода категории и для вывода списка из отрендеренных категорий. И вывести категорию в 2 местах страницы картинкой, а потом текстовой ссылкой нельзя. Нельзя просто написать 2 раза foreach (...){} для списка категорий. По крайней мере, я не нашел как это сделать.
Если копать дальше, можно хоть каждый компонент Друпала разобрать и объяснить, почему это неправильно.
Единственное, что мне напоминает код Друпала, это код всяких CMS типа битрикс и амиро, он такой же кривой, бестолковый, и написан студентами, которые про современные архитектуры приложений и концепции только краем уха слышали.
Если мне не изменяет память, там есть шаблон для вывода отдельной ноды, и шаблон для вывода списка нод, который получает на вход HTML-код отрендеренной ноды (а не массив с данными этой ноды). Вывести одним шаблоном 2 раза список нод в разном виде (один раз картинками, другой — текстом) — невозможно. Либо я тогда что-то не нашел, либо вы меня не поняли.
По поводу ООП — вы знаете, зачем его придумали? Думаете, академикам было скучно и они решили внедрить новую концепцию программирования? ООП нужно для упорядочивания, организации кода больших проектов, над которыми работает много человек. Потому, что ООП-код подразумевает отсутствие глобальных переменных: это значит, область видимости переменной ограничены одной функцией и вам не надо гадать, в каком из 1000 файлов в эту переменную записалось что-то не подходящее. ООП позволяет разбить код на классы, и вы знаете, что в классе Database_Access не окажется кода переписывания УРЛ. Классы хранятся каждый в своем файле, файлы по папкам. У классов есть приватные функции: вы можете быть спокойными, что эту функцию из другого файла никто не вызовет, и легко найти все места ее вызова. С таким кодом действительно проще работать.
А вы мне что-то рассказываете про альтернативный подход в Друпале. Альтернативный в том, что мы сваливаем 200 функций в один файл common.inc?
И сваливаем файлы с кодом все в одну папку? Да, это скорее неумение организовать код.
Поэтому и появляются специалисты за 200 долларов в час, потому, что никто потом в этом коде разобраться не может.
Кстати, запутанный код очень трудно поддерживать и оптимизировать — возможно, поэтому никто до сих пор и не может нормально этот друпал ускорить, кроме как кешированием страниц на нгинксе.
Да и непонятно, как кешировать результаты выборки списка сущностей, и как сбрасывать этот кеш, если, например, отдельные модули могут менять на ходу как параметры запроса, так и менять что-то в результате его выполнения.
Простите, мне кажется, вы так и не поняли, что такое ORM. ORM — средство для организации хранения объектов бизнес-логики в реляционной таблице, получения этих объектов, их валидации и их получения коллекций с учетом связей между ними, а не средство выполнения SQL-запросов. То, что есть в Друпале, называется DBAL — Database Access Layer. Если там вопросики в запросе заменяются на значения параметров — это не ORM.
Вы не видите разницы между изменением схемы данных (добавление полей и валидаторов) в момент установки модуля и костылем, который на ходу при выполнении каждого запроса добавляет в массив поля? Это то же самое? По моему, нет.
Почему валидация сущности привязана к использованию формы редактирования? Какая ему, Друпалу, разница, откуда (из формы или другого источника) пришли данные? Что, нельзя провалидировать сущность, полученную не через форму редактирования?
Как я уже написал, индусы, которые этот код написали, своим ограниченным мышлением не понимают, что объекты можно создавать и без форм и участия пользователя, скриптом, например.
Они просто не могут разделить компоненту для обработки форм и пользовательского ввода от компоненты для поверки и сохранения сущностей в БД.
Ладно, я думаю, дальнейший спор уже ни к чему не приведет. Все равно я останусь при своей точке зрения, а вы при своей.
7 причин для перехода с Drupal на Yii