10 принципов современной разработки на PHP

Для большинства разработчиков работа над PHP приложениями сейчас и десять лет назад отличается кардинально. В те времена многие из нас были веб-дизайнерами в чью ответственность входила не только разработка бекэнда, но и проектирование БД, системное администрирование, фронтэнд программирование, а иногда и создание UI.

За последние года картина довольно сильно изменилась. Простые сайты теперь представляют из себя целые SaaS приложения — зачем создавать очередной движок для блога, встраивать CMS или ecommerce систему, когда уже десятки разных продуктов существуют. Другими словами, всё что можно было автоматизировать уже оптимизировано. Но остается один момент не поддающийся этому процессу — нужды заказчиков.

Поэтому веб-разработчики стали специализироваться именно на тех участках, которые невозможно оптимизировать — веб-приложениях. В паре с этим пришли основные идеи корректной разработки на PHP.

10 основополагающих моментов в современной разработки на PHP

Нас часто спрашивают, как лучше проектировать приложения под нашу инфраструктуру (fortrabbit.com). Конечно существуют тысячи подходов к этому вопросу, я приведу самые часто распространенные исходя из личного опыта.

Многие применяют фреймворки как Laravel5, CakePHP3, Symfony2 и т.д.. Они уже содержат в себе стили и шаблоны проектирования. Но остаются участки на усмотрение разработчика. Так внесем же свою лепту в этом вопросе.

1. Код

Самая важная часть вашего приложения.

Управление

Следует использовать системы контроля версий. Опередим все холивары о лучшей системе и скажем сразу — используйте GIT, так как он самый распространенный.

Стиль

Придерживайтесь одного стиля: один стиль проще читать вашим коллегам, соответственно новые сотрудники легко смогут освоить ваш код. Независимо от размера команды (даже если вы один), управление кодом может занимать очень много времени (соответственно и денег), а хорошо отформатированный и задокументированный код снижает эти затраты. В конце концов, такой код просто приятно читать.

Открытый исходный код

Открывать исходный код вашего приложения (или его модулей) может очень положительно сказаться: бесплатная помощь в разработке, бесплатная реклама вас как разработчика или вашей компании, да и самого сообщества, работающего над проектом. Опять же вернемся к GIT, применение редкой системы контроля версий ведет к высокому порогу вхождения новых участников проекта.

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

2. Тесты

Автоматическое тестирование всегда отставало в PHP по сравнению с другими языками программирования. Но, к счастью, ситуация изменилась в лучшую сторону. Мнение, что написание тестов удваивает затраченное время, практически искоренено, и добавление нового функционала стало немыслимо без соответствующего теста.

Хорошо покрытое тестами приложение даёт ряд преимуществ. Вот список моих трех любимых:

  • Рефакторинг такого ПО значительно проще
  • Юнит тестирование подталкивает вас использовать модульный стиль (увеличивает повторное использование кода)
  • Тесты предоставляют не только примеры кода, но и документацию к нему

Конечно список преимуществ на этом не заканчивается, но для меня идея такова: лучше код — меньше проблем.

3. Зависимости

Зависимостями однозначно должен управлять Composer. Так как код очень тесно связан с определенными библиотеками и их версиями, то заявленные зависимости (composer.lock) должен также находится в GIT.

Каталог с зависимостями (vendor) не должен быть в GIT, так как их версиями уже управляет другой файл, который уже в GIT. Поэтому два раза добавлять в репозиторий одно и то же смысла нет.

Модульность

Применение сторонних библиотек подталкивает вас к модульному написанию собственного приложения. Как следствие — меньше повторного кода, меньше трудозатрат и повышение качества кода. И не забывайте о раскрытии исходного кода этих модулей.

4. Настройки

Некорректное хранение настроек приложения — немалая головная боль при переносе приложения, да к тому же и немалый риск в плане безопасности.

Разделение кода и настроек

Лучший вариант — использование сред. Под средами я подразумеваю переменные среды ОС, но локальные файлы настроек тоже отличный вариант, если их внедрение четко описано.

Главное правило, которое помогает определить полностью ли отделен ваш код от настроек, это ответ на вопрос: “Сможете ли вы показать свой код, не показав значения настроек?”. Если вы ответили “Да”, то все отлично.

Плохо: где нибудь в config.inc.php:

$database = "foobar";
$user     = "foobar";
$password = "foobar";

Хорошо: переменные среды Apache, SetEnv и подобные:

// $_SERVER["DB_NAME"];
// $_SERVER["DB_USER"];
// $_SERVER["DB_PASSWORD"];

Сложные настройки

Переменные среды могут содержать сложные данные (многоуровневые массивы). Их следует перевести в JSON, закодировать в base 64 и сохранить в БД. Таким образом вы сможете легко их читать и изменять вне приложения.

// somewhere in the bootstrap, assuming all encoded variables are prefixed with "::"..
foreach ($_SERVER as $k => $v) {
   if (0 === strpos($v, "::")) {
       $_SERVER[$k] = json_decode(base64_decode(substr($v, 2)));
   }
}

5. Статические ресурсы

Над такими ресурсами как (скомпилированные) CSS, Javascript, изображения и так далее, нужно задуматься. Но отвечу сразу — храните их в системе контроля версий.

