<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8537947668655047091</id><updated>2012-02-02T00:41:10.430+04:00</updated><category term='Личное'/><category term='phpDocumentor'/><category term='DVCS'/><category term='Headhunter'/><category term='Build'/><category term='тестирование'/><category term='JS'/><category term='PHPMD'/><category term='менеджмент'/><category term='ООП'/><category term='codestyle'/><category term='HTTP'/><category term='PHP CodeSniffer'/><category term='Userscript'/><category term='TDD'/><category term='TCP'/><category term='Git'/><category term='pdt'/><category term='Phing'/><category term='Задачи'/><category term='производительность'/><category term='html 5'/><category term='Xdebug'/><category term='Hudson'/><category term='Software People'/><category term='GDD'/><category term='eclipse'/><category term='мотивация'/><category term='Битрикс'/><category term='database'/><category term='Continuous Integration'/><category term='mysql'/><category term='CSS'/><category term='Subversion'/><category term='phpUnderControl'/><category term='паттерны'/><category term='Основы PHP'/><category term='ssh'/><category term='высокие нагрузки'/><category term='TELNET'/><category term='nix'/><category term='pinba'/><category term='phpconf'/><category term='PHP'/><category term='PHP Depend'/><category term='VCS'/><category term='scrum'/><category term='Jenkins'/><category term='sql'/><category term='Agile'/><category term='zend framework'/><category term='html'/><category term='PHPUnit'/><category term='CruiseControl'/><category term='rse'/><category term='CDN'/><category term='Exceptions'/><category term='SVN'/><category term='highload'/><category term='конференция'/><category term='ide'/><category term='Тесты'/><title type='text'>Yet another Blog</title><subtitle type='html'>YaB посвящен теме веб-разработки (PHP и MySQL), безопасности и IT вообще</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>53</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-3201419814141742810</id><published>2012-02-02T00:40:00.000+04:00</published><updated>2012-02-02T00:41:10.438+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='тестирование'/><category scheme='http://www.blogger.com/atom/ns#' term='Тесты'/><category scheme='http://www.blogger.com/atom/ns#' term='менеджмент'/><title type='text'>Автоматизируем тестирование</title><content type='html'>Вчера я побывал на встрече участников &lt;a href="http://testing-club.ru/2012/01/mstc2012/"&gt;Московского клуба тестировщиков&lt;/a&gt; и просто людей, неравнодушных к тестированию. Встреча проходила в новом офисе Афиши-Рамблера. Здесь я попробую поделиться услышанным.&lt;br /&gt;&lt;br /&gt;Во-первых, это было мое первое знакомство с такими специалистами в тестировании, как &lt;b&gt;Алексей Баранцев&lt;/b&gt; и &lt;b&gt;Наталья Руколь&lt;/b&gt;. Очень понравился и Алексей, и Наталься, и шляпа в которой была Наталья :-)&lt;br /&gt;&lt;br /&gt;Но рассказать бы я хотел только о выступлении Алексея Баранцева о внедрении автоматизации, потому что эта тема мне показалась более обширной. И принципы, о которых говорил Алексей, я думаю, можно без труда распространить на любой другой вид автоматизации, которую есть желание внедрить в проект. Попробую коротко пересказать эти принципы своими словами. В чем-то я могу ошибиться, уж простите, как понял, так и пишу.&lt;br /&gt;&lt;br /&gt;Итак, новому участнику в проекте (представьте, что это вы) наверняка захочется сделать тестирование более оптимальным: ручное тестирование заменить автоматизированным. Чтобы за одно и тоже время можно было запустить больше прогонов с большим набором тестовых данных и т.д. Особенно актуальны эти намерения для тестировщика, который автоматизацией уже занимался ранее.&lt;br /&gt;&lt;br /&gt;Алексей говорил, что начать следует с &lt;b&gt;обоснования&lt;/b&gt;. Это отдельная стадия, во время которой нужно проанализировать работу коллег-тестировщиков, разработчиков, убедиться, что сокращение времени одного тестирования будет оценено по достоинству. Еще бы!&lt;br /&gt;&lt;br /&gt;Далее следует заняться &lt;b&gt;составлением стратегического плана&lt;/b&gt;. При этом нужно использовать информацию, которую вы получили при обосновании. Нужно решить, что можно поменять, а что нет. Решить, что можно поменять, но не сразу. Очень сокращенный пример такого плана быть таким: «за год сократить время выполнения тестов в 2 раза без снижения полноты покрытия». Или таким: «за год увеличить покрытия кода тестами с 40 до 80 процентов а счет увеличения количества негативных тестов без увеличения времени выполнения».&lt;br /&gt;&lt;br /&gt;Далее, собственно идет стадия &lt;b&gt;реализация вашей стратегии&lt;/b&gt;. При этом есть пять разновидностей ваших действий:&lt;ul&gt;&lt;li&gt;выжидание – вы тратите какое-то небольшое время, возможно случайно образовавшееся. Например, если заболел ведущий разработчик, то у тестировщиков наверняка будет меньше работы. Это время стоит использовать с пользой, например, подготовить один из тестов.&lt;/li&gt;&lt;li&gt;прорыв – вы определенными, не самыми сложными действиями, получаете сравнительно легкий и эффектный результат. Пример прорыва – это использование рекордера тестов.&lt;/li&gt;&lt;li&gt;давление – вы посвящаете автоматизации каждый день один-два часа, а то и больше. Или, например, автоматизируете тест любого бага, который проявился дважды.&lt;/li&gt;&lt;li&gt;массированный удар – до достижения запланированного уровня автоматизации осталось уже совсем немного, и вы начинаете тратить уже как минимум половину рабочего времени на автоматизацию, чтобы быстрее все «добить».&lt;/li&gt;&lt;li&gt;и последняя стадия – это удержание, когда приоритетом для вас является защита и реагирование. Здесь например, вы принимаете решение сразу автоматизировать тесты.&lt;/li&gt;&lt;/ul&gt;Таким образом, последовательность осуществления плана по автоматизации: ожидание, прорыв, давление, массированный удар, удержание и т.д.&lt;br /&gt;&lt;br /&gt;Друзья, если мой скромный пересказ выступления Алексея вам показался интересным, то обязательно отправляйтесь на &lt;a href="http://software-testing.ru/test_automation/"&gt;ресурс&lt;/a&gt;, где вы можете посмотреть скринкасты именно этой темы, они должны быть довольно развернутыми.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-3201419814141742810?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/3201419814141742810/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=3201419814141742810' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3201419814141742810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3201419814141742810'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2012/02/blog-post.html' title='Автоматизируем тестирование'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-3614591107804684753</id><published>2011-11-13T20:47:00.001+04:00</published><updated>2011-11-13T21:43:19.578+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ide'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><category scheme='http://www.blogger.com/atom/ns#' term='rse'/><category scheme='http://www.blogger.com/atom/ns#' term='pdt'/><title type='text'>Eclipse PDT: начало работы</title><content type='html'>Разбирая свои старые файлы, я наткнулся на черновик статьи, которую я так и не опубликовал. В материале речь идет об установке Eclipse для работы с PHP на удаленном сервере. Ранее я уже приводил &lt;a href="/2009/10/eclipse-galileo-pdt-21-sftp.html"&gt;решение&lt;/a&gt; для комфортной работы с Eclipse PDT по SSH. Здесь же будет небольшой гид, который должен быть полезен прежде всего тем, кто совсем немного работал с данной IDE.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Выбор дистрибутива&lt;/b&gt;&lt;br/&gt;Прежде всего нужно выбрать подходящий дистрибутив Eclipse. Разработку для PHP в Eclipse можно вести благодаря проекту  PHP Developer Tools (PDT). Чтобы загрузить дистрибутив IDE можно выбрать одну из опций, которые доступны на текущий момент:&lt;ul&gt;&lt;li&gt;скачать &lt;a href="http://www.eclipse.org/downloads/"&gt;Eclipse 3.7 Classic&lt;/a&gt; и через меню Install new Software установить пакет "PDT Development Tools All in One SDK";&lt;/li&gt;&lt;li&gt;скачать &lt;a href="http://www.eclipse.org/downloads/packages/release/helios/sr2"&gt;Eclipse 3.6&lt;/a&gt; для PHP-разработчиков (т.е. предыдущую версию IDE, но специальную сборку для PHP);&lt;/li&gt;&lt;li&gt;найти на &lt;a href="http://www.eclipse.org/pdt/downloads/"&gt;странице&lt;/a&gt; PDT &lt;a href="http://code.google.com/p/zend-sdk/downloads/list"&gt;ссылки&lt;/a&gt; для загрузки Eclipse 3.7 для PHP-разработчиков (такие сборки у проекта PDT появились сравнительно недавно).&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;&lt;b&gt;Начало работы&lt;/b&gt;&lt;br/&gt;Eclipse не нужно устанавливать. Достаточно просто разместить файлы в директорию, например "C:\eclipse" для пользователей Windows.&lt;br/&gt;&lt;br/&gt; После этого можно просто запустить "eclipse.exe". Среда разработки начнет запускаться и предложит выбрать путь до вашего рабочего каталога "Workspace". Можно выбрать примерно такой же путь, как на рисунке ниже: "С:\Users\username\workspace". &lt;br/&gt;&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="285" width="400" src="http://4.bp.blogspot.com/-a-xvTy5F3ec/Tr_2yhZM8lI/AAAAAAAAAds/UTyox62mybE/s400/begin_2009-10-23.png" /&gt;&lt;/div&gt;&lt;br/&gt;Теперь Eclipse должен запуститься. Начальный вид окна может быть различным, но нам, PHP разработчикам, интересна перспектива PHP (это настройки и вид среды разработки). Открыть перспективу PHP можно способом, показанным на рисунке ниже: выполнить команды меню "Window =&gt; Open perspective =&gt; PHP (или Other…, если PHP нет в списке)".&lt;br/&gt;&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="286" width="299" src="http://3.bp.blogspot.com/-s53zfnjclro/Tr_3bSF0kKI/AAAAAAAAAd4/fKEN3mqCIUI/s400/begin_2009-10-23-2.png" /&gt;&lt;/div&gt;&lt;br/&gt;&lt;b&gt;Редактирование удаленных файлов&lt;/b&gt;&lt;br/&gt;В нашей работе довольно распространена необходимость редактировать файлы, расположенные на удаленных серверах. Eclipse PDT изначально позволяет работать в основном через проекты.  Для удаленных файлов – удаленные проекты.  Это не совсем удобно, и было бы лучше иметь возможность простого редактирования файлов, неважно локальных или удаленных.&lt;br/&gt;&lt;br/&gt;Для этого необходимо установить расширение "Target Management"  или по-другому его еще называют "Remote Systems". Для установки расширения необходимо отрыть меню "Help =&gt; Install New Software". Далее в окне выбора пакетов для установки необходимо найти "Remote System Explorer End-User-Runtime", обычно пакет находится в разделе "General Purpose Tools". После перезапуска в перспективу PHP следует добавить окно из только что установленного дополнения. Для этого следует выполнить команды: "Window =&gt; Show View =&gt; Other…".&lt;br/&gt;&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="267" width="400" src="http://3.bp.blogspot.com/-pcA8ebQmh-k/Tr_4b5AO-kI/AAAAAAAAAeE/jB5yVRZku-0/s400/remote_2009-10-23-4.png" /&gt;&lt;/div&gt;&lt;br/&gt;В списке следует найти и выбрать "Remote Systems", как на рисунке ниже:&lt;br/&gt;&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="400" width="274" src="http://4.bp.blogspot.com/-EB_mfDTCQ6Q/Tr_4vPIKnXI/AAAAAAAAAeQ/8xX7DWqafcU/s400/remote_2009-10-23-5.png" /&gt;&lt;/div&gt;&lt;br/&gt;Новое окно для удаленного редактирования, скорее всего, появится внизу экрана. Окно удобнее всего перетащить в левую часть, так с ним будет удобно и привычно работать. Теперь окно «Remote Systems» находится в привычном месте, это основное окно, в котором можно открывать удаленные или локальные файлы.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Создание соединения с сервером&lt;/b&gt;&lt;br/&gt;Теперь попробуем установить соединение с удаленным сервером . Первое, что нужно сделать, это кликнуть правой кнопкой в пустой области окна "Remote Systems" и выбрать там: "New =&gt; Connection…". Далее из списка следует выбрать тип соединения "SSH Only".&lt;br/&gt;&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="395" width="400" src="http://3.bp.blogspot.com/-bebeH9YpPqU/Tr_50IHpmnI/AAAAAAAAAec/MToxHyqO2oI/s400/connection_2009-10-23-2.png" /&gt;&lt;/div&gt;&lt;br/&gt;Теперь нужно указать параметры соединения, достаточно ввести только Host Name, например "example.hostname.ru". Соединение создано, теперь можно попробовать подключиться. Для этого следует открыть одну из папок на удаленном сервере, например "My Home". Eclipse должен запросить у вас параметры учетной записи: логин и пароль. Если все параметры были указаны верно, теперь есть возможность легко открывать и редактировать удаленные файлы.&lt;br/&gt;&lt;br/&gt;Кроме того, в Remote Systems можно без проблем открывать и локальные файлы, как это показано на рисунке ниже:&lt;br/&gt;&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-nnYxtFa-l4o/Tr_7TjelMuI/AAAAAAAAAeo/UAFtSzf3k0M/s1600/local_2009-10-23%2Bcopy.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="400" width="184" src="http://1.bp.blogspot.com/-nnYxtFa-l4o/Tr_7TjelMuI/AAAAAAAAAeo/UAFtSzf3k0M/s400/local_2009-10-23%2Bcopy.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br/&gt;&lt;b&gt;Автодополнение и временные файлы&lt;/b&gt;&lt;br/&gt;Несмотря на то, что мы использовали готовый дистрибутив для PHP разработчиков или установили пакет PDT All-in-One, есть некоторые проблемы при редактировании удаленных файлов. В частности, плохо работает автодополнение.&lt;br/&gt;&lt;br/&gt;Этот вопрос уже изучался, и было найдено некоторое решение проблемы. Оказалось, что для удаленного редактирования файлов через Remote Systems используется специальный проект. Если этот проект преобразовать в PHP-проект, то проблем с автодополнением не должно быть.&lt;br/&gt;&lt;br/&gt;Фактически нужно выполнить следующие действия:&lt;ol&gt;&lt;li&gt;Необходимо закрыть Eclipse;&lt;/li&gt;&lt;li&gt;В проводнике или в другом файловом менеджере, например Nautilus’е,  открыть рабочий каталог Workspace, для меня это каталог "С:\Users\hamuhin\workspace";&lt;/li&gt;&lt;li&gt;В каталоге Workspace должна быть папка "RemoteSystemsTempFiles", - это и есть проект, который нужно преобразовать;&lt;/li&gt;&lt;li&gt;В папку RemoteSystemsTempFiles необходимо скопировать файлы ".buildpath: и ".project", скачать их можно &lt;a href="http://gamextreme.ru/khamukhin.blogspot.com/2009/10/buildpath-project.zip"&gt;здесь&lt;/a&gt;. Если файлы уже существуют в каталоге, то их нужно переименовать в бэкап, а новые файлы разместить на их место;&lt;/li&gt;&lt;li&gt;Это почти все, теперь можно снова запустить Eclipse.&lt;/li&gt;&lt;/ol&gt;Проверим, что автодополнение работает. Для этого откроем любой файл на сервере webdev и попробуем ввести код &lt;code&gt;$abc  = str&lt;/code&gt; и нажать Ctrl+Пробел. Должен появиться список функций, как на рисунке ниже:&lt;br/&gt;&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="230" width="400" src="http://1.bp.blogspot.com/-H6x06nK-bkA/Tr_8WphBtbI/AAAAAAAAAe0/1lkprYUBulI/s400/autocomplete_2009-10-23.png" /&gt;&lt;/div&gt;&lt;br/&gt;В процессе работы на диске может скопиться очень много файлов, которые когда то открывались на удаленных серверах. Со временем это может сильно замедлить работу Eclipse. Чтобы этого избежать, нужно ограничить количество временных файлов. Для этого необходимо открыть настройки Eclipse: "Window =&gt; Preferences".&lt;br/&gt;&lt;br/&gt;В окне настроек следует найти раздел "Remote Systems / File Cache" и там включить опцию Limit cache size. Оптимальное значение может зависеть от объема оперативной памяти на машине, я обычно устанавливаю 512 или 256 МБ.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Настройки Proxy&lt;/b&gt;&lt;/br&gt;Если Eclipse не может соединиться с сервером, то эти проблемы с сетью могут быть связаны с настройками Proxy. Для того чтобы проверить или изменить эти параметры следует открыть окно настроек Eclipse: "Window =&gt; Preferences". В фильтре можно написать "proxy", чтобы быстро найти нужный раздел.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Фильтры и скрытые файлы в Remote Systems&lt;/b&gt;&lt;br/&gt;Часто необходимо редактировать файлы, которые находятся, например, по такому длинному пути: "/var/www/my-big-project/htdocs". Чтобы каждый раз не выбирать последовательно эти каталоги в окне Remote Systems, можно создать фильтр, который позволит быстро открывать нужные файлы.&lt;br/&gt;&lt;br/&gt;Для создания фильтра на интересуещем каталоге, например "my-big-project", нужно кликнуть правой кнопкой и выбрать из меню: "New =&gt; Filter…". Далее можно следовать инструкциям, ничего не меняя, и только на заключительном этапе указать имя фильтра, например «my-big-project». Теперь к файлам можно обращаться по более короткому пути, с помощью нового фильтра.&lt;br/&gt;&lt;br/&gt;Кроме того, часто бывает нужно отредактировать скрытые файлы, например ".htaccess". Обычно скрытые файлы с точкой вначале не отображаются в Remote Systems. Чтобы изменить эту опцию, нужно открыть окно настроек "Remote Systems / Files" и установить галочку в опции "Show hidden files".&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Работа с разными кодировками&lt;/b&gt;&lt;br/&gt;В настройках Eclipse можно устанавливать кодировку по умолчанию. Однако бывает так, что один проект создается в UTF-8, а другие ведутся в CP1251. Каждый раз менять настройку кодировки не очень удобно. К счастью можно задавать кодировку только для отдельных проектов, файлов или каталогов. Чтобы изменить кодировку для каталога, необходимо кликнуть правой кнопкой по нему и выбрать «Properties». В окне свойств каталога можно установить нужную кодировку, например UTF-8.&lt;br/&gt;&lt;br/&gt;Это все, о чем хотелось бы рассказать в данном гиде, и я надеюсь, что он принес пользу. Спасибо за внимание!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-3614591107804684753?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/3614591107804684753/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=3614591107804684753' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3614591107804684753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3614591107804684753'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/11/eclipse-pdt.html' title='Eclipse PDT: начало работы'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-a-xvTy5F3ec/Tr_2yhZM8lI/AAAAAAAAAds/UTyox62mybE/s72-c/begin_2009-10-23.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-5201720807957348577</id><published>2011-11-05T17:49:00.000+04:00</published><updated>2011-11-05T17:49:22.236+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Exceptions'/><title type='text'>Обработка исключительных ситуаций</title><content type='html'>Сегодня мне бы хотелось затронуть тему обработки исключительных ситуаций. Если быть точнее, то я предлагаю рассмотреть один аспект этой темы, а именно, взлянуть на проверяемые и непроверяемые исключительные ситуации.&lt;br /&gt;&lt;br /&gt;Рассмотрим пример, в котором вызывается метод закрытия учетной записи покупателя (customer) в нашей небольшой системы по продаже книг. Однако, это действие не может быть выполнено, если у покупателя, для примера, имеется незакрытый счет. В данном случае уместно говорить об исключительной ситуации.&lt;br /&gt;&lt;br /&gt;Если мы решили сделать исключительную ситуацию &lt;b&gt;непроверяемой&lt;/b&gt; (unchecked exception), то нам следует разместить блок проверки для возможного незакрытого счета покупателя в месте вызова метода &lt;code&gt;closeAccount&lt;/code&gt;. Таким образом за проверку условия отвечает вызывающий.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Customer&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;closeAccount&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!empty(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;uncompletePayments&lt;/span&gt;&lt;span style="color: #007700"&gt;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Exception&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;"Cannot&amp;nbsp;close&amp;nbsp;customer&amp;nbsp;account&amp;nbsp;with&amp;nbsp;uncomplete&amp;nbsp;payments"&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;accountClosed&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;true&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;if&amp;nbsp;(!&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$customer&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;canClose&lt;/span&gt;&lt;span style="color: #007700"&gt;())&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;handleCloseError&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;}&amp;nbsp;else&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$customer&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;closeAccount&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//do&amp;nbsp;some&amp;nbsp;other&amp;nbsp;usual&amp;nbsp;things&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;В данном случае невыполнение условия в методе &lt;code&gt;closeAccount&lt;/code&gt; будет являться ошибкой программирования (возлагаемая на вызывающего обязанность не была правильно выполнена).&lt;br /&gt;&lt;br /&gt;В случае, если мы решили сделать исключительную ситуацию &lt;b&gt;проверяемой&lt;/b&gt; (checked exception), то нам следует разместить вызов метода в блоке &lt;code&gt;try&lt;/code&gt;.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;CustomerCloseException&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;extends&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Exception&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Customer&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Some&amp;nbsp;description&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@throws&amp;nbsp;CustomerCloseException&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;closeAccount&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!empty(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;uncompletePayments&lt;/span&gt;&lt;span style="color: #007700"&gt;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;CustomerCloseException&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;accountClosed&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;true&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$customet&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;closeAccount&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//do&amp;nbsp;some&amp;nbsp;usual&amp;nbsp;things&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;}&amp;nbsp;catch&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;CustomerCloseException&amp;nbsp;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;handleCloseError&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;Здесь необходимо явно сообщить о возможной исключительной ситуации в интерфейсе (в данном случае я это делаю с помощью тэга phpdoc &lt;code&gt;@exception&lt;/code&gt; или &lt;code&gt;@throws&lt;/code&gt;). Так вызывающий может понять, что ему следует ожидать.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-5201720807957348577?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/5201720807957348577/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=5201720807957348577' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5201720807957348577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5201720807957348577'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/11/blog-post.html' title='Обработка исключительных ситуаций'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-4129211546038671095</id><published>2011-11-01T22:14:00.000+04:00</published><updated>2011-11-02T00:00:42.279+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHPUnit'/><title type='text'>Новое в PHPUnit 3.6</title><content type='html'>Несколько дней назад вышла новая версия фреймворка для модульного тестирования &lt;a href="http://www.phpunit.de/manual/3.6/en/"&gt;PHPUnit 3.6&lt;/a&gt;. Попробуем разобраться, какие нововведения вошли в этот релиз.&lt;br/&gt;&lt;br/&gt;Одно из нововведений - это возможность пользоваться методом &lt;code&gt;returnSelf&lt;/code&gt; для mock-объектов. Ниже приведу пример, похожий на пример в документации:&lt;br/&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;SomeClass&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;doSomething&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//do&amp;nbsp;something&amp;nbsp;and&amp;nbsp;return&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;null&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;ReturnSelfTest&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;extends&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;PHPUnit_Framework_TestCase&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;testReturnSelfExample&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//GIVEN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//create&amp;nbsp;a&amp;nbsp;stub&amp;nbsp;for&amp;nbsp;the&amp;nbsp;SomeClass&amp;nbsp;class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getMock&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'SomeClass'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//configure&amp;nbsp;the&amp;nbsp;stub&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;expects&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;any&lt;/span&gt;&lt;span style="color: #007700"&gt;())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;method&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'doSomething'&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;will&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;returnSelf&lt;/span&gt;&lt;span style="color: #007700"&gt;());&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//WHEN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$result&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;doSomething&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//THEN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;assertSame&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$result&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;Другой новый метод для Mock-объектов называется &lt;code&gt;returnValueMap&lt;/code&gt;. Метод позволяет указывать какое должно быть возвращаемое значение в зависимости от аргументов. Попробуем разобраться на примере:&lt;br/&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;SomeClass&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;doSomething&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//do&amp;nbsp;something&amp;nbsp;and&amp;nbsp;return&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;return&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;null&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;ReturnValueMapTest&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;extends&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;PHPUnit_Framework_TestCase&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;testReturnValueMapExample&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//GIVEN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//create&amp;nbsp;a&amp;nbsp;stub&amp;nbsp;for&amp;nbsp;the&amp;nbsp;SomeClass&amp;nbsp;class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getMock&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'SomeClass'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//create&amp;nbsp;a&amp;nbsp;map&amp;nbsp;of&amp;nbsp;arguments&amp;nbsp;to&amp;nbsp;return&amp;nbsp;values.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$map&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;array(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Fry'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Bender'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ExampleResultFirst'&lt;/span&gt;&lt;span style="color: #007700"&gt;,),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;array(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Lisa'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Bart'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Homer'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ExampleResultSecond'&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//configure&amp;nbsp;the&amp;nbsp;stub&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;expects&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;any&lt;/span&gt;&lt;span style="color: #007700"&gt;())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;method&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'doSomething'&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;will&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;returnValueMap&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$map&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//WHEN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$resultFirst&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;doSomething&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Fry'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Bender'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$resultSecond&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stub&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;doSomething&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Lisa'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Bart'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Homer'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//THEN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//the&amp;nbsp;provided&amp;nbsp;arguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;assertEquals&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ExampleResultFirst'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$resultFirst&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;assertEquals&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ExampleResultSecond'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$resultSecond&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;Следующее нововведение - это директива &lt;code&gt;@requires&lt;/code&gt; для анотации тестовых методов:&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;RequiresTest&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;extends&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;PHPUnit_Framework_TestCase&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@requires&amp;nbsp;PHP&amp;nbsp;6.0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;testRequiresExample&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//test&amp;nbsp;something&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;Выполнение теста будет выглядеть таким образом:&lt;pre&gt;&lt;code&gt;phpunit -v&lt;br /&gt;&lt;br /&gt;PHPUnit 3.6.0 by Sebastian Bergmann.&lt;br /&gt;&lt;br /&gt;Configuration read from /home/username/application/tests/phpunit.xml&lt;br /&gt;&lt;br /&gt;S&lt;br /&gt;&lt;br /&gt;Time: 0 seconds, Memory: 4.25Mb&lt;br /&gt;&lt;br /&gt;There was 1 skipped test:&lt;br /&gt;&lt;br /&gt;1) ArticleTest::testRequiresExample&lt;br /&gt;PHP 6.0 (or later) is required.&lt;br /&gt;&lt;br /&gt;OK, but incomplete or skipped tests!&lt;br /&gt;Tests: 1, Assertions: 0, Incomplete: 0, Skipped: 1.&lt;/code&gt;&lt;/pre&gt;Новое утверждение &lt;code&gt;assertCount&lt;/code&gt; (и противоположное &lt;code&gt;assertNotCount&lt;/code&gt;) для проверки количества элементов в массиве. И еще несколько нововведений коротко:&lt;ul&gt;&lt;li&gt;появилась возможность выводить результаты &lt;a href="http://www.phpunit.de/manual/3.6/en/logging.html#logging.codecoverage.text"&gt;code coverage&lt;/a&gt; в текстовом виде;&lt;/li&gt;&lt;li&gt;еще одна новая анотация &lt;a href="http://www.phpunit.de/manual/3.6/en/appendixes.annotations.html#appendixes.annotations.testdox"&gt;@testdox&lt;/a&gt;, очевидно, для генерации документации для выбранных методов;&lt;/li&gt;&lt;li&gt;режим strict, в котором тесты без утверждений считаются незавершенными;&lt;/li&gt;&lt;li&gt;и еще несколько опций запуска phpunit (узнать о них лучше всего из &lt;a href="http://www.phpunit.de/manual/3.6/en/textui.html#textui.clioptions"&gt;документации&lt;/a&gt;): coverage-php и printer.&lt;/li&gt;&lt;/ul&gt;Пользуясь случаем, поздравляю данный фреймворк, а точнее его создателей, со скорой круглой датой: первая версия PHPUnit вышла 27 ноября 2001 года, т.е. уже почти 10 лет назад!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-4129211546038671095?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/4129211546038671095/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=4129211546038671095' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/4129211546038671095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/4129211546038671095'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/11/phpunit-36.html' title='Новое в PHPUnit 3.6'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-2145013329223395374</id><published>2011-10-30T20:02:00.002+04:00</published><updated>2011-10-30T20:02:57.190+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP Depend'/><category scheme='http://www.blogger.com/atom/ns#' term='codestyle'/><category scheme='http://www.blogger.com/atom/ns#' term='PHPMD'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP CodeSniffer'/><title type='text'>Незаменимые инструменты: PHP_CodeSniffer, PHP Depend и PHPMD</title><content type='html'>В &lt;a href="/2011/10/phploc-phpcpd.html"&gt;прошлом посте&lt;/a&gt;, мы начали обсуждать небольшие утилиты, которые, находясь всегда под рукой, способны помочь разработчикам находить в исходном коде проблемные места, позволяют взглянуть на код с другой стороны, и в общем случае помогают быстрее выполнять свои задачи. Сегодня эта тема будет продолжена. На этот раз я бы хотел обсудить три таких инструмента:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://pear.php.net/package/PHP_CodeSniffer"&gt;PHP_CodeSniffer&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://pdepend.org/"&gt;PHP Depend&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://phpmd.org/"&gt;PHPMD&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Сначала мы поговорим о &lt;strong&gt;PHP_CodeSniffer&lt;/strong&gt;. Этот инструмент позволяет “понюхать” ваш код на дурные запахи. CodeSniffer незаменим, если вы хотите использовать такую инженерную практику, как code review. Не стоит самостоятельно проверять код на соблюдение принятого code style. Эту работу лучше сделает CodeSniffer. Запустить проверку можно таким способом:&lt;br/&gt;&lt;pre&gt;&lt;code&gt;phpcs --standard=PEAR application/classes&lt;br /&gt;&lt;br /&gt;FILE: application/classes/legacy.class.php&lt;br /&gt;------------------------------------------------------------------------&lt;br /&gt;FOUND 4 ERROR(S) AND 1 WARNING(S) AFFECTING 5 LINE(S)&lt;br /&gt;------------------------------------------------------------------------&lt;br /&gt;  2 | ERROR   | Missing file doc comment&lt;br /&gt;  3 | ERROR   | Missing class doc comment&lt;br /&gt;  6 | ERROR   | Missing function doc comment&lt;br /&gt; 11 | ERROR   | You must use "/**" style comments for a function comment&lt;br /&gt; 14 | WARNING | Line exceeds 85 characters; contains 89 characters&lt;br /&gt;------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;Time: 0 seconds, Memory: 3.25Mb&lt;/code&gt;&lt;/pre&gt;Безусловно существует возможность настроить правила проверки под свои стандарты кодирования. Для этого можно обратиться к &lt;a href="http://pear.php.net/manual/en/package.php.php-codesniffer.coding-standard-tutorial.php"&gt;документации&lt;/a&gt;, где рассмотрен один простой пример. В этом месте я бы хотел остановиться немного дольше, чем при рассмотрение других инструментов, и показать другой пример для создания своего правила проверки стиля написания кода в PHP_CodeSniffer.&lt;br/&gt;&lt;br/&gt;В качестве примера, будет рассмотрена такая практика, как &lt;a href="http://ru.wikipedia.org/wiki/%D0%92%D0%B5%D0%BD%D0%B3%D0%B5%D1%80%D1%81%D0%BA%D0%B0%D1%8F_%D0%BD%D0%BE%D1%82%D0%B0%D1%86%D0%B8%D1%8F"&gt;венгерская нотация&lt;/a&gt; (Hungarian Notation). Эта практика должна помочь в понимании программного кода благодаря небольшим префиксам для идентификаторов. Префиксы обычно означают тип данной переменной или тип возвращаемого значения для функций. Например, название &lt;code&gt;$aUser&lt;/code&gt; сразу говорит нам, что данная переменная является массивом. В примере мы будем проверять установлены ли префиксы названий переменных. Саму венгерскую нотацию вы можете использовать по своему усмотрению, я не являюсь ни приверженцем данной практики, ни ее противником, а здесь просто использую ее в качестве примера.&lt;br/&gt;&lt;br/&gt;Итак, для начала, мы создадим свой стандарт кодирования, разместив свой каталог в иерархию PHP_CodeSniffer. В моем случае это такой путь: &lt;code&gt;/usr/share/php/PHP/CodeSniffer/Standards/Example&lt;/code&gt;. Здесь мы должны разместить файл &lt;code&gt;ruleset.xml&lt;/code&gt; со следующим содержанием. См. &lt;a href="http://pear.php.net/manual/en/package.php.php-codesniffer.annotated-ruleset.php"&gt;синтаксис&lt;/a&gt; файлов ruleset.&lt;br/&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;ruleset&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;description&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;The Example coding standard.&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;description&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;rule&lt;/span&gt; &lt;span style='color:#274796; '&gt;ref&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;PEAR&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;ruleset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Здесь мы позаимствовали все стандарты PEAR, а свой стандарт для проверки использования венгерской нотации для переменных мы поместим в файл &lt;code&gt;Sniffs/NamingConventions/HungarianNotationSniff.php&lt;/code&gt; внутри нашего каталога &lt;code&gt;Example&lt;/code&gt;. Так будет выглядеть примерное содержания для выбранной проверки:&lt;br/&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Example_Sniffs_NamingConventions_HungarianNotationSniff&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;extends&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;PHP_CodeSniffer_Standards_AbstractVariableSniff&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$_variablePrefixes&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'b'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//bool&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'a'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'i'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//int&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'s'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//string&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'f'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//float&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'o'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'m'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//mixed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$_predefinedVariables&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'this'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'GLOBALS'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'_SERVER'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'_GET'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'_POST'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'...'&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//something&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Processes&amp;nbsp;class&amp;nbsp;member&amp;nbsp;variables.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;PHP_CodeSniffer_File&amp;nbsp;$phpcsFile&amp;nbsp;The&amp;nbsp;file&amp;nbsp;being&amp;nbsp;scanned.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;int&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stackPtr&amp;nbsp;&amp;nbsp;The&amp;nbsp;position&amp;nbsp;of&amp;nbsp;token.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;protected&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;processMemberVar&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;PHP_CodeSniffer_File&amp;nbsp;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$tokens&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getTokens&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$memberProps&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getMemberProperties&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(empty(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$memberProps&lt;/span&gt;&lt;span style="color: #007700"&gt;)&amp;nbsp;===&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;true&lt;/span&gt;&lt;span style="color: #007700"&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$memberName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;ltrim&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$tokens&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'content'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'$'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$scope&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$memberProps&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'scope'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_isVariablePredefined&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$memberName&lt;/span&gt;&lt;span style="color: #007700"&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;!&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_isVariablePrefixed&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$memberName&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$error&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'%s&amp;nbsp;member&amp;nbsp;var&amp;nbsp;"%s"&amp;nbsp;must&amp;nbsp;be&amp;nbsp;prefixed&amp;nbsp;with&amp;nbsp;a&amp;nbsp;type&amp;nbsp;code'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;ucfirst&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$scope&lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$memberName&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;addError&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$error&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'MemberVarWithoutPrefix'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Processes&amp;nbsp;normal&amp;nbsp;variables.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;PHP_CodeSniffer_File&amp;nbsp;$phpcsFile&amp;nbsp;The&amp;nbsp;file&amp;nbsp;being&amp;nbsp;scanned.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;int&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stackPtr&amp;nbsp;&amp;nbsp;The&amp;nbsp;position&amp;nbsp;of&amp;nbsp;token.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;protected&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;processVariable&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;PHP_CodeSniffer_File&amp;nbsp;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$tokens&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getTokens&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;ltrim&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$tokens&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'content'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'$'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_isVariablePredefined&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&lt;/span&gt;&lt;span style="color: #007700"&gt;)&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;!&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_isVariablePrefixed&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$error&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Variable&amp;nbsp;"%s"&amp;nbsp;must&amp;nbsp;be&amp;nbsp;prefixed&amp;nbsp;with&amp;nbsp;a&amp;nbsp;type&amp;nbsp;code'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;addError&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$error&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'VariableWithoutPrefix'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Processes&amp;nbsp;variables&amp;nbsp;in&amp;nbsp;double&amp;nbsp;quoted&amp;nbsp;strings.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;protected&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;processVariableInString&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$phpcsFile&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$stackPtr&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//TODO&amp;nbsp;process&amp;nbsp;variables&amp;nbsp;in&amp;nbsp;string&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Check&amp;nbsp;if&amp;nbsp;variable&amp;nbsp;is&amp;nbsp;predefined&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;&amp;nbsp;string&amp;nbsp;$variableName&amp;nbsp;Variable&amp;nbsp;name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;bool&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;private&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_isVariablePredefined&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;in_array&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&lt;/span&gt;&lt;span style="color: #007700"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_predefinedVariables&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Check&amp;nbsp;if&amp;nbsp;variable&amp;nbsp;is&amp;nbsp;correctly&amp;nbsp;prefixed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;&amp;nbsp;string&amp;nbsp;$variableName&amp;nbsp;Variable&amp;nbsp;name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;bool&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;private&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_isVariablePrefixed&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;preg_match&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/^_?['&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;.&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;implode&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_variablePrefixes&lt;/span&gt;&lt;span style="color: #007700"&gt;).&amp;nbsp;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'][A-Z]/'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$variableName&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;Теперь попробуем что-нибудь проверить. Для этого у меня есть тестовый файл &lt;code&gt;example.class.php&lt;/code&gt; с таким содержимом (обратите внимание, что тестовый файл не содержит никаких нарушений стандартов кодирования от PEAR):&lt;br/&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&amp;lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;Example&amp;nbsp;file&amp;nbsp;for&amp;nbsp;PHP_CodeSniffer&lt;br /&gt;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;*&amp;nbsp;PHP&amp;nbsp;version&amp;nbsp;5&amp;nbsp;&lt;br /&gt;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@category&amp;nbsp;Example_File&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@package&amp;nbsp;&amp;nbsp;Example_File&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@author&amp;nbsp;&amp;nbsp;&amp;nbsp;Eugene&amp;nbsp;Khamukhin&amp;nbsp;&amp;lt;khamukhin@gmail.com&amp;gt;&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@license&amp;nbsp;&amp;nbsp;Some&amp;nbsp;free&amp;nbsp;licence&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@link&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://blog.yetanother.ru/&lt;br /&gt;&amp;nbsp;*/&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;&amp;nbsp;*&amp;nbsp;Example&amp;nbsp;class&amp;nbsp;for&amp;nbsp;PHP_CodeSniffer&lt;br /&gt;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@category&amp;nbsp;Example_Class&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@package&amp;nbsp;&amp;nbsp;Example_Class&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@author&amp;nbsp;&amp;nbsp;&amp;nbsp;Eugene&amp;nbsp;Khamukhin&amp;nbsp;&amp;lt;khamukhin@gmail.com&amp;gt;&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@license&amp;nbsp;&amp;nbsp;Some&amp;nbsp;free&amp;nbsp;licence&lt;br /&gt;&amp;nbsp;*&amp;nbsp;@link&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://blog.yetanother.ru/&lt;br /&gt;&amp;nbsp;*/&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Example&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$_cargo&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Set&amp;nbsp;cargo&amp;nbsp;for&amp;nbsp;space&amp;nbsp;ship&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;ExampleCargo&amp;nbsp;$cargo&amp;nbsp;Cargo&amp;nbsp;to&amp;nbsp;deliver&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;setCargo&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$cargo&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_cargo&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$cargo&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Deliver&amp;nbsp;cargo&amp;nbsp;via&amp;nbsp;Planet&amp;nbsp;Express&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;ExampleCargo&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;public&amp;nbsp;function&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;diliver&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;//do&amp;nbsp;some&amp;nbsp;work&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #007700"&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;Запускаем проверку на дурные запахи и изучаем результат:&lt;br/&gt;&lt;pre&gt;&lt;code&gt;phpcs --standard=Example example.class.php &lt;br /&gt;&lt;br /&gt;FILE: /home/khamukhin/phpcs/example.class.php&lt;br /&gt;------------------------------------------------------------------------&lt;br /&gt;FOUND 3 ERROR(S) AFFECTING 3 LINE(S)&lt;br /&gt;------------------------------------------------------------------------&lt;br /&gt; 25 | ERROR | Private member variable "_cargo" must be prefixed&lt;br /&gt; 34 | ERROR | Variable "cargo" must be prefixed with a type code&lt;br /&gt; 36 | ERROR | Variable "cargo" must be prefixed with a type code&lt;br /&gt;------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;Time: 1 second, Memory: 3.50Mb&lt;/code&gt;&lt;/pre&gt;Вторая программа, о которой я бы хотел рассказать - это &lt;strong&gt;PHP Depend&lt;/strong&gt;. Эта утилита вычисляет много различных метрик (о которых можно будет рассказать в отдельной статье), а также строит графики зависимостей пакета.&lt;br/&gt;&lt;br/&gt;Использование PHP Depend более актуально в контексте сервера непрерывной интеграции. Например, вот так будет выглядеть запуск PHP Depend в скрипте сборки для Phing:&lt;br/&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.phpdepend                        &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.phpdepend&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpdepend&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/application/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;logger&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;jdepend-xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/jdepend.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;logger&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;jdepend-chart&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/pdepend/dependencies.svg&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;logger&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;overview-pyramid&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/pdepend/overview-pyramid.svg&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;analyzer&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;coderank-mode&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;method&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpdepend&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Последний инструмент, который будет рассмотрен в данной статье, это &lt;strong&gt;PHPMD&lt;/strong&gt; - Mess Detector. Данная утилита позволяет проверить исходный код на потенциальные проблемы, не очень оптимальные участки кода, неиспользуемые параметры, методы и т.д. Вот как может выглядеть запуск phpmd:&lt;br/&gt;&lt;pre&gt;&lt;code&gt;phpmd classes text codesize,unusedcode,naming&lt;br /&gt;&lt;br /&gt;classes/legacy.class.php:3 This class has too many methods, &lt;br /&gt;                                consider refactoring it.&lt;br /&gt;&lt;br /&gt;classes/legacy.class.php:3 The class Legacy has an overall &lt;br /&gt;                                complexity of 68 which is very high. &lt;br /&gt;                                The configured complexity threshold is 50.&lt;br /&gt;...&lt;/code&gt;&lt;/pre&gt;Для этой утилиты также можно настраивать свои правила, а как это сделать можно найти в &lt;a href="http://phpmd.org/documentation/writing-a-phpmd-rule.html"&gt;документации&lt;/a&gt;. Для code review данный инструмент также, как и PHP_CodeSniffer является просто незаменимым.&lt;br/&gt;&lt;br/&gt;На этом серия постов про полезные инструменты не завершается, продолжение следует!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-2145013329223395374?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/2145013329223395374/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=2145013329223395374' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2145013329223395374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2145013329223395374'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/10/phpcodesniffer-php-depend-phpmd.html' title='Незаменимые инструменты: PHP_CodeSniffer, PHP Depend и PHPMD'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-5556797977110936629</id><published>2011-10-28T08:07:00.000+04:00</published><updated>2011-10-28T08:07:26.650+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='codestyle'/><title type='text'>Незаменимые инструменты: phploc и phpcpd</title><content type='html'>Опытные разработчики стараются окружить свою повседневную работу различными тулзами, инструментами и утилитами, которые помогают выполнять задачи быстрее. Если есть инструмент, который может автоматизировать какую-то часть ежедневной работы, то почему бы его не использовать.&lt;br/&gt;&lt;br/&gt;Несколько статей в этом блоге будут посвящены таким тулзам, будут описаны основные возможности утилит. В этом посте я бы хотел рассказать о двух инструментах:&lt;ul&gt;&lt;li&gt;&lt;a href="https://github.com/sebastianbergmann/phploc#readme"&gt;Phploc&lt;/a&gt;;&lt;/l&gt;&lt;li&gt;&lt;a href="https://github.com/sebastianbergmann/phpcpd/#readme"&gt;Phpcpd&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;Обе утилиты предлагает использовать известный и уважаемый разработчик Sebastian Bergmann, что уже является неплохой рекомендацией. Phploc и Phpcpd особенно актуальны для использования на сервере непрерывной интеграции, но и не будут лишними, находясь под рукой разработчика.&lt;br/&gt;&lt;br/&gt;Начнем с &lt;b&gt;Phploc&lt;/b&gt;. Эта утилита позволяет померить PHP проект, т.е. это такая своеобразная линейка, lines of code. Опций у phploc совсем мало: помимо указания каталога или файла и других не очень важных параметров, можно установить путь до лог-файла, в который phploc запишет результат измерений в XML или CSV.&lt;br/&gt;&lt;br/&gt;Запускаем phploc:&lt;pre&gt;&lt;code&gt;phploc --log-csv reports/phploc.csv application/classes &lt;br /&gt;&lt;br /&gt;phploc 1.6.1 by Sebastian Bergmann.&lt;br /&gt;&lt;br /&gt;Lines of Code (LOC):                               2992&lt;br /&gt;  Cyclomatic Complexity / Lines of Code:           0.10&lt;br /&gt;Comment Lines of Code (CLOC):                       587&lt;br /&gt;Non-Comment Lines of Code (NCLOC):                 2405&lt;br /&gt;&lt;br /&gt;Namespaces:                                           0&lt;br /&gt;Interfaces:                                           0&lt;br /&gt;Classes:                                              1&lt;br /&gt;  Abstract:                                           0 (0.00%)&lt;br /&gt;  Concrete:                                           1 (100.00%)&lt;br /&gt;  Average Class Length (NCLOC):                    2660&lt;br /&gt;Methods:                                             62&lt;br /&gt;  Scope:&lt;br /&gt;    Non-Static:                                      62 (100.00%)&lt;br /&gt;    Static:                                           0 (0.00%)&lt;br /&gt;  Visibility:&lt;br /&gt;    Public:                                          27 (43.55%)&lt;br /&gt;    Non-Public:                                      35 (56.45%)&lt;br /&gt;  Average Method Length (NCLOC):                     42&lt;br /&gt;  Cyclomatic Complexity / Number of Methods:       4.94&lt;br /&gt;&lt;br /&gt;Anonymous Functions:                                  0&lt;br /&gt;Functions:                                            0&lt;br /&gt;&lt;br /&gt;Constants:                                            5&lt;br /&gt;  Global constants:                                   0&lt;br /&gt;  Class constants:                                    5&lt;/code&gt;&lt;/pre&gt;Два показателя (Cyclomatic Complexity / Lines of Code и Cyclomatic Complexity / Number of Methods) используют такую характеристику кода, как &lt;a href="http://ru.wikipedia.org/wiki/%D0%A6%D0%B8%D0%BA%D0%BB%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C"&gt;Цикломатическая сложность&lt;/a&gt;. Этот показатель характеризует число ветвей в коде и вычисляется путем подсчета операторов цикла, условного перехода и переключений. Цикломатическая сложность была разработана еще в 1976 году, а ее автор Томас Дж. Мак-Кейб предлагал заставлять разработчиков разбивать код на более простые участки, если сложность модуля превышает значение 10.&lt;br/&gt;&lt;br/&gt;Вторая утилита, о которой будет рассказано в данном посте - это &lt;b&gt;Phpcpd&lt;/b&gt;, детектор “копипаста”. Пожалуй, никто не будет спорить, что копипаст дурно пахнет и почти наверняка приведет к ошибкам в приложении, которые проявятся рано или поздно. Утилита phploc ищет такие дурные, повторяющиеся места в коде.&lt;pre&gt;&lt;code&gt;phpcpd --min-tokens 50 --verbose lib&lt;br /&gt;&lt;br /&gt;phpcpd 1.3.2 by Sebastian Bergmann.&lt;br /&gt;&lt;br /&gt;Processing files&lt;br /&gt;49 / 49 [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&gt;] 100.00%&lt;br /&gt;&lt;br /&gt;Found 3 exact clones with 66 duplicated lines in 4 files:&lt;br /&gt;&lt;br /&gt;  - foo.class.php:241-252&lt;br /&gt;    foo.class.php:285-296&lt;br /&gt;&lt;br /&gt;  - copy.class.php:12-22&lt;br /&gt;    paste.class.php:20-30&lt;br /&gt;&lt;br /&gt;  - boo.class.php:833-848&lt;br /&gt;    foo.class.php:391-406&lt;br /&gt;&lt;br /&gt;0.25% duplicated lines out of 26439 total lines of code.&lt;br /&gt;&lt;br /&gt;Time: 3 seconds, Memory: 24.25Mb&lt;/code&gt;&lt;/pre&gt;Параметры &lt;code&gt;min-lines&lt;/code&gt; и &lt;code&gt;min-tokens&lt;/code&gt; позволяют повышать или понижать планку того, что считать Copy/Paste. Опцией &lt;code&gt;log-pmd&lt;/code&gt; результаты можно сохранить в формате PMD-CPD XML.&lt;br/&gt;&lt;br/&gt;На этом пока все, продолжение следует. Делитесь в комментариях своими тулзами, которые помогают вам!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-5556797977110936629?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/5556797977110936629/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=5556797977110936629' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5556797977110936629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5556797977110936629'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/10/phploc-phpcpd.html' title='Незаменимые инструменты: phploc и phpcpd'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-2160134037644926144</id><published>2011-10-26T01:29:00.000+04:00</published><updated>2011-10-26T08:29:50.771+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Jenkins'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Phing'/><category scheme='http://www.blogger.com/atom/ns#' term='Continuous Integration'/><title type='text'>Переходим на непрерывную интеграцию с Jenkins</title><content type='html'>В &lt;a href="/2011/10/php.html"&gt;предыдущей статье&lt;/a&gt; мы подключили проект к серверу постоянной интеграции &lt;a href="http://phpundercontrol.org/"&gt;phpUnderControl&lt;/a&gt;. На этом мы не остановимся и теперь попробуем другой сервер непрерывной интеграции — &lt;a href="http://jenkins-ci.org/"&gt;Jenkins&lt;/a&gt; (ранее назывался &lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Прежде чем начинать установку Jenkins, стоит еще раз проговорить о преимуществах непрерывной интеграции. В большом проекте, как правило, участвуют несколько разработчиков. Если вы работали с большим проектом и с большой командой, то наверняка вы сталкивались с проблемами, когда все фитчи итерации или спринта вроде бы уже готовы, но если собрать все вместе, то не работает ничего. Интеграция кода, написанного каждым разработчиком, отнимает много времени. Жизнь становится немного приятней, когда после каждого коммита, вы можете быть уверены, что сборка проекта прошла успешно. А если при сборке были какие-то проблемы, то вы об этом сразу же узнаете, - вам будет отправлено какое-либо уведомление. И, если использовать сервер непрерывной интеграции, для этого не нужны какие-то специальные ручные действия. Сервер CI сразу после коммита сам выполнит все тесты проекта, запустит анализаторы кода и соберет различные метрики.&lt;br /&gt;&lt;br /&gt;Зачем использовать именно Jenkins? Его стоит использовать, потому что это превосходный проект, у которого есть огромное количество дополнений, его легко устанавливать и настраивать. Кроме того, для Jenkins существует мини-проект php-jenkins-template от &lt;a href="http://sebastian-bergmann.de/"&gt;Sebastian Bergmann&lt;/a&gt; (создатель &lt;a href="http://www.phpunit.de/"&gt;PHPUnit&lt;/a&gt; и не только), который позволяет достаточно легко подключать PHP проекты. Да что долго говорить, лучше один раз попробовать!&lt;br /&gt;&lt;br /&gt;Приступаем к установке. Установить Jenkins достаточно легко, например для Ubuntu нужно выполнить такие команды:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | \&lt;br /&gt;sudo apt-key add -&lt;br /&gt;&lt;br /&gt;sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ &gt; \&lt;br /&gt;/etc/apt/sources.list.d/jenkins.list'&lt;br /&gt;&lt;br /&gt;sudo aptitude update&lt;br /&gt;sudo aptitude install jenkins&lt;/code&gt;&lt;/pre&gt;Теперь можно приступить к установке &lt;a href="http://jenkins-php.org/"&gt;php-jenkins-template&lt;/a&gt;. Подробное руководство по установке представлено на странице проекта, здесь же я отмечу только наиболее важные моменты.&lt;br /&gt;&lt;br /&gt;Установить необходимые плагины (для PHP нужно установить checkstyle, cloverphp, dry, htmlpublisher, jdepend, plot, pmd, violations, xunit) можно как через терминал, так и через веб-интерфейс. Кстати, вероятно для многих главным различием между CruiseControl и Jenkins будет то, что для конфигурации первого необходимо работать преимущественно с командной строкой, а для  Jenkins — в графическом интерфейсе. Прежде чем, начать установку плагинов, нужно обновить в Jenkins список доступных дополнений. Обновить этот список можно на странице: &lt;code&gt;http://hostname:8080/pluginManager/advanced&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Следующим важным шагов будет установка самого шаблона для PHP проекта. Это можно сделать такими командами:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;cd $JENKINS_HOME/jobs&lt;br /&gt;git clone git://github.com/sebastianbergmann/php-jenkins-template.git php-template&lt;br /&gt;chown -R jenkins:nogroup php-template/&lt;/code&gt;&lt;/pre&gt;Далее необходимо создать свою конфигурацию  на основе заготовки для PHP проектов. Здесь самое главное проследить за корректностью путей до XML-логов, которые создаются при сборке проекта.&lt;br /&gt;&lt;br /&gt;Для сборки проекта в этом примере мы будем использовать Phing (соответствующий плагин для Jenkins нужно также установить). За основу build-скприта проекта мы будем использовать файл, который уже рассматривался в статье про phpUnderControl и Phing. Но здесь мы добавим еще несколько задач: code.browser, run.phploc, run.phpdepend.&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;encoding&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;UTF-8&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;default&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;property&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;build.dir&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; (DEFAULT) Target: default                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy, run.tests.legacy, run.coverage, run.mess.detector, run.copypast.detector, run.phpcodesniffer, api.docs, code.browser, run.phploc, run.phpdepend&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;All done.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: api.docs                             &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;api.docs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;docblox&lt;/span&gt; &lt;span style='color:#274796; '&gt;title&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;API Documentation&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;destdir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/public/apidocs/&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;quiet&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;docblox&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: code.browser                         &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;code.browser&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;exec&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;command&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;phpcb --source ${build.dir}/classes --output ${build.dir}/public/code-browser&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: lint.legacy                          &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.tests.legacy                     &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.tests.legacy&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;coverage-setup&lt;/span&gt; &lt;span style='color:#274796; '&gt;database&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/coverage.db&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;coverage-setup&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonfailure&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonerror&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;codecoverage&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;todir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpunit&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;clover&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;todir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpunit&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;plain&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*Test.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.coverage                         &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.coverage&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.tests.legacy&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;coverage-report&lt;/span&gt; &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/coverage.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;report&lt;/span&gt; &lt;span style='color:#274796; '&gt;todir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/coverage&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;styledir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;/usr/share/php/data/phing/etc&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;coverage-report&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.mess.detector                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.mess.detector&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpmd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpmd.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;text&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpmd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.copypast.detector                &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.copypast.detector&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcpd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;pmd&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpcpd.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcpd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.phpcodesniffer                   &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.phpcodesniffer&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcodesniffer&lt;/span&gt; &lt;span style='color:#274796; '&gt;standard&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Zend&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;showSniffs&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;showWarnings&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;checkstyle&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpcodesniffer.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;summary&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcodesniffer&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.phploc                           &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.phploc&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;exec&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;command&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;phploc --log-csv ${build.dir}/build/phploc.csv ${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.phpdepend                        &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.phpdepend&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpdepend&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;logger&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;jdepend-xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/jdepend.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;analyzer&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;coderank-mode&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;method&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpdepend&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Можно запустить сборку проекта вручную и, если все хорошо, смело включать проект в Jankins. За сборкой проекта в этом сервере непрерывной интеграции можно очень удобно следить:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-V92r_CnvrRQ/TqbQNZyTg3I/AAAAAAAAAdY/Cp-QeE5xuoI/s1600/canvas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="209" src="http://1.bp.blogspot.com/-V92r_CnvrRQ/TqbQNZyTg3I/AAAAAAAAAdY/Cp-QeE5xuoI/s400/canvas.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;В заключении я бы хотел поделиться своими субъективными наблюдениями:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;в Jankins довольно удобно настраивать проект, а некорректная конфигурация одного проекта не сломает другие проекты в отличии от CruiseControl;&lt;/li&gt;&lt;li&gt;поражает количество плагинов, доступных для установки (например, с помощью некоторых плагинов можно отправлять сообщения о неудачных билдах в Jabber или Twitter);&lt;/li&gt;&lt;li&gt;интерфейс более объемный (больше разнообразных станиц для каждой сборки), чем в phpUnderControl;&lt;/li&gt;&lt;li&gt;если вы используете phpUnderControl, то как минимум посмотреть на Jenkins вы просто обязаны :)&lt;/li&gt;&lt;/ul&gt;Удачных экспериментов с непрерывной интеграцией и благодарю за внимание!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-2160134037644926144?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/2160134037644926144/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=2160134037644926144' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2160134037644926144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2160134037644926144'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/10/jenkins.html' title='Переходим на непрерывную интеграцию с Jenkins'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-V92r_CnvrRQ/TqbQNZyTg3I/AAAAAAAAAdY/Cp-QeE5xuoI/s72-c/canvas.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-584445058890412892</id><published>2011-10-25T00:03:00.000+04:00</published><updated>2011-10-26T01:38:03.669+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='CruiseControl'/><category scheme='http://www.blogger.com/atom/ns#' term='Xdebug'/><category scheme='http://www.blogger.com/atom/ns#' term='PHPUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='phpUnderControl'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP CodeSniffer'/><category scheme='http://www.blogger.com/atom/ns#' term='phpDocumentor'/><category scheme='http://www.blogger.com/atom/ns#' term='Phing'/><category scheme='http://www.blogger.com/atom/ns#' term='Continuous Integration'/><title type='text'>Подключаем PHP проект к серверу непрерывной интеграции</title><content type='html'>В прошлый раз мы обсуждали &lt;a href="/2011/10/build-php-phing.html"&gt;автоматизацию build проекта с использованием Phing&lt;/a&gt;. В этом посте тема будет продолжена: настало время подключить наш проект к серверу Continuous Integration.&lt;br /&gt;&lt;br /&gt;Прежде чем начинать все устанавливать, настраивать и улучшать, скажем несколько слов о непрерывной интеграции в принципе. Постоянная интеграция — это практика, которая позволяет как можно быстрее выявить возможные интеграционные проблемы в проекте. Это достигается благодаря частым автоматизированным сборкам проекта. Как правило, участие человека здесь сводится к минимуму: на отдельном сервере по мере коммита нового кода в центральный репозиторий, запускаются различные тесты, которые могут сказать появились ли вместе с нововведениями какие-то проблемы.&lt;br /&gt;&lt;br /&gt;Если это первый проект, который вы подключаете к серверу непрерывной интеграции, то скорее всего стоит использовать &lt;a href ="http://cruisecontrol.sourceforge.net/"&gt;CruiseControl&lt;/a&gt; с установленным дополнением &lt;a href="http://phpundercontrol.org/"&gt;phpUnderControl&lt;/a&gt;. Для PHP-проектов такая конфигурация является (или покрайней мере являлась) своеобразном стандартом.&lt;br /&gt;&lt;br /&gt;Переходим от слов к делу. Нам понадобится один сервер, свежие версии &lt;a href="http://cruisecontrol.sourceforge.net/download.html"&gt;CruiseControl&lt;/a&gt; и &lt;a href="http://phpundercontrol.org/download.html"&gt;phpUnderControl&lt;/a&gt;, &lt;a href="http://subversion.apache.org/packages.html"&gt;Subversion&lt;/a&gt; (в нашем примере будет использована эта система контроля версий), пакеты sun-java6-jre, sun-java6-jdk. Кроме того далее будут упоминаться различные утилиты, которые также потребуется установить на сервере CI.&lt;br /&gt;&lt;br /&gt;Начнем с установки  CruiseControl:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;unzip cruisecontrol-bin-2.8.4.zip -d /opt &lt;br /&gt;ln -s /opt/cruisecontrol-bin-2.8.4 /opt/cruisecontrol&lt;/code&gt;&lt;/pre&gt;Чтобы это приложение можно было легче запускать, останавливать и перезапускать, пригодится следующий скрипт, который изначально был опубликован в &lt;a href="http://blog.felixdv.com/2009/02/07/setting-up-phpundercontrol/"&gt;этой статье&lt;/a&gt;. &lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#696969; '&gt;#!&lt;/span&gt;&lt;span style='color:#007997; '&gt;/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#797997; '&gt;PATH&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/usr/local/sbin&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/usr/local/bin&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/usr/sbin&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/usr/bin&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/sbin&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/bin&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt; &lt;span style='color:#40015a; '&gt;/lib/lsb/init-functions&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#797997; '&gt;JAVA_HOME&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/usr&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#797997; '&gt;NAME&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;cruisecontrol&lt;br /&gt;&lt;span style='color:#797997; '&gt;DAEMON&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/opt/cruisecontrol/cruisecontrol.sh&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#797997; '&gt;PIDFILE&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/opt/cruisecontrol/cc.pid&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style='color:#bb7977; font-weight:bold; '&gt;test&lt;/span&gt; &lt;span style='color:#44aadd; '&gt;-x&lt;/span&gt; &lt;span style='color:#797997; '&gt;$DAEMON&lt;/span&gt; &lt;span style='color:#800080; '&gt;||&lt;/span&gt; &lt;span style='color:#bb7977; font-weight:bold; '&gt;exit&lt;/span&gt; &lt;span style='color:#008c00; '&gt;5&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style='color:#797997; '&gt;RUNASUSER&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;cruisecontrol&lt;br /&gt;&lt;span style='color:#797997; '&gt;UGID&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;$&lt;span style='color:#800080; '&gt;(&lt;/span&gt;getent passwd &lt;span style='color:#797997; '&gt;$RUNASUSER&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;|&lt;/span&gt; cut &lt;span style='color:#44aadd; '&gt;-f&lt;/span&gt; &lt;span style='color:#008c00; '&gt;3&lt;/span&gt;,&lt;span style='color:#008c00; '&gt;4&lt;/span&gt; -d&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#800080; '&gt;)&lt;/span&gt; &lt;span style='color:#800080; '&gt;||&lt;/span&gt; &lt;span style='color:#44aadd; '&gt;true&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;case&lt;/span&gt; &lt;span style='color:#797997; '&gt;$1&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;in&lt;/span&gt;&lt;br /&gt;  start&lt;span style='color:#e34adc; '&gt;)&lt;/span&gt;&lt;br /&gt;    log_daemon_msg &lt;span style='color:#0000e6; '&gt;"Starting Cruisecontrol server"&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"cc"&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#808030; '&gt;[&lt;/span&gt; &lt;span style='color:#44aadd; '&gt;-z&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#797997; '&gt;$UGID&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#808030; '&gt;]&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;then&lt;/span&gt;&lt;br /&gt;        log_failure_msg &lt;span style='color:#0000e6; '&gt;"user &lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#797997; '&gt;$RUNASUSER&lt;/span&gt;&lt;span style='color:#0f69ff; '&gt;\"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt; does not exist"&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#bb7977; font-weight:bold; '&gt;exit&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;fi&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#bb7977; font-weight:bold; '&gt;cd&lt;/span&gt; &lt;span style='color:#40015a; '&gt;/opt/cruisecontrol&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;.&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/cruisecontrol.sh&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;&gt;&lt;/span&gt; &lt;span style='color:#40015a; '&gt;/dev/null&lt;/span&gt; &lt;span style='color:#008c00; '&gt;2&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;&gt;&amp;amp;1&lt;/span&gt;&lt;br /&gt;    log_end_msg &lt;span style='color:#797997; '&gt;$?&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#e34adc; '&gt;;;&lt;/span&gt;&lt;br /&gt;  stop&lt;span style='color:#e34adc; '&gt;)&lt;/span&gt;&lt;br /&gt;    log_daemon_msg &lt;span style='color:#0000e6; '&gt;"Stopping Cruisecontrol server"&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"cc"&lt;/span&gt;&lt;br /&gt;    start-stop-daemon --stop --quiet --oknodo --pidfile &lt;span style='color:#797997; '&gt;$PIDFILE&lt;/span&gt;&lt;br /&gt;    log_end_msg &lt;span style='color:#797997; '&gt;$?&lt;/span&gt;&lt;br /&gt;    rm &lt;span style='color:#44aadd; '&gt;-f&lt;/span&gt; &lt;span style='color:#797997; '&gt;$PIDFILE&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#e34adc; '&gt;;;&lt;/span&gt;&lt;br /&gt;  restart&lt;span style='color:#e34adc; '&gt;|&lt;/span&gt;force-reload&lt;span style='color:#e34adc; '&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#797997; '&gt;$0&lt;/span&gt; stop &lt;span style='color:#800080; '&gt;&amp;amp;&amp;amp;&lt;/span&gt; sleep &lt;span style='color:#008c00; '&gt;2&lt;/span&gt; &lt;span style='color:#800080; '&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style='color:#797997; '&gt;$0&lt;/span&gt; start&lt;br /&gt;    &lt;span style='color:#e34adc; '&gt;;;&lt;/span&gt;&lt;br /&gt;  status&lt;span style='color:#e34adc; '&gt;)&lt;/span&gt;&lt;br /&gt;    pidofproc &lt;span style='color:#44aadd; '&gt;-p&lt;/span&gt; &lt;span style='color:#797997; '&gt;$PIDFILE&lt;/span&gt; &lt;span style='color:#797997; '&gt;$DAEMON&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#40015a; '&gt;/dev/null&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#797997; '&gt;status&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#797997; '&gt;$?&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#808030; '&gt;[&lt;/span&gt; &lt;span style='color:#797997; '&gt;$status&lt;/span&gt; -eq &lt;span style='color:#008c00; '&gt;0&lt;/span&gt; &lt;span style='color:#808030; '&gt;]&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;then&lt;/span&gt;&lt;br /&gt;        log_success_msg &lt;span style='color:#0000e6; '&gt;"Cruisecontrol server is running."&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;else&lt;/span&gt;&lt;br /&gt;        log_failure_msg &lt;span style='color:#0000e6; '&gt;"Cruisecontrol server is not running."&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;fi&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#bb7977; font-weight:bold; '&gt;exit&lt;/span&gt; &lt;span style='color:#797997; '&gt;$status&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#e34adc; '&gt;;;&lt;/span&gt;&lt;br /&gt;  &lt;span style='color:#808030; '&gt;*&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#bb7977; font-weight:bold; '&gt;echo&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Usage: &lt;/span&gt;&lt;span style='color:#797997; '&gt;$0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt; {start|stop|restart|force-reload|status}"&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#bb7977; font-weight:bold; '&gt;exit&lt;/span&gt; &lt;span style='color:#008c00; '&gt;2&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#e34adc; '&gt;;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;esac&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Этот скрипт нужно поместить в /etc/init.d/cruisecontrol и установить права на исполнение. Нужно также обратить внимание на пользователя &lt;code&gt;RUNASUSER=cruisecontrol&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Приступаем к установке  phpUnderControl, и здесь все сводится к выполнению нескольких команд:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;pear channel-discover components.ez.no&lt;br /&gt;pear channel-discover pear.phpundercontrol.org&lt;br /&gt;pear install --alldeps phpuc/phpUnderControl-beta&lt;br /&gt;/usr/bin/phpuc install /opt/cruisecontrol&lt;/code&gt;&lt;/pre&gt;Проверим, что наш сервер постоянной интеграции запускается, запускаем его &lt;code&gt;/etc/init.d/cruisecontrol start&lt;/code&gt; и смотрим в браузере http://localhost:8080/cruisecontrol/.&lt;br /&gt;&lt;br /&gt;Теперь займемся конфигурацией самого проекта. У CruiseControl конфигурация всех проектов хранится в одном файле config.xml. Установим наш проект:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;cruisecontrol&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;buildafterfailed&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;plugin&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;svnbootstrapper&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;classname&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;net.sourceforge.cruisecontrol.bootstrappers.SVNBootstrapper&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;plugin&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;svn&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;classname&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;net.sourceforge.cruisecontrol.sourcecontrols.SVN&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;plugin&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;phing&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;classname&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;net.sourceforge.cruisecontrol.builders.PhingBuilder&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;listeners&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;currentbuildstatuslistener&lt;/span&gt; &lt;span style='color:#274796; '&gt;file&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;logs/${project.name}/status.txt&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;listeners&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;bootstrappers&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;svnbootstrapper&lt;/span&gt; &lt;span style='color:#274796; '&gt;localWorkingCopy&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;projects/${project.name}/source/&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;bootstrappers&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;modificationset&lt;/span&gt; &lt;span style='color:#274796; '&gt;quietperiod&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;svn&lt;/span&gt; &lt;span style='color:#274796; '&gt;localWorkingCopy&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;projects/${project.name}/source/&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;modificationset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;schedule&lt;/span&gt; &lt;span style='color:#274796; '&gt;interval&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;120&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phing&lt;/span&gt; &lt;span style='color:#274796; '&gt;buildfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;projects/${project.name}/source/build-development.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;uselogger&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usedebug&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;schedule&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;log&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;logs/${project.name}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;merge&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;projects/${project.name}/source/&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;log&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;publishers&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;artifactspublisher&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;projects/${project.name}/build/coverage&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;dest&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;logs/${project.name}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;subdirectory&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;coverage&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;artifactspublisher&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;projects/${project.name}/public/apidocs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;dest&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;logs/${project.name}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;subdirectory&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;api&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;execute&lt;/span&gt; &lt;span style='color:#274796; '&gt;command&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;/usr/bin/phpuc graph logs/${project.name}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;htmlemail&lt;/span&gt; &lt;span style='color:#274796; '&gt;mailhost&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;xx.xx.xx.xx&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;returnaddress&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;noreply@example.com&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;buildresultsurl&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;http://localhost:8080/buildresults/${project.name}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;returnname&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;phpUnderControl server&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;logdir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;logs/${project.name}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;failure&lt;/span&gt; &lt;span style='color:#274796; '&gt;address&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;fail@example.com&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;reportWhenFixed&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;htmlemail&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;publishers&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;cruisecontrol&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Обращу внимание на самое главное, исходных код будет располагаться в &lt;code&gt;projects/example/source&lt;/code&gt;. Здесь же мы должны самостоятельно выполнить checkout проекта. Директивами &lt;code&gt;svn&lt;/code&gt;, &lt;code&gt;svnbootstrapper&lt;/code&gt; мы указываем, чтобы CruiseControl выполнял в каталоге с исходным кодом &lt;code&gt;svn up&lt;/code&gt;. По мере появления новых изменений (в данном случае из центрального svn-репозитория) будет запущен процесс сборки проекта. Для сборки мы используем Phing и скрипт похожий на тот, который обсуждали в &lt;a href="/2011/10/build-php-phing.html"&gt;прошлом посте&lt;/a&gt;. Секция &lt;code&gt;publishers&lt;/code&gt; помимо прочего содержит настройки для отправки уведомлений в случае неудачного билда.&lt;br /&gt;&lt;br /&gt;Теперь стоит взглянуть на сам build-скрипт. Мы немного его дополним: добавим задачу по запуску проверки кода на «дурные запахи», поиск дублирования кода, и т.д.&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;encoding&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;UTF-8&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;default&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;property&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;build.dir&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; (DEFAULT) Target: default                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.tests, run.mess.detector, run.copypast.detector, run.phpcodesniffer, api.docs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;All done.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: api.docs                             &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;api.docs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpdoc&lt;/span&gt; &lt;span style='color:#274796; '&gt;title&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;API Documentation&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;destdir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/public/apidocs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;sourcecode&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;templatebase&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;/usr/share/php/data/phpUnderControl/data/phpdoc&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;output&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;HTML:Phpuc:phpuc&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpdoc&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.tests                            &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonfailure&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonerror&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;todir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpunit&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;plain&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*Test.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.mess.detector                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.mess.detector&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpmd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpmd/phpmd.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;text&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpmd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.copypast.detector                &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.copypast.detector&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcpd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;pmd&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpcpd/phpcpd.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcpd&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.phpcodesniffer                   &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.phpcodesniffer&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcodesniffer&lt;/span&gt; &lt;span style='color:#274796; '&gt;standard&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Zend&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;showSniffs&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;showWarnings&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/classes&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;checkstyle&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#274796; '&gt;outfile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/build/phpcodesniffer/phpcodesniffer.xml&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;summary&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpcodesniffer&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Этот скрипт мы можем проверить, запустив самостоятельно &lt;code&gt;phing -f build-development.xml&lt;/code&gt;. Конечно, чтобы все это работало, нужно установить &lt;a href="http://www.phpdoc.org/"&gt;phpdoc&lt;/a&gt;, &lt;a href="http://pear.php.net/package/PHP_CodeSniffer"&gt;phpcs&lt;/a&gt;, &lt;a href="https://github.com/sebastianbergmann/phpunit/"&gt;phpunit&lt;/a&gt; и &lt;a href="http://www.xdebug.org/"&gt;xdebug&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Теперь можно выполнить несколько тестовых коммитов и понаблюдать за статистикой новых build'ов. Можно даже что-то специально сломать, чтобы проверить, как сервер непрерывной интеграции сообщит о проблеме.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-584445058890412892?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/584445058890412892/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=584445058890412892' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/584445058890412892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/584445058890412892'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/10/php.html' title='Подключаем PHP проект к серверу непрерывной интеграции'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-6357532226459290553</id><published>2011-10-19T15:04:00.000+04:00</published><updated>2011-10-19T15:04:53.666+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='тестирование'/><category scheme='http://www.blogger.com/atom/ns#' term='JS'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Build'/><category scheme='http://www.blogger.com/atom/ns#' term='Тесты'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Phing'/><title type='text'>Автоматизируем build для PHP-проекта с помощью Phing</title><content type='html'>Традиционно с процессом build связывают такие действия, как компиляция, линковка, в итоге представление в исполняемый код. Для PHP и других скриптовых языков во всем этом нет необходимости, однако, build проекта на PHP довольно частая задача. С чем это связано? Прежде всего в понятие build веб-проектов сейчас вкладывают, помимо задач вроде компиляции, такие активности, как:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Тестирование;&lt;/li&gt;&lt;li&gt;Проведение необходимых изменений в БД;&lt;/li&gt;&lt;li&gt;Анализ исходного кода;&lt;/li&gt;&lt;li&gt;Генерация документации;&lt;/li&gt;&lt;li&gt;Минимизация;&lt;/li&gt;&lt;li&gt;Какие-то другие специфические для проекта задачи, которые можно выполнять автоматизированно.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Для PHP-проекта фактическим стандартом для задач build'а является приложение Phing, очень похожее своим подходом на Ant для Java. Подробно изучить Phing можно с помощью документации на &lt;a href="http://www.phing.info/"&gt;официальном сайте&lt;/a&gt;, а также будет полезна вот &lt;a href="http://wiki.agiledev.ru/doku.php?id=automation:build_package_deploy"&gt;эта&lt;/a&gt; развернутая статья (кстати не только про Phing). В этом же посте я расскажу, что Phing довольно стабильно &lt;a href="http://www.phing.info/trac/roadmap"&gt;развивается&lt;/a&gt; с релизом примерно раз в три месяца, в заключении приведу пример build-скрипта.&lt;br /&gt;&lt;br /&gt;Итак начнем с установки (возможностей у Phing'а много, для некоторых типов задач понадобится установить дополнительные библиотеки):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;pear channel-discover pear.phing.info&lt;br /&gt;pear install phing/phing&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Теперь создадим простой build-скрипт build.xml в корне проекта.&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;encoding&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;UTF-8&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Phing example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;default&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;property&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;build.dir&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; (DEFAULT) Target: default                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.speech.engine&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Hello world!&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.speech.engine                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.speech.engine&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;I can speak now!&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Выполнив команду &lt;code&gt;phing&lt;code&gt; (можно также запускать &lt;code&gt;phing&amp;nbsp;-f&amp;nbsp;build.xml&lt;/code&gt; для указания имени запускаемого скрипта) мы получим такой вывод:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Buildfile: /home/username/build-example/build.xml&lt;br /&gt;&lt;br /&gt;Phing example &gt; run.speech.engine:&lt;br /&gt;&lt;br /&gt;     [echo] I can speak now!&lt;br /&gt;&lt;br /&gt;Phing example &gt; default:&lt;br /&gt;&lt;br /&gt;     [echo] Hello world!&lt;br /&gt;&lt;br /&gt;BUILD FINISHED&lt;br /&gt;&lt;br /&gt;Total time: 0.1666 seconds&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Одной из интересных практик для написания build-скриптов является создание несколько разных файлов для разных сред. Например: build-dev.xml, build-stage.xml, build-production.xml. Это действительно имеет смысл, т.к. задачи для каждой среды исполнения разные. Дальше мы попробуем написать два скрипта: build-dev.xml и build-production.xml.&lt;br /&gt;&lt;br /&gt;Первый скрипт для среды разработки будет решать задачи проверки кода, запуска тестов и генерации документации. Начнем с проверки кода на синтаксические ошибки, для этого нужно использовать тип задач &lt;a href="http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixC-OptionalTasks.html#PhpLintTask"&gt;PhpLintTask&lt;/a&gt;:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;encoding&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;UTF-8&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Phing example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;default&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;property&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;build.dir&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; (DEFAULT) Target: default                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;All done.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: lint.legacy                          &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/application/lib&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;После запуска вывод будет примерно таким: &lt;br /&gt;&lt;pre&gt;&lt;code&gt;Buildfile: /home/username/build-example/build-dev.xml&lt;br /&gt;&lt;br /&gt;Phing example &gt; lint.legacy:&lt;br /&gt;&lt;br /&gt;  [phplint] ./application/lib/auth.class.php: No syntax errors detected&lt;br /&gt;  [phplint] ./application/lib/session.class.php: No syntax errors detected&lt;br /&gt;  [phplint] ./application/lib/video.class.php: No syntax errors detected&lt;br /&gt;&lt;br /&gt;Phing example &gt; default:&lt;br /&gt;&lt;br /&gt;     [echo] All done.&lt;br /&gt;&lt;br /&gt;BUILD FINISHED&lt;br /&gt;&lt;br /&gt;Total time: 2.3877 seconds&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Переходим к запуску тестов, и здесь можно использовать задачи &lt;a href="http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixC-OptionalTasks.html#PHPUnitTask"&gt;PHPUnitTask&lt;/a&gt; или &lt;a href="http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixC-OptionalTasks.html#SimpleTestTask"&gt;SimpleTestTask&lt;/a&gt; в зависимости от используемого фреймворка для тестирования.&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;encoding&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;UTF-8&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Phing example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;default&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;property&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;build.dir&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; (DEFAULT) Target: default                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy, run.tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;All done.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: lint.legacy                          &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/application/lib&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.tests                            &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonfailure&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonerror&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;plain&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/application/tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*Test.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Последнее, что мы решили делать, это получать документацию API исходного кода. Для этого я рекомендую использовать задачу &lt;a href="http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixC-OptionalTasks.html#DocBloxTask"&gt;DocBloxTask&lt;/a&gt;.&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;encoding&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;UTF-8&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Phing example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;default&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;property&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;build.dir&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; (DEFAULT) Target: default                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy, run.tests, api.docs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;All done.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: lint.legacy                          &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;lint.legacy&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/application/lib&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phplint&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: run.tests                            &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;run.tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonfailure&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;haltonerror&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;formatter&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;plain&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;usefile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;false&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/application/tests&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*Test.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;batchtest&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;phpunit&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: api.docs &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;api.docs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;docblox&lt;/span&gt; &lt;span style='color:#274796; '&gt;title&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;API Docs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;destdir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/public/apidocs&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#274796; '&gt;quiet&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/application/lib&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;**/*.php&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;docblox&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;В итоге при запуске phing -f build-dev.xml у нас получается такой вывод:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Buildfile: /home/username/build-example/build-dev.xml&lt;br /&gt;&lt;br /&gt;Phing example &gt; lint.legacy:&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;Phing example &gt; run.tests.legacy:&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;Phing example &gt; api.docs:&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;Phing example &gt; default:&lt;br /&gt;&lt;br /&gt;     [echo] All done.&lt;br /&gt;&lt;br /&gt;BUILD FINISHED&lt;br /&gt;&lt;br /&gt;Total time: 26.5158 seconds&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Переходим к build-production.xml. Здесь задачи уже другие, нам более интересно минимизировать некоторые файлы (css, js) и объединить небольшие файлы одного типа. У нас получится примерно такой build-скрипт:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#004a43; '&gt;&amp;lt;?&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;xml&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;version&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#7d0045; '&gt;1.0&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;encoding&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;UTF-8&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#004a43; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Phing example&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;default&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;property&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;build.dir&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;value&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;./public&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; (DEFAULT) Target: default                    &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;default&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify.css.all, minify.js.all, concatenate.css, concatenate.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;All done.&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: minify.css.all                       &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify.css.all&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Compressing CSS with YUI Compressor&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;fileset.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;global.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;blocks.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;foreach&lt;/span&gt; &lt;span style='color:#274796; '&gt;param&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;filename&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;absparam&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;absfilename&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;target&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;refid&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;fileset.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;foreach&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;move&lt;/span&gt; &lt;span style='color:#274796; '&gt;todir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;overwrite&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;mapper&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;glob&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;from&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;to&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*.min.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;refid&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;fileset.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;move&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: minify.js.all                        &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify.js.all&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Compressing JS with YUI Compressor&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;fileset.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;global.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;foreach&lt;/span&gt; &lt;span style='color:#274796; '&gt;param&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;filename&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;absparam&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;absfilename&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;target&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;refid&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;fileset.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;foreach&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;move&lt;/span&gt; &lt;span style='color:#274796; '&gt;todir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;overwrite&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;true&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;mapper&lt;/span&gt; &lt;span style='color:#274796; '&gt;type&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;glob&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;from&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;to&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;*.min.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;refid&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;fileset.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;move&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: minify                               &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Minimizing: ${filename}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;exec&lt;/span&gt; &lt;span style='color:#274796; '&gt;command&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;java -jar yuicompressor.jar ${absfilename} -o ${absfilename}&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: concatenate.css                      &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;concatenate.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify.css.all&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Concatenating CSS&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;delete&lt;/span&gt; &lt;span style='color:#274796; '&gt;file&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/css/all.min.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;append&lt;/span&gt; &lt;span style='color:#274796; '&gt;destFile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/css/all.min.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;global.min.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;blocks.min.css&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;append&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; Target: concatenate.js                       &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#696969; '&gt;&amp;lt;!--&lt;/span&gt;&lt;span style='color:#696969; '&gt; ============================================ &lt;/span&gt;&lt;span style='color:#696969; '&gt;--&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;concatenate.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#274796; '&gt;depends&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;minify.js.all&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;echo&lt;/span&gt; &lt;span style='color:#274796; '&gt;msg&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;Concatenating JS&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;delete&lt;/span&gt; &lt;span style='color:#274796; '&gt;file&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/js/all.min.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;append&lt;/span&gt; &lt;span style='color:#274796; '&gt;destFile&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/js/all.min.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt; &lt;span style='color:#274796; '&gt;dir&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;${build.dir}/js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;global.min.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;include&lt;/span&gt; &lt;span style='color:#274796; '&gt;name&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;gallery.min.js&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"&lt;/span&gt; &lt;span style='color:#a65700; '&gt;/&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;fileset&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;append&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;target&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;project&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Здесь для минимизации мы использовать &lt;a href="http://developer.yahoo.com/yui/compressor/"&gt;YUI compressor&lt;/a&gt;, а для объединения файлов — директиву &lt;a href="http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixB-CoreTasks.html#AppendTask"&gt;append&lt;/a&gt;. Вывод будет примерно таким:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Buildfile: /home/username/build-example/build-dev.xml&lt;br /&gt;&lt;br /&gt;Phing example &gt; minify.css.all:&lt;br /&gt;&lt;br /&gt;     [echo] Compressing CSS with YUI Compressor&lt;br /&gt;&lt;br /&gt;Phing example &gt; minify.js.all:&lt;br /&gt;&lt;br /&gt;     [echo] Compressing JS with YUI Compressor&lt;br /&gt;&lt;br /&gt;Phing example &gt; concatenate.css:&lt;br /&gt;&lt;br /&gt;     [echo] Concatenating CSS&lt;br /&gt;     ...&lt;br /&gt;&lt;br /&gt;Phing example &gt; concatenate.js:&lt;br /&gt;&lt;br /&gt;     [echo] Concatenating JS&lt;br /&gt;     ...&lt;br /&gt;&lt;br /&gt;Phing example &gt; default:&lt;br /&gt;&lt;br /&gt;     [echo] All done.&lt;br /&gt;&lt;br /&gt;BUILD FINISHED&lt;br /&gt;&lt;br /&gt;Total time: 3.3199 seconds&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;На этом пример build для PHP проекта можно считать завершенным. Спасибо за внимание, и делитесь, для чего вы используете build в ваших проектах!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-6357532226459290553?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/6357532226459290553/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=6357532226459290553' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/6357532226459290553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/6357532226459290553'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/10/build-php-phing.html' title='Автоматизируем build для PHP-проекта с помощью Phing'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-6615667715578879120</id><published>2011-10-09T21:31:00.001+04:00</published><updated>2011-10-09T21:32:02.830+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='производительность'/><category scheme='http://www.blogger.com/atom/ns#' term='высокие нагрузки'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='highload'/><category scheme='http://www.blogger.com/atom/ns#' term='конференция'/><title type='text'>Самые интересные выступления Highload++ 2011</title><content type='html'>&lt;p&gt;Сегодня я бы хотел рассказать о выступлениях на &lt;a href="http://www.highload.ru/"&gt;Highload++&lt;/a&gt;, которые мне запомнились и показались полезными.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Впервые в рунете: сказ о 100М писем в день / Андрей Сас (Badoo)&lt;/b&gt;&lt;br /&gt;Андрей рассказывал о том, как в Badoo организована отправка многочисленных писем, как они следят за средним временем с момента постановки письма в очередь и до момента доставки. О чем Андрей категорически не стал рассказывать, так это о том, как они добиваются попадания письма именно во входящие, а не спам – NDA. Одной из интересных деталей архитектуры от Badoo является очередь, как я уже заметил. Более того, одна очередь существует для генерации самих писем, а другая очередь – для их отправки. В качестве движка очередей ребята выбрали… файловую систему, так как, по мнению Андрея, очень легко добавлять новое сообщение в очередь (создать файл), легко посмотреть сколько всего сообщений в очереди (сколько файлов)  и т.д. Если такое решение о файловой системе не дает вам покоя (почему сделан такой выбор), то можно отыскать почту Андрея и расспросить все у него.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Web-scale MySQL at Facebook / Domas Mituzas&lt;/b&gt;&lt;br /&gt;Это выступление проходило на английском, но интересно, что Domas может даже немного говорить на русском и еще лучше понимает наш прекрасный язык. Выступление было обзорным, то есть никаких потрясающих вещей мы не услышали, нам просто рассказали какие патчи для MySQL написали в Facebook. Думаю, что всю эту информацию можно найти вот здесь: &lt;a href="https://launchpad.net/mysqlatfacebook"&gt;https://launchpad.net/mysqlatfacebook&lt;/a&gt;. Во время выступления я делал некоторые заметки, и вот кое-что: для лучшего масштабирования в Facebook используют свое творение &lt;a href="https://github.com/facebook/flashcache"&gt;Flashcache&lt;/a&gt; (прозрачное кэширование данных на дисках SSD); свои патчи ребята разрабатывают для MySQL 5.1, версию 5.5 они решили пропустить, а вот MySQL 5.6 не пропустят.&lt;/p&gt;&lt;p&gt;&lt;b&gt;12 вариантов использования Redis — в Tarantool / Александр Календарев, Константин Осипов (Mail.ru)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Решардинг Redis "на живую" / Андрей Смирнов, Василий Евсеенко (Skype)&lt;/b&gt;&lt;br /&gt;Два эти выступления мне показались интересным, несмотря на то, что с Redis я не работал. Здесь я просто рекомендую, если эта тема вам интересна, найти видеозаписи этих докладом или как минимум слайды, они должны быть адекватными и полезными.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Pconnect: граната в руках обезьяны / Сергей Аверин (Badoo)&lt;/b&gt;&lt;br /&gt;В течение 45 минут Сергей пытался напугать публику постоянными подключениями к БД, что у него скорее всего получилось. На самом деле, Сергей разложил по полочкам на что обязательно нужно обращать внимание перед тем, как начать использовать pconnect, например для MySQL. Здесь, мне кажется, слайды должны быть не менее полезными, чем видео.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Низкоуровневая оптимизация C/C++ / Андрей Аксенов (Sphinx)&lt;/b&gt;&lt;br /&gt;Поймал себя на мысли, что я перестал обращать внимание на тему выступлений Андрея Аксенова, а мне достаточно увидеть только имя, чтобы решить пойти на его доклад. Такая вот у него особенная стилистика выступлений. Что же касается темы, то она должна быть интересна тем, кто имеет дело с C/C++: сначала были общие интересные принципы (было показано на примерах, как последовательное чтение из оперативной памяти отличается от не совсем последовательного), а затем пошла специфика, вплоть до того сколько микро-нано-секунд можно выиграть от замены оператора switch на несколько if.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Новое в MySQL 5.5, 5.6 и Percona Server для высоких нагрузок / Петр Зайцев (Percona)&lt;/b&gt;&lt;br /&gt;Петр Зайцев очень уважаемый человек в мире MySQL, слушать его интересно, но увы, это выступление было полностью обзорным. Петр рассказал о нововведениях в версиях 5.5 и будущей версии 5.6. И то и другое можно без труда найти на mysql.com. У меня сложилось впечатление, что нет смысла чего-то ожидать от получасового выступления Петра, на какой бы конференции оно не состоялось – лучше рассмотреть возможность участия в мастер-классах.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Архитектура хранилища бинарных данных на Одноклассниках / Александр Христофоров, Олег Анастасьев (Одноклассники)&lt;/b&gt;&lt;br /&gt;Ребята из Одноклассников рассказали, какие изменения они проделали для более оптимального хранения изображений, загруженных пользователями. Видео этого выступления должно быть полезным хотя бы для того, чтобы изучить какие вообще решения этой задачи выбирают разные команды. У меня не получится рассказать полностью идею Одноклассников, но вот некоторые интересные особенности: каждые данные дублируются на трех жестких дисках, а бэкапы создаются не для самих данных, а для индексов (что на этом диске есть); все данные (все изображения) на одном диске записываются в один файл; неважно на каком сервере установлен диск, если его подключить к другому серверу, то данные с этого диска будут работать.&lt;p&gt;&lt;p&gt;Это было последнее выступление, о котором я хотел бы рассказать. Кстати, именно такого типа выступлений (как наша команда решила архитектурную задачу) я ждал от этой конференции, но их было чрезвычайно мало. Тем не менее, наверняка на Highload были и другие интересные доклады, которые я не смог послушать или просто пропустил, об этом наверняка поделились другие участники конференции.&lt;/p&gt;&lt;p&gt;Спасибо за внимание!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-6615667715578879120?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/6615667715578879120/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=6615667715578879120' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/6615667715578879120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/6615667715578879120'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/10/highload-2011.html' title='Самые интересные выступления Highload++ 2011'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-5476424844221230908</id><published>2011-08-29T22:31:00.001+04:00</published><updated>2011-08-29T22:34:15.329+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Личное'/><title type='text'>Немного о работе</title><content type='html'>Сегодня я бы хотел рассказать читателям о своей новой работе. На работе многие из нас проводят огромную часть своего времени, и поэтому почему бы этим не поделиться, рассказать над чем сейчас работаешь, и что будет впереди.&lt;br /&gt;&lt;br /&gt;Итак, уже полгода я работаю ведущим разработчиком в &lt;a href="http://tobecontinued.ru/"&gt;объединенной компании&lt;/a&gt; «Афиши» и «Рамблера». Сейчас это две компании, которые уже примерно год пробуют работать совместно. &lt;br /&gt;&lt;br /&gt;В объединенной компании я занимаюсь проектом &lt;a href="http://nightparty.ru/"&gt;Nightparty&lt;/a&gt;. Этот проект был запущен еще в 2003 году и сейчас является одним из самых популярных проектов о клубной культуре, вечеринках, музыке и людях, которые ко всему этому причастны. Тематика проекта мне очень нравится и близка. Редакция Nightparty — весьма молодая и состоит из очень креативных людей.  &lt;br /&gt;&lt;br /&gt;С 2003 года проект не один раз менял, как технически, так и визуально. Вот так выглядел логотип Nightparty в прошлом :)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="283" width="400" src="http://3.bp.blogspot.com/-IAmsnYTXEYU/TlvVlHEZQcI/AAAAAAAAAas/EkLd3QesRYc/s400/poster3.gif" /&gt;&lt;/div&gt;&lt;br /&gt;А вот более современное изображение проекта (плакат с прошлогоднего Казантипа):&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://msk.nightparty.ru/foto/ofsession/one/kazantip_z19_by_grebenev_chast_1_2011_08_20/4575877/" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="267" width="400" src="http://2.bp.blogspot.com/-5_hRCYV80uI/TlvWogiONMI/AAAAAAAAAa8/-yVK9Ci-9k4/s400/00000-000-4575877-992.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Nightparty работает, что не удивительно на PHP, используется Zend Framework. Код проекта выполняется на нескольких application-серверах, между которыми балансируется нагрузка. Для СУБД используется MySQL 5.1. &lt;br /&gt;&lt;br /&gt;Одной из самых востребованных фитч проекта являются фотоотчеты — выполненные профессионалами фотографии с интересных событий и вечеринок. Для работы фотоотчетов организовано несколько серверов-хранилищ.&lt;br /&gt;&lt;br /&gt;Помимо решения интересных и технически нетривиальных задач, я бы хотел рассказать что еще мне нравится в своей работе. Первое, что бросилось в глаза — это то, что здесь работают очень сильные менеджеры, специалисты по проектированию и usability-специалисты: новые фитчи, которые отправляются в разработку, действительно интересные и продуманные. Еще я бы хотел отметить большой опыт коллег в содержании и администрировании огромного количества серверов.&lt;br /&gt;&lt;br /&gt;Мои коллеги-разработчики здесь работают на других платформах, и их опыт мне очень интересен. В Афише традиционно разрабатывают на ASP.NET, в Рамблере - это Python и Perl, а также мобильные платформы. Вообще опыт работы в объединенной компании похож на работу сразу в двух организациях, очень интересно наблюдать над тем как сотрудники Афиши и Рамблера знакомятся друг с другом, начинают вместе работать, придумывают и делают новые продукты.&lt;br /&gt;&lt;br /&gt;Наша команда, сейчас ищет новых участников — PHP разработчиков, которые уверенно работают с PHP5. Если вы хотите присоединиться, то смело пишите &lt;a href="mailto:khamukhin@gmail.com"&gt;мне&lt;/a&gt;, и я отвечу на все вопросы!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-5476424844221230908?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/5476424844221230908/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=5476424844221230908' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5476424844221230908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5476424844221230908'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/08/blog-post.html' title='Немного о работе'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-IAmsnYTXEYU/TlvVlHEZQcI/AAAAAAAAAas/EkLd3QesRYc/s72-c/poster3.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-3489675746340958245</id><published>2011-08-07T21:29:00.000+04:00</published><updated>2011-08-07T21:29:39.601+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='zend framework'/><title type='text'>Блоки и виджеты в  Zend Framework</title><content type='html'>В проектах, где используется Zend Framework, часто по-своему решается вопрос с размещением на страницах одинаковых блоков или виджетов. Например, это может быть блок авторизации, где для новых посетителей отображается приглашение для регистрации или авторизации. Другой пример – это блок рекламы на странице. &lt;br /&gt;&lt;br /&gt;В самом простом виде такие блоки помещаются в макете (layout), но если требования к блокам хотя бы не много возрастают (например, блок рекламы должен быть не на всех страницах), то приходится что-то придумывать.&lt;br /&gt;&lt;br /&gt;Одним из вариантов решения данной проблемы в ZF является вызов какого-то специального действия этого же или другого контроллера из шаблона страницы:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;div&lt;/span&gt;&lt;span style='color:#274796; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;id&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"sidebar right"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;div&lt;/span&gt;&lt;span style='color:#274796; '&gt; &lt;/span&gt;&lt;span style='color:#074726; '&gt;class&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"item"&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; background:#ffffe8; '&gt;&amp;lt;?php&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;echo&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;action&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'list'&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'comment'&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;null&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;array&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'count'&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#008c00; background:#ffffe8; '&gt;10&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#a65700; background:#ffffe8; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;div&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;div&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Здесь в шаблоне вызывается действие «list» контроллера «comment» с передачей параметра count = 10. Такой подход имеет ряд недостатков. Во-первых, здесь происходит дополнительная диспетчеризация. Во-вторых, в самих таких действиях для виджетов приходится что-то придумывать, чтобы их не вызывали напрямую (по URL). И еще одна проблема заключается в том, что логика запрашиваемой страницы строится не только вызванным контроллером, но и, возможно, каким-то другим контроллером, вызываемым из представления. То есть получается частично перевернутая модель MVC. &lt;br /&gt;&lt;br /&gt;Более интересным был бы механизм в ZF, позволяющий в контроллере определять, какие блоки должны быть на запрашиваемой странице. Что-то подобное у меня получилось найти в &lt;a href="http://torqueo.net/blocks-in-zend-framework-final-version/"&gt;одном&lt;/a&gt; и &lt;a href="http://weierophinney.net/matthew/archives/246-Using-Action-Helpers-To-Implement-Re-Usable-Widgets.html"&gt;втором&lt;/a&gt; посте. Немного совместив эти идеи, получилось примерно следующее.&lt;br /&gt;&lt;br /&gt;Каждый блок оформляется как Action Controller Helper. Чтобы выделить все блоки вместе, необходимо определить в своем &lt;code&gt;Bootstrap.php&lt;/code&gt;:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//init resourse type for blocks&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;protected&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; _initResourceLoader&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;{&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$loader&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;new&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; Zend_Loader_Autoloader_Resource&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;array&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'basePath'&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; APPLICATION_PATH&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'namespace'&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;''&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$loader&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;addResourceType&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'block'&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'blocks'&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'Block'&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;}&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Тогда код всех блоком можно смело размещать в каталоге &lt;code&gt;applications\blocks&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Чтобы было легче добавлять блоки в контроллерах, необходимо добавить еще один хелпер, который я назвал &lt;code&gt;Project_Controller_Action_Helper_Block&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Хелпер подключается в &lt;code&gt;Bootstrap’е&lt;/code&gt; и содержит пока только один интересный метод &lt;code&gt;add()&lt;/code&gt;, который можно использовать в коде контроллеров для добавления на страницы блоков:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;public&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; indexAction&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;{&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//add blocks to page&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;_helper&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;_block&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#400000; background:#ffffe8; '&gt;add&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'userLogin'&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;_helper&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;_block&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#400000; background:#ffffe8; '&gt;add&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'wellcomeMessage'&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;}&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Сами блоки сохраняют какой-то готовый для вывода контент в свои собственные сегменты макета. В макете вывод выглядит обычным образом:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#a65700; background:#ffffe8; '&gt;&amp;lt;?php&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;echo&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;layout&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;userLogin&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#a65700; background:#ffffe8; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; background:#ffffe8; '&gt;&amp;lt;?php&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;echo&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;layout&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;wellcomeMessage&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#a65700; background:#ffffe8; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Если блок не добавляли в контроллере, то просто ничего не будет выведено.&lt;br /&gt;&lt;br /&gt;На этом пока все. В реальных проектах, здесь, конечно, много что можно добавить, и в одном из следующих постов я постараюсь об этом написать!&lt;br /&gt;&lt;br /&gt;Весь исходный код можно посмотреть &lt;a href="https://github.com/khamukhin/zf-examples/tree/master/block-helpers"&gt;здесь&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-3489675746340958245?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/3489675746340958245/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=3489675746340958245' title='Комментарии: 9'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3489675746340958245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3489675746340958245'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/08/zend-framework.html' title='Блоки и виджеты в  Zend Framework'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-1155092835066907938</id><published>2011-06-08T22:43:00.001+04:00</published><updated>2011-06-08T22:46:43.725+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='тестирование'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Тесты'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Хорошие практики написания тестов для TDD</title><content type='html'>Не так давно для разработчиков в &lt;a href="http://tobecontinued.ru/"&gt;компании&lt;/a&gt;, где я теперь работаю, &lt;a href="http://www.google.com/profiles/biBIGone#about"&gt;Андрей Бибичев&lt;/a&gt; проводил тренинг TDD - Test Driven Development. Сейчас, спустя некоторое время, я бы хотел записать здесь самые основные моменты, рассказать о тех приемах, которые мне помогли, и которыми у меня получается пользоваться каждый день.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Название тестовых методов&lt;/b&gt;&lt;br /&gt;Как ни странно, правильное название для класса или метода - это очень важная часть разработки. Тоже самое действует и для методов тестов. Одна из хороших практик названий методов - давать названия вроде &lt;code&gt;ShouldDoSomethingIfSomeValueGiven&lt;/code&gt;, начиная с "should". Или, если использовать PHPUnit, то &lt;code&gt;testShouldDoSomethingForEmptyString&lt;/code&gt;, тоже самое с приставкой "test". Ничего страшного, если название получается длинным, зато название точно отражает, что сейчас тестируется.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Что тестировать&lt;/b&gt;&lt;br /&gt;Если честно признаться, то до тренинга, я всегда старался писать по одному методу в тесте на один проверяемый метод. Теперь я поступаю иначе: каждый метод теста, это какой-то определенный случай. Что-то, что должно произойти, если дернуть за какую-то ручку. Или наоборот не должно произойти. Сколько методов теста писать? Столько, сколько придумаете! На самом деле нужно самому уметь останавливаться на чем-то разумном (сразу вспомнилось, что первые 20% усилий - дают 80% результата). &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Пример выделения тест-кейсов&lt;/b&gt;  &lt;br /&gt;Приведу небольшой пример для тестирования диалогового окна печати в Windows (воображаемый класс page с интересуемым методом parse), нам надо проверить поле, в котором вводятся номера страниц, которые нужно напечатать.&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#a65700; background:#ffffe8; '&gt;&amp;lt;?php&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;class&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; pageTest &lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;extends&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;{&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; testShouldBeEmptyForEmptyString&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;{&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//GIVEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$emptyString&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;''&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//WHEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$result&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; page&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;::&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;parse&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$emptyString&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//THEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;assertEquals&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; background:#ffffe8; '&gt;0&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#400000; background:#ffffe8; '&gt;sizeof&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$result&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;}&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; testShoultBeSinglePageForStringWithNumber&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;{&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//GIVEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$numberString&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;'123'&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//WHEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$result&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; page&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;::&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;parse&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$numberString&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//THEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;assertEquals&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; background:#ffffe8; '&gt;1&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#400000; background:#ffffe8; '&gt;sizeof&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$result&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;}&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; testShouldThrowOutOfRangeExceptionWhenGetWithInvalidIndex&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;{&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//GIVEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$wrongString&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#0000e6; background:#ffffe8; '&gt;"2345"&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$result&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;=&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; page&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;::&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;parse&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$wrongString&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//WHEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//get some index (123) from page range ($result)&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#696969; background:#ffffe8; '&gt;//THEN&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$&lt;/span&gt;&lt;span style='color:#800000; background:#ffffe8; font-weight:bold; '&gt;this&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;assertFalse&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#400000; background:#ffffe8; '&gt;in_array&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; background:#ffffe8; '&gt;123&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;,&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt; &lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;$result&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; background:#ffffe8; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;;&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&amp;#xa0;&amp;#xa0;&amp;#xa0;&amp;#xa0;&lt;/span&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;}&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; background:#ffffe8; '&gt;}&lt;/span&gt;&lt;span style='color:#000000; background:#ffffe8; '&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; background:#ffffe8; '&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Структура каждого теста&lt;/b&gt;&lt;br /&gt;Каждый тестовый метод можно разбить на три части: GIVEN, WHEN, THEN (дано, когда, тогда). В первой части мы задаем какие-то начальные условия, когда тестовый случай может наступить. Во второй части, выполняем какой-то метод проверяемого кода, здесь должно быть основное действие, которое мы хотим проверить. В последней части мы размещаем набор ассертов, делаем проверку, что результат имеет ожидаемые значения.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Писать тесты трудно&lt;/b&gt;&lt;br /&gt;Да, очень трудно писать тесты, если проверяемый код уже был написан до тестов. Если следовать TDD, то этот процесс совсем не трудный, но увлекательный. Архитектура самого кода становится при этом более правильной.&lt;br /&gt;&lt;br /&gt;Happy TDDing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-1155092835066907938?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/1155092835066907938/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=1155092835066907938' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/1155092835066907938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/1155092835066907938'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/06/tdd.html' title='Хорошие практики написания тестов для TDD'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-7181383936994323010</id><published>2011-05-26T22:31:00.001+04:00</published><updated>2011-05-27T10:35:11.069+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nix'/><category scheme='http://www.blogger.com/atom/ns#' term='Userscript'/><title type='text'>Userscript для уведомлений в OWA</title><content type='html'>Во многих компаниях в качестве корпоративной почты используется Microsoft Exchange. При этом сотрудники, которые предпочитают ОС на основе Linux, в любом случае испытывают неудобства: всеми возможностями корпоративной почты удается воспользоваться с трудом. Если администраторы разрешили поддержку IMAP, SMTP, то половина проблем решена. Однако получить доступ к календарю и адресной книге сложнее.&lt;br /&gt;&lt;br /&gt;Один из вариантов решения проблемы &amp;mdash; это использование программы &lt;a href="http://davmail.sourceforge.net/"&gt;DavMail&lt;/a&gt;. Программа позволяет получить из Exchange открытые стандарты: IMAP, SMTP, LDAP и Caldav, с которыми умеет работать огромное количество свободных программ. К сожалению, это решение пока плохо работает с новой версией Exchange 2010 (там нет поддержки Webdav).&lt;br /&gt;&lt;br /&gt;С другой стороны в Exchange 2010 представлен более пригодный к повседневному использованию веб-интерфейс (OWA). Но, чтобы полностью перейти на работу с почтой через веб-интерфейс, не хватает уведомлений о новых сообщениях. Чтобы победить этот недостаток, можно воспользоваться таким userscript'ом:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#696969; '&gt;// ==UserScript==&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;// @name           OWA 2010 Notify&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;// @namespace      &amp;lt;namespace&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;// @include        &amp;lt;include&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#696969; '&gt;// ==/UserScript==&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;window&lt;span style='color:#808030; '&gt;.&lt;/span&gt;checkNewMailElement &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;function&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;var&lt;/span&gt; newMailCount &lt;span style='color:#808030; '&gt;=&lt;/span&gt; document&lt;span style='color:#808030; '&gt;.&lt;/span&gt;getElementById&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;'spnCV'&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;var&lt;/span&gt; count &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;newMailElement&lt;span style='color:#808030; '&gt;.&lt;/span&gt;style&lt;span style='color:#808030; '&gt;.&lt;/span&gt;display &lt;span style='color:#808030; '&gt;!=&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;'none'&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;newMailCount&lt;span style='color:#808030; '&gt;.&lt;/span&gt;innerHTML&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;{&lt;/span&gt;&lt;br /&gt;            count &lt;span style='color:#808030; '&gt;=&lt;/span&gt; newMailCount&lt;span style='color:#808030; '&gt;.&lt;/span&gt;innerHTML&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#800080; '&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        GM_notification&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"New "&lt;/span&gt; &lt;span style='color:#808030; '&gt;+&lt;/span&gt; count &lt;span style='color:#808030; '&gt;+&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;" message(s)"&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Outlook"&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#0f4d75; '&gt;null&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;        window&lt;span style='color:#808030; '&gt;.&lt;/span&gt;setTimeout&lt;span style='color:#808030; '&gt;(&lt;/span&gt;checkNewMailElement&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#008c00; '&gt;5000&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800080; '&gt;}&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;else&lt;/span&gt;&lt;span style='color:#800080; '&gt;{&lt;/span&gt;&lt;br /&gt;        window&lt;span style='color:#808030; '&gt;.&lt;/span&gt;setTimeout&lt;span style='color:#808030; '&gt;(&lt;/span&gt;checkNewMailElement&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1000&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#800080; '&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; '&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;var&lt;/span&gt; newMailElement &lt;span style='color:#808030; '&gt;=&lt;/span&gt; document&lt;span style='color:#808030; '&gt;.&lt;/span&gt;getElementById&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;'lnkNwMl'&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;newMailElement&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;{&lt;/span&gt;&lt;br /&gt;    window&lt;span style='color:#808030; '&gt;.&lt;/span&gt;setTimeout&lt;span style='color:#808030; '&gt;(&lt;/span&gt;checkNewMailElement&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1000&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#800080; '&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Сами уведомления скрипт создает с помощью функции &lt;a href="https://github.com/erikvold/scriptish/wiki/GM_notification"&gt;GM_notification&lt;/a&gt;, которой нет в Greasemonkey, но она есть в его форке - &lt;a href="https://github.com/erikvold/scriptish"&gt;Scriptish&lt;/a&gt;. Для Firefox нужно именно дополнение Scriptish, чтобы воспользоваться приведенным скриптом.&lt;br /&gt;&lt;br /&gt;А вот так это выглядит (Mac + Growl и Ubuntu 11.04):&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-mrikRuQ9WZE/Td6ZTsChKOI/AAAAAAAAAXY/KCC9ksg4GBk/s1600/Screen%2Bshot%2B2011-05-26%2Bat%2B22.16.53.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="115" width="400" src="http://4.bp.blogspot.com/-mrikRuQ9WZE/Td6ZTsChKOI/AAAAAAAAAXY/KCC9ksg4GBk/s400/Screen%2Bshot%2B2011-05-26%2Bat%2B22.16.53.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-o0D2sOZYXYs/Td9FwjCJO7I/AAAAAAAAAXg/FhDeYJdQXSo/s1600/Screenshot.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="191" width="376" src="http://1.bp.blogspot.com/-o0D2sOZYXYs/Td9FwjCJO7I/AAAAAAAAAXg/FhDeYJdQXSo/s400/Screenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-7181383936994323010?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/7181383936994323010/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=7181383936994323010' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/7181383936994323010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/7181383936994323010'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/05/userscript-owa.html' title='Userscript для уведомлений в OWA'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-mrikRuQ9WZE/Td6ZTsChKOI/AAAAAAAAAXY/KCC9ksg4GBk/s72-c/Screen%2Bshot%2B2011-05-26%2Bat%2B22.16.53.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-8747368719212475406</id><published>2011-03-01T00:31:00.001+03:00</published><updated>2011-03-01T00:33:18.155+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='производительность'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><title type='text'>Как MySQL выполняет соединения</title><content type='html'>В MySQL соединения реализуются с помощью вложенных циклов (nested-loop). Причем соединения &amp;mdash; это более общее понятие, чем запросы с JOIN'ами. Даже запросы адресованные к одной таблице выполняются по алгоритму nested-loop.&lt;br /&gt;&lt;br /&gt;Если попробовать коротко словами описать этот алгоритм, то получится примерно следующее. Первоначально перебираются все строки первой таблицы, для каждой найденной строки во вложенном цикле идет поиск в следующей таблицы. Для найденных строк во второй таблице продолжается поиск строк третьей таблицы также во вложенном цикле, и так далее. Если во вложенном цикле строки, удовлетворяющие условию соединения не могут быть найдены, то происходит возврат к предыдущей таблице для поиска дополнительной строки.&lt;br /&gt;&lt;br /&gt;Звучит более запутанно, чем есть на самом деле :)&lt;br /&gt;&lt;br /&gt;Псевдокод для выбора строк вложенными циклами может выглядеть следующим образом (для таблиц Table1 — range join, Table2 — ref join , Table3 — ALL join):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;// $rowSetTable1 - matching range&lt;br /&gt;foreach ($rowSetTable1 as $row) {&lt;br /&gt; &lt;br /&gt; // $rowSetTable2 - matching ref key&lt;br /&gt; foreach ($rowSetTable2 as $row) {&lt;br /&gt;  &lt;br /&gt;  foreach ($rowSetTable3 as $row) {&lt;br /&gt;  &lt;br /&gt;   if ( $row condition ) {&lt;br /&gt;    // send to client&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;Рассмотрим пример запроса, в котором участвуют таблицы Table1 и Table2:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;SELECT t1.col1, t1.col2, t2.col3&lt;br /&gt;FROM Table1 t1 INNER JOIN Table2 t2 USING (col2)&lt;br /&gt;WHERE t1.col1 = 'a' OR t1.col1 = 'b';&lt;/code&gt;&lt;/pre&gt;Визуально план выполнения запроса показан на swimlane-диаграмме:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-3MWLPLT1NK8/TWwTPU80nYI/AAAAAAAAAW8/gw8ra8CjMPo/s1600/nested-loop.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="158" width="400" src="http://4.bp.blogspot.com/-3MWLPLT1NK8/TWwTPU80nYI/AAAAAAAAAW8/gw8ra8CjMPo/s400/nested-loop.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Существуют определенные виды запросов, которые выполняются крайне неэффективно с использованием вложенных циклов, о таких запросах и способах оптимизации я расскажу в одном из следующих постов.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-8747368719212475406?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/8747368719212475406/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=8747368719212475406' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/8747368719212475406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/8747368719212475406'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/03/mysql.html' title='Как MySQL выполняет соединения'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-3MWLPLT1NK8/TWwTPU80nYI/AAAAAAAAAW8/gw8ra8CjMPo/s72-c/nested-loop.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-5195655704799829600</id><published>2011-02-27T21:34:00.000+03:00</published><updated>2011-02-27T21:34:07.503+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nix'/><title type='text'>Используем по полной cd</title><content type='html'>Команду &lt;code&gt;cd&lt;/code&gt; (или иногда &lt;code&gt;chdir&lt;/code&gt;), меняющую текущий каталог, пожалуй знают все. Поэтому важно уметь пользоваться такими базовыми командами на все 100.&lt;br /&gt;&lt;br /&gt;Что может быть особенного в &lt;code&gt;cd&lt;/code&gt;? На самом деле только два интересных момента.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;cd без параметров&lt;/b&gt;&lt;br /&gt;Если просто написать &lt;code&gt;cd&lt;/code&gt; без параметров, то также как и &lt;code&gt;cd ~&lt;/code&gt;, команда переместит вас в домашний каталог.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;cd -&lt;/b&gt;&lt;br /&gt;&lt;code&gt;cd -&lt;/code&gt; сменит директорию на прошлую, там где вы были до того, как в прошлый раз выполняли &lt;code&gt;cd&lt;/code&gt;. Так можно быстро перемещаться между какими-то двумя каталогами. Путь до прошлой директории хранится в переменной окружения OLDPWD, с помощью значения этой переменной &lt;code&gt;cd -&lt;/code&gt; и работает.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;user@desktop:~$ cd /usr/share/&lt;br /&gt;user@desktop:/usr/share$ cd ~/www/sorting/&lt;br /&gt;user@desktop:~/www/sorting$ cd -&lt;br /&gt;/usr/share&lt;br /&gt;user@desktop:/usr/share$ cd -&lt;br /&gt;/home/user/www/sorting&lt;/code&gt;&lt;/pre&gt;Текущий каталог хранится в переменной окружения PWD, одноименная команда &lt;code&gt;pwd&lt;/code&gt; (print working directory) выводит текущий каталог.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-5195655704799829600?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/5195655704799829600/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=5195655704799829600' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5195655704799829600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5195655704799829600'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/02/cd.html' title='Используем по полной cd'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-950332584322489480</id><published>2011-01-18T19:39:00.001+03:00</published><updated>2011-01-18T19:42:12.013+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nix'/><category scheme='http://www.blogger.com/atom/ns#' term='Битрикс'/><title type='text'>Stdin, stdout, stderr</title><content type='html'>Стандартные потоки в Unix-подобных ОС являются каналами ввода/вывода между программой и окружением.&lt;br /&gt;&lt;br /&gt;Дескрипторы стандартных потоков:&lt;ul&gt;&lt;li&gt;0 — стандартный ввод stdin;&lt;/li&gt;&lt;li&gt;1 — стандартный вывод stdout;&lt;/li&gt;&lt;li&gt;2 — поток для ошибок stderr.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Очень полезны конструкции, которые позволяют вывод из одного потока направить в другой. Например, так ошибки будут сохранены в заданный файл:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;command 2&gt; error.log&lt;/code&gt;&lt;/pre&gt;Другой пример сохраняет вывод  stderr и  stdout в файл:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;command &gt; file-name 2&gt;&amp;1&lt;br /&gt;command &amp;&gt; file-name&lt;/code&gt;&lt;/pre&gt;При запуске команд из PHP с помощью &lt;a href="http://www.php.net/manual/en/function.shell-exec.php" target="_blank"&gt;shell_exec()&lt;/a&gt; или `обратных кавычек`, в PHP возвращается только  stdout, но не  stderr. Здесь будет полезным перенаправление из stderr в  stdout: &lt;br /&gt;&lt;pre&gt;&lt;code&gt;command 2&gt;&amp;1&lt;/code&gt;&lt;/pre&gt;В качестве небольшого дополнения, а также финального отступление от темы, приведу небольшой совет, как получить дополнительный доступ при работе с сайтами на Битриксе (конечно, если доступ нужен). С помощью командной PHP-строки (обычно страница доступна по URL /bitrix/admin/php_command_line.php) можно запускать терминальные команды:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;echo nl2br(`tail -n 100 /var/log/apache2/site-error.log 2&gt;&amp;1`);&lt;/code&gt;&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="222" width="400" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/TTXBf8_afII/AAAAAAAAAWw/IAO0JparQ8Y/s400/Selection_002.png" /&gt;&lt;/div&gt;Дополнение в конце команды &lt;code&gt;2&gt;&amp;1&lt;/code&gt;, как уже определили, позволяет вывести ошибки, которые могут возникнуть.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-950332584322489480?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/950332584322489480/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=950332584322489480' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/950332584322489480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/950332584322489480'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2011/01/stdin-stdout-stderr.html' title='Stdin, stdout, stderr'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/__mL_0Lk97DQ/TTXBf8_afII/AAAAAAAAAWw/IAO0JparQ8Y/s72-c/Selection_002.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-3625754678841473936</id><published>2010-12-16T19:55:00.000+03:00</published><updated>2010-12-16T19:55:44.113+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>Нововведения в  MySQL 5.5</title><content type='html'>На прошлой неделе у меня получилось принять участие во встрече Moscow MySQL User Group (&lt;a href="https://groups.google.com/group/moscow-mysql-user-group?hl=ru"&gt;MMUG&lt;/a&gt;), где в основном обсуждали новую версию MySQL.&lt;br /&gt;&lt;br /&gt;Сегодня также вышла новость о &lt;a href="http://www.opennet.ru/opennews/art.shtml?num=29009"&gt;релизе стабильной версии MySQL 5.5&lt;/a&gt;, и поэтому сейчас определенно настало самое лучшее время для написания поста про нововведения в версии 5.5.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Исправление ошибок&lt;/b&gt;&lt;br /&gt;Одной из главных тем новой версии, стало исправление многочисленных ошибок. Даже исправили один или несколько очень старых багов еще с трехзначным номером.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Повышение быстродействия&lt;/b&gt;&lt;br /&gt;Для большей скорости было добавлено много улучшений:&lt;ul&gt;&lt;li&gt;Несколько buffer_pool'ов (рекомендуется разбивать после того, как один buffer_pool становится больше 1 GB, так лучше утилизируется CPU, растет масштабируемость);&lt;/li&gt;&lt;li&gt;Теперь insert_buffer работает не только для insert'ов, но и для update'ов, detele'ов;&lt;/li&gt;&lt;li&gt;Снова работает group commit (в момент fsync собирается несколько транзакция);&lt;/li&gt;&lt;li&gt;Flush из  buffer_pool теперь более плавный (иначе обычно видны скачки в быстродействии).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Инструменты диагностики&lt;/b&gt;&lt;ul&gt;&lt;li&gt;Performance_schema — содержит данные для диагностики производительности (но данные на текущем этапе очень низкоуровневые, в основном на уровне мьютексов);&lt;/li&gt;&lt;li&gt;Команда SHOW ENGINE INNODB STATUS;&lt;/li&gt;&lt;li&gt;Новые таблицы в information_schema (можно посмотреть такие параметры, как trx_innodb_locks и trx_innodb_waits).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Репликация&lt;/b&gt;&lt;ul&gt;&lt;li&gt;Полу-синхронная репликация в виде плагина, позволяет добиться следующего: если был сделан коммит, то можно быть уверенным, что соответствующая запись на диск была сделана в bin log  на slave;&lt;/li&gt;&lt;li&gt;Heartbeat — события на slave (насколько я понял, позволяют раньше находить проблемы между master и slave);&lt;/li&gt;&lt;li&gt;Relay log — автоматическое восстановление при падении slave.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Удобство&lt;/b&gt;&lt;ul&gt;&lt;li&gt;SIGNAL и RESIGNAL для обработки ошибок в хранимых процедурах (как throw catch);&lt;/li&gt;&lt;li&gt;Появилось больше опций для Partitioning;&lt;/li&gt;&lt;li&gt;Возможность выполнить truncate для одной партиции;&lt;/li&gt;&lt;li&gt;Pluggable authentication - пока есть только интерфейс, а сами плагины появятся через примерно полгода.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Если очень коротко, то это все основные моменты, о которых я узнал. Вообще на встрече MMUG звучали настойчивые призывы переходить на версию MySQL 5.5. Было сказано, что это один из лучших релизов, в котором проделана большая работа над ошибками (исправили много багов, причем очень давних), а также сделан упор на стабильность и производительность.&lt;br /&gt;&lt;br /&gt;В заключении несколько материалов со встечи MMUG в тему: &lt;a href="http://narod.ru/disk/1226855001/MySQL-5.5-Features-ru-MMUG.pdf.html"&gt;cлайды&lt;/a&gt; о новых возможностей MySQL 5.5 и &lt;a href="http://devconf.tv/video/NKSKB94D9MG3/MySQL-55"&gt;видео со встречи&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-3625754678841473936?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/3625754678841473936/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=3625754678841473936' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3625754678841473936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3625754678841473936'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/12/mysql-55.html' title='Нововведения в  MySQL 5.5'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-1649625442231191095</id><published>2010-12-06T20:17:00.000+03:00</published><updated>2010-12-06T20:17:33.848+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><category scheme='http://www.blogger.com/atom/ns#' term='nix'/><title type='text'>Скачиваем файл с сервера по SSH</title><content type='html'>Случаются такие моменты, когда на удаленном сервере находится файл, который нужен на локальной машине. Например, это может быть какой-то большой лог-файл, который нужно проанализировать.&lt;br /&gt;&lt;br /&gt;Загрузить файл с сервера можно с помощью огромного множества программ, наверняка любимая IDE способна это сделать. Но здесь я опишу, как можно скачать файл не имея практически ничего под рукой, кроме стандартной консоли (или &lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/"&gt;PuTTY&lt;/a&gt; для случая с Windows).&lt;br /&gt;&lt;br /&gt;Скачать файл можно такой командой:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;scp user@host:/directory/SourceFile TargetFile&lt;/code&gt;&lt;/pre&gt;Синтаксис здесь очень похож на синтаксис команды cp. Обратное копирование файла с локальной машины на удаленный сервере (или с одного сервера на другой):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;scp SourceFile user@host:directory/TargetFile&lt;/code&gt;&lt;/pre&gt;Если на локальной машине для авторизация с сервером по протоколу SSH &lt;a href="/2008/10/ssh.html"&gt;настроен ключ&lt;/a&gt;, то команду можно записывать с помощью вашего алиаса сервера:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;scp myserver:/directory/SourceFile TargetFile&lt;/code&gt;&lt;/pre&gt;И в заключении, стоит отметить, что на машинах с Windows можно воспользоваться pscp, одной из утилит, которая идет в комплекте PuTTY:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;pscp user@host:/directory/SourceFile TargetFile&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-1649625442231191095?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/1649625442231191095/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=1649625442231191095' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/1649625442231191095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/1649625442231191095'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/12/ssh.html' title='Скачиваем файл с сервера по SSH'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-5283007126438386339</id><published>2010-10-20T22:41:00.002+04:00</published><updated>2010-11-09T08:31:02.477+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='паттерны'/><category scheme='http://www.blogger.com/atom/ns#' term='ООП'/><title type='text'>Синонимы паттернов проектирования</title><content type='html'>Одним из преимуществ шаблонов проектирования принято считать легкость в обсуждении проектных решений: достаточно одному разработчику назвать ключевое слово (название шаблона проектирования) и все сразу поймут, о чем идет речь. При этом нет необходимости многословно описывать различные отношения между объектами или схемы наследования классов, и это действительно хорошо.&lt;br /&gt;&lt;br /&gt;Но бывает так, что в обсуждении проектных решений становится не так легко понять друг друга, если собеседники используют синонимы паттернов. Чтобы помочь в этом разобраться, в этом посте я попробую привести мини-сводку синонимов наиболее распространенных шаблонов проектирования.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Abstract Factory&lt;/b&gt;: Kit;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Adapter&lt;/b&gt;: Wrapper;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Bridge&lt;/b&gt;: Handle-body (описатель-тело);&lt;/li&gt;&lt;li&gt;&lt;b&gt;Command&lt;/b&gt;: Action, Transaction;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Facade&lt;/b&gt;: Glue;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Factory Method&lt;/b&gt;: Virtual Constructor;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Iterator&lt;/b&gt;: Cursor;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Memento (хранитель)&lt;/b&gt;: Token (лексема);&lt;/li&gt;&lt;li&gt;&lt;b&gt;Observer&lt;/b&gt;: Dependents, Publish-subscribe;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Proxy (заместитель)&lt;/b&gt;: Surrogate;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Singleton&lt;/b&gt;: Solitaire (холостяк);&lt;/li&gt;&lt;li&gt;&lt;b&gt;Visitor&lt;/b&gt;: Walker (бродяга).&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-5283007126438386339?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/5283007126438386339/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=5283007126438386339' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5283007126438386339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5283007126438386339'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/10/blog-post_20.html' title='Синонимы паттернов проектирования'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-2240647367131327780</id><published>2010-10-14T22:24:00.001+04:00</published><updated>2010-10-14T22:25:34.936+04:00</updated><title type='text'>Небольшие перемены</title><content type='html'>У меня давно было желание использовать свой домен YetAnother, который я случайно нашел. И сегодня это получилось сделать — представляю новое, более IT-ишное имя моего блога — &lt;a href="http://blog.yetanother.ru"&gt;Yet Another Blog&lt;/a&gt; или в сокращенном варианте YaB.&lt;br /&gt;&lt;br /&gt;Как мне подсказали поисковики, блогов с таким названием на самом деле много, но, думаю, что это не страшно, - на то и "Yet Another" в  Yet Another Blog.&lt;br /&gt;&lt;br /&gt;P.S. Постараюсь делать посты в YaB чаще :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-2240647367131327780?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/2240647367131327780/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=2240647367131327780' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2240647367131327780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2240647367131327780'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/10/blog-post.html' title='Небольшие перемены'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-5181423504487092454</id><published>2010-10-06T00:52:00.002+04:00</published><updated>2010-10-06T01:05:19.547+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><title type='text'>Буферизация результатов запроса в MySQL</title><content type='html'>Иногда на стороне PHP требуется обработать большое количество данных, например, перебрать все строки большой таблицы.&lt;br /&gt;&lt;br /&gt;Недавно мой коллега &lt;a href="http://alexey.shockov.com/"&gt;Алексей Шоков&lt;/a&gt; рассказал об интересной возможности — использование результатов выборки MySQL без буферизации. Обычно, при выполнении запроса на выборку такая функция, как mysql_query, буферизирует все строки данных на стороне клиента, прежде чем передать эти данные в PHP-приложение, то есть весь результат сначала накапливается. Но есть возможность начать работать с результатом раньше, по мере поступления данных.&lt;br /&gt;&lt;br /&gt;Для этого существует функция &lt;a href="http://www.php.net/manual/en/function.mysql-unbuffered-query.php"&gt;mysql_unbuffered_query&lt;/a&gt;:&lt;blockquote&gt;mysql_unbuffered_query() sends the SQL query query to MySQL without automatically fetching and buffering the result rows as mysql_query() does. This saves a considerable amount of memory with SQL queries that produce large result sets, and you can start working on the result set immediately after the first row has been retrieved as you don't have to wait until the complete SQL query has been performed.&lt;/blockquote&gt;Пока идет обработка результатов сам запрос можно увидеть в списке процессов MySQL со статусом «Writing to net». В памяти на стороне клиента при этом находятся только данные для одной строки.&lt;br /&gt;&lt;br /&gt;В блоге MySQL Performance Blog можно посмотреть &lt;a href="http://www.mysqlperformanceblog.com/2006/06/26/handling-of-big-parts-of-data/"&gt;статью&lt;/a&gt; с замерами времени выполнения запросов при использовании функций mysql_query против mysql_unbuffered_query. При обработке большой таблицы последняя выигрывает.&lt;br /&gt;&lt;br /&gt;Однако, есть некоторые ограничения использования запросов без буферизации. Здесь все вполне очевидно — нельзя использовать функции mysql_num_rows() и mysql_data_seek(), а также нельзя выполнять другие запросы в пределах одного соединения, пока не завершена работа с первым небуферизированным.&lt;br /&gt;&lt;br /&gt;Кроме того, согласно документации &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/mysql-use-result.html"&gt;MySQL C API&lt;/a&gt; пока идет обработка результатов запроса без буферизации (например обработка на стороне PHP), &lt;span style="font-weight:bold;"&gt;невозможно обновлять данные ни в одной таблице&lt;/span&gt;, которая задействована в запросе. Это ограничение представляется самым неприятным на первый взгляд. Но на самом деле, это справедливо в случае, если используется MyISAM со своей блокировкой на уровне таблиц. Если же для таблиц используется InnoDB, то обновлять данные в таблицах, задействованных для запроса без буферизации, очень даже можно. Таким образом, для определенного круга задач, такой подход в построении запросов на выборку может дать дополнительный выигрыш.&lt;br /&gt;&lt;br /&gt;В заключении приведу небольшие участки кода для использования запросов без буферизации с другими драйверами MySQL в PHP, а также для Perl.&lt;code&gt;&lt;pre&gt;//PDO&lt;br /&gt;$dbh = new PDO(&lt;br /&gt;    'mysql:host=localhost;dbname=example', &lt;br /&gt;    'user', &lt;br /&gt;    'password', &lt;br /&gt;    array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY =&gt; false));&lt;br /&gt;//execute some unbuffered query&lt;br /&gt;//...&lt;br /&gt;&lt;br /&gt;//change buffered settings&lt;br /&gt;$dbh-&gt;setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);&lt;/code&gt;&lt;/pre&gt;Для mysqli аналогичный результат можно получить, если добавить второй параметр MYSQLI_USE_RESULT к вызову &lt;a href="http://php.net/manual/en/mysqli.query.php"&gt;mysqli::query&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Для Perl пример кода выглядит так:&lt;code&gt;&lt;pre&gt;use DBI();&lt;br /&gt;my $dbh = DBI-&gt;connect(&lt;br /&gt; "DBI:mysql:database=example;mysql_use_result=1;host=localhost", &lt;br /&gt; "user", &lt;br /&gt; "password");&lt;br /&gt;//execute some unbuffered query&lt;br /&gt;//...&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-5181423504487092454?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/5181423504487092454/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=5181423504487092454' title='Комментарии: 6'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5181423504487092454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/5181423504487092454'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/10/mysql.html' title='Буферизация результатов запроса в MySQL'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-4829677972283012309</id><published>2010-10-05T20:58:00.003+04:00</published><updated>2010-10-05T21:12:05.062+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TCP'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTP'/><category scheme='http://www.blogger.com/atom/ns#' term='TELNET'/><title type='text'>Немного о TELNET</title><content type='html'>TELNET — это сетевой протокол, первая версия которого появилась в 1969 году, для удаленного доступа к серверу с помощью передачи текстовых команд. Так же называют различные утилиты для клиентской работы с этим протоколом.&lt;br /&gt;&lt;br /&gt;Изначально протокол был задуман для удаленного доступа к интерфейсу командной строки операционной системы. Однако в TELNET не предусмотрено ни шифрование, ни проверка подлинности данных, и поэтому от протокола давно отказались, как от средства для управления ОС (в пользу SSH).&lt;br /&gt;&lt;br /&gt;Сейчас чаще всего TELNET можно использовать для проверки работоспособности ресурсов, отладки по протоколам HTTP, SMTP, POP3 и других текстовых протоколов. Кроме того, TELNET используется для управляющего соединения FTP.&lt;br /&gt;&lt;br /&gt;Попробуем провести диагностику одного из наших сайтов.&lt;br /&gt;&lt;br /&gt;Для подключения необходимо ввести: &lt;code&gt;&lt;pre&gt;telnet allsoft.ru 80&lt;/pre&gt;&lt;/code&gt;После этого необходимо ввести запрос и указать хост – доменное имя сайта, к которому этот запрос относится (ведь на сервере может быть несколько виртуальных хостов).&lt;br /&gt;&lt;br /&gt;Чтобы посмотреть заголовки индексной страницы сайта, нужно ввести:&lt;code&gt;&lt;pre&gt;HEAD / HTTP/1.1&lt;br /&gt;Host: allsoft.ru&lt;/pre&gt;&lt;/code&gt;И после два раза нажать Enter. Ответ будет примерно таким (можно производить диагностику по коду 200 OK):&lt;code&gt;&lt;pre&gt;HTTP/1.1 200 OK&lt;br /&gt;Server: nginx&lt;br /&gt;Date: Tue, 05 Oct 2010 17:00:06 GMT&lt;br /&gt;Content-Type: text/html; charset=windows-1251&lt;br /&gt;Transfer-Encoding: chunked&lt;br /&gt;Connection: keep-alive&lt;br /&gt;X-Powered-By: PHP/4.4.4-8+etch6&lt;br /&gt;Set-Cookie: PHPSESSID=11de9255db99fcf0c439bec8eb1712df; path=/&lt;br /&gt;Expires: Mon, 26 Jul 1997 05:00:00 GMT&lt;br /&gt;Cache-Control: no-cache, must-revalidate&lt;br /&gt;Pragma: no-cache&lt;/pre&gt;&lt;/code&gt;Чтобы посмотреть не только заголовки, но и исходный код, например, этой страницы http://allsoft.ru/sysadmins/, то можно ввести:&lt;code&gt;&lt;pre&gt;GET /sysadmins/ HTTP/1.1&lt;br /&gt;Host: allsoft.ru&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-4829677972283012309?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/4829677972283012309/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=4829677972283012309' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/4829677972283012309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/4829677972283012309'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/10/telnet.html' title='Немного о TELNET'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-3241527447239867824</id><published>2010-08-05T23:12:00.009+04:00</published><updated>2010-08-05T23:38:10.237+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='мотивация'/><category scheme='http://www.blogger.com/atom/ns#' term='менеджмент'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Innovation games</title><content type='html'>На этой неделе во вторник мне вместе с коллегами посчастливилось побывать на специальном семинаре Innovation Games, который для нас провел &lt;a href="http://nikfilippov.moikrug.ru/"&gt;Никита Филиппов&lt;/a&gt;. Мероприятие мне понравилось, и поэтому я бы хотел немного рассказать о нем.&lt;br /&gt;&lt;br /&gt;В качестве небольшого вступления стоит рассказать, что Innovation games – это в первую очередь произведение от &lt;a href="http://www.lukehohmann.com/"&gt;Luke Hohmann’а&lt;/a&gt; (полное название книги "Innovation Games: Creating Breakthrough Products Through Collaborative Play"). Речь идет о небольших мероприятиях, которые можно провести с командой, об играх. Цель этих игр – это не только провести весело время, а выявить то, чего вы не знаете, о чем вы не подозреваете или, как рассказывал Никита Филиппов – не знаете, что это не знаете. Таким образом, инновационные игры являются для наблюдателей  своеобразным маркетинговым исследованием. &lt;br /&gt;&lt;br /&gt;Теперь я расскажу о каждой игре, в которой участвовал, плюс несколько фотографий с места событий.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Spider Web&lt;/span&gt;&lt;br /&gt;Для нас в центре большого листа был подготовлен круг с надписью "Product Owner", необходимо было придумать другие роли и связать их с Product Owner’ом, а также пояснить эти связи.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__mL_0Lk97DQ/TFsPIChPvGI/AAAAAAAAAUM/KefTecxC964/s1600/photo+2.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 283px; height: 320px;" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/TFsPIChPvGI/AAAAAAAAAUM/KefTecxC964/s320/photo+2.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5502008000552877154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Speed Boat&lt;/span&gt;&lt;br /&gt;Участникам нужно было представить быструю яхту, которая может нестись по морю. Однако на пути яхты могут быть препятствия, так называемые "камни", которые мешают быстро двигаться, да и яхта может повредиться. Нужно было придумать такие "камни", и самые опасные поместить выше – ближе всего к лодке. В нашем случае в качестве лодки нужно было представить свою карьеру.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__mL_0Lk97DQ/TFsPqigZ4sI/AAAAAAAAAUU/vahuYLZ4wI8/s1600/photo+4.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/TFsPqigZ4sI/AAAAAAAAAUU/vahuYLZ4wI8/s320/photo+4.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5502008593254834882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Remember the Future&lt;/span&gt;&lt;br /&gt;В компанию приходит новый разработчик, и первое время он, как правило, обучается. Полноценную пользу он начинает приносить, скажем, через три месяца работы. Участникам игры Remember the Future нужно было придумать, что нужно за три месяца сделать руководителю для нового сотрудника, чтобы он полностью влился, стал самым классным Разработчиком! Игра сложна тем, что действия нужно было придумывать в обратном порядке: то есть сначала нужно было придумать самое последнее действие (примерно на третьем месяце), затем ближе к тому моменту, когда новый сотрудник только появился (второй и первый месяц).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__mL_0Lk97DQ/TFsQptoxuKI/AAAAAAAAAUc/5aQgTiit5mc/s1600/photo+1.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/TFsQptoxuKI/AAAAAAAAAUc/5aQgTiit5mc/s320/photo+1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5502009678574500002" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Prune the Product Tree&lt;/span&gt;&lt;br /&gt;На очень большой заготовке было нарисовано дерево с большими корнями, ветками и листвой.  В общем случае, листья на ветка – это фитчи, сами ветки – это релизы продукта. Корни – это то, на чем стоит проект, например техническая инфраструктура. В нашем случае правила были немного другие, для нас проектом была карьера в компании.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__mL_0Lk97DQ/TFsQ7k92LhI/AAAAAAAAAUk/Y1UAFFBZEfc/s1600/photo+5.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://2.bp.blogspot.com/__mL_0Lk97DQ/TFsQ7k92LhI/AAAAAAAAAUk/Y1UAFFBZEfc/s320/photo+5.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5502009985484598802" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Buy a Feature&lt;/span&gt;&lt;br /&gt;Участники получили прайс-лист с ценами за каждую фитчу. Каждый участник располагает определенной суммой, скажем, каждый имеет по $10. На все фитчи каждому не хватает, и чтобы что-то купить, нужно договориться с другими участниками, убедить их, что именно эта фитча более необходима.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Product Box&lt;/span&gt;&lt;br /&gt;Участники представляют, что они продают коробку с… в нашем случае с лучшем Product owner’ом. Нам нужно было разработать дизайн коробки, сделать ее такой, чтобы именно нашего Product owner’а все хотели купить! В распоряжении были белые коробки, цветные фломастеры, клей, ножницы, несколько журналов и стикеров.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__mL_0Lk97DQ/TFsRoXUUanI/AAAAAAAAAU8/qsuE9Su127k/s1600/photo+32.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 246px; height: 320px;" src="http://3.bp.blogspot.com/__mL_0Lk97DQ/TFsRoXUUanI/AAAAAAAAAU8/qsuE9Su127k/s320/photo+32.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5502010754914871922" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__mL_0Lk97DQ/TFsRn69Hi2I/AAAAAAAAAU0/fueeomes8I0/s1600/photo+31.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://4.bp.blogspot.com/__mL_0Lk97DQ/TFsRn69Hi2I/AAAAAAAAAU0/fueeomes8I0/s320/photo+31.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5502010747301366626" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__mL_0Lk97DQ/TFsRnldeiqI/AAAAAAAAAUs/uBCYoNfcjxI/s1600/photo+3.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://2.bp.blogspot.com/__mL_0Lk97DQ/TFsRnldeiqI/AAAAAAAAAUs/uBCYoNfcjxI/s320/photo+3.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5502010741531511458" /&gt;&lt;/a&gt;Команда, где я участвовал, выпустила очень клевую коробку с Product Owner’ом "S. Jobs"!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-3241527447239867824?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/3241527447239867824/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=3241527447239867824' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3241527447239867824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3241527447239867824'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/08/innovation-games.html' title='Innovation games'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/__mL_0Lk97DQ/TFsPIChPvGI/AAAAAAAAAUM/KefTecxC964/s72-c/photo+2.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-4802474722794321383</id><published>2010-08-05T10:31:00.002+04:00</published><updated>2010-08-05T10:40:01.625+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Headhunter'/><title type='text'>Требования к разработчику</title><content type='html'>В очередной раз составлял требования к разработчику в нашу команду. И на этот раз решил записать этот список в свой блог, чтобы:&lt;ul&gt;&lt;li&gt;во-первых, не забывать о том, что уже писал;&lt;/li&gt;&lt;li&gt;и во-вторых, спросить, &lt;span style="font-weight:bold;"&gt;что на Ваш взгляд нужно добавить или убрать?&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Основные обязанности&lt;/span&gt;&lt;ul&gt;&lt;li&gt;проектирование архитектуры проекта, поиск нестандартных решений;&lt;/li&gt;&lt;li&gt;разработка веб-приложения под большую нагрузку (PHP/MySQL) и активное участие во всём процессе разработки (от проектирования и до запуска и поддержки);&lt;/li&gt;&lt;li&gt;взаимодействие с коллегами, обсуждение дизайна приложений.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Требования&lt;/span&gt;&lt;ul&gt;&lt;li&gt;PHP - опыт работы с языком от 2 лет, отличное знание сильных и слабых сторон, в т.ч. нововведения версии 5.3 (приветствуется Сертификат Zend Certified Engineer, также приветствуется опыт работы с 1С-Битрикс);&lt;/li&gt;&lt;li&gt;ООП - опыт самостоятельного создания и использования объектов (любого языка программирования) от 6 мес.;&lt;/li&gt;&lt;li&gt;Шаблоны проектирования - уверенное знание и способность на собеседовании продемонстрировать эффективное использование на языке PHP любого из 23 шаблонов GoF;&lt;/li&gt;&lt;li&gt;SQL и MySQL - понимание стратегии оптимизации веб-приложений, опыт написания запросов к MySQL от 1 года (приветствуется опыт работы с PostgreSQL);&lt;/li&gt;&lt;li&gt;Unix/linux как минимум на уровне продвинутого пользователя.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Личные качества&lt;/span&gt;&lt;ul&gt;&lt;li&gt;доброжелательность, исполнительность,  желание развиваться;&lt;/li&gt;&lt;li&gt;ориентированность на результат, умение соблюсти срок или вовремя сигнализировать о проблемах;&lt;/li&gt;&lt;li&gt;уважение к чужому мнению, умение идти на компромиссы.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-4802474722794321383?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/4802474722794321383/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=4802474722794321383' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/4802474722794321383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/4802474722794321383'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/08/blog-post.html' title='Требования к разработчику'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-7573910329552072542</id><published>2010-04-23T21:16:00.007+04:00</published><updated>2010-04-24T00:08:49.099+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software People'/><category scheme='http://www.blogger.com/atom/ns#' term='конференция'/><title type='text'>Репортаж с Software People - часть 2</title><content type='html'>Сегодня прошел второй день конференции Software People 2010. И сегодня же я сразу попробую изложить некоторые интересные тезисы с разных выступлений. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Типичный день эффективного лидера – Сурен Самарчан&lt;/span&gt;&lt;br /&gt;Из чего состоит день менеджера проекта? Сурен рассказал о дневных активностях и качествах менеджеров.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__mL_0Lk97DQ/S9HqvKy7nsI/AAAAAAAAATY/Lq3jgcusC-M/s1600/IMG_0504.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/__mL_0Lk97DQ/S9HqvKy7nsI/AAAAAAAAATY/Lq3jgcusC-M/s320/IMG_0504.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5463405919049850562" /&gt;&lt;/a&gt;Усиление своей команды. До того, как человек стал менеджером, было важно, насколько хорошо он сам работал. Теперь важно другое – насколько хорошо работает команда. Пути усиления команды:&lt;ul&gt;&lt;li&gt;Поиск и привлечение лучших сотрудников, и увольнение худших;&lt;/li&gt;&lt;li&gt;Использовать любое событие (провал или победу) для обучения;&lt;/li&gt;&lt;li&gt;Работать в паре (2 менеджера): фидбэк, рассуждение вслух;&lt;/li&gt;&lt;li&gt;Кросс-функциональные задания;&lt;/li&gt;&lt;li&gt;Для трудных задач донести команде, что любое задание – это последовательность простых шагов,  это повысит уверенность;&lt;/li&gt;&lt;li&gt;Критика;&lt;/li&gt;&lt;li&gt;Стараться мыслить в реальном времени, например, на совещании принимать решение не заранее, а во время.&lt;/li&gt;&lt;/ul&gt;Самостоятельность. Это должно сводиться практически к одному – лидер уходит, команда продолжает добиваться успехов и развиваться. Все понятные лидеру активности должны выполняться без него.&lt;br /&gt;&lt;br /&gt;Энергия. Лидер должен заряжать энергией команду – показывать светлое будущее и конкретные шаги к нему. На практике, это предполагает:&lt;ul&gt;&lt;li&gt;Работать больше всех, не уставать, не жаловаться, не паниковать, не унывать;&lt;/li&gt;&lt;li&gt;Проактивно реагировать на инициативы;&lt;/li&gt;&lt;li&gt;Организация легкой конкуренции;&lt;/li&gt;&lt;li&gt;Устраивать демонстрации клиентам, топ-менеджерам;&lt;/li&gt;&lt;li&gt;Не отдаляться от команды, жить успехом команды;&lt;/li&gt;&lt;li&gt;Переоценивать людей (немного выше, чем они есть).&lt;/li&gt;&lt;/ul&gt;Атмосфера. Должна быть искренность и открытость, слова и мысли должны быть синхронны. Что можно сделать на практике:&lt;ul&gt;&lt;li&gt;Начать с себя;&lt;/li&gt;&lt;li&gt;Давать обещания на 1 уровень абстракции выше (например, не обещать, что сложный проект будет сделан через год, а пообещать, что разработка будет идти итерациями с демонстрацией результатов после каждой итерации);&lt;/li&gt;&lt;li&gt;Не нужно присваивать чужие заслуги, это плохо сказывается на атмосфере;&lt;/li&gt;&lt;li&gt;Необходимо показывать отношение к проблемам, как-то реагировать на каждое негативное высказывание участников команды.&lt;/li&gt;&lt;/ul&gt;Вопросы. До того, как вы были менеджером, вам нужно было отвечать на вопросы. Теперь ваша задача – задавать вопросы. На практике могут пригодиться такие приемы:&lt;ul&gt;&lt;li&gt;Если вы не эксперт в области, то нужно детально изучить какой-то небольшой фрагмент, и задавать вопросы по нему. Тогда команда будет думать, что вы знаете все;&lt;/li&gt;&lt;li&gt;Должно чувствоваться ваше присутствие (проверять решение вопроса, задавать его еще раз через какое-то время).&lt;/li&gt;&lt;/ul&gt;И последнее, что я бы хотел передать с этого выступления – это очень интересный прием. Если команда теряет интерес к работе (у команды уже длительное время все получается), то можно назначить для очередной итерации deadline в 2 раза меньший, то есть поделить настоящий deadline пополам и назвать команде эту цифру  :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Технология командообразования – Сергей Архипенков&lt;/span&gt;&lt;br /&gt;По мнению Сергея, процесс командообразования состоит из трех шагов:&lt;ol&gt;&lt;li&gt;Правильные люди;&lt;/li&gt;&lt;li&gt;Лидерство;&lt;/li&gt;&lt;li&gt;Точим пилу.&lt;/li&gt;&lt;/ol&gt;Мне показалось очень интересным определением «правильных людей». Их эффективность - это интеллект (IQ) помноженный на эмоциональный интеллект (EQ) в квадрате.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__mL_0Lk97DQ/S9Hq69gCpPI/AAAAAAAAATg/4i_zANoASKg/s1600/IMG_0507.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/S9Hq69gCpPI/AAAAAAAAATg/4i_zANoASKg/s320/IMG_0507.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5463406121639388402" /&gt;&lt;/a&gt;Эмоциональный интеллект предполагает, что человек осознал себя, что он есть и чего хочет. Также должна быть воля, и умение увидеть глазами другого человека.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Связи решают все Особенно обратные – Александр Орлов&lt;/span&gt;&lt;br /&gt;Александр потрясающе рассказал о том, какие проблемы бывают у менеджера с получением или пониманием обратной связи, что нужно сделать, чтобы избежать этих проблем, и быть на коне!&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__mL_0Lk97DQ/S9HrIihEdTI/AAAAAAAAATo/SzU7ugDDtGE/s1600/IMG_0512.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/__mL_0Lk97DQ/S9HrIihEdTI/AAAAAAAAATo/SzU7ugDDtGE/s320/IMG_0512.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5463406354914112818" /&gt;&lt;/a&gt;Вот ключевые мысли:&lt;ul&gt;&lt;li&gt;Должен быть канал обратной связи между разработчиком и пользователем продукта;&lt;/li&gt;&lt;li&gt;Необходимо регулярно встречаться с людьми (участниками команды) один на один;&lt;/li&gt;&lt;li&gt;Доносить до людей конструктивную обратную связь;&lt;/li&gt;&lt;li&gt;Говорить Спасибо;&lt;/li&gt;&lt;li&gt;Не ругать публично человека, это нужно делать наедине;&lt;/li&gt;&lt;li&gt;Конструктивно доносить обратную связь – иначе останется осадок, человек будет думать, что менеджер не хочет видеть его в команде; здесь можно использовать правило «сэндвича»: похвалить, затем поругать, затем снова похвалить;&lt;/li&gt;&lt;li&gt;Думать о результате, а не о процессе (например, не отключать доступ к башоргу, вполне возможно, что это никак отрицательно на результат, на работу человека не влияет);&lt;/li&gt;&lt;li&gt;Получать обратную связь от сотрудников к менеджеру;&lt;/li&gt;&lt;li&gt;Устраивать личные ретроспективы, например для того, чтобы посмотреть все ли перечисленные рекомендации выполняются.&lt;/li&gt;&lt;/ul&gt;И последнее что я бы хотел отметить, это доклады, которые я не буду пересказывать, но, тем не менее, они мне очень понравились. Это выступления Константина Кондратюка, Максима Дорофеева и Асхата Уразбаева.&lt;br /&gt;&lt;br /&gt;Спасибо за внимание! Ждем новых конференций!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-7573910329552072542?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/7573910329552072542/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=7573910329552072542' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/7573910329552072542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/7573910329552072542'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/04/software-people-2.html' title='Репортаж с Software People - часть 2'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/__mL_0Lk97DQ/S9HqvKy7nsI/AAAAAAAAATY/Lq3jgcusC-M/s72-c/IMG_0504.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-3213457940989638907</id><published>2010-04-22T20:45:00.010+04:00</published><updated>2010-04-23T22:55:28.707+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software People'/><category scheme='http://www.blogger.com/atom/ns#' term='конференция'/><title type='text'>Репортаж с Software People - часть 1</title><content type='html'>Сегодня я посетил конференцию Software People 2010, и теперь хочу поделиться полученными новыми идеями.&lt;br /&gt;&lt;br /&gt;Больше других хочется мне отметить три выступления, и здесь я немного напишу о каждом из них.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Гибкое мировоззрение - Питер Хрущка (Peter Hruschka)&lt;/span&gt;&lt;br /&gt;Питер рассказывал об Agile подходе. Если пересказывать коротко, то было выделено три ключевые роли в команде:&lt;ul&gt;&lt;li&gt;Product owner – отвечает за требования;&lt;/li&gt;&lt;li&gt;Project manager – отвечает за весь проект;&lt;/li&gt;&lt;li&gt;Software architect – отвечает за решение требований.&lt;/li&gt;&lt;/ul&gt;Остановиться я бы хотел на роли архитектора, потому что об этом на выступлениях об Agileили Scrum обычно не говорится.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__mL_0Lk97DQ/S9CUuVNQzGI/AAAAAAAAAS4/vJKqsmTBQws/s1600/IMG_0497.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://4.bp.blogspot.com/__mL_0Lk97DQ/S9CUuVNQzGI/AAAAAAAAAS4/vJKqsmTBQws/s320/IMG_0497.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5463029871688076386" /&gt;&lt;/a&gt;Питер сравнивает роль архитектора с таким видом спорта, как десятиборье (сразу 10 видов соревнований по легкой атлетике). У архитектора, как и у спортсмена в  десятиборье должны быть развиты необходимые навыки (умение балансировать, коммуникабельность, документирование, способность упрощения и другие).&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__mL_0Lk97DQ/S9CVFjrh6CI/AAAAAAAAATA/bRNGV9Df8t4/s1600/IMG_0498.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://2.bp.blogspot.com/__mL_0Lk97DQ/S9CVFjrh6CI/AAAAAAAAATA/bRNGV9Df8t4/s320/IMG_0498.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5463030270710114338" /&gt;&lt;/a&gt;При этом все навыки должны быть развиты в равной степени. Нельзя очень хорошо разбираться во всем, но быть, например, некоммуникабельным архитектором – это будет провал. На каком-то совещании не будет выбрана проектная идея, которую придумал некоммуникабельный архитектор, потому что он не сможет о ней хорошо рассказать, не сможет ее продать. &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__mL_0Lk97DQ/S9CVXqeeHiI/AAAAAAAAATI/X4JfxzAGKzI/s1600/IMG_0500.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://3.bp.blogspot.com/__mL_0Lk97DQ/S9CVXqeeHiI/AAAAAAAAATI/X4JfxzAGKzI/s320/IMG_0500.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5463030581772033570" /&gt;&lt;/a&gt;Также это можно сравнить с жонглированием: можно это делать не очень быстро, однако главное не уронить ни один предмет.&lt;br /&gt;&lt;br /&gt;Важна деталь – не следует делать Project manager’а и архитектора одним человеком.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Кто такой менеджер продукта и что он может дать компании разработчику – Дмитрий Безуглый, Константин Бредюк&lt;/span&gt;&lt;br /&gt;Дмитрий и Константин рассказывали о разнице в управлении проектом (заказная разработка) и управление продуктом. У этих видов управления разные цели:&lt;ul&gt;&lt;li&gt;заказная разработка – сделать работу в рамках бюджета и сроков;&lt;/li&gt;&lt;li&gt;для продукта – вывести его на рынок.&lt;/li&gt;&lt;/ul&gt;Если сравнивать этап R&amp;D, то для разработки проекта, будет больше development’а, чем research. Здесь выбираются более стабильные надежные технологии. Для продукта же наоборот необходимо рисковать, выбирать что-то новое из технологий, чтобы быть впереди конкурентов, здесь больше research.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__mL_0Lk97DQ/S9CVzNiP1II/AAAAAAAAATQ/BjzRxRlBEr8/s1600/IMG_0502.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/__mL_0Lk97DQ/S9CVzNiP1II/AAAAAAAAATQ/BjzRxRlBEr8/s320/IMG_0502.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5463031055039583362" /&gt;&lt;/a&gt;Очень интересное определение Product Manager – Прослойка Между :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Тестирование – это не просто тестирование – Юлия Нечаева&lt;/span&gt;&lt;br /&gt;Юлия очень хорошо рассказала о своем подходе – Business driven testing. Этот подход отличается от других, традиционных видов тестирования, например Requirements  driven testing (проверка на соответствие требованиям, удобен менеджерам), Development driven testing (поиск ошибок. Удобен разработчикам), Priorities driven testing (тестируется часть продукта, например, которая будет демонстрироваться, удобен для души) и другие.&lt;br /&gt;&lt;br /&gt;Business driven testing предполагает тестирование на успех продукта. То есть это может быть:&lt;ul&gt;&lt;li&gt;тестирование на основании целей проекта;&lt;/li&gt;&lt;li&gt;юзабилити-тестирование;&lt;/li&gt;&lt;li&gt;бета-тестирование пользователями;&lt;/li&gt;&lt;li&gt;бета-тестирование бизнесом;&lt;/li&gt;&lt;li&gt;работа с поддержкой.&lt;/li&gt;&lt;/ul&gt;Все это не смогут делать только тестировщики, это могут делать также:&lt;ul&gt;&lt;li&gt;руководитель отдела тестирования;&lt;/li&gt;&lt;li&gt;менеджер;&lt;/li&gt;&lt;li&gt;маркетолог;&lt;/li&gt;&lt;li&gt;аналитик.&lt;/li&gt;&lt;/ul&gt;То есть это тестирование, очевидно, должно выполняться всеми лицами, участвующими в создании продукта.&lt;br /&gt;&lt;br /&gt;Завтра будет второй день конференции, продолжение следует!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-3213457940989638907?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/3213457940989638907/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=3213457940989638907' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3213457940989638907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/3213457940989638907'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/04/software-people-1.html' title='Репортаж с Software People - часть 1'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__mL_0Lk97DQ/S9CUuVNQzGI/AAAAAAAAAS4/vJKqsmTBQws/s72-c/IMG_0497.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-8106876861946577905</id><published>2010-03-01T21:42:00.011+03:00</published><updated>2010-03-06T15:09:26.157+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='DVCS'/><category scheme='http://www.blogger.com/atom/ns#' term='VCS'/><title type='text'>Что такое "Index" в Git?</title><content type='html'>Данный пост был написан по мотивам статей &lt;a href="http://tomayko.com/writings/the-thing-about-git" target="_blank"&gt;The Thing About Git&lt;/a&gt; и &lt;a href="http://osteele.com/archives/2008/05/my-git-workflow" target="_blank"&gt;My Git Workflow&lt;/a&gt;, в которых затрагивалась тема Индексов (Index) в Git’е.&lt;br /&gt;&lt;br /&gt;Git чудесен! Git позволяет писать код в своей рабочей копии для, например, пяти различных фич. И для этого не нужно взаимодействие с удаленной VCS. У себя можно делать коммиты сколь угодно часто, или наоборот редко. После этого можно что-то изменить в своих коммитах, например, поменять свое аннотационное сообщение. Можно объединить коммиты, или разбить их, - в общем можно делать &lt;span style="font-weight:bold;"&gt;все что угодно&lt;/span&gt; и Git никак вас в этом не ограничивает.&lt;br /&gt;&lt;br /&gt;Но Git трудно изучить, как минимум по трем основным причинам:&lt;ol&gt;&lt;li&gt;Git слишком мощный, он обладает большим количество функций, которые могут напугать новичка;&lt;/li&gt;&lt;li&gt;Git использует нестандартные названия команд, в отличии от других VCS, где например устоялись значения для таких команд, как "checkout" или "revert", но не в Git'е!&lt;/li&gt;&lt;li&gt;И третье – Индексы в Git, механизм позволяющий выбирать, что коммитить, например, только протестированные файлы.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Справиться с первой трудностью, с мощностью Git’а, можно изучением различной документации, например, &lt;a href="http://progit.org/" target="_blank"&gt;эта книга&lt;/a&gt; заслуживает внимания. &lt;br /&gt;&lt;br /&gt;Победить вторую трудность, нестандартные названия команд, можно также изучением документации. Но если не получается привыкнуть к необычным наименованиям, то можно пойти другим путем и установить знакомые синонимы для некоторых команд:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ cat ~/.gitconfig&lt;br /&gt;[alias]&lt;br /&gt;  ci = commit -a&lt;br /&gt;  co = checkout&lt;br /&gt;  st = status -a&lt;br /&gt;$ git ci -m 'some changes'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Так можно работать с Git почти как с Subversion.  Обратите внимание на синоним для &lt;code&gt;ci = commit –a&lt;/code&gt;. Здесь ключ &lt;code&gt;–a&lt;/code&gt;, кажется, позволяет решить и третью проблему, не использовать Индексы. Но все же лучше разобраться, как применять Индексы в своей работе.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__mL_0Lk97DQ/S41ue_e-GSI/AAAAAAAAARs/iakANoJ7In4/s1600-h/git_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 318px;" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/S41ue_e-GSI/AAAAAAAAARs/iakANoJ7In4/s400/git_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444129003277261090" /&gt;&lt;/a&gt;&lt;br /&gt;На изображении выше показаны основные команды и хранилища данных, здесь же можно найти и Индекс. Получается, что команда &lt;code&gt;git add&lt;/code&gt; нужна только для того, чтобы потом команда &lt;code&gt;git commit&lt;/code&gt; могла увидеть обновленные файлы. И как мы уже выяснили, если выполнять коммиты с дополнительным ключом &lt;code&gt;git commit –a&lt;/code&gt;, то можно забыть о добавлении файлов в Индекс.&lt;br /&gt;&lt;br /&gt;Тем не менее, есть как минимум два интересных применения для Индексов, о которых будет рассказано ниже. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Использование Индексов в качестве контрольных точек&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Часто бывает, что при изменении кода точно не знаешь удачная это идея, или нет. То есть это просто эксперимент. Эксперименты могут затянуться, и поэтому нужно делать контрольные точки. Но стоит ли выполнять коммит с экспериментальным и скорее всего неработающим кодом? Этого не хочется делать. Однако для контрольных точек можно использовать Индексы, причем неоднократно. Это похоже на маленькие шаги, после которых код достигнет рабочего состояния, и тогда уже можно выполнить коммит.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__mL_0Lk97DQ/S41uuvD3JNI/AAAAAAAAAR0/JcPYti9FWu4/s1600-h/git_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 279px;" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/S41uuvD3JNI/AAAAAAAAAR0/JcPYti9FWu4/s400/git_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444129273746498770" /&gt;&lt;/a&gt;&lt;br /&gt;При подходе с контрольными точками используются такие команды Git:&lt;ul&gt;&lt;li&gt;&lt;code&gt;git diff&lt;/code&gt; покажет какие изменения были сделаны с момента последней контрольной точки;&lt;/li&gt;&lt;li&gt;&lt;code&gt;git diff head&lt;/code&gt; покажет изменения с последнего коммита;&lt;/li&gt;&lt;li&gt;&lt;code&gt;git checkout .&lt;/code&gt; откатит все изменения до последней контрольной точки;&lt;/li&gt;&lt;li&gt;&lt;code&gt;git checkout head .&lt;/code&gt; вернет состояние последнего коммита;&lt;/li&gt;&lt;li&gt;&lt;code&gt;git stash&lt;/code&gt; и &lt;code&gt;git checkout -m -b&lt;/code&gt; позволяют прятать и возвращать все изменения со времени последнего коммита.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;Контрольные точки позволяют неплохо справляться с ситуациями, когда необходимо экспериментировать, пробовать несколько различных вариантов подряд. На самом деле, это всего лишь один из вариантов использование Индекса, не обязательно делать именно так. В качестве альтернативы Индексу, здесь могут служить ветки, которые вскоре понадобится удалить, или же временные файлы, вроде CMainApplication.class.php, CMainApplication_new.class.php :-)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Использование индексов для разрешения проблем в рабочей копии&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Рассмотрим пример, допустим, прошлым вечером, я работал над своим проектом, работал над фичей "форма добавления комментариев". Тогда вечером я думал, что это очень простая задача, и мне нужно на нее всего 10 минут. Спустя пару часов, я отправился спать, а в моей рабочей копии остались полу-завершенные изменения.&lt;br /&gt;&lt;br /&gt;Утром я неожиданно обнаружил в почте важное сообщение об ошибке на сайте – была найдена проблема с javascript на странице.  Это была довольно критичная ошибка, и мне сразу нужно было ее исправить. Правка не заняла много времени, но когда все было готово к коммиту, я обнаружил, что &lt;code&gt;git status&lt;/code&gt; выдает такой результат:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ git status&lt;br /&gt;# On branch master&lt;br /&gt;# Changed but not updated:&lt;br /&gt;# &lt;br /&gt;#     modified: models.class.php&lt;br /&gt;#     modified: views/entry.html&lt;br /&gt;#     modified: js/dfunctions.js&lt;br /&gt;#     modified: stylesheets/ dfunctions.css&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Получилось так, что в этом списке приведены файлы от двух несвязанных между собой изменений:&lt;ol&gt;&lt;li&gt;Изменились models.class.php и views/entry.html для формы добавления комментариев;&lt;/li&gt;&lt;li&gt;Изменились models.class.php, js/dfunctions.js и stylesheets/ dfunctions.css для исправления утренней ошибки с javascript.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Проблема заключается в файле models.class.php, который содержит правки и от одного, и от другого изменения. И в этом месте обычно начинаются танцы с бубном, и сожаления, что нужно было сделать все по-другому.&lt;br /&gt;&lt;br /&gt;Что же может мне помочь? Можно воспользоваться командой вроде &lt;code&gt;git stash&lt;/code&gt;, которая позволяет временно "припрятать" изменения. Но есть другой способ решения, более элегантный и с использование Индекса Git.&lt;br /&gt;&lt;br /&gt;Итак, мне нужно выполнить коммит с js/dfunctions.js, stylesheets/ dfunctions.css и с частью изменений из models.class.php. Так попробуем добавить этот набор в Индекс:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ git add js/dfunctions.js&lt;br /&gt;$ git add stylesheets/ dfunctions.css&lt;br /&gt;$ git add --patch models.class.php&lt;br /&gt;diff --git a/models.class.php b/models.class.php&lt;br /&gt;index be4159d..3efd4ce 100644&lt;br /&gt;--- a/models.class.php&lt;br /&gt;+++ b/models.class.php&lt;br /&gt;@@ -256,7 +256,7 @@&lt;br /&gt;     class Bookmark {&lt;br /&gt;       …&lt;br /&gt;-      $bookmark_update_attributes = $this-&gt;…&lt;br /&gt;+      $bookmark_save_attributes = $this-&gt;…&lt;br /&gt;       …&lt;br /&gt;Stage this hunk [y/n/a/d/j/J/?]?&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Здесь волшебным является ключ &lt;code&gt;--patch&lt;/code&gt; (aka &lt;code&gt;--interactive&lt;/code&gt;) для команды добавления в Индекс &lt;code&gt;git add&lt;/code&gt;. Этот ключ указывает Git на то, что нужно показать все изменения в указанных файлах кусок-за-куском. И для каждого куска изменений можно выбрать одну из следующих опций:&lt;ul&gt;&lt;li&gt;&lt;code&gt;y&lt;/code&gt; – добавить кусок в Индекс;&lt;/li&gt;&lt;li&gt;&lt;code&gt;n&lt;/code&gt; – не добавлять кусок в Индекс;&lt;/li&gt;&lt;li&gt;&lt;code&gt;a&lt;/code&gt; –  добавить в Индекс этот и все последующие куски в файле;&lt;/li&gt;&lt;li&gt;&lt;code&gt;d&lt;/code&gt; – не добавлять в Индекс этот и все оставшиеся куски в файле;&lt;/li&gt;&lt;li&gt;&lt;code&gt;j&lt;/code&gt; – оставить этот кусок неразрешенным, перейти к следующему неразрешенному куску;&lt;/li&gt;&lt;li&gt;&lt;code&gt;J&lt;/code&gt; – оставить этот кусок неразрешенным и перейти к следующему куску;&lt;/li&gt;&lt;li&gt;&lt;code&gt;k&lt;/code&gt; – оставить этот кусок неразрешенным и перейти к предыдущему неразрешенному куску;&lt;/li&gt;&lt;li&gt;&lt;code&gt;K&lt;/code&gt; – оставить этот кусок неразрешенным и перейти к предыдущему куску;&lt;/li&gt;&lt;li&gt;&lt;code&gt;s&lt;/code&gt; – разбить этот кусок на более мелкие кусочки.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Опций довольно много, что позволяет удобно выбрать, какие изменения добавлять в Индекс. Несколько кусков изменений models.class.php, которые относятся к решению бага с javascript, я добавил в Индекс, а все остальные куски изменений отклонил (они относились к фиче с добавлением комментариев).&lt;br /&gt;&lt;br /&gt;Теперь я могу проверить, что все сделано верно:&lt;ul&gt;&lt;li&gt;&lt;code&gt;git diff --cached&lt;/code&gt; показывает изменения которые добавлены в Индекс;&lt;/li&gt;&lt;li&gt;&lt;code&gt;git diff&lt;/code&gt; показывает все изменения в рабочей копии.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Теперь можно смело коммитить исправление бага &lt;code&gt;git commit -m "fix javascript bug"&lt;/code&gt; и продолжать работать над формой добавления комментария. Продолжить можно в отдельной ветке, но это не обязательно – Git позволяет работать, как вам хочется!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-8106876861946577905?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/8106876861946577905/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=8106876861946577905' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/8106876861946577905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/8106876861946577905'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/03/index-git.html' title='Что такое &quot;Index&quot; в Git?'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/__mL_0Lk97DQ/S41ue_e-GSI/AAAAAAAAARs/iakANoJ7In4/s72-c/git_1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-207448988627279689</id><published>2010-02-23T21:26:00.006+03:00</published><updated>2010-02-23T22:20:22.203+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='VCS'/><category scheme='http://www.blogger.com/atom/ns#' term='Subversion'/><category scheme='http://www.blogger.com/atom/ns#' term='Битрикс'/><category scheme='http://www.blogger.com/atom/ns#' term='SVN'/><title type='text'>Миграция репозитория из Subversion в Git</title><content type='html'>В этом посте мне хочется написать о своем опыте работы с Git. Моя работа с Git началась не с чистого листа, т.е. не со старта проекта. Проект уже существовал, когда появилась идея перевести его с текущей системы контроля версий (Subversion) на Git.&lt;br /&gt;&lt;br /&gt;Почему возникла необходимость перейти на Git? Такое может понадобиться, если в проекте очень много исходных файлом, и поменять их расположение невозможно. Очень хорошим примером такой ситуации является проект на Битриксе, где очень много исходных файлов и их общий объем превышает 200 МБ. В таких случаях либо вообще не используют VCS, либо используют VCS лишь частично, покрывая только те исходные файлы, которые создала команда разработки. Последний пример с частичным покрытием кода проекта на Битриксе хорошо описан в &lt;a href="http://dev.1c-bitrix.ru/community/webdev/user/27606/blog/978/" target="_blank"&gt;статье&lt;/a&gt; моего друга.&lt;br /&gt;&lt;br /&gt;Частичный контроль версий кода решает проблемы при командной работе лишь частично. Возникла необходимость иметь в VCS весь код, и поэтому начался процесс перехода от SVN к Git. Git обещал быть невероятно быстрым, что позволяло работать с очень большим количеством исходных файлов.&lt;br /&gt;&lt;br /&gt;За руководство к действиям я взял &lt;a href="http://leonid.shevtsov.me/22-07-2009/perenos-svn-repozitariya-v-git/" target="_blank"&gt;статью&lt;/a&gt; Леонида Шевцова, однако не все у меня получилось, как там описано. И поэтому я привожу здесь описание своего опыта.&lt;br /&gt;&lt;br /&gt;Для миграции необходим &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html"&gt;git-svn&lt;/a&gt;, его можно установить привычным способом:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo apt-get install git-svn&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Теперь, чтобы можно было выполнить клонирование существующего SVN-репозитория, необходимо собрать всех авторов, которые выполняли коммиты. Форматы автором в SVN и Git отличаются, в частности для Git нужны не логины пользователей (как в SVN), а их e-mail’ы.&lt;br /&gt;&lt;br /&gt;Список авторов можно получить, выполнив такой скрипт в папке с рабочей копией SVN-репозитория:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;#!/usr/bin/env bash&lt;br /&gt;authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)&lt;br /&gt;for author in ${authors}; do&lt;br /&gt;  echo "${author} = "${author} &amp;lt;EMAIL&amp;gt;";&lt;br /&gt;done&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Скрипт выведет список авторов примерно в таком формате:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;bender = bender &amp;lt;EMAIL&amp;gt;&lt;br /&gt;zoidberg = zoidberg &amp;lt;EMAIL&amp;gt;&lt;br /&gt;leela = leela &amp;lt;EMAIL&amp;gt;&lt;br /&gt;fry = fry &amp;lt;EMAIL&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Этот вывод нужно сохранить в файл (рядом с местом, где вы хотите выполнить клонирование), но сначала заменить EMAIL на действительный e-mail для каждого автора. &lt;br /&gt;&lt;br /&gt;Теперь можно выполнить клонирование:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;git svn clone -s --authors-file=my_authors http://svn.domain.ru/project .&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;В этой команде ключи означают:&lt;ul&gt;&lt;li&gt;&lt;code&gt;s&lt;/code&gt; – git-svn будет понимать стандартные папки SVN: trunk, branches, tags;&lt;/li&gt;&lt;li&gt;&lt;code&gt;authors-file&lt;/code&gt; – это файл с авторами, который был подготовлен ранее.&lt;/li&gt;&lt;/ul&gt;Через пару минут, если проект не очень большой, мы получим Git-репозиторий со всей историей проекта. Далее можно навести блеск: создать .gitignore; убрать упоминания об SVN, если они есть; упорядочить ветки. Но на данном этапе, нам достаточно получившегося Git-репозитория, с ним уже можно делать первые шаги и проводить эксперименты – способен ли Git решить проблемы, о которых было написано выше.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-207448988627279689?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/207448988627279689/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=207448988627279689' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/207448988627279689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/207448988627279689'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2010/02/subversion-git.html' title='Миграция репозитория из Subversion в Git'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-2962135242830919978</id><published>2009-12-31T14:22:00.012+03:00</published><updated>2010-09-07T20:27:15.561+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GDD'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>Немного о GDD и Agile Days</title><content type='html'>Сегодня 31 декабря, канун нового 2010 года. Перед тем как попрощаться со старым годом, мне бы хотелось немного рассказать о двух важных событиях, которых произошли в ноябре и декабре 2009 года. Это &lt;a href="http://code.google.com/intl/ru/events/developerday/2009/home.html" target="_blank"&gt;Google Developer Day&lt;/a&gt; и &lt;a href="http://agiledays.ru/" target="_blank"&gt;Agile Days&lt;/a&gt; — конференции в которых я с радостью принял участие.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Google Developer Day&lt;/span&gt;&lt;br /&gt;GDD проходил 10 ноября в здании кинотеатра Октябрь: атмосфера зрелищности комедий, триллеров, фильмов ужасов и прочих катастроф полностью передалась участникам дня. Выступающие отлично говорили и выглядели очень профессионально, иногда казалось, что они больше шоу-мены или актеры, нежели синьоры-разработчики.&lt;br /&gt;&lt;br /&gt;Сейчас доступны практически все &lt;a href="http://code.google.com/intl/ru/events/developerday/2009/sessions.html" target="_blank"&gt;материалы&lt;/a&gt; конференции, и даже видео, вот например ниже видеоролик с открытия GDD.&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Pheluv5nu5I&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Pheluv5nu5I&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Чтобы не повторятся, я попробую рассказать только об одном выступлении «&lt;span style="font-weight:bold;"&gt;Как написать API&lt;/span&gt;», которое мне было ближе чем другие, а его автор &lt;span style="font-weight:bold;"&gt;Вадим Герасимов&lt;/span&gt; показался мне наиболее похожим на профессионального разработчика (хоть и не таким забавным как Чуи Трюэлла).&lt;br /&gt;&lt;br /&gt;Вот основные моменты выступления:&lt;ul&gt;&lt;li&gt;Должно быть небольшое общее описание API, до 1 страницы;&lt;/li&gt;&lt;li&gt;При проектировании API на начальной стадии лучше всего договориться с большим количеством участников, чтобы заручиться поддержкой;&lt;/li&gt;&lt;li&gt;API не сможет удовлетворить всех пользователей, выбирая между группами пользователей, лучше сделать API таким, чтобы оно было одинаково неудобно для всех групп пользователей, нежели удобным только для какой-то одной группы;&lt;/li&gt;&lt;li&gt;API должно быть настолько малым, насколько это возможно, нужно помнить, что добавить что-то можно всегда, а убрать — нет;&lt;/li&gt;&lt;li&gt;Реализация не должна влиять на API;&lt;/li&gt;&lt;li&gt;Если классы API могут быть наследованы — то это необходимо документировать, либо запрещать наследование (например, директивой final в PHP);&lt;/li&gt;&lt;li&gt;Исключения следует использовать только для исключительных ситуаций, а не для управления порядком выполнения кода;&lt;/li&gt;&lt;li&gt;Следует избегать возвращения значений, которые требуют дополнительной обработки;&lt;/li&gt;&lt;li&gt;Следить за единообразием порядка параметров для различных методов;&lt;/li&gt;&lt;li&gt;И последний универсальный совет  - всегда придерживаться принципа наименьшей неожиданности.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__mL_0Lk97DQ/SzyO7lyHpSI/AAAAAAAAAP4/GxisVkZniqE/s1600-h/dscn0028.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/__mL_0Lk97DQ/SzyO7lyHpSI/AAAAAAAAAP4/GxisVkZniqE/s320/dscn0028.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5421365205852988706" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__mL_0Lk97DQ/SzyPQgVmanI/AAAAAAAAAQQ/IKl2xxAI34Y/s1600-h/dscn0148.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/__mL_0Lk97DQ/SzyPQgVmanI/AAAAAAAAAQQ/IKl2xxAI34Y/s320/dscn0148.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5421365565168446066" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__mL_0Lk97DQ/SzyPLhjOe1I/AAAAAAAAAQI/Y6OKqtAaj9U/s1600-h/dscn0121.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/__mL_0Lk97DQ/SzyPLhjOe1I/AAAAAAAAAQI/Y6OKqtAaj9U/s320/dscn0121.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5421365479594687314" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__mL_0Lk97DQ/SzyPERyoRpI/AAAAAAAAAQA/l1aqX37nW-4/s1600-h/dscn0077.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/__mL_0Lk97DQ/SzyPERyoRpI/AAAAAAAAAQA/l1aqX37nW-4/s320/dscn0077.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5421365355105240722" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__mL_0Lk97DQ/SzyPXRg4UgI/AAAAAAAAAQY/qBIWks4Lrxc/s1600-h/dscn0154.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/__mL_0Lk97DQ/SzyPXRg4UgI/AAAAAAAAAQY/qBIWks4Lrxc/s320/dscn0154.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5421365681448309250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Agile Days&lt;/span&gt;&lt;br /&gt;На этой конференции 9 декабря гуру в разработке и управлении проектами делились своими success story, а также рассказывали о проблемах с которыми они столкнулись при использовании гибкого agile-подхода к проектам. Здесь я попробую рассказать основные мысли из некоторых выступлений.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Евгений Сорокин&lt;/span&gt; из Intel рассказывал, какие трудности ждут распределенную команду:&lt;ul&gt;&lt;li&gt;У разных команд может быть разная шкала оценок;&lt;/li&gt;&lt;li&gt;Разные временные зоны;&lt;/li&gt;&lt;li&gt;Трудность с обменом знаниями;&lt;/li&gt;&lt;li&gt;Неудобно общаться только по телефону.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;В качестве советов для преодоления этих проблем, автор рекомендовал больше общаться и вести общий бэклог. Вот еще несколько интересных мыслей от Евгения:&lt;ul&gt;&lt;li&gt;Новичков лучше направлять на повышение знаний по ООП, добиваться кроссфункциональности, использовать парное программирование, и через несколько месяцев разница между новичками и более опытными работниками будет размываться;&lt;/li&gt;&lt;li&gt;Очень большие user story называют epic story, они будут постоянно готовы на 90%. Чтобы легче с ними справляться, нужно лучше понимать мотивы, стараться разбивать «эпики» на бизнес-сценарии, двигаться от простого к сложному;&lt;/li&gt;&lt;li&gt;Разбивать требования не следует по техническим деталям (например, если разбить требование на 1 — составить таблицы БД, 2 — написать классы), потому что в этом не будет бизнес-ценности.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Дмитрий Викторов&lt;/span&gt; из F-Secure рассказывал о проведении ретроспектив. Здесь самое основное это сфокусировать команду на процесс улучшений в проекте. При этом, если команда начинает шутить, например, предлагать для улучшения в проекте переместить офис на Багамы, - то фокус может быть потерян. Очень важно придумывать что-нибудь новенькое на ретроспективах, так чтобы людям не надоело. Например, можно попросить команду вместо рассказа о прошедшем спринте, сделать рисунок, то есть выразить спринт в изображении на бумаге. Это может быть более интересным, а также более полезным.&lt;br /&gt;&lt;br /&gt;Вообще многие на конференции отметили, что различные фишки, fun — очень полезны для команды разработчиков. Вот несколько идей, какими могут быть эти фишки:&lt;ul&gt;&lt;li&gt;«Шапка-чеканка» - разработчик, у которого находится эта шапка может делать merge с главной веткой кода;&lt;/li&gt;&lt;li&gt;Какой-либо аксессуар, например меч Джедая, на ретроспективе каждый кто хочет высказаться сначала берет этот меч, и говорит только когда аксессуар в руках;&lt;/li&gt;&lt;li&gt;«Сокровища и проклятия» - карточки с различными наградами (сокровища) или заданиями (проклятия). Задание может быть например таким: вытереть пыль с компьютеров коллег. Карточки можно раздавать тем членам команды, которые как-то проявили себя в спринте или наоборот в чем-то провинились;&lt;/li&gt;&lt;li&gt;Веселое оформление карточек с заданиями для доски;&lt;/li&gt;&lt;li&gt;Зарядка.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__mL_0Lk97DQ/SzyQcf5lR4I/AAAAAAAAAQw/Oht7m7m8wgU/s1600-h/dscn0273.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://1.bp.blogspot.com/__mL_0Lk97DQ/SzyQcf5lR4I/AAAAAAAAAQw/Oht7m7m8wgU/s320/dscn0273.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5421366870720989058" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__mL_0Lk97DQ/SzyQSCZIcjI/AAAAAAAAAQo/ov2JzW6NYLc/s1600-h/dscn0275.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://3.bp.blogspot.com/__mL_0Lk97DQ/SzyQSCZIcjI/AAAAAAAAAQo/ov2JzW6NYLc/s320/dscn0275.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5421366691001561650" /&gt;&lt;/a&gt;&lt;br /&gt;Это все что я хотел рассказать вам сегодня, спасибо за внимание и.... радостно поздравляю вас с новым годом, с новыми возможностями!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8537947668655047091-2962135242830919978?l=blog.yetanother.ru' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.yetanother.ru/feeds/2962135242830919978/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8537947668655047091&amp;postID=2962135242830919978' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2962135242830919978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8537947668655047091/posts/default/2962135242830919978'/><link rel='alternate' type='text/html' href='http://blog.yetanother.ru/2009/12/ggd-agile-days.html' title='Немного о GDD и Agile Days'/><author><name>Евгений Хамухин</name><uri>http://www.blogger.com/profile/15879192810296083049</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/-X9WJjsmJ8XU/TpiaBHy0fCI/AAAAAAAAAcY/1wjWpM37OWA/s220/profile_2011-10-14.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__mL_0Lk97DQ/SzyO7lyHpSI/AAAAAAAAAP4/GxisVkZniqE/s72-c/dscn0028.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8537947668655047091.post-6042489603664631827</id><published>2009-10-25T11:42:00.011+03:00</published><updated>2009-10-25T14:32:31.765+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ide'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><category scheme='http://www.blogger.com/atom/ns#' term='rse'/><category scheme='http://www.blogger.com/atom/ns#' term='pdt'/><title type='text'>Eclipse Galileo, PDT 2.1 и редактирование файлов по sftp</title><content type='html'>В &lt;a href="/2009/03/eclipse-pdt-20.html"&gt;одном &lt;/a&gt;из прошлых постов я рассматривал вопрос, как можно в Eclipse PDT редактировать файлы на удаленных серверах с помощью дополнения Remote Systems. Тогда я изучал различные варианты (создание удаленных проектов,  монтирование удаленных каталогов в ОС) и пришел к выводу, что самым лучшим и простым спо
