Эта история началась с комментария к моей статье на Хабре. Точнее, с части этого комментария:
«Попробуйте постройте приложение уровня и функционала WordPress — и оно точно так же будет задыхаться от наплыва пользователей»
Я посчитал это аргументом в стиле «сперва добейся» и, в общем, прошел мимо. Но некоторое время спустя звезды сложились совершенно неожиданным образом. Во-первых, я лишился основного источника дохода. Во-вторых, после недели судорожных метаний я решил прекратить это занятие и отвлечься на что-нибудь постороннее. Где-нибудь на неделю. Растущие бюджетные дыры и случайная простуда решительно сократили список возможных развлечений.
Сначала я попробовал игры. Но то ли я стал староват, то ли игры пошли не те — уже под вечер первого дня я ходил по квартире и с мрачным лицом подкидывал под потолок мячик. И тут я почему-то вспомнил про этот комментарий. И про то, что всегда хотел попробовать написать собственную простую CMS.
Вот так сошлись звезды. А результаты этого моего эксперимента — в статье.
Расстановка акцентов
Почему CMS. Потому, что CMS — это одна из первых вещей, которые встречает начинающий сайтостроитель, сразу после того, как изучает основы HTML, CSS и JS. А иногда даже до. Во-вторых, потому, что все, кто имеет дело с CMS достаточно регулярно, получают объективный или субъективный повод их ненавидеть. И у многих из них рождается мысль, что он мог бы сделать лучше. Это как детская мечта «вырасту и стану пожарным». Я к таким вещам отношусь довольно трепетно.
Актуальность CMS. Некоторые упорно хоронят CMS как класс продуктов. Я не согласен. Во многих случаях по совокупности условий CMS все еще являются оптимальным решением. Например, при старте бизнеса, для личных нужд и т.д. Мне кажется, что этот класс решений будет жить еще довольно долго, т.к. у него есть вполне конкретная целевая аудитория, которая не собирается никуда пропадать. Я даже почти готов поспорить на последние штаны, что самые распространенные CMS переживут многие шибко модные нынче фреймворки и иже с ними.
Качество моего кода. О, это больной вопрос. Я — веб-разработчик-любитель. Не более того. Мое призвание (и основное занятие) — придумывать разные штуки. И (часто) реализовывать их в виде MVP. Мне нравится искать общие решения проблем, придумывать полезные (или просто забавные) вещи и приложения, собирать и анализировать информацию и т.п. Высокопрофессиональные решения я оставляю узкоспециализированным специалистам. Главное, чего я пытаюсь добиться, это чтобы дорогое и очень правильно сделанное решение не оказалось вдруг абсолютно бесполезным. Обычно, в этих рамках, у меня все неплохо получается. Но последний проект кончился полнейшим фиаско и вверг меня в финансовую яму. И моей вины в этом достаточно много. Многие из тех, кто захочет пнуть меня за быдлокод будут правы. И мне будет стыдно за свое невежество, из-за которого я не смог сделать все проще, быстрее и правильнее. Или вообще ошибся. И тут следующий пункт.
Просто важно. Хотелось бы, чтобы читающие эту статью понимали: перед вами не готовый, протестированный продукт. Это просто работающая модель. Сделанная для проверки тех концепций, которые были у меня в голове. Думаю, большинство согласится, что шесть дней — это очень немного для создания такой сложной штуки как CMS. Тут необходимо отметить, что документацию я писал еще неделю урывками. Честно говоря, это стало невероятно сложным для меня процессом. Только мое ослиное упрямство дало возможность довести эту работу до хотя бы промежуточного итога. Которым я остался недоволен: документация получилась слишком длинной и не такой простой и понятной, как мне хотелось. А именно она должна была стать одним из ключевых моментов проекта: документация должна быть максимально полной и при этом емкой. Так, чтобы после пары часов у читающего было практически полное понимание механизма работы системы и минимум «непоняток». В общем, за эту часть я ставлю себе «неуд.». Если я все-таки решу продолжать заниматься этим проектом, то сразу после войны с багами и бредом в коде я бы занялся переосмыслением подхода к написанию документации.
О багах. Они, несомненно, присутствуют. Возможно, очень серьезные. Если вы хотите помочь мне — напишите письмо на почту (она есть на сайте проекта). Это самый верный и удобный для меня способ коммуникации.
Маленькое лирическое отступление
Очень давно я был геофизиком. Занимался интерпретацией геофизических данных. Для этих целей в то время существовало некоторое количество специализированного ПО. И оно было жутковатым: написанные разными людьми части, костыли, модули, которые отдают данные в разных странных форматах, модули конвертации данных для предыдущих модулей… При этом все это стоило весьма существенных денег. И все равно достаточно часто отваливалось, падало, делало странные вещи и вообще требовало квалифицированной тех. поддержки за отдельные деньги. В результате половина времени уходила на сражения с «особенностями» системы и перепроверку результатов. И тут мне в попалась отечественная разработка на ту же тему. Простая и понятная как калькулятор, да еще и с нейронными сетями из коробки. Да, она не умела так красиво выводить карты и не имела пары ультрамодных в те времена вещей, а «нейронные сети» были более чем примитивными. Но для простых рутинных операций и проверки гипотез это был клад: устанавливалась эта штука на любой компьютер с Windows, крайне редко падала и шустро работала. Не знаю, какова была дальнейшая судьба продукта, но он сберег мне в свое время массу времени и нервов. Вот так я полюбил простые и цельные решения.
Размышления
Прежде чем что-то делать, почти всегда стоит подумать. Иногда из этого может выйти что-то толковое. Именно размышлениями я и занялся вначале.
Зачем вообще нужны CMS? Они упрощают процесс разработки сайта и его использования. Конечные пользователи (под ними, здесь и далее, я подразумеваю администраторов сайта, контент-менеджеров, а не посетителей сайта) получают дружественный интерфейс для управления данными, использование которого не требует больших знаний и умений. Разработчик получает готовые решения базовых задач, которые позволяют сделать получение результата в разы быстрее, чем если он будет заниматься их самостоятельной реализацией «с нуля». При этом готовые решения тестируются и развиваются, что резко снижает вероятность критических ошибок. Использование популярных решений дает еще одну важную возможность: владелец сайта (теоритически) всегда может найти разработчика, который решит его проблему. Это упрощает поддержку проекта и не привязывает его к кому-то конкретному и незаменимому.
Все это было бы прекрасно, если бы работало именно так. На практике, часто выходит иначе. Давайте пробежимся по основным пунктам.
Простота и интуитивность для конечного пользователя. Некоторое время назад я провел небольшой эксперимент. Группе из шести человек я предложил попробовать себя в роли контент-менеджера двух сайтов: интернет-магазина на базе «Битрикс» и блога на WordPress. В группе были довольно разные люди: моя мама, геолог, танцовщица, гитарный мастер, журналист и таксист. Каждому было предложено простое задание: добавить товар в интернет-магазине и статью в блоге. Сначала это нужно было попытаться сделать самостоятельно (после краткого общего инструктажа), а потом — по подробной инструкции. Результат был такой: самостоятельно абсолютно правильный результат достичь не смог никто; с инструкцией ошибок стало меньше, но они все равно были. В плане «дружественности» с точки зрения группы победил WordPress. В общем, «интуитивность», «понятность» и «дружелюбность» для конечных пользователей — это, по большей части, мечты маркетологов и идеологов того или иного решения. В реальности эти параметры находятся на довольно среднем уровне, а для осознанного использования все-таки требуется определенная подготовка. По крайней мере, это относится к CMS, которые я видел или активно использовал. Где-то с этим лучше, где-то хуже.
Быстрота получения результата разработки. Этот пункт обычно отлично работает пока речь идет об установке готового шаблона и пары готовых расширений. Т.е. об абсолютно стандартном сайте в вакууме. Но, как правило, требуется что-то более сложное. Хотя бы правка этого стандартного шаблона. И тут обычно начинается ковыряние в файлах с кусками кода этого шаблона, логики его вывода и т.д. Ситуация усугубляется наличием десятков, а то и сотен предопределенных разработчиками конкретной CMS функций (методов, классов, констант и т.д) с непроизносимыми названиями. Изначальная идея этих конструкций, несомненно, была благой: «вызови в коде вот эту функцию и получи отличный результат одной строчкой кода и, заодно, застрахуй себя от выстрела в ногу/друга/кактус». Но я считаю их злом. По крайней мере такой вариант их применения, который вижу сейчас в большинстве CMS: количество таких конструкций постоянно растет, растет и их собственная сложность. Все это подается под соусом «универсальности». Но, на самом деле, создает массивный, уникальный для данной конкретной системы промежуточный слой. Который необходимо изучать, на что уходит значительное количество времени. Когда я вижу целые книги или платные курсы по CMS, мне становится как-то грустно. Но самое интересное начинается, когда оказывается, что для реализации необходимого функционала разработчики CMS пока не придумали готового решения. Начинается время костылей, которые чреваты проблемами т.к. часто делаются без особого понимания внутреннего устройства системы. Конечно, со временем, у разработчика растет опыт использования системы, многие вещи становятся проще, понятнее, привычнее. Но есть и обратная сторона: многие привязываются к конкретным CMS и не хотят изучать что-то другое. Потому, что помнят мучения с уже изученной. Это иногда рождает очень странные решения, когда CMS применяются для очевидно несвойственных им целей. Но, экономия времени все равно существенна: красивая панель управления уже есть в комплекте, а управление данными более-менее организовано.
Качество результата. Если все было сделано «по учебнику» для данной CMS и без случаев использования «костылей» из предыдущего пункта, то качество результата будет примерно равно качеству самой CMS. Тут все зависит от конкретной CMS. Чаще всего у меня возникают вопросы к производительности. Прежде всего, к потребляемым ресурсам и времени отдачи страницы. Когда я вижу отдельные, более дорогие, хостинг-решения для конкретных CMS, мне опять становится немного грустно.
Отсутствие привязанности к конкретной команде разработчиков и относительно низкие требования к квалификации разработчиков. Это, наверное, одно из главных преимуществ популярных решений: первый разработчик решил стать менеджером, ушел в запой или женился? Нет проблем, найдем другого! В реальности, все, конечно, не так просто. Несколько месяцев назад я наблюдал такую картину: на одном проекте решили сменить команду разработчиков на запущенном проекте. Один «золотой партнер» заменил другого. Думаете, все прошло гладко? Нет. Три недели проект штормило: сроки запланированных работ срывались, постоянно что-то отваливалось или работало не так, как надо. Часто CMS столь огромны, монструозны и необъятны, что даже в очень средний по сложности проект невозможно быстро вникнуть и продолжить чужую работу без особых потерь времени и нервов. Справедливости ради, надо отметить, что в примере выше виноват в ситуации был менеджмент, его амбиции и крайне слабое понимание технической части.
Думаю, многие согласятся, что работать с инструментом, чье внутреннее устройство просто и понятно гораздо комфортнее, чем работать с «черным ящиком» (я не имею в виду бортовой самописец). За довольно долгое время рабочего общения с разными веб-разработчиками у меня сложилось впечатление, что достаточно многие из них (в том числе и те, что работают в коммерческих студиях) работают именно так: знает, что и где можно «положить» в CMS и что получится на выходе. Но не всегда точно знают, как именно получается этот результат.
Если резюмировать, то я считаю, что все те CMS с которыми мне приходилось иметь дело, сами по себе неоправданно сложны по сравнению со сложностью решаемых ими задач. И мне это не нравится. Я хотел бы более простое решение, желательно без потери универсальности и с максимальным контролем над происходящим внутри. Конечно, пока это просто мечты, которые подобны разновидности салфеток. Пора переходить к каким-то решениям.
Решения
Вначале — еще одно небольшое лирическое отступление. О том, что меня раздражает. Это, скорее, чистая «вкусовщина», но она повлияла на конечный вид решения. Итак, меня раздражают дистрибутивы по 40 000 файлов и каталогов, некоторые из которых имеют уровень вложенности больше 10. Я чувствую тошноту, когда вижу 2 000 строчек шаблона, представляющего из себя месиво HTML и PHP, которые занимаются выводом относительно небольшой части страницы. У меня неприятные ощущения, когда HTML-тег открывается в одном файле с таким месивом, а закрывается где-то в другом. И когда таких файлов больше трех, мне становится хуже. Не меньший дискомфорт доставляют PHP-файлы, которые содержат в себе (без явной на то необходимости) HTML-разметку или ничего, кроме списка include’ов.
А теперь к, собственно, решениям. Напомню, что я решил поднять флаг максимальной простоты. Первое решение — разделить разработчиков и конечных пользователей. Разработчик — это тот, кто более-менее владеет основным стеком веб-технологий: PHP, HTML, CSS, JavaScript, MySQL. Конечный пользователь — это тот, кто будет пользоваться уже готовым продуктом и чье владение вышеупомянутым стеком может быть любым, начиная с нуля.
Многие CMS продолжают заигрывать с конечными пользователями фразами вроде «вам не понадобится программист, чтобы создать сайт!». Да, иногда, для некоторой категории пользователей, это очень полезно. Но сайты становятся сложнее, требования к ним повышаются. И если речь идет о проекте с хоть какими-то амбициями, то на каком-то этапе программист обязательно появится. Для всех остальных есть, например, Wix (гадость). У такого заигрывания есть обратная сторона: в системе появляется масса кнопок, настроек и т.п. Все это должно где-то храниться и как-то работать, что означает новые таблицы в БД, файлы в дистрибутиве и общее усложнение системы. А общее усложнение системы приближает ее к состоянию «черного ящика», и т.д. Поэтому в RushCMS (так я назвал свой эксперимент) всего этого просто не будет.
Следующий удар будет нанесен по предопределенным конструкциям. Большинство популярных готовых CMS используют все тот же вышеупомянутый стек технологий. На базе которого и реализуется большинство предопределенных конструкций. Когда я смотрю в руководство разработчика Битрикс, то у меня создается впечатление, что методов, классов и функций там больше, чем в самом PHP. Конечно, без предопределенных конструкций обойтись не удастся. Иначе просто произойдет полный возврат к «самописной CMS на чистом PHP». Но их количество необходимо минимизировать: оставляем несколько служебных функций (авторизация и некоторые другие) и фиксированную структуру файлов и каталогов — разработчик всегда должен точно знать, где что искать. PHP и HTML должны быть разделены. От всех предопределенных функций вывода отказываемся. Никаких больше get_posts().
Как же тогда выводить данные? Давайте предположим, что вам за 20 минут объяснят, как хранятся данные в БД и в файловой системе. Так, чтобы у вас не было сомнений, что, где, как и для чего хранится. Сколько времени у вас уйдет на составление SQL-запроса и написание PHP-кода, которые вернут вам все записи типа «Статья блога» начинающиеся на букву «А», в названии которых нет слова «Вася» и отсортированные по дате добавления? Наверное, немного. Выводить результаты будем с помощью простого шаблонизатора. И да, пусть шаблоном вывода будет один файл. Нет, конечно, можно разделить его на несколько. Но разве кого-то испугает длинный, но «читабельный» файл, после «простыней» из смеси HTML и PHP? Тем более, что, например, шаблон сайта-примера (включен в дистрибутив) не такой и длинный: если убрать все пустые строки, он умещается примерно в 200 строк. Логика для его обработки умещается примерно в 220 строк (с пустыми строками). При этом, сайт-пример — это очень маленький, но почти настоящий интернет-магазин. Добавим сюда очень простую (хотя, конечно, не идеальную) систему кэширования «из коробки», механизм действия которой объясняется за 15 минут и которую можно отключать.
Но, конечно, CMS затевается в еще и ради конечного пользователя и его красивой панели управления. Самым простым решением будет дать конечному пользователю редактор БД. Не спешите смеяться, это важная отправная точка.
Потому как однажды я так и сделал. Задача была очень простая: изредка менять значение одного поля с 1 на 0 и наоборот, что обычно делал я (это было временное решение, честно). Но в какой-то момент мне нужно было срочно уехать. Я оставил простую инструкцию секретарю босса и улетел в ночь. Когда я вернулся, меня ждал сюрприз: были случайно изменены значения совершенно других полей этой таблицы. Рука секретаря дрогнула!
Итак, как показывает практика, дать неподготовленному человеку в руки редактор БД — плохая, очень плохая идея. Но давайте разберем, почему именно она так плоха. И, заодно, представим, что можем менять характеристики редактора БД силой мысли.
Во-первых, пользователя пугает и заставляет делать ошибки обилие лишней информации. Пусть наш воображаемый редактор БД получит возможность устанавливать права на просмотр и редактирование полей в таблицах. И, заодно, научится устанавливать такие же права на сами записи в таблицах БД. Теперь бы секретарь из моего примера выше смог бы редактировать только один тип поля и только для нужных записей. Скрываем от него все поля, кроме, например, поля с названием записи и поля, в которое он должен вносить значения. Редактировать он может только последнее. Идем чуть дальше и добавляем возможность проверки введенных данных. Чтобы он не мог случайно записать «2» или «Ы» вместо положенных 1 или 0. Теперь шанс на ошибку минимален. Переносим наш редактор БД в браузер. Как известно, среднестатистический пользователь не любит представление данных в виде таблиц и не понимает его. Вводим в структуру таблиц служебные поля для хранения данных об иерархии записей. Заставляем редактор выводить записи таблиц в виде привычных всем «файлов» и «папок», а значение полей — как их «свойства». Добавляем возможность присваивать нашим «свойствам» человекопонятные псевдонимы. Например, «Наличие на складе» вместо непонятного data_available. Конечно, пользователь предпочитает ставить галочки вместо ввода нулей и единиц в текстовые поля. А работа в духе «загрузи файл по FTP в этот каталог и введи название файла в это поле» — это совсем плохо. Поэтому добавляем в наш редактор возможность назначать «свойствам» js-обработчик, которые выведут данные так, как это нравится пользователю. Добавляем возможность назначать разные обработчики на одно и то же поле разным группам пользователей и возможность назначать права на добавление/удаление «файлов» и «папок». Т.е. записей. Конечно, некоторые данные необходимо обрабатывать на стороне сервера: расшифровывать зашифрованное или, например, осуществлять некоторую дополнительную логику, скрытую от пользователя. Например, пользователь поставил свою галочку «нет в наличии», а в таблице изменилось не только значение соответствующего поля, но и еще какое-нибудь связанное логикой значение. Или на почту нач.склада ушло гневное письмо. Что угодно. Для всего этого добавляем возможность реализации логики обработки событий на стороне сервера.
Именно таким сильно упрощенным и настраиваемым редактором таблиц БД и является RushCMS. Точнее, ее главный (и единственный функциональный) «модуль». Задача разработчика — настроить логику, назначить полям псевдонимы и обработчики, определить права и отдать конечному пользователю. Все относительно немногочисленные настройки хранятся в служебных файлах. В БД оригинального дистрибутива — только данные относящиеся непосредственно к сайту. У сайта-примера (тот самый мини-магазин) в БД три таблицы: для хранения данных страниц сайта, пользователей и заказов. Все три имеют простую и однотипную структуру.
Вот, как это выглядит (дизайнер я совсем плохой, особенно если приходится заниматься дизайном быстро) для конечного пользователя из группы «Контент-менеджеры» сейчас:
Запутаться, как мне кажется, довольно сложно. Мне не удалось протестировать этот прототип на той же контрольной группе о которой писал выше. Только на четырех из шести. С тем же заданием. Все справились лучше, ошибок было меньше. Это, конечно, не слишком научный эксперимент, но все-таки.
Конечно, процесс настройки рабочего окружения имеет свои сложности. Это, наверное, самая непростая часть всего процесса работы с RushCMS. Но, в сегменте где используются CMS, много типовых задач. И решив их один раз можно достаточно легко использовать наработки повторно. Так что это не должно стать большой проблемой. Написание собственных обработчиков для полей тоже не слишком сложная задача. Как мне кажется, общий результат получился достаточно универсальным и простым.
Мои 5 копеек про Open Source
А тут я немного погрущу и поною. Простите меня. До этого момента мое участие в Open Source заключалось в пожертвованиях десятку проектов без известных мне серьезных спонсоров, результатами работы которых я регулярно пользуюсь. Я «заносил» им в среднем по 2$ в месяц. Кроме того, изредка я писал баг-репорты и еще реже пытался что-то предложить авторам на GitHub.
Пару-тройку месяцев назад Хабре вышла статья «Так почему же ты не участвуешь в разработке Open Source программного обеспечения?». Когда я на нее наткнулся, там уже было много комментариев и я не стал встревать, тем более, что большую часть того, что я хотел сказать, уже было сказано другими. Теперь, когда я решил выложить свой почти случайный пет-проект, вставлю здесь свои пять копеек.
Многие мои знакомые (чаще всего те, кто лишь косвенно имеет отношение к IT, но при этом так или иначе используют OS-проекты) ставят знак равенства между Open Source и такими понятиями как «бесплатный» и «не нацеленный на получение выгоды». Что, конечно, в корне не верно. Однако это достаточно широко распространенное заблуждение играет против Open Source. Значительная часть аудитории считает их авторов чудаками, готовыми жертвовать материальными благами во имя идеалов человечества. Такие, несомненно, есть. Но их не так много. Большинство OS-проектов, как мне кажется, похожи на стартапы и делаются в ожидании некоторой выгоды. Если даже и не прямой, то хотя бы косвенной: поддержка пользователей, спонсорство, платная поддержка, рост репутации и т.п. Оба эти явления мне кажутся похожими: все начинается с приступа энтузиазма, когда все делается просто из желания реализовать идею и посмотреть, что получится и продолжается уже рутинными процессами: доработка, поддержка, обработка фидбэка и т.д. Но рутина всегда подтачивает любую мотивацию. Если мотивация не подпитывается какой-то отдачей, то проект постепенно погибает. Как только мотивация иссякает полностью, проект оказывается на кладбище. Даже если он при этом остается полезным и востребованным. Есть такие «зомби-проекты», которые мертвы, но все еще ходят.
По опыту нескольких своих знакомых я знаю, что на пользовательский донат (особенно в России) может прожить, в лучшем случае, кактус (или стример игр). Спонсоры — редкое явление, для получения прочих выгод проект должен быть очень большим и востребованным. Причины массового появления стартапов и OS-проектов — радужные перспективы, которые рисуются в голове, причины кончины — то, что эти перспективы слишком долгое время не желают становиться реальностью.
Пока я игрался с этой статьей и ее предметом, мне было весело. Положительные эмоции и неподдельный интерес к процессу в некотором смысле окупают затраченное время. С другой стороны, дыхание рутины уже вполне ощущалось, когда я пытался написать более-менее полную и внятную документацию. Я никогда не был в этом силен и, повторюсь, это далось мне тяжело. В этот момент я просто ради интереса я прикинул, сколько времени у меня бы уходило на поддержку этого проекта, если бы я решил серьезно его развивать. Получается минимум один день в неделю. Полный. Потому как идея делать что-то подобное по часу после основной работы — утопия. Я проверял, пусть и не на OS-проектах. Можно, конечно, каждый рабочий (т.е. посвященный добыче денег) день перерабатывать час, освобождая себе один день. Но не факт, что эта схема окажется удачной: все равно получается дополнительная неоплачиваемая нагрузка, а основная работа редко позволяет реализовать такой подход в принципе. А получить со стандартных источников доходов OS-проектов сумму, которая будет компенсировать этот один день — задача, как мне кажется, из области ненаучной фантастики. Немного все это грустно, конечно.
И ладно мое развлечение. Но сколько действительно классных проектов погибает. По моему, в мире Open Source пока все существует по принципу «лучше, чем ничего».
Заключение
Несмотря на минорный предыдущий раздел, я, конечно, еще какое-то время поиграюсь со своей моделью. Думаю, у многих была эта навязчивая мысль: «хочу написать свою CMS». Практически детская мечта. Я теперь могу сказать себе: «о да, я попробовал ее осуществить. Так, как мог, но попробовал». И мне чертовски приятно где-то внутри. Я все равно буду улыбаться. Всем добра и отличной весны, друзья.
Ссылка на проект на GitHub, там все есть.
Автор: boilroom