<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Разработка &#187; проектирование</title>
	<atom:link href="http://www.job-blog.bullgare.ru/category/%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.job-blog.bullgare.ru</link>
	<description>о программировании и работе</description>
	<lastBuildDate>Wed, 08 Feb 2012 09:39:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Сравнение 12 javascript MVC-фреймворков</title>
		<link>http://www.job-blog.bullgare.ru/2012/01/%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-12-javascript-mvc-%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba%d0%be%d0%b2/</link>
		<comments>http://www.job-blog.bullgare.ru/2012/01/%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-12-javascript-mvc-%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba%d0%be%d0%b2/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 08:05:14 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=1394</guid>
		<description><![CDATA[The Top 10 Javascript MVC Frameworks Reviewed Лучшим признан Ember.js. Надо поковырять) UPD: поковырял. В принципе, более стройная архитектура, чем у того же backbone, у которого часть логики контроллера во вью. Но из коробки нет router и не так просто с pushState, так что не стал использовать серьёзно. Возможно, через полгода-год этот фреймворк будет интереснее.]]></description>
			<content:encoded><![CDATA[<p><a href="http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/">The Top 10 Javascript MVC Frameworks Reviewed</a><br />
Лучшим признан <a href="http://emberjs.com/">Ember.js</a>. Надо поковырять)</p>
<p>UPD: поковырял. В принципе, более стройная архитектура, чем у того же backbone, у которого часть логики контроллера во вью. Но из коробки нет router и не так просто с pushState, так что не стал использовать серьёзно. Возможно, через полгода-год этот фреймворк будет интереснее.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2012/01/%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-12-javascript-mvc-%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba%d0%be%d0%b2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Интересный доклад про разработку API</title>
		<link>http://www.job-blog.bullgare.ru/2011/12/%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%b5%d1%81%d0%bd%d1%8b%d0%b9-%d0%b4%d0%be%d0%ba%d0%bb%d0%b0%d0%b4-%d0%bf%d1%80%d0%be-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d1%83-api/</link>
		<comments>http://www.job-blog.bullgare.ru/2011/12/%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%b5%d1%81%d0%bd%d1%8b%d0%b9-%d0%b4%d0%be%d0%ba%d0%bb%d0%b0%d0%b4-%d0%bf%d1%80%d0%be-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d1%83-api/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 12:32:25 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[клиентская оптимизация]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[серверная оптимизация]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[ссылка]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=1334</guid>
		<description><![CDATA[На конференции &#171;.Тостер&#187; попал на доклад Jordi Romero API design and more (слайды). Говорил про создание API, про кеширование, про масштабирование, клиентскую оптимизацию. Понемножку, сжато. Понравилось. Странно только, что у них три уровня хранения данных: mySQL master-slave Redis для сложного кеша, чтобы не нагружать mySQL memcache для простого кеша]]></description>
			<content:encoded><![CDATA[<p>На конференции &laquo;.Тостер&raquo; попал на доклад Jordi Romero API design and more (<a href="http://jrom.net/api-design-and-more">слайды</a>).<br />
Говорил про создание API, про кеширование, про масштабирование, клиентскую оптимизацию.<br />
Понемножку, сжато.<br />
Понравилось.<br />
Странно только, что у них три уровня хранения данных:</p>
<ol>
<li>mySQL master-slave</li>
<li>Redis для сложного кеша, чтобы не нагружать mySQL</li>
<li>memcache для простого кеша</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2011/12/%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%b5%d1%81%d0%bd%d1%8b%d0%b9-%d0%b4%d0%be%d0%ba%d0%bb%d0%b0%d0%b4-%d0%bf%d1%80%d0%be-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d1%83-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Самый хороший способ подгрузки яваскриптов – тегом script</title>
		<link>http://www.job-blog.bullgare.ru/2011/11/%d1%81%d0%b0%d0%bc%d1%8b%d0%b9-%d1%85%d0%be%d1%80%d0%be%d1%88%d0%b8%d0%b9-%d1%81%d0%bf%d0%be%d1%81%d0%be%d0%b1-%d0%bf%d0%be%d0%b4%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b8-%d1%8f%d0%b2%d0%b0%d1%81%d0%ba/</link>
		<comments>http://www.job-blog.bullgare.ru/2011/11/%d1%81%d0%b0%d0%bc%d1%8b%d0%b9-%d1%85%d0%be%d1%80%d0%be%d1%88%d0%b8%d0%b9-%d1%81%d0%bf%d0%be%d1%81%d0%be%d0%b1-%d0%bf%d0%be%d0%b4%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b8-%d1%8f%d0%b2%d0%b0%d1%81%d0%ba/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 07:24:51 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[клиентская оптимизация]]></category>
		<category><![CDATA[проектирование]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=1309</guid>
		<description><![CDATA[Использовали мы на проекте одну лебедевскую библиотеку &#8211; include.js. Умеет она интересные вещи, вроде последовательной загрузки зависимых библиотек в нужном порядке. Нужно в яваскрипте написать js.include( &#8216;my/coolwiidget&#8217; );. Работает она, если на пальцах, следующим образом: делается ajax-запрос, которым грузится текст нужного скрипта, потом ищутся в тексте все js.include, делается их подгрузка, после чего делается eval [...]]]></description>
			<content:encoded><![CDATA[<p>Использовали мы на проекте одну лебедевскую библиотеку &#8211; <a href="http://www.artlebedev.ru/tools/technogrette/js/include/">include.js</a>. Умеет она интересные вещи, вроде последовательной загрузки зависимых библиотек в нужном порядке. Нужно в яваскрипте написать <strong>js.include( &#8216;my/coolwiidget&#8217; );</strong>. Работает она, если на пальцах, следующим образом: делается ajax-запрос, которым грузится текст нужного скрипта, потом ищутся в тексте все <strong>js.include</strong>, делается их подгрузка, после чего делается <strong>eval</strong> полученных текстов в обратном порядке. При этом ещё и отсекаются попытки по несколько раз грузить один и тот же яваскрипт.<br />
Работал он очень неплохо, хотя и неудобно было в firebug-е искать скрипт по его имени.<br />
Основная проблема встала, когда стало нужно вынести все яваскрипты на отдельный домен. Вот тут-то и проявились проблемы &#8211; ajax-ом нельзя грузить код с других доменов. Помогает заголовок <strong>Access-Control-Allow-Origin</strong>, но его понимают только современные браузеры (к примеру, firefox с версии 3.5), а на проекте критична максимально возможная совместимость (как обычно и бывает). Так что этот способ может быть актуален года через 3-5.<br />
Посмотрели на другие способы, в итоге пришли к динамическому добавлению тега <strong>script</strong> в <strong>head</strong>, но особого смысла в этом нет, т.к. зависимости, для которых и городился изначально огород, при этом способе не отслеживаются (JSONP с колбэками не подошёл, т.к. в проекте много legacy-кода, который использует глобальные переменные, причём даже не как константы).<br />
В итоге было принято гениальное в своей простоте решение &#8211; отказаться от всех этих изысков нафик и грузить скрипты как раньше &#8211; при загрузке страницы.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2011/11/%d1%81%d0%b0%d0%bc%d1%8b%d0%b9-%d1%85%d0%be%d1%80%d0%be%d1%88%d0%b8%d0%b9-%d1%81%d0%bf%d0%be%d1%81%d0%be%d0%b1-%d0%bf%d0%be%d0%b4%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b8-%d1%8f%d0%b2%d0%b0%d1%81%d0%ba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Фреймворки для создания MVC-подобной архитектуры на javascript</title>
		<link>http://www.job-blog.bullgare.ru/2011/11/%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-mvc-%d0%bf%d0%be%d0%b4%d0%be%d0%b1%d0%bd%d0%be%d0%b9-%d0%b0%d1%80%d1%85/</link>
		<comments>http://www.job-blog.bullgare.ru/2011/11/%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-mvc-%d0%bf%d0%be%d0%b4%d0%be%d0%b1%d0%bd%d0%be%d0%b9-%d0%b0%d1%80%d1%85/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 12:08:23 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[MVVM]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=1270</guid>
		<description><![CDATA[Выбирал между backbone (habrahabr.ru/blogs/javascript/118782/) и knockout (http://habrahabr.ru/blogs/javascript/121926/). Для выбора полезно почитать stackoverflow.com/questions/5112899/knockout-js-vs-backbone-js-vs. В итоге выбрал knockout &#8211; менее монструозный и лично мне показался понятнее, к тому же не навязывает REST и не требует дополнительных библиотек. Он реализует паттерн MVVM, который, думаю, больше подходит для клиентской части web-приложения, чем MVC. На сайте есть подробные доки и [...]]]></description>
			<content:encoded><![CDATA[<p>Выбирал между <a href="http://documentcloud.github.com/backbone/">backbone</a> (<a href="habrahabr.ru/blogs/javascript/118782/">habrahabr.ru/blogs/javascript/118782/</a>) и <a href="http://knockoutjs.com/">knockout</a> (<a href="http://habrahabr.ru/blogs/javascript/121926/">http://habrahabr.ru/blogs/javascript/121926/</a>).<br />
Для выбора полезно почитать <a href="stackoverflow.com/questions/5112899/knockout-js-vs-backbone-js-vs">stackoverflow.com/questions/5112899/knockout-js-vs-backbone-js-vs</a>.<br />
В итоге выбрал <strong>knockout</strong> &#8211; менее монструозный и лично мне показался понятнее, к тому же не навязывает REST и не требует дополнительных библиотек.<br />
Он реализует паттерн <a href="ru.wikipedia.org/wiki/MVVM">MVVM</a>, который, думаю, больше подходит для клиентской части web-приложения, чем MVC.<br />
На сайте есть подробные доки и очень удобный интерактивный туториал.<br />
Пока в проектах не использовал, так что писать особо нечего(</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2011/11/%d1%84%d1%80%d0%b5%d0%b9%d0%bc%d0%b2%d0%be%d1%80%d0%ba%d0%b8-%d0%b4%d0%bb%d1%8f-%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-mvc-%d0%bf%d0%be%d0%b4%d0%be%d0%b1%d0%bd%d0%be%d0%b9-%d0%b0%d1%80%d1%85/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Планирование и учёт рабочего времени</title>
		<link>http://www.job-blog.bullgare.ru/2011/03/%d0%bf%d0%bb%d0%b0%d0%bd%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b8-%d1%83%d1%87%d1%91%d1%82-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%b3%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d0%b5%d0%bd%d0%b8/</link>
		<comments>http://www.job-blog.bullgare.ru/2011/03/%d0%bf%d0%bb%d0%b0%d0%bd%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b8-%d1%83%d1%87%d1%91%d1%82-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%b3%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d0%b5%d0%bd%d0%b8/#comments</comments>
		<pubDate>Sat, 12 Mar 2011 20:29:35 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[книги]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[работа в команде и управление]]></category>
		<category><![CDATA[Спольски]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=972</guid>
		<description><![CDATA[Читаю книгу Джоэла Спольски &#171;И снова о программировании&#187;. Книжка несколько скаучная, постоянно рекламирует свою компанию и свои продукты, но есть и интересные главы (а книга собственно и состоит из отдельных глав &#8211; записей в блоге). Интересная глава &#8211; двадцатая, &#171;Планирование с учётом прежних результатов&#187; (http://www.joelonsoftware.com/items/2007/10/26.html). Основная мысль &#8211; надо учитывать всё время над задачей, неважно, [...]]]></description>
			<content:encoded><![CDATA[<p>Читаю книгу Джоэла Спольски &laquo;И снова о программировании&raquo;.<br />
Книжка несколько скаучная, постоянно рекламирует свою компанию и свои продукты, но есть и интересные главы (а книга собственно и состоит из отдельных глав &#8211; записей в блоге). Интересная глава &#8211; двадцатая, &laquo;Планирование с учётом прежних результатов&raquo; (<a href="http://www.joelonsoftware.com/items/2007/10/26.html">http://www.joelonsoftware.com/items/2007/10/26.html</a>).<br />
Основная мысль &#8211; надо учитывать всё время над задачей, неважно, занимался ли ты в это время этой задачей или чем-то совсем другим. Потом постоянно вести график соотношения оцененного времени к реально затраченному &laquo;грязному&raquo;. При этом соотношение всегда будет меньше единицы, но главное &#8211; это добиться постоянности этого соотношения, чтобы потом оценивать более объективно оценивать время, которое реально потребуется для реализации задачи, которая была оценена в определённое количество часов.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2011/03/%d0%bf%d0%bb%d0%b0%d0%bd%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b8-%d1%83%d1%87%d1%91%d1%82-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b5%d0%b3%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d0%b5%d0%bd%d0%b8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Построение UML-диаграмм</title>
		<link>http://www.job-blog.bullgare.ru/2009/09/%d0%bf%d0%be%d1%81%d1%82%d1%82%d1%80%d0%be%d0%b5%d0%bd%d0%b8%d0%b5-uml-%d0%b4%d0%b8%d0%b0%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/09/%d0%bf%d0%be%d1%81%d1%82%d1%82%d1%80%d0%be%d0%b5%d0%bd%d0%b8%d0%b5-uml-%d0%b4%d0%b8%d0%b0%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 10:27:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[проектирование]]></category>
		<category><![CDATA[freeware]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[UML]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=277</guid>
		<description><![CDATA[Обнаружил вот такой бесплатный инструмент для построения UML-диаграмм &#8211; ArgoUML]]></description>
			<content:encoded><![CDATA[<p>Обнаружил вот такой <a href="http://argouml.tigris.org/">бесплатный инструмент для построения UML-диаграмм &#8211; ArgoUML</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/09/%d0%bf%d0%be%d1%81%d1%82%d1%82%d1%80%d0%be%d0%b5%d0%bd%d0%b8%d0%b5-uml-%d0%b4%d0%b8%d0%b0%d0%b3%d1%80%d0%b0%d0%bc%d0%bc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Пример архитектуры таблиц иерархических данных</title>
		<link>http://www.job-blog.bullgare.ru/2009/09/%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80-%d0%b0%d1%80%d1%85%d0%b8%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d1%8b-%d1%82%d0%b0%d0%b1%d0%bb%d0%b8%d1%86-%d0%b8%d0%b5%d1%80%d0%b0%d1%80%d1%85%d0%b8%d1%87%d0%b5/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/09/%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80-%d0%b0%d1%80%d1%85%d0%b8%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d1%8b-%d1%82%d0%b0%d0%b1%d0%bb%d0%b8%d1%86-%d0%b8%d0%b5%d1%80%d0%b0%d1%80%d1%85%d0%b8%d1%87%d0%b5/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 15:06:57 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Базы данных]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[архитектура]]></category>
		<category><![CDATA[примеры]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=238</guid>
		<description><![CDATA[http://dev.mysql.com/tech-resources/articles/hierarchical-data.html]]></description>
			<content:encoded><![CDATA[<p>http://dev.mysql.com/tech-resources/articles/hierarchical-data.html</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/09/%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80-%d0%b0%d1%80%d1%85%d0%b8%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d1%8b-%d1%82%d0%b0%d0%b1%d0%bb%d0%b8%d1%86-%d0%b8%d0%b5%d1%80%d0%b0%d1%80%d1%85%d0%b8%d1%87%d0%b5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Структура хранения данных в поисковых движках</title>
		<link>http://www.job-blog.bullgare.ru/2009/08/%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d1%85%d1%80%d0%b0%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%bf%d0%be%d0%b8%d1%81%d0%ba%d0%be%d0%b2%d1%8b/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/08/%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d1%85%d1%80%d0%b0%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%bf%d0%be%d0%b8%d1%81%d0%ba%d0%be%d0%b2%d1%8b/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 08:26:40 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[Базы данных]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[архитектура]]></category>
		<category><![CDATA[база данных]]></category>
		<category><![CDATA[бд]]></category>
		<category><![CDATA[поиск]]></category>
		<category><![CDATA[Ссылки]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=168</guid>
		<description><![CDATA[Вот заинтересовало;). Решил почитать. Статья в Википедии (англ.) Архитектура Google (оригинал). видео про BigTable]]></description>
			<content:encoded><![CDATA[<p>Вот заинтересовало;).<br />
Решил почитать.<br />
<a href="http://en.wikipedia.org/wiki/Index_%28search_engine%29">Статья в Википедии</a> (англ.)<br />
<a href="http://www.insight-it.ru/net/scalability/arkhitektura-google/">Архитектура Google</a> (<a href="http://highscalability.com/google-architecture">оригинал</a>).<br />
<a href="http://video.google.com/videoplay?docid=7278544055668715642">видео про BigTable</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/08/%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d1%85%d1%80%d0%b0%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%bf%d0%be%d0%b8%d1%81%d0%ba%d0%be%d0%b2%d1%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Паттерн Decorator (Wrapper) в php</title>
		<link>http://www.job-blog.bullgare.ru/2009/07/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd-decorator-wrapper-%d0%b2-php/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/07/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd-decorator-wrapper-%d0%b2-php/#comments</comments>
		<pubDate>Sat, 25 Jul 2009 18:30:28 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[паттерн]]></category>
		<category><![CDATA[паттерн Decorator]]></category>
		<category><![CDATA[паттерны проектирования]]></category>
		<category><![CDATA[структурный паттерн]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=36</guid>
		<description><![CDATA[Паттерн &#171;Decorator&#187; (&#171;Wrapper&#187;) динамически добавляет объекту новые обязанности. Является гибкой альтернативой подклассам, расширяющим базовый класс. Схема следующая: Поместить целевой объект в другой объект, называемый декоратором, который большинство обращений переводит к переданному объекту, а часть (особенности) реализует самостоятельно. Могут вкладываться друг в друга по цепочке. Интерфейс декоратора и декорируемого объекта должны совпадать. Отличается от паттерна &#171;Strategy&#187; [...]]]></description>
			<content:encoded><![CDATA[<p>Паттерн &laquo;Decorator&raquo; (&laquo;Wrapper&raquo;) динамически добавляет объекту новые обязанности.<br />
Является гибкой альтернативой подклассам, расширяющим базовый класс.<br />
<span id="more-36"></span></p>
<p>Схема следующая:<br />
Поместить целевой объект в другой объект, называемый декоратором, который большинство обращений переводит к переданному объекту, а часть (особенности) реализует самостоятельно.<br />
Могут вкладываться друг в друга по цепочке.<br />
Интерфейс декоратора и декорируемого объекта должны совпадать.</p>
<p>Отличается от паттерна &laquo;Strategy&raquo; тем, что в последнем всё наоборот &#8211; главным является целевой объект, который распределяет обращения &laquo;расширениям&raquo;.</p>
<blockquote><p>
Листинг1. Decorator.php (PHP 5.2.5)
</p></blockquote>
<pre class="code">
&lt;?
//интерфейс, который будут реализовывать все: и целевой класс, и все декораторы
interface ClassInterface
{
	public function method1();

	public function method2();
}

//целевой класс
class TargetClass implements ClassInterface
{
	public function method1()
	{
		echo 'called "method1"';
	}

	public function method2()
	{
		echo '"called method2"';
	}
}

//от этого класса будут наследоваться все декораторы
abstract class AbstractTargetDecorator implements ClassInterface
{
	private $_componentObject = null;

	//т.к. реализуем интерфейс
	public function method1()
	{
		$this->_componentObject->method1();
	}

	public function method2()
	{
		$this->_componentObject->method2();
	}

	public function __construct(ClassInterface $componentObject)
	{
		$this->_componentObject = $componentObject;
	}

	//для вызова методов декораторов по цепочке
	public function __call($methodName, $arguments)
	{
		//чтобы не было ошибок; можно кидать Exception
		if (method_exists($this->_componentObject, $methodName))
			call_user_func_array(array($this->_componentObject, $methodName), $arguments);
	}

	public function abstractTargetDecoratorMethod()
	{
		echo 'called "abstractTargetDecoratorMethod"';
	}

}

//первый декоратор
class TargetDecorator1 extends AbstractTargetDecorator
{
	public function decorator1Method()
	{
		echo 'called "decorator1Method"';
	}
}

//второй декоратор
class TargetDecorator2 extends AbstractTargetDecorator
{
	public function decorator2Method()
	{
		echo 'called "decorator2Method"';
	}
}

//Использование

$decoratedObject = new TargetDecorator2(new TargetDecorator1(new TargetClass()));
//$decoratedObject = new TargetDecorator1(new TargetDecorator2(new TargetClass()));
//$decoratedObject = new TargetDecorator2(new TargetClass());
$decoratedObject->decorator1Method();
$decoratedObject->decorator2Method();
$decoratedObject->method1();
$decoratedObject->method2();
$decoratedObject->abstractTargetDecoratorMethod();

?&gt;
</pre>
<p>Ну, вообще-то, что совсем необязательно <em>AbstractTargetDecorator</em>&#8216;у реализовывать интерфейс <em>ClassInterface</em>. Это сделано для того, чтобы потомки могли друг в друга вкладываться. Хотя это и не нужно для паттерна декоратор.<br />
Можно применить в следующем примере:<br />
Есть 2 типа статей, которые состоят из нескольких типов модулей каждый. Причём эти модули одинаковы для обоих типов статей за исключением механизма их хранения. При этом все они наследуются от класса <em>module</em>.<br />
Специфичность ситуации в том, что данные сохраняются в виде сериализованных объектов модулей, и второй тип статей вводился намного позже первого (накопилось много сохранённых данных).<br />
При этом наследовать каждый модуль второго типа статей от соответствующего модуля первого типа нехорошо, т.к. механизм хранения один для всех модулей одного типа.<br />
Именно в этом случае мог бы помочь паттерн Декоратор: для каждого типа статей создаётся класс, отвечающий за сохранение в зависимости от типа статьи, и декорирующий исходный объект.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/07/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd-decorator-wrapper-%d0%b2-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Паттерны проектирования в php</title>
		<link>http://www.job-blog.bullgare.ru/2009/07/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd%d1%8b-%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2-php/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/07/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd%d1%8b-%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2-php/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 08:02:49 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[проектирование]]></category>
		<category><![CDATA[паттерн]]></category>
		<category><![CDATA[паттерн Factory]]></category>
		<category><![CDATA[паттерн Observer]]></category>
		<category><![CDATA[паттерн Singleton]]></category>
		<category><![CDATA[паттерн Strategy]]></category>
		<category><![CDATA[паттерн Сhain-of-command]]></category>
		<category><![CDATA[паттерны проектирования]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[шаблон]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=3</guid>
		<description><![CDATA[Введение Шаблоны проектирования были представлены общественности в книге Design Patterns (Erich Gamma, Richard Helm, Ralph Johnson и John Vlissides (известные как &#171;банда четырёх&#187;)). Основная концепция, представленная во введении, была простой. За годы разработки программного обеспечения Gamma и сотоварищи открыли определённые шаблоны (&#171;паттерны&#187;) проектирования, как и архитекторы, строящие дома и здания, могут разработать шаблоны расположения уборных [...]]]></description>
			<content:encoded><![CDATA[<h3>Введение</h3>
<p>Шаблоны проектирования были представлены общественности в книге Design Patterns (Erich Gamma, Richard Helm, Ralph Johnson и John Vlissides (известные как &laquo;банда четырёх&raquo;)). Основная концепция, представленная во введении, была простой. За годы разработки программного обеспечения Gamma и сотоварищи открыли определённые шаблоны (&laquo;паттерны&raquo;) проектирования, как и архитекторы, строящие дома и здания, могут разработать шаблоны расположения уборных или обустройства кухни. Используя эти шаблоны, или паттерны проектирования, можно проектировать качественные здания быстрее. То же применимо и к разработке программного обеспечения.<br />
<span id="more-3"></span><br />
Паттерны проектирования представляют не только удобный способ для более быстрой разработки надёжного ПО, но и способ для инкапсуляции больших идей в понятных терминах. К примеру, можно говорить о написании системы сообщений для обеспечения слабой связности, а можно &#8211; о паттерне observer, а означать это будет одно и то же.</p>
<p>Сложно продемонстрировать значение паттернов на небольших примерах. Они при этом часто выглядят как излишнее усложнение кода, потому что проявляют себя обычно в крупных системах с большим количеством исходного кода. В этой статье не будут рассматриваться большие приложения, так что нужно использовать воображение, чтобы применить принципы примера (и далеко не обязательно точный его код) в своих больших приложениях. Это не означает, что не нужно использовать паттерны в маленьких приложениях. Многие приложения начинаются как небольшие и развиваются в крупные, так что нет причин не придерживаться этих правил сразу.</p>
<p>Теперь, когда стало немного понятно, что такое паттерны проектирования, и для чего они применяются, пора переходить к пяти самым популярным паттернам проектирования PHP 5.</p>
<h3>Паттерн Factory (фабрика)</h3>
<p>Многие паттерны проектирования в оригинальной книге Design Patterns поощряют слабую связанность. Для понимания этой концепции нужно упомянуть о борьбе, через которую проходят многие разработчики крупных систем. Проблема возникает при изменении куска кода и дальнейшей попытке отследить влияние этого изменения на систему (и в худшем случае &#8211; наблюдением за каскадом отказов системы, которые, предполагалось, никак с изменённым кодом не связанными).</p>
<p>Проблема в сильной свзязанности. Функции и классы в одной части системы слишком сильно полагаются на поведение и архитектуру других функций и классов (в другой части системы). Тут нужны паттерны, которые позволят классам общаться между собой, но при этом позволят избежать слишком сильной их привязки друг к другу, что привело бы к некоторому &laquo;переплетению&raquo; кода независимых частей.</p>
<p>В больших системах большее количество завязано на нескольких ключевых классах. Проблемы могут возникнуть при изменении этих классов. Предположим, у нас есть класс User, который читает из файла. Нам нужно поменять его на другой класс, который читает из базы данных, но во всём коде идут обращения к классу, ктороый читает из файла. Здесь пригодится паттерн <strong>factory</strong>.</p>
<p>Паттерн <strong>factory</strong> &#8211; это класс, который предоставляет методы для создания объектов. Вместо использования конструкции new напрямую, для создания объектов мы используем factory-класс. Весь код, который использует этот factory-класс, меняется автоматически.<br />
В листинге1 приводится пример factory-класса. Серверная сторна состоит из двух частей: база данных и набор php-страниц для добавления каналов (фидов), запроса списка каналов и получения статьи, привязанной к определённому каналу.</p>
<blockquote><p>Листинг1. Factory1.php</p></blockquote>
<pre class="code">
&lt;?php
interface IUser
{
  function getName();
}

class User implements IUser
{
  public function __construct( $id ) { }

  public function getName()
  {
    return "Jack";
  }
}

class UserFactory
{
  public static function Create( $id )
  {
    return new User( $id );
  }
}

$uo = UserFactory::Create( 1 );
echo( $uo-&gt;getName()."\n" );
?&gt;
</pre>
<p>Интерфейс IUser определяет, что следует делать объекту user. Реализация IUser называется User, и factory-класс UserFactory создаёт объекты User (в оригинале написано IUser). На рисунке1 показана связь в виде UML.</p>
<blockquote><p>Рисунок1. Factory-класс и его интерфейс IUser и класс User</p></blockquote>
<p><img alt="" src="http://www.ibm.com/developerworks/library/os-php-designptrns/factory1.gif" class="alignnone" width="229" height="86" /><br />
Если запустить этот код в комендной строке, получим:</p>
<pre class="code">
% php factory1.php
Jack
%
</pre>
<p>В коде примера у factory запрашивается объект User и выводится результат метода getName().</p>
<p>Как вариант, паттерн factory использует factory-методы. Эти статические публичные методы класса создают объекты этого типа. Такой подход полезен, если создание объекта нетривиально. Предположим, что нам нужно сначала создать объект, а потом установить множество свойств для него. Такая версия паттерна factory инкапсулирует этот процесс, и поэтому сложный код инициализации не приходится копипастить по всему проекту. В листинге 2 показан пример использования factory-методов.</p>
<blockquote><p>Листинг2. Factory2.php</p></blockquote>
<pre class="code">
&lt;?php
interface IUser
{
  function getName();
}

class User implements IUser
{
  public static function Load( $id )
  {
        return new User( $id );
  }

  public static function Create( )
  {
        return new User( null );
  }

  public function __construct( $id ) { }

  public function getName()
  {
    return "Jack";
  }
}

$uo = User::Load( 1 );
echo( $uo-&gt;getName()."\n" );
?&gt;
</pre>
<p>Этот код гораздо проще. В нём только один интерфейс &#8211; IUser &#8211; и один класс &#8211; User &#8211; для реализации этого интерфейса. У класса User два статических метода, создающих объект (поясню: оба метода создают объект класса User, но с разными параметрами; при этом можно было бы инициализировать свойства класса по-разному в разных методах). На рисунке2 показана связь в виде UML. </p>
<blockquote><p>Рисунок2. Интерфейс IUser и класс User с двумя factory-методами</p></blockquote>
<p><img alt="" src="http://www.ibm.com/developerworks/library/os-php-designptrns/factory2.gif" class="alignnone" width="95" height="113" /><br />
 Запустив скрипт в командной строке, получим тот же результат, что и в первом примере:</p>
<pre class="code">
% php factory2.php
Jack
%
</pre>
<p>Как и было сказано, иногда использование этих паттернов похоже на стрельбу из пушки по воробьям. Тем не менее, всё равно полезно изучить конкретный код, а уж потом использовать в реальных системах.</p>
<h3>Паттерн Singleton (синглтон)</h3>
<p>Некоторые ресурсы приложения уникальны, т.е. может быть один и только один его экземпляр. К примеру, соединение с базой данных через соответствующий дескриптор уникально. Нам нужно иметь доступ к созданному дескриптору базы данных, т.к. каждый раз при запросе открывать и закрывать соединение во время загрузки страницы накладно.</p>
<p>Для этого отлично подойдёт паттерн Singleton. Объект является синглтоном, если в приложении можно обратиться к одному и только к одному такому объекту.</p>
<p>Код в листинге 3 показывает реализацию синглтона соединения с базой данных. </p>
<blockquote><p>Листинг3. Singleton.php</p></blockquote>
<pre class="code">
&lt;?php
require_once("DB.php");

class DatabaseConnection
{
  public static function get()
  {
    static $db = null;
    if ( $db == null )
      $db = new DatabaseConnection();
    return $db;
  }

  private $_handle = null;

  private function __construct()
  {
    $dsn = 'mysql://root:password@localhost/photos';
    $this-&gt;_handle =&amp; DB::Connect( $dsn, array() );
  }

  public function handle()
  {
    return $this-&gt;_handle;
  }
}

print( "Handle = ".DatabaseConnection::get()-&gt;handle()."\n" );
print( "Handle = ".DatabaseConnection::get()-&gt;handle()."\n" );
?&gt;
</pre>
<p> В коде присутствует один класс, DatabaseConnection. Нельзя создать экземпляр класса DatabaseConnection напрямую, т.к. конструктор класса закрытый. Но можно получить один и только один экземпляр класса DatabaseConnection, использую метод get. UML-диаграмма этого кода показана на рисунке 3.</p>
<blockquote><p>Рисунок 3. Синглтон соединения с базой данных</p></blockquote>
<p><img alt="" src="http://www.ibm.com/developerworks/library/os-php-designptrns/singleton.gif" class="alignnone" width="165" height="41" /><br />
Для подтверждения того, что указанным методом можно получить доступ к одному и тому же ресурсу, достаточно запустить код в командной строке.</p>
<pre class="code">
% php singleton.php
Handle = Object id #3
Handle = Object id #3
%
</pre>
<p>Оба вызова возвращают один и тот же объект. При использовании этого синглтона в приложении, одно и то же соединение будет использоваться всегда.<br />
В небольших приложениях можно обойтись глобальными переменными, но в крупных приложениях следует этого избегать путём использования объектов и методов для получения доступа к ресурсам.</p>
<h3>Паттерн Observer (наблюдатель)</h3>
<p>Паттерн Observer предлагает ещё один способ, чтобы избежать сильной связанности между компонентами. Этот паттерн простой: один объект делает себя наблюдаемым, добавляя метод, который позволяет другому объекту, наблюдателю, себя зарегистрировать.<br />
Когда наблюдаемый объект изменяется, он посылает уведомление зарегистрированным наблюдателям. Что происходит после получения уведомления с наблюдателем, не зависит от наблюдаемого объекта. В результате получаем способ общения между объектами без необходимости понимания, зачем.</p>
<p>Простой пример &#8211; список пользователей системы. Код в Листинге 4 показывает список пользователей, который отсылает уведомление при добавлении новых пользователей. За этим списком следит наблюдатель, ведущий лог; при получении уведомления он выводит сообщение.</p>
<blockquote><p>Листинг 4. Observer.php</p></blockquote>
<pre class="code">
&lt;?php
interface IObserver
{
  function onChanged( $sender, $args );
}

interface IObservable
{
  function addObserver( $observer );
}

class UserList implements IObservable
{
  private $_observers = array();

  public function addCustomer( $name )
  {
    foreach( $this-&gt;_observers as $obs )
      $obs-&gt;onChanged( $this, $name );
  }

  public function addObserver( $observer )
  {
    $this-&gt;_observers []= $observer;
  }
}

class UserListLogger implements IObserver
{
  public function onChanged( $sender, $args )
  {
    echo( "'$args' added to user list\n" );
  }
}

$ul = new UserList();
$ul-&gt;addObserver( new UserListLogger() );
$ul-&gt;addCustomer( "Jack" );
?&gt;
</pre>
<p>В коде определяются 4 элемента: 2 интерфейса и 2 класса. Интерфейс IObservable определяет наблюдаемый объект, а UserList реализует этот интерфейс, чтобы зарегистрироваться в качестве наблюдаемого. IObserver определяет, что нужно, чтобы стать наблюдателем, а UserListLogger реализует интерфейс IObserver. Это показано в виде UML на рисунке 4.</p>
<blockquote><p>Рисунок 4. Наблюдаемый UserList и наблюдатель UserListLogger</p></blockquote>
<p><img alt="" src="http://www.ibm.com/developerworks/library/os-php-designptrns/observer.gif" class="alignnone" width="414" height="99" /><br />
При запуске в командной строке получим вывод: </p>
<pre class="code">
% php observer.php
'Jack' added to user list
%
</pre>
<p>Код примера создаёт UserList и добавляет UserListLogger в качестве наблюдателя. Затем добавляется новый посетитель, и UserListLogger уведомляется об этом изменении.<br />
Важно понимать, что UserList не знает, что логгер собирается сделать. Может быть один или несколько наблюдателей, которые будут делать что-то другое. К примеру, можно сделать наблюдателя, который будет посылать некоторое сообщение новому пользователю, приветствуя вновь прибывшего.<br />
Ценность такого подхода &#8211; в том, что UserList ничего не знает об объектах, зависимых от него; он концентрируется на управлении списком пользователей и рассылает уведомления при его изменении.</p>
<p>Этот паттерн не ограничивается объектами, хранящимися в памяти. Он используется и для систем очереди сообщений на базе баз данных (database-driven message queuing systems), использующихся в крупных приложениях. </p>
<h3>Паттерн Сhain-of-command (цепочка команд)</h3>
<p>Для реализации идеи слабой связанности паттерн Сhain-of-command передаёт сообщение, команду, запрос, как угодно, через набор обработчиков. Каждый обработчик решает, сможет ли он обработать этот запрос. Если может, запрос обрабатывается и процесс передачи останавливается. Можно добавлять/удалять обработчики без влияния на другие обработчики. Листинг 5 показывает пример реализации этого паттерна.</p>
<blockquote><p>Листинг 5. Chain.php</p></blockquote>
<pre class="code">
&lt;?php
interface ICommand
{
  function onCommand( $name, $args );
}

class CommandChain
{
  private $_commands = array();

  public function addCommand( $cmd )
  {
    $this-&gt;_commands []= $cmd;
  }

  public function runCommand( $name, $args )
  {
    foreach( $this-&gt;_commands as $cmd )
    {
      if ( $cmd-&gt;onCommand( $name, $args ) )
        return;
    }
  }
}

class UserCommand implements ICommand
{
  public function onCommand( $name, $args )
  {
    if ( $name != 'addUser' ) return false;
    echo( "UserCommand handling 'addUser'\n" );
    return true;
  }
}

class MailCommand implements ICommand
{
  public function onCommand( $name, $args )
  {
    if ( $name != 'mail' ) return false;
    echo( "MailCommand handling 'mail'\n" );
    return true;
  }
}

$cc = new CommandChain();
$cc-&gt;addCommand( new UserCommand() );
$cc-&gt;addCommand( new MailCommand() );
$cc-&gt;runCommand( 'addUser', null );
$cc-&gt;runCommand( 'mail', null );
?&gt;
</pre>
<p>В коде определяется класс CommandChain, который управляет списком ICommand-объектов. Два класса реализуют интерфейс ICommand &#8211; один отвечает на запросы на почту, а другой &#8211; за добавление пользователей. UML показан на рисунке 5.</p>
<blockquote><p>Рисунок 5. Цепочка команд и соответствующие команды</p></blockquote>
<p><img alt="" src="http://www.ibm.com/developerworks/library/os-php-designptrns/chain.gif" class="alignnone" width="359" height="121" /><br />
При запуске из командной строки скрипт выведет:</p>
<pre class="code">
% php chain.php
UserCommand handling 'addUser'
MailCommand handling 'mail'
%
</pre>
<p>Код сначала создаёт объект CommandChain и добавляет в него два объекта команд. Потом запускаются две команды, чтобы посмотреть, кто на них ответит. Если имя команды не соответствует ни UserCommand, ни MailCommand, то код отрабатывает и ничего не происходит.</p>
<p>Паттерн Chain-of-command может быть ценным при создании расширяемой архитектуры обработки запросов, которая может быть применена для решения многих проблем.</p>
<h3>Паттерн Strategy (стратегия)</h3>
<p>Последним мы рассмотрим паттерн Strategy. В этом паттерне алгоритмы выносятся из сложных классов, чтобы их можно было быть легко изменить. К примеру, паттерн Strategy &#8211; это вариант, если нужно изменить способ ранжирования страниц в поисковой системе. Разобьём поисковый движок на несколько составных частей &#8211; одна пробегает по страницам, одна ранжирует каждую страницу, а ещё одна сортирует результаты, основываясь на рейтинге. Сложный путь &#8211; объединить все части в один класс. Используя паттерн Strategy, можно вынести часть, отвечающую за ранжирование страницы в другой класс, и можно будет изменять механизм ранжирования без вмешательства в остальной код поискового движка.</p>
<p>В более простом примере Листинга 6 приведён класс списка пользователей, который обеспечивает метод поиска набора пользователей, основанный на plug-and-play-наборе стратегий.</p>
<blockquote><p>Листинг 6. Strategy.php</p></blockquote>
<pre class="code">
&lt;?php
interface IStrategy
{
  function filter( $record );
}

class FindAfterStrategy implements IStrategy
{
  private $_name;

  public function __construct( $name )
  {
    $this-&gt;_name = $name;
  }

  public function filter( $record )
  {
    return strcmp( $this-&gt;_name, $record ) &lt;= 0;
  }
}

class RandomStrategy implements IStrategy
{
  public function filter( $record )
  {
    return rand( 0, 1 ) &gt;= 0.5;
  }
}

class UserList
{
  private $_list = array();

  public function __construct( $names )
  {
    if ( $names != null )
    {
      foreach( $names as $name )
      {
        $this-&gt;_list []= $name;
      }
    }
  }

  public function add( $name )
  {
    $this-&gt;_list []= $name;
  }

  public function find( $filter )
  {
    $recs = array();
    foreach( $this-&gt;_list as $user )
    {
      if ( $filter-&gt;filter( $user ) )
        $recs []= $user;
    }
    return $recs;
  }
}

$ul = new UserList( array( "Andy", "Jack", "Lori", "Megan" ) );
$f1 = $ul-&gt;find( new FindAfterStrategy( "J" ) );
print_r( $f1 );

$f2 = $ul-&gt;find( new RandomStrategy() );
print_r( $f2 );
?&gt;
</pre>
<p>UML примера представлен на рисунке 6. </p>
<blockquote><p>Рисунок 6. Список пользователей и стратегии отбора пользователей</p></blockquote>
<p><img alt="" src="http://www.ibm.com/developerworks/library/os-php-designptrns/strategy.gif" class="alignnone" width="309" height="138" /><br />
 Класс UserList представляет собой обёртку для массива имён. Он реализует метод find, который работает с одной из нескольких стратегий отбора из этих имён. Эти стратегии определены интерфейсом IStrategy, у которого есть две реализации: одна выбирает пользователей случайным образом, а в другой выбираются все имена после определённого (т.е. с учётом алфафвита).</p>
<p>При запуске в командной строке получим следующее:</p>
<pre class="code">
% php strategy.php
Array
(
    [0] =&gt; Jack
    [1] =&gt; Lori
    [2] =&gt; Megan
)
Array
(
    [0] =&gt; Andy
    [1] =&gt; Megan
)
%
</pre>
<p>В примере один и тот же список пользователей прогоняется через две стратегии и выводятся результаты. В первом случае стратегия ищет все имена, &laquo;больше&raquo;, чем &laquo;J&raquo; (Jack, Lori и Megan). Вторая стратегия выбирает имена случайным образом, и поэтому выдаёт разные результаты при разных запусках. В нашем случае это Andy и Megan.</p>
<p>Паттерн Strategy очень хорош для сложных систем управления данными, где нужна большая гибкость в фильтрации, поиске и обработке данных.</p>
<h3>Выводы</h3>
<p>Это лишь некоторые из наиболее распространённых паттернов проектирования, используемые в PHP-приложениях. Намного больше можно найти в книге Design Patterns. Не надо шарахаться от паттернов как от чего-то мистического. Паттерны &#8211; это отличные идеи, которые можно использовать при программировании на любом языке и любом уровне профессионального мастерства.</p>
<p>Перевод <a target="_blank" href="http://www.ibm.com/developerworks/library/os-php-designptrns/">статьи</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/07/%d0%bf%d0%b0%d1%82%d1%82%d0%b5%d1%80%d0%bd%d1%8b-%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2-php/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

