<?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/tag/%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%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>Основы ООП на Javascript</title>
		<link>http://www.job-blog.bullgare.ru/2009/09/%d0%be%d1%81%d0%bd%d0%be%d0%b2%d1%8b-%d0%be%d0%be%d0%bf-%d0%bd%d0%b0-javascript/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/09/%d0%be%d1%81%d0%bd%d0%be%d0%b2%d1%8b-%d0%be%d0%be%d0%bf-%d0%bd%d0%b0-javascript/#comments</comments>
		<pubDate>Thu, 10 Sep 2009 16:08:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[ООП]]></category>
		<category><![CDATA[программирование]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=222</guid>
		<description><![CDATA[Объект представляет собой экземпляр класса. Javascript &#8211; это объектно-ориентированный язык, но в нём нет классов, а вместо наследования на основе классов используется наследование на основе прототипов. Объекты создаются при помощи выражений вида var obj = new MyObj(param1, param2); В приведённом примере за оператором new следует имя функции-конструктора MyObj. Его главная задача, как обычно, установка всех [...]]]></description>
			<content:encoded><![CDATA[<p>Объект представляет собой экземпляр класса.<br />
Javascript &#8211; это объектно-ориентированный язык, но в нём нет классов, а вместо наследования на основе классов используется наследование на основе прототипов.<br />
<span id="more-222"></span><br />
Объекты создаются при помощи выражений вида</p>
<pre class="code">
var obj = new MyObj(param1, param2);
</pre>
<p>В приведённом примере за оператором <em>new</em> следует имя функции-конструктора <em>MyObj</em>.<br />
Его главная задача, как обычно, установка всех свойств объекта перед дальнейшим использованием.</p>
<pre class="code">
//определение конструктора
function Rectangle(width, height)
{
    this.width = width;
    this.height = height;
    this.area = function()
    {
        return this.width * this.height;
    }
}
//или
Rectangle = function(width, height)
{
    this.width = width;
    this.height = height;
    this.area = function()
    {
        return this.width * this.height;
    }
}
//создание объектов
var rect1 = new Rectangle(5, 7);
var rect2 = new Rectangle(3.2, 1);
</pre>
<p>Мы создали два объекта со свойствами и методом.<br />
Метод <em>area</em> не имеет особенностей реализации для разных объектов, но каждый раз создаётся заново.<br />
Этого можно избежать, если методы и постоянные свойства определять через прототип, который существует для любого javascript-объекта и доступен через значение свойства <em>prototype</em> функции-конструктора. Все функции имеют свойство <em>prototype</em>, которое инициализируется в момент определения функции.<br />
Любые свойства прототипа становятся свойствами объектов, созданных через конструктор.</p>
<pre class="code">
Rectangle = function(width, height)
{
    this.width = width;
    this.height = height;
}
Rectangle.prototype.area = function()
{
	return this.width * this.height;
}
var rect1 = new Rectangle(5, 7);
var rect2 = new Rectangle(3.2, 1);
</pre>
<p>При чтении свойства объекта сначала проводится поиск среди его свойств, а затем среди свойств объекта-прототипа.<br />
При записи &#8211; если такого свойства у объекта нет, то оно создаётся. К прототипу обращений нет. Сделано это для того, чтобы из одного объекта не поменять свойства всех объектов, созданных через тот же конструктор.</p>
<p>Аналоги классических ООП-конструкций:</p>
<blockquote><p>Свойства объекта</p></blockquote>
<pre class="code">
rect1.width
</pre>
<blockquote><p>Методы объекта</p></blockquote>
<pre class="code">
rect1.area()
</pre>
<blockquote><p>Свойства класса</p></blockquote>
<pre class="code">
Rectangle.unit = new Rectangle(1, 1);
</pre>
<p>* Такая запись возможна потому, что все функции в javascript явлются объектами.</p>
<blockquote><p>Методы класса</p></blockquote>
<pre class="code">
Rectangle.unitArea();
</pre>
<p>При этом ключевое слово <em>this</em> внутри метода класса ссылается на функцию-конструктор класса.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/09/%d0%be%d1%81%d0%bd%d0%be%d0%b2%d1%8b-%d0%be%d0%be%d0%bf-%d0%bd%d0%b0-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL. Выборка значений из нескольких таблиц.</title>
		<link>http://www.job-blog.bullgare.ru/2009/09/mysql-%d0%b2%d1%8b%d0%b1%d0%be%d1%80%d0%ba%d0%b0-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9-%d0%b8%d0%b7-%d0%bd%d0%b5%d1%81%d0%ba%d0%be%d0%bb%d1%8c%d0%ba%d0%b8%d1%85-%d1%82%d0%b0%d0%b1%d0%bb/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/09/mysql-%d0%b2%d1%8b%d0%b1%d0%be%d1%80%d0%ba%d0%b0-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9-%d0%b8%d0%b7-%d0%bd%d0%b5%d1%81%d0%ba%d0%be%d0%bb%d1%8c%d0%ba%d0%b8%d1%85-%d1%82%d0%b0%d0%b1%d0%bb/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 07:44:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Базы данных]]></category>
		<category><![CDATA[JOIN]]></category>
		<category><![CDATA[LEFT JOIN]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[кортеж]]></category>
		<category><![CDATA[подзапрос]]></category>
		<category><![CDATA[программирование]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=200</guid>
		<description><![CDATA[Для примеров используем следующие таблицы: 1. JOIN. Полное объединение Операторы JOIN, INNER JOIN и &#171;,&#187; (запятая) с указанием условий объединения дают пересечение для всех совпадающих значений из условия. SELECT t1.*, t2.* FROM t1, t2 WHERE t1.i1 = t2.i2 #Аналоги: SELECT t1.*, t2.* FROM t1 JOIN t2 ON t1.i1 = t2.i2 SELECT t1.*, t2.* FROM t1 [...]]]></description>
			<content:encoded><![CDATA[<p>Для примеров используем следующие таблицы:<br />
<div id="attachment_202" class="wp-caption alignnone" style="width: 208px"><img src="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/mysql_multiselect_1.png" alt="Используемые таблицы" title="mysql_multiselect_1" width="198" height="124" class="size-full wp-image-202" /><p class="wp-caption-text">используемые таблицы</p></div></p>
<h4>1. JOIN.</h4>
<h5>Полное объединение</h5>
<p>Операторы <em>JOIN</em>, <em>INNER JOIN</em> и <em>&laquo;,&raquo; (запятая)</em> с указанием условий объединения дают пересечение для всех совпадающих значений из условия.</p>
<pre class="code">
SELECT t1.*, t2.* FROM t1, t2 WHERE t1.i1 = t2.i2
#Аналоги:
SELECT t1.*, t2.* FROM t1 JOIN t2 ON t1.i1 = t2.i2
SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ON t1.i1 = t2.i2
</pre>
<p>В результате получим:<br />
<img src="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/mysql_multiselect_2.png" alt="mysql_multiselect_2" title="mysql_multiselect_2" width="258" height="88" class="alignnone size-full wp-image-203" /><br />
При этом если не указать для оператора <em>&laquo;,&raquo; (запятая)</em> условие выборки <em>WHERE</em>, то получим полное декартово произведение (пересечение каждой строки из первой таблицы с каждой строкой из второй):<br />
<img src="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/mysql_multiselect_1_1.png" alt="mysql_multiselect_1_1" title="mysql_multiselect_1_1" width="259" height="197" class="alignnone size-full wp-image-207" /><br />
(аналогичный результат получается при использовании <em>CROSS JOIN</em>)<br />
<em>INNER JOIN</em> можно представить как декартово произведение таблиц, из которого потом отобрали только те строки, которые удовлетворяют условию <em>ON</em>, хотя на практике, конечно, используются более совершенные алгоритмы, такие как <a href="http://en.wikipedia.org/wiki/Hash_join">Hash join</a> и <a href="http://en.wikipedia.org/wiki/Sort-merge_join">Self-merge join</a>, поскольку алгоритм декартова произведения очень неэффективен.</p>
<h5>LEFT JOIN, RIGHT JOIN</h5>
<p>При использовании оператора LEFT JOIN выбираются все значения из левой таблицы, после чего к ним подбираются соответствующие значения из правой, если таких нет, то все значения для правой таблицы в этой строке равны <em>NULL</em>.<br />
RIGHT JOIN противоположен LEFT JOIN: всё абсолютно так же, но выбираются все значения для правой таблицы из выражения.</p>
<pre class="code">
SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON t1.i1 = t2.i2
</pre>
<p>В результате получим:<br />
<div id="attachment_204" class="wp-caption alignnone" style="width: 262px"><img src="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/mysql_multiselect_3.png" alt="результаты LEFT JOIN" title="mysql_multiselect_3" width="252" height="104" class="size-full wp-image-204" /><p class="wp-caption-text">результаты LEFT JOIN</p></div></p>
<pre class="code">
SELECT t1.*, t2.* FROM t1, t2 ON t1.i1 = t2.i2
#другая запись
SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ON t1.i1 = t2.i2 WHERE
#аналогично по результату, хотя обычно медленнее
SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON t1.i1 = t2.i2 WHERE t2.i2 IS NOT NULL
</pre>
<p>При указании любого из операторов <em>JOIN</em> можно использовать ключевое слово <em>USING()</em> вместо <em>ON</em>, если названия столбцов в обеих таблицах одинаковы.</p>
<pre class="code">
SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON t1.i = t2.i
#аналогично
SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 USING(i)
</pre>
<p><em>JOIN</em>&#8216;ы можно комбинировать:</p>
<pre class="code">
SELECT t1.*, t2.*
FROM t1, t2
LEFT JOIN t3
ON t1.i = t3.i1 AND t2.i = t3.i2
WHERE t3.i2 IS NOT NULL
</pre>
<h5>Self-join</h5>
<p>Self-join объединяет таблицу саму с собой. Проще показать на примере.<br />
Допустим есть таблица<br />
<div id="attachment_726" class="wp-caption alignnone" style="width: 342px"><a href="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/EmployeeTable.png"><img src="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/EmployeeTable.png" alt="" title="EmployeeTable" width="332" height="195" class="size-full wp-image-726" /></a><p class="wp-caption-text">Таблица Employee</p></div><br />
И допустим, что нужно получить пары сотрудников, которые работают в одной стране. Результата можно добиться и уже описанными join&#8217;ами, но эффективнее будет следующий запрос:</p>
<pre class="code">
SELECT F.EmployeeID, F.LastName, S.EmployeeID, S.LastName, F.Country
FROM Employee F, Employee S
WHERE F.Country = S.Country
AND F.EmployeeID < S.EmployeeID
ORDER BY F.EmployeeID, S.EmployeeID;
</pre>
<p>В результате получим:<br />
<div id="attachment_728" class="wp-caption alignnone" style="width: 374px"><a href="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/EmployeeTable-self-join.png"><img src="http://www.job-blog.bullgare.ru/wp-content/uploads/2009/09/EmployeeTable-self-join.png" alt="" title="EmployeeTable-self-join" width="364" height="145" class="size-full wp-image-728" /></a><p class="wp-caption-text">Результат self-join таблицы Employee</p></div><br />
В данном случае:<br />
<em>F</em> и <em>S</em> - алиасы таблицы Employee<br />
условие <em>F.Country = S.Country</em> исключает из результата пары, для которых страны не совпадают<br />
условие <em>F.EmployeeID < S.EmployeeID</em> исключает пары с одинаковыми <em>EmployeeID</em>, а также дублирование ранее выведенных пар (т.е. сотрудник с <em>EmployeeID</em>=145 не выведется слева).</p>
<p><strong>INNER JOIN в некоторых случаях значительно быстрее, чем OUTER JOIN (LEFT JOIN или RIGHT JOIN), поэтому лучше по возможности использовать INNER JOIN.</strong> <a href="http://forums.mysql.com/read.php?24,205080">Пример сравнения производительности с объяснением</a>.<br />
<a href="http://en.wikipedia.org/wiki/Join_%28SQL%29">Виды JOIN'ов</a></p>
<h4>2. Подзапросы.</h4>
<p>Подзапросы организуются в виде вложенных <em>SELECT</em>'ов.<br />
В принципе, в подзапросах можно использовать и другие операторы, но модифицирующие <em>INSERT</em>, <em>REPLACE</em>, <em>DELETE</em>, <em>UPDATE</em> при этом не могут модифицировать таблицу из основного запроса.</p>
<pre class="code">
SELECT t1.*FROM t1 WHERE t1.i1 IN (SELECT i2 FROM t2 WHERE c2 = 'a')
</pre>
<p>Подзапрос может возвращать одно значение (скалярный подзапрос), несколько значений одного столбца, несколько значений нескольких столбцов (фактически, таблицу).<br />
Со скалярным подзапросом можно использовать операторы сравнение ("=", "&gt;", "&lt;", "&lt;&gt;" и т.д.).<br />
Приэтом важно, чтобы подзапрос возвращал только одно значение.<br />
Это очень удобно в запросах типа</p>
<pre class="code">
#так писать нельзя, т.к. значение MIN(i) неизвестно
#до того момента, как произойдёт выборка
#т.е. уже после того, как понадобится "WHERE"
SELECT * FROM t1 WHERE i = MIN(i)
#а вот так писать можно
SELECT * FROM t1 WHERE i = (SELECT MIN(i) FROM t1)
</pre>
<p>Если подзапрос возвращает одну строку, то можно использовать <strong>кортеж</strong> (набор значений для сравнения):<br />
Это очень удобно в запросах типа</p>
<pre class="code">
SELECT t1.* FROM t1
WHERE (i, c) = (SELECT i, c FROM t2 WHERE i = 2 LIMIT 1)
</pre>
<p>Если подзапрос может вернуть несколько значений, то лучше ипользовать операторы <em>IN</em> и <em>NOT IN</em> вместо <em>=</em> и <em>&lt;&gt;</em> соответственно.</p>
<pre class="code">
SELECT t1.* FROM t1
WHERE (i, c) IN (SELECT i, c FROM t2)
</pre>
<p>Операторы <em>EXISTS</em> и <em>NOT EXISTS</em> нужны для того, чтобы определить, вернулись ли значения из подзапроса (используются для <strong>коррелированных подзапросов</strong>).</p>
<pre class="code">
SELECT * FROM t1
WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE i > 10000)
</pre>
<h5>Коррелированные подзапросы</h5>
<p>содержат ссылки на значения внешнего запроса.</p>
<pre class="code">
SELECT i FROM t1 WHERE j IN (SELECT k FROM t2 WHERE k = i)
</pre>
<p>Пример несколько странный получился.<br />
Более реалистичный:</p>
<pre class="code">
SELECT i FROM t1
WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.i1 = t1.i)
</pre>
<p>Подзапросы можно переписывать через операторы <em>JOIN</em> (в некоторых случаях может работать быстрее).</p>
<pre class="code">
SELECT * FROM t1
WHERE i IN (SELECT i1 FROM t2 WHERE t2.i = 15)
#аналогично
SELECT t1.* FROM t1, t2
WHERE t1.i = t2.i1 AND t2.i = 15
</pre>
<p>* При этом могут возвращаться несколько разные результаты, если в <em>t2.i1</em> содержатся неуникальные значения. В таком случае подзапрос выдаст только уникальные значения, а <em>JOIN</em> выдаст все. Чтобы этого избежать, нужно во втором запросе использовать оператор <em>SELECT DISTINCT</em> (выбрать только уникальные значения).</p>
<pre class="code">
SELECT * FROM t1
WHERE i NOT IN (SELECT i1 FROM t2)
#аналогично
SELECT t1.*
FROM t1 LEFT JOIN t2 ON t2.i1 = t1.i
WHERE t2.i1 IS NULL
</pre>
<p>(при этом в подзапросе можно заметить отсутствие условия выборки;))</p>
<h4>3. UNION</h4>
<p>Выборка из нескольких таблиц последовательно.<br />
<em>UNION</em> действует как <em>SELECT DISTINCT</em>, т.е. отбрасывает повторяющиеся значения. чтобы этого избежать, нужно использовать оператор <em>UNION ALL</em></p>
<pre class="code">
(SELECT i, c FROM t1 ORDER BY i DESC)
UNION
(SELECT i, d FROM t2 ORDER BY i)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/09/mysql-%d0%b2%d1%8b%d0%b1%d0%be%d1%80%d0%ba%d0%b0-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9-%d0%b8%d0%b7-%d0%bd%d0%b5%d1%81%d0%ba%d0%be%d0%bb%d1%8c%d0%ba%d0%b8%d1%85-%d1%82%d0%b0%d0%b1%d0%bb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Оптимизация и скорость выполнения в jQuery</title>
		<link>http://www.job-blog.bullgare.ru/2009/08/%d0%be%d0%bf%d1%82%d0%b8%d0%bc%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%b8-%d1%81%d0%ba%d0%be%d1%80%d0%be%d1%81%d1%82%d1%8c-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-jquery/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/08/%d0%be%d0%bf%d1%82%d0%b8%d0%bc%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%b8-%d1%81%d0%ba%d0%be%d1%80%d0%be%d1%81%d1%82%d1%8c-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-jquery/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 14:26:08 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[клиентская оптимизация]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[оптимизация]]></category>
		<category><![CDATA[программирование]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=173</guid>
		<description><![CDATA[ссылка на интересный доклад по jQuery]]></description>
			<content:encoded><![CDATA[<p><a href="http://mabp.kiev.ua/2009/08/10/presentation-from-coffee-n-code/">ссылка на интересный доклад по jQuery</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/08/%d0%be%d0%bf%d1%82%d0%b8%d0%bc%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%b8-%d1%81%d0%ba%d0%be%d1%80%d0%be%d1%81%d1%82%d1%8c-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPillow &#8211; php-библиотека для работы с CouchDB</title>
		<link>http://www.job-blog.bullgare.ru/2009/07/phpillow-php-%d0%b1%d0%b8%d0%b1%d0%bb%d0%b8%d0%be%d1%82%d0%b5%d0%ba%d0%b0-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b-%d1%81-couchdb/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/07/phpillow-php-%d0%b1%d0%b8%d0%b1%d0%bb%d0%b8%d0%be%d1%82%d0%b5%d0%ba%d0%b0-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b-%d1%81-couchdb/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 12:03:37 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Базы данных]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[CouchDb]]></category>
		<category><![CDATA[PHPillow]]></category>
		<category><![CDATA[база данных]]></category>
		<category><![CDATA[бд]]></category>
		<category><![CDATA[программирование]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=97</guid>
		<description><![CDATA[&#171;официальный&#187; сайт объяснение работы с CouchDB через php]]></description>
			<content:encoded><![CDATA[<p><a href="http://arbitracker.org/phpillow.html">&laquo;официальный&raquo; сайт</a></p>
<p><a href="http://wiki.apache.org/couchdb/Getting_started_with_PHP">объяснение работы с CouchDB через php</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/07/phpillow-php-%d0%b1%d0%b8%d0%b1%d0%bb%d0%b8%d0%be%d1%82%d0%b5%d0%ba%d0%b0-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b-%d1%81-couchdb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPUnit в MVC-подобных системах</title>
		<link>http://www.job-blog.bullgare.ru/2009/07/phpunit-%d0%b2-mvc-%d0%bf%d0%be%d0%b4%d0%be%d0%b1%d0%bd%d1%8b%d1%85-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85/</link>
		<comments>http://www.job-blog.bullgare.ru/2009/07/phpunit-%d0%b2-mvc-%d0%bf%d0%be%d0%b4%d0%be%d0%b1%d0%bd%d1%8b%d1%85-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 09:13:27 +0000</pubDate>
		<dc:creator>bullgare</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[тестирование]]></category>

		<guid isPermaLink="false">http://www.job-blog.bullgare.ru/?p=61</guid>
		<description><![CDATA[Установка PHPUnit производится через PEAR (Описание на англ.). Главное дальше &#8211; это научить систему работать не только (а лучше &#8211; совсем не) с серверными переменными вроде $_SERVER['REQUEST_URI'], а с переданными урлами (чтобы эмулировать обращение к конкретной странице) (Dependency Injection). В рассматриваемом конкретном случае предполагается в начале каждого теста подгружать файл TestInit.php. Листинг1. TestInit.php &#60;? $_SERVER['HTTP_HOST'] [...]]]></description>
			<content:encoded><![CDATA[<p>Установка PHPUnit производится через PEAR (<a href="http://www.phpunit.de/manual/3.4/en/installation.html">Описание на англ.</a>).<br />
Главное дальше &#8211; это научить систему работать не только (а лучше &#8211; совсем не) с серверными переменными вроде $_SERVER['REQUEST_URI'], а с переданными урлами (чтобы эмулировать обращение к конкретной странице) (Dependency Injection).</p>
<p>В рассматриваемом конкретном случае предполагается в начале каждого теста подгружать файл TestInit.php.<br />
Листинг1. TestInit.php</p>
<pre class="code">&lt;?
$_SERVER['HTTP_HOST'] = 'хост';
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['QUERY_STRING'] = '';
//возникают ошибки, т.к. не все серверные переменные установлены
ini_set('display_errors','off');
error_reporting(E_ERROR);
require_once ('абсолютный-путь-к-рут-сайта/htdocs/init.php');
ini_set('display_errors','on');
error_reporting(E_ALL);

ini_set('include_path', ini_get('include_path')
    . ';абсолютный-путь-к-рут-сайта;абсолютный-путь-к-PEAR;.');

require_once 'PHPUnit/Framework.php';

echo "--started--\n";
?&gt;</pre>
<p>Проблема &#8211; отключить вывод из шаблонов (система была сделана слишком прямолинейной &#8211; нет единого центра управления выводом).<br />
Запуск получается следующий:</p>
<pre class="code">C:\wamp\php5\PEAR&gt;pear-phpunit.bat C:\wamp\www\moikompas\tests\ModelGroup.php</pre>
<p><strong>ССылки</strong><br />
Написание тестов &#8211; <a href="http://www.phpunit.de/manual/3.4/en/writing-tests-for-phpunit.html">страницы PHPUnit Manual</a></p>
<p><a href="http://zendframework.ru/articles/automated-testing-with-zend-framework-and-phpunit">Автоматизированное тестирование ZendFramework-приложений (manual)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.job-blog.bullgare.ru/2009/07/phpunit-%d0%b2-mvc-%d0%bf%d0%be%d0%b4%d0%be%d0%b1%d0%bd%d1%8b%d1%85-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%85/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>