Развернутый ответ: компиляция CSS и Javascript или создание изменённых изображений само по себе требует разных инструментов, которые в свою очередь тянут за собой новые зависимости (представьте себе компилятор node расширения, который ужимает изображения при помощи magick или Java приложение для компиляции CSS…). Все это неоправданно усложняет процесс размещения приложения. А потом еще вспомним про распределение ответственности. Такими ресурсами, как правило, заведуют фронтэнд разработчики. У каждого из них свой набор инструментов, к которому они привыкли. А компиляции ресурсов при размещении приложения ограничит их в использовании своих любимых инструментов.

Более глубокие размышления на тему доступны в недавней статье Френка.

6. Данные во время работы программы

Под такими данными я подразумеваю файлы (не БД), которые генерируются во время работы с пользователем. Как правило их хранят на отдельном сетевом файловом хранилище.

Я бы порекомендовал облачные хранилища (S3, Cloud Files, Cloud Storage…), так как они: берут на себя проблемы мастабируемости, (масштабируют приложение между несколькими серверами или странами), избавляют от возможных проблем с переносом приложения (синхронизация данных), балансируют нагрузку между выполнением (PHP скриптов) и отдачей (файлов).

7. Ресурсы

Ресурсы приложения — все службы, которое оно использует, а именно БД, кеширование, очереди, вышеупомянутые хранилища, почтовые службы и так далее.

Абстрагирование

Доступ к ресурсам должен быть абстрагированным. Степень абстракции зависит от ваших будущих планов (планируете ли вы масштабировать приложение, если да, то следует применить адаптер для локальных ресурсов, который потом можно будет заменить на сетевой адаптер). Абстрагировать систему кеширования легко, что не скажешь о замене MySQL на ElasticSearch, поэтому применение шаблона репозиторий, поможет разрешить эту проблему. Размещение ресурсов должно указываться в настройках приложения.

Плохо:

$conn = new mysqli($servername, $username, $password);

Код слишком тесно связан с определенным драйвером MySQL. Если вдруг драйвер перестанет быть доступным или вы не сможете использовать MySQL, то вам придется переписывать код.

Хорошо:

use Illuminate\Database\Capsule\Manager;
// $_SERVER['DATABASE'] = ["host" => "localhost", ...]
$mgr = new Manager->addConnection($_SERVER['DATABASE']);

Легко использовать разные БД, изменить местоположение БД сервера также просто.

Слабое связывание

Все службы, без которых приложение может работать должны легко отключаться. Допустим, почтовая служба используется для приветствия новых пользователей: вы должны иметь возможность отключить её при помощи одной команды, в случае если поставщик службы перестанет работать. А еще лучше автоматизировать такое отключение. Самый лучшый вариант — создать очередь запросов, которая будет пытаться заново соединиться с почтовой службой.

8. Размещение приложения

Нет ничего более проблемного и опасного в ПО, чем большие обновления. Обновляйтесь заранее и часто — такой принцип убережёт вас от масштабных обновлений. В результате процесс размещения приложения на сервере будет легок, прозрачен и быстр.

Высокое качество кода, тестирование и абстрагирование в итоге сказываются положительно на долгосрочной перспективе, а это упрощает вашу повседневную работу.

9. Ступень развития приложения

Конечно автоматическое тестирование — это фундамент хорошего приложения, но место для ошибки всегда остается. Тут и появляется понятие об этапах разработки приложения. Рабочее приложения на локальной машине (development) — первая этап разработки. Другая стадия разработки — рабочий режим приложения (production). А между ними большая пропасть, в которой есть место тестированию, рецензированию, да и много чему еще.

В целом, все стадии должно по максимуму приближать стадии рабочего режима. Чем больше они от нее удаляются, тем меньше смысла в их создании.

Количество этапов зависит от размера приложения, команды, типа приложения и так далее. В этой статье вы найдете более подробное описание этого процесса. Я рекомендую применять три этапа: локальный (development), продуктовый (production) и, конечно же этап тестирования (testing).

10. Масштабируемость

Наверняка вас уже не раз называли DevOp. Что означает: при разработке надо учитывать технические возможности оборудования, на котором будет работать приложения, чтобы не бороться с недостатками, а использовать преимущества.

Конечно, это недостаток облачный инфраструктур. Ранее: все что вы делали, да и могли сделать это вертикально масштабировать свою машину — чем больше сервер, тем лучше. Вы не задумывались об узких местах работы, так как существовало только одно решение. А теперь вы не только можете горизонтально масштабировать ресурсы, но и делать это для каждого отдельного ресурса, а следовательно надо понимать, что именно замедляет работу приложения. Или что вы можете сделать чтобы компенсировать это замедление. А что еще важнее — понимать какой еще ресурс можно подключить для повышения работоспособности. В общем, у вас появился доступ к красной кнопке, а соответственно и ответственность за свои решения.

Заключение

Все стало намного сложнее: надо знать шаблоны проектирования, стратегии размещения, тестирования и дизайна приложения. Но есть и то, что упростилось: ряд новых инструментов, улучшились службы, а стандарты кода упрощают поддержку как никогда. Искусство написания PHP кода изменилось. Сильно. И процесс стал интересным как никогда.

Что дальше?

При написании статей о современной разработке приложений в облачной среде, стоит помнить о 12-ти факторах приложения Адама Виггинса. Они раскрывают весь дизайн и жизненный цикл современного приложения. Кори МакМахон написал отличную серию из трех статей о том, как применить это 12 факторов.

С точки зрения чистого PHP я готов подписаться под некоторыми абстрактными идеями базового подхода. В целом, я считаю, что область их документа переходит границы того, о чем должен задумываться разработчик.