«Построение свободно-масштабируемых веб-приложений» Максим Мирошниченко WebProduction
«Построение свободно-масштабируемыхвеб-приложений»
Максим МирошниченкоWebProduction
Масштабированиене означает, что будет ООП или АОП.
Масштабированиене означает, что разработчик может
сделать «всё» в своем проекте.
Разработчик и так может сделать всё в своем проекте.Разработчик всегда знает баги своей программы.
Но разработчик масштабные изменения воспринимает негативно.
Масштабированиеподразумевает легкость изменений и
корректировок в проекте.
Не стоит бояться, если нужно внести крупные правки в API, базу данных, сервисы проекта. Опыт будет полезным, он научит думать абстрактнее.
Опыт научить решать проблемы клиентов, а не разработчиков.
Это касается и дизайнеров, и верстальщиков, и программистов.
Что-такое свободное масштабирование для web?
Чего всем хотелось бы? И насколько это реально? :-)
Хорошее масштабирование — когда есть возможность быстро и красиво
подключить уже готовое решение к вашему текущему проекту.
Проблема fork’a
Задача: нужно создать форум.Default-решение: скачиваете phpBB/SMF/IPB/... и разворачиваете его в директорию /forum/.Проблема №1: вышло обновление — нужно сделать ручной update.Проблема №2: customize форума приводит к тяжести update’a.
Корень проблемы: делается fork (копируется код без обратной связи).
Правильное решение: расширять форум, не меняя его кода. Например, наследоваться, конфигурироваться, создавать свои шаблоны.
Проблема fork’a
Задача: начинаем новый проект.Default-решение: разворачиваете свои старые наработки или сторонние движки/CMS/frameworks (Joomla, Drupal, WordPress, ...), делаете default-install, получаете demo-решение, модифицируете его в свой проект.Проблема №1: движок никогда не получит обновления автоматически.Проблема №2: через время N вы fork’ните текущий проект и он станет основой для следующего. Получится два проекта, которые нужно поддерживать. Вы тратите больше времени на copy-paste.
Корень проблемы: делается fork, а не агрегация.
Правильное решение: для большинства доступных OpenSource-движков — в принципе невозможно.
Что всем хотелось бы?
Пример 1. Нужно создать новый проект, который отличается, например, только дизайном и наличием блога. Вы делаете связь (агрегацию) с вашим готовым проектом и расширяете его до необходимого уровня.
Пример 2. Программистам хочется написать «подключить систему авторизации и регистрации с проекта X», а не делать copy-paste.
Пример 3. Верстальщикам хочется написать «подключить CSS-стили такие-то с проекта Y», а не делать copy-paste.
Пример 4. Всем хочется исправить баг, сделать улучшение в одном месте проекта, и чтобы изменения автоматически разошлись по всем «дочерним» проектам. А не copy-paste :-)
Пишите повторяемый код?
Все так говорят. Но никто не говорит «как его писать» и «как его применить».
А у разработчиков одни и те же проблемы: как назвать директорию для классов, как назвать класс, почему именно так, как
организовать структуру директорий проекта...
Пишите пакетами
Пакет — это всего-лишь группировка кода.В большинстве языков — это группировка классов.
Но можно пойти дальше:группировка классов, функций, CSS-стилей, JavaScript-решений, ...
Даже если в языке нет пакетов, их можно имитировать директориями.
MyProject
1. Определитесь, как другие проекты смогут подключить MyProject.MyProject/include.*
2. Определитесь, как смогут взаимодействовать с MyProject.Для разработчиков должна быть точка старта, например:MyProject::..., MyProject::Initialize()MyProject::Get()->...
3. Какие зависимости MyProject может за собой понянуть.Например, MyProject требует Smarty. Не стоит делать include(<path-to-smarty>). Лучше используйте свой загузчик.
Стиль кода спасает от объяснений
/MailUtils//MailUtils/include.php/MailUtils/MailUtils.class.php/MailUtils/MailUtils_Sender.class.php/MailUtils/MailUtils_SmartySender.class.php/...
1. Разработчик знает, что подключить пакет можно только одним способом — include.php в директории пакета. Не давайте права выбора.
2. Подключая MailUtils разработчик подразумевает, что есть класс MailUtils с которого все начинается, а IDE все подскажет по Ctrl+Space.
Cамое важное —любой проект это такой-же пакет.
У него должна быть единая система подключения (include), инициализации, все классы/функции/css-стили должны начинаться одинаково.
MyProject_<Class>myproject_<function>myproject_<css-selector>...
Следуя таким простым правилам, можно в будущем вкладывать проект в проект.Возможно, то что вы сейчас делаете, завтра станет основой для чего-то другого, а никому не нужны конфликты с переимнованием файлов, классов, стилей.
Магические абсолютные пути
Все подключения в проекте должны быть построены на абсолютных путях, но не зашивайте в код или конфигурацию эти пути.
Плохой способ:include(‘xxx.php’);
Хороший способ:include(dirname(__FILE__).’/xxx.php’);
Не полагайтесь на окружение, оно может слишком сильно меняться.
Используйте «загрузчик»
Не используйте include.Подключайте все классы, css, js через загрузчик (loader).
Пример с Zend_Loader
В Zend Framewok есть Zend_Loader, который по сути заменяет include() и spl_autoload_register().
Но можно пойти дальше и сделать подключение JavaScript/CSS/пакетов/плагинов через такой же загрузчик.
Пример подключения JavaScript’a
Сколько раз вы писали такую строку?<script type="text/javascript" src="/.../prototype.js"></script>
А теперь представьте, что вы хотите расширить prototype.js.
1. prototype.js менять нельзя, потому что “он не ваш”, поэтому вы создадите еще один файл prototype-fix.js
2. Везде где понадобится этот fix нужно будет дописывать руками:<script type="text/javascript" src="/.../prototype-fix.js">
А можно было так:Loader::Get()->import(‘prototype’);
Использование VCSнаводит порядок в хранении проекта,
но не в архитектуреSVN, git, ... - это несомненно хорошо.
Теперь вы точно знаете где лежат материалы по проекту, кто и когда их менял. Знаете откуда брать последнюю версию.
VCS externalsНапример, svn:externals позволяет подключать любую внешнюю ветку в ваш репозиторий.
Используете Smarty? Не копируйте его в свой репозиторий, тяните его из официальной ветки разработчиков.
/.../dir1//smarty/ - externals на smarty-svn/...//dirN/
Externals-links не даст вам поменять что-то в коде, который приходит снаружи.
Создайте свой репозитарий своих готовых решений и линкуйтесь на него.
В git, mercurial есть аналоги externals.
MVCПостроить масштабируемое веб-приложение без MVC — не реально.
В web MVC позволяет разделить между собой логику (API), контроллеры (скрипты) и отображение (верстку). MVC в web подразумевает использование шаблонизатора.
Идеальное MVC достигается при использовании XSLT или XQuery.
Но в реальности все используют native-шаблонизаторы, Smarty, JSP, HTML::* для perl и т.д.
«Синхронизатор БД»
Делать и применять SQL-патчи очень хлопотно.
Чтобы следить за структорой БД можно использовать «синхронизаторы таблиц БД» - они описывают структуры таблиц на основом языке разработки.Синхронизатор — можно назвать одним из шагов mapping’a.
$table = SQLObjectSync::Get()->addTable('contacts');$table->addField('id', 'int(11)', 'auto_increment');$table->addKey('id', 'primary');$table->addField('cdate', 'datetime');$table->addField('userid', 'int(11)');$table->addIndexUnique(‘userid’);$table->addField('name', 'varchar(255)');$table->addField('phones', 'text');
// ... еще таблицы ...
SQLObjectSync::Get()->sync();
Небольшие выводы
1. Рассчитывайте, что ваш код повторно применится.
2. Используйте системы контроля версий.
3. Разработайте единый стиль кодирования.
4. Следуйте одинаковым правилам подключения и инициализации.
5. Используйте «загрузчик».
6. Используйте MVC и шаблонизаторы.
7. Не рассчитывайте на окружение.
8. Используйте «синхронизаторы для БД».