Кто будет использовать код?
25-03-2024Reading time ~ 9 min.PHP 816
Об этом вообще никто не говорит. Подавляющее большинство программистских проектов начинались как вещь для себя. Потом они разрастались, становились интересны другим, подключались другие прогеры. Но если кто-то думает, что популярность проекта зависит от его качества кода, то он жестоко ошибается. Качество проекта вообще никак не связано с его популярностью. Популярность проекта — прямое следствие его маркетинговой раскрутки. Чем больше вбухано денег в пиар, тем больше пользователей. Даже если его код — полный отстой. Дальше текст для 18+.
В мире программирования это приводит к забавным казусам. Есть некие базовые вещи, которые считаются истинными a priori. Например качество кода нужно оценивать как его полезность. То есть каждая строчка кода должна приближать решение задачи. Если строчка кода ничего не делает, то она не нужна. Таким образом, чем меньше нужно написать кода, чтобы решить задачу, тем лучше.
Учителя программирования (раньше, во всяком случае) предлагали решать задачу в условиях ограниченности доступной памяти и размеров файлов. Это стимулировало развивать навыки придумывания разных алгоритмов для решения одной и той же задачи. Поэтому код будет зависеть от используемого алгоритма и возможностей языка, но итоговый критерий будет включать в себя количество шагов (строк) — чем меньше, тем лучше.
Проблемы возникают, когда программисты, которые на самом деле не программисты, а пиарщики и маркетологи, занимаются не созданием качественного кода, а тупо пиарят свой продукт, как нечто особенное. По сути это говно, но если его подать красиво, то будет считаться дефлопе.
И потом возникает вторичная идея, как оправдание, что похуй на качество кода, главное, что он работает и выполняет поставленные задачи. В итоге никто даже не парится с тем, чтобы исправить ситуацию. Маркетинг заменил всё.
Если прогер начинает ориентироваться на такие продукты, то его понимание мира искажается до степени, когда он перестаёт понимать, как именно правильно писать код. Он ориентируется на популярность других проектов и создаёт у себя ложную причинно-следственную связь, что это и есть то, к чему нужно стремиться. Начинающий прогер ещё не научился понимать где хорошо, а где плохо и тупо копирует говнокод. Его аргументация проста — миллионы леммингов не могут ошибаться.
Ну а кто эти лемминги?
За многие годы работы с клиентами и другими прогерами я понял несколько важностей. Самая главная ошибка, которую я совершал, когда только стал публиковать свой код — это думать, что кто-то другой будет его читать, анализировать и предлагать усовершенствовать. Короче, я предполагал, что есть некто, кто окажется умней меня и подскажет, что именно не так в моём коде.
На самом деле такое происходило очень и очень редко. Помощь всегда приходила только тогда, когда я прямо о ней просил. Такие задачи были редки, поэтому почти весь код я писал сам, сам же его тестировал, сам же его поддерживал, изменял, улучшал.
Из этого делаем простой вывод: код, который вы пишите нужен только вам. Всем остальным на него плевать с высокой колокольни.
Как я понимаю, что начинаю говнокодить? Довольно просто. Если я вижу, что код разрастается и количество функций библиотеки начинает превышать количество функций, которыми буду реально пользоваться, то это и есть первый признак говнокода.
Например прогер решил написать свой роутинг. Начинать нужно с конца, а именно с того, как именно им будут пользоваться. Скорее всего это будет некий массив данных, где задаются регулярки для адресов. Сам же роутинг будет вызываться одной-единственной функцией и отдавать массив с результатом.
Таким образом вся библиотека формально может быть заключена в одну-единственную функцию. То есть никто из конечных пользователей никогда не будет использовать любые другие функции этой библиотеки. Следовательно, внутренне устройство библиотеки может быть написано компактно и понятно, а может быть написано по говностандартам с распухшими классами.
Это можно оценить численно. Общее кол-во функций (методы тоже считаем функциями) для решения какой-то задачи минус кол-во функций, которые будут реально востребованы конечным пользователем. Например всего 100 функций, а на выходе одна для пользователя. Итого 99 единиц говнокода.
Понятно, что нужно стремиться к нулю, хотя не всегда это возможно. В зависимости от задачи, код делится на подпрограммы, чтобы с им было удобней работать. Но опять же, если функция из одной строчки, то нахера она нужна? Таки вещи хороши для хелперов, но не для библиотек. Если функция заменяется одной строчкой на PHP, то она не нужна в принципе. Не нужно создавать суррогаты там, где язык прекрасно работает сам по себе.
При отработке задачи вначале нужно придумать функцию-пустышку, которая будет как бы выполнять эту задачу. То есть двигаемся от конечного пользователя. На начальном этапе весь код запихивается в одну функцию, если это удовлетворяет условиям использования. После того, как код заработает, можно его проанализировать и ответить на несколько вопросов.
Первый — есть ли в этой функции повторяющиеся блоки кода? Если есть и они большие и могут считаться отдельной подзадачей, то выносим её в отдельную функцию.
Второй — если участки ресурсоёмкого кода? Его лучше вынести отдельно с тем, чтобы закешировать хотя бы на уровне static-переменной.
Третий вопрос — не выполняет ли функция слишком много подзадач? Если какие из них могут использоваться в других частях проекта, то можно выделить их отдельные функции. Но если такой задачи нет, то не нужно специально дробить функцию. Есть такая тенденция, что функция не должна быть слишком длинной и нужно её ограничить, например 20-ю строками. Это дурь чистейшей воды. Хоть 1000 строк, если все они по делу.
Теперь поднимемся на уровень конечного пользователя продукта/приложения.
Поскольку речь о сайтах, то есть два основных потребителя. Первый — обычный чел, в задачу которого входит публикация материалов сайта - назовём его редактором. Второй — вебмастер, который должен настроить и напрограммировать сайт.
Для вебмастера важны готовые функции, которыми он будет решать задачи программирования. Например настройки шапки, подвала, меню и т.д. То есть достаточно утилитарные вещи и разработчик продукта должен продумать как именно это можно сделать. Если фреймворк вообще ничего не предлагает для вебмастера, то такой проект — бессмысленное говно.
Вообще проблема шаблонизации очень сложна. Я не знаю ни одного популярного php-фреймворка, который предложил бы хоть какое-то нормальное решение. Любая, даже самая тупая CMS, намного лучше в этом плане, чем голый фреймворк. Хотя фреймворк, по своему определению и должен предлагать решения подобных задач, поскольку является каркасом для других приложений/CMS. CMS по идее и должна строиться из кирпичиков (функций) фреймворка.
Другую задачу, который решает вебмастер — это создание механизма управления сайтом. Чаще всего это делается через опции, настройки или предопределённые файлы. То есть вебмастер может придумать опцию, которой сможет пользоваться редактор. Потому что опция нужна там, где есть выбор. Например, на одной странице хочу такую шапку, а на другой — другую. Ок, вебмастер делает опцию, редактор выбирает то что ему нужно.
Механизм настройки вывода страниц сайта — это обязательная часть любого полноценного фреймворка. Вебмастер не изобретает его, он им сразу пользуется на уровне готовых функций. Потому что готовые функции снимают с вебмастера сразу кучу головняка. Например как и где хранить значение опции? Можно ли в опции использовать PHP/HTML/JS-код? Может ли опция быть массивом, строкой, объектом и т.д.?
Все эти вещи должны быть заранее продуманы автором php-проекта, потому что вебмастер — это тоже конечный пользователь его кода. Чем больше возможностей проект предлагает для вебмастера, тем лучше. Понятно, мы не говорим о тупом дублировании кода, но исходим из той же формулы — чем меньше единиц невостребованного кода конечным пользователем, тем лучше.
Здесь есть ещё один важный момент — понимание того, какие задачи стоят перед вебмастером. Пара примеров.
Создание миниатюры изображений. Например все картинки удобно держать в png или jpg-формате. С ними работают все просмотрщики, вроде Fast Stone. Но для Сети удобней формат webp, с которым уже не так удобно работать. Таким образом функция миниатюры (на самом деле может быть любой размер) будет принимать исходной jpg/png-файл, но на выходе отдавать сгенерированное webp-изображение в виде готового IMG-тэга со всякими плюшками.
Другой пример, защита контента в зависимости от уровня пользователя. Скажем мы хотим скрыть часть контента. На техническом уровне это достаточно сложная задача, которая включает в себя авторизацию пользователя и проверку его уровня доступа. Если автор проекта не предусмотрит готовые решения, то вебмастер может нагородить такого... Но когда есть решение, то вебмастер будет им пользоваться, просто обратившись к документации.
При этом решение может быть разным, но критерий будет всегда одним: чем меньше кода придётся писать вебмастеру/редактору, тем лучше. Это тоже не простая задача.
У меня изначально в Albireo CMS нужно было писать что-то вроде такого:
if (!checkUserAccess(getUser(), ['reader'])) { snippet('access1'); return; }
То есть в функции проверки доступа нужно было указать уровни доступа юзера. В процессе создания сайта, выяснилось, что закрывать контент можно выборочно, хоть по каждому предложению, что делает использование такого кода неоптимальным. К тому же функция проверки явно требует указания уровня доступа, а это значит, что в случае его смены, потребуется найти все вхождения php-кода.
Теперь это так (как вариант if):
<?php if (noUserAccess(snippet: 'access1')) goto end; ?> закрытый текст, часто очень длинный <?php end: ?>
Сам же уровень доступа указывается в поле страницы:
user-level: reader, admin
То есть это не просто функция, это системный механизм, который решает поставленную задачу, но и избавляет пользователя от необходимости самостоятельно изобретать велосипед.
Теперь рассмотрим роль редактора сайта. Есть два типа людей. Большинство из них, процентов 70, изначально не готовы даже смотреть на html/php-код в тексте страниц. У меня была клиентка, которой я показал, как использовать несколько html-тэгов под её меняющиеся задачи. Через какое-то время она написала, что чувствует себя программистом. Я к тому, что со временем все они прекрасно разбираются в таких задачах, тем более, что это примитивные текстовые вставки на уровне copy/paste.
Изначальное отторжение происходит из-за страха что-то сломать или пугающей новизны. Это легко обходится простым обучением и им достаточно попробовать самостоятельно сделать несколько вставок кода, и вопросов больше не возникает. Все эти 70% чувствуют себя достаточно уверенно при наполнении сайта.
Среди разработчиков систем для сайтов господствует мнение, что пользователя нужно ограничить в возможностях. Запрещают ему использовать HTML, CSS, JS и тем более PHP код в своих текстах. Это ошибочное предположение, дескать неопытный пользователь может всё сломать, поэтому нехер совать свои руки.
На самом деле, опыт показывает, что такие пользователи, как раз очень аккуратны и очень редко что-то ломают. В 99% случаев, если они не уверены, то обращаются к вебмастеру, который уже знает что делать. Таким образом все эти ограничения бессмысленны, поскольку очень сильно ограничивают возможности страниц сайта. Это порождает ещё одну проблему: поскольку всё равно на сайте нужна возможность выполнения произвольного кода, то придумываются всякие говноподелки, вроде bbcode и многочисленных шорткодов. Всё это можно выкинуть если просто разрешить выполнять код обычному редактору и вебмастеру.
Очень часто, вместо того, чтобы пользователю разрешить использовать обычный HTML, придумывают всякие свистоперделки, которые делают этот же самый html-код, только через жопу. Обычный html-код простой и понятный и не требует излишних манипуляций руками. Но там, где это запрещено, создаётся просто гигантский пласт работ, как раз для того, чтобы обойти это ограничение. Нахуя???
Есть, конечно, мазохисты, которым нравятся таки ограничения. Вместо того, чтобы написать пару строчек кода, они будут мудохаться с разного рода визуальными построителями контента, которые всё равно сгенерируют мусорный говнокод.
Подытожим. Разраб должен думать о том, кто будет конечным пользователем его кода. Двигаться нужно от его задач и предлагать готовые решения. Сам же код нужно освобождать от говна и не стремиться подражать популярным проектам. Качественный код — это компактный код.
Слава Украине! Смерть рашистам!
Ну, є й такий варіант:
Не бажаючи зачепити оригінальний код фреймворку, кінцевий користувач буде намагатись написати свою функцію (модуль). Ймовірно, це буде неоптимально, бо порушуватиме якусь початкову архітектуру, або дублюватиме існуюче, що теж не айс.
Це, як з водіями на дорогах - професіоналів мало, але їхати потрібно всім. Тому, автор CМS або делегує, або обмежує кінцевого користувача у цьому праві, стаючи на шлях волюнтаризму. В будь-якому випадку, обмеження (або користувацькі самообмеження) завжди дратуватимуть перфекціонізм автора.
Схоже, що рішення полягає у площині доступності готових модулів-бібліотек, їх різноманітності, кількості, публічності і якості. А тут уже, без популяризації, не обійтися і маркетинг знову стане основою розвитку продукту. Годувати Уробороса прийдеться.
Так и пусть пишет свою функцию или библиотеку. Всех задач система всё равно решить не может, поэтому пользователи всегда изобретают свой велосипед. Не вижу в этом проблем.