<?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>Insight IT &#187; Программирование</title>
	<atom:link href="http://www.insight-it.ru/category/programmirovanie/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.insight-it.ru</link>
	<description>Информационные технологии</description>
	<lastBuildDate>Sun, 25 Apr 2010 14:19:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Django в гостях у Google</title>
		<link>http://www.insight-it.ru/masshtabiruemost/django-v-gostyakh-u-google/</link>
		<comments>http://www.insight-it.ru/masshtabiruemost/django-v-gostyakh-u-google/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 20:53:28 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Масштабируемость]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[app engine patch]]></category>
		<category><![CDATA[BigTable]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[gae]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[google app engine]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[платформа]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/?p=213</guid>
		<description><![CDATA[
Давным-давно, в далекой-предалекой галактике...
Хотя да, достаточно давно уже Google выпустили в свет платформу Google App Engine. Описание этого продукта меня заинтересовало еще до открытия публичного доступа к системе и я даже записался на полу-закрытое тестирование. Вскоре пришло подтверждение, что мол &#171;мы рады сообщить, что Ваша учетная запись активирована и теперь у Вас есть возможность попробовать [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/appengine.jpg" title="Google App Engine" alt="Google App Engine" style="float:left;" /><br />
<span style="text-decoration: line-through;">Давным-давно, в далекой-предалекой галактике...</span></p>
<p>Хотя да, достаточно давно уже Google выпустили в свет платформу <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.appspot.com/" id="ix89" title="Google App Engine"  target="_blank" rel="external nofollow">Google App Engine</a></noindex>. Описание этого продукта меня заинтересовало еще до открытия публичного доступа к системе и я даже записался на полу-закрытое тестирование. Вскоре пришло подтверждение, что мол &laquo;мы рады сообщить, что Ваша учетная запись активирована и теперь у Вас есть возможность попробовать наш новый продукт, для этого нажмите ссылку такую-то&raquo;. Но пришло оно как-то не очень удачно, когда ни лишнего свободного времени не было, да и идеи подходящей для создания чего-нибудь эдакого на новой платформе тоже на горизонте не наблюдалось. В общем зашел на их сайт, посмотрел админку, поставил демо-приложение, поигрался чуток и забросил. Но с тех пор руки так и не прекращали чесаться от желания попробовать GAE на каком-нибудь более приближенном к реальности приложении, что мне совсем недавно и довелось сделать. Спешу поделиться впечатлениями.<br />
<span id="more-213"></span><br />
Если Вы даже краем уха не слышали о платформе <span style="font-family: Courier New;">Google App Engine</span> и после прочтения вступления не удосужились скопировать это название в свою любимую поисковую систему, чтобы почитать по-подробнее, то Вам повезло: для порядка я все-таки расскажу чуть-чуть о тех вкусностях, которые так долго поддерживали мой интерес к данному проекту.</p>
<p>Если взглянуть издалека, то GAE представляет собой условно-бесплатный хостинг для веб-приложений, для разработчиков предоставляется все необходимое: начиная от минимально-необходимого <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://code.google.com/appengine/downloads.html" id="t39e" title="SDK"  target="_blank" rel="external nofollow">SDK</a></noindex> со встроенным веб-сервером, локально эмулирующим саму платформу, заканчивая неплохой документацией по самой системе и доступным из нее API от Google. Почему условно-бесплатный? Бесплатно приложениям выделяется лишь ограниченное количество вычислительных ресурсов, при превышении которых по выбору владельца приложения либо взимается вполне <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://code.google.com/appengine/docs/quotas.html" id="ly53" title="скромная плата"  target="_blank" rel="external nofollow">скромная плата</a></noindex>, либо всем пользователям начинают показывать &laquo;извиняйте, заходите завтра&raquo; (в прямом смысле, счетчики потребления ресурсов сбрасываются ежедневно).</p>
<p>Но финансовый вопрос далеко не самый интересный, давайте взглянем на техническую сторону медали. Написанное с использованием SDK приложение загружается в production-окружение, которое физически размещается на тех самых известных кластерах Google, о которых у меня даже <a id="t6li" title="есть пост" href="../net/scalability/arkhitektura-google/" target="_blank" rel="external nofollow">есть пост</a> (конечно же под GAE используется только очень небольшая часть их вычислительных можностей). Причем все заботы о распределенной работе приложения на большом количестве машин платформа берет на себя: разработчику не нужно думать ни о балансировке нагрузки, ни о партиционировании данных, ни о других аспектах. Сразу же после окончания процессов загрузки и развертывания приложение готово становится готово к работе и доступно по домену третьего уровня на <span style="font-family: Courier New;">*.appspot.com</span>, либо можно подключить свой отдельный домен.</p>
<p>Технические ограничения тоже имеют быть: для разработки под GAE можно использовать лишь небольшой набор языков программирования, в частности Python 2.5, а также Java и все остальные языки, компилируемые или интерпретируемые под JVM (JRuby, Scala, Rhino, etc.). Все приложения исполняются в песочнице, ограничивающей доступ к окружающему миру, то есть определенные подмножества языков становятся недоступны, например: доступ к файловым системам, встроенные средства обработки изображений, доступ к сторонним ресурсам по HTTP, отправка почты. Про реляционные базы данных, memcached и библиотеки, использующие нативный, платформозависимый код, также стоит забыть. Но не все так плохо, как кажется: для реализации всех &laquo;отобранных&raquo; у разработчиков функциональных компонент Google предоставляет собственные сервисы-заменители, доступные через хорошо документированный API или вовсе замаскированные под стандартные методы языка. В качестве дополнительных бонусов предоставляются и возможности по интеграции с другими продуктами Google, скажем можно легко сделать авторизацию пользователей в приложении по учетным записям от <em>GMail</em> или нотификацию пользователей по Jabber через <em>GTalk</em>.</p>
<p>Отдельного внимания заслуживает используемая в данной платформе система хранения данных, основанная на <strong>BigTable</strong>, о которой более подробно можно почитать в уже упомянутом <a id="j:55" title="посте об архитектуре Google" href="../net/scalability/arkhitektura-google/" target="_blank">посте об архитектуре Google</a>. Если в двух словах, то она представляет собой распределенное <strong>не</strong>реляционное хранилище данных, автоматически обеспечивающее репликацию и кеширование данных, а также практически гарантирующее постоянную доступность данных вне зависимости от сбоев низлежащего оборудования. Для доступа к нему разработчикам предоставляется специальный API и язык доступа к данным <em>GQL</em>, слегка напоминающий упрощенный диалект <em>SQL</em> (лишь отдаленно). Продукт в обращении достаточно своеобразен, как оказалось самый простой способ привыкнуть к работе с ним&nbsp;&mdash; выкинуть из головы все знания о традиционных СУБД и взглянуть на процесс хранения данных с чистого листа. Разномастные JOIN&#39;ы и прочие изыски лишь мешают думать в терминах подобных систем.</p>
<p>Закончив тему с рекламой GAE, позвольте перейти к моим личным впечатлениям. Попробовал я данную платформу на вполне конкретном примере (в конце поста дам ссылочку на частично-готовый результат, если кому интересно), надо же в конце-концов на что-то с пользой убивать внезапно появившееся свободное время. ОтJava и прочей компании языков, основанных на JVM, я невероятно устал на теперь уже &laquo;прошлой&raquo; работе, так что взор мой упал на Python и давно находящийся у меня на слуху (в основном благодаря  <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.softwaremaniacs.org/" id="vdse" title="Ивану Сагалаеву"  target="_blank" rel="external nofollow">Ивану Сагалаеву</a></noindex>) фреймворк <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.djangoproject.com/" id="mnk8" title="Django"  target="_blank" rel="external nofollow">Django</a></noindex>. Ни с тем, ни с другим я ранее почти не был знаком на практике, разве что когда-то пытался помогать своим очень хорошим подругам с прохождением Python в университете (пользуясь случаем, передаю привет Полине, Кате и Юле, очень по вам скучаю <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). Стоит упомянуть, что существует несколько сборок Django, адаптированных под GAE, наиболее продуманным и готовым к эксплуатации мне показался проект под названием  <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://code.google.com/p/app-engine-patch/" id="u899" title="app engine patch"  target="_blank">app engine patch</a></noindex>, которым я и воспользовался для экспериментов.</p>
<p>Django, как известно, является вполне традиционным веб-фрейморком, пропагандирующим свою вариацию на тему MVC (именуемую <strong>MVT</strong>&nbsp;&mdash; <span style="font-family: Courier New;">Model-View-Template</span>, но по сути абсолютно то же самое), а также целый ряд философских верований (вроде <em>DRY, Don&#39;t repeat yourself</em>), которым даже отведена <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://docs.djangoproject.com/en/dev/misc/design-philosophies/" id="m71-" title="отдельная страница на сайте"  target="_blank" rel="external nofollow">отдельная страница на официальном сайте</a></noindex>. Адаптированная под GAE версия фреймворка отличается от стандартной по большому счету лишь замененной частью <span style="font-family: Courier New;">Model</span>, в которую очень неплохо вписался предоставляемый API к уже упоминавшемуся хранилищу данных. По всем остальным компонентам системы официальная документация по Django практически полностью актуальна и сильно помогла понять всю картину разработки веб-приложений с использованием данных технологий.</p>
<p>Пересказывать функциональные возможности Django как-то не входило в мои планы, все кому интересно и так уже в курсе или знают где посмотреть. Хочу лишь сказать, что со своей задачей упрощения и ускорения процесса разработки веб-приложений он полностью справляется: все основные функциональные компоненты реализуются просто, легко и быстро, при этом особой необходимости (да и желания) вникать в то, как оно в итоге работает не возникает. Если же взглянуть на Django в совокупности с возможностями GAE&nbsp;&mdash; вопросы масштабируемости также по большей части с плеч разработчика снимаются (если не забыть прочитать документацию по хранилищу и не творить глупостей). В общем что-что, а количество человекочасов, требуемых на создание качественного масштабируемого веб-приложения, эта парочка способна сократить изрядно.</p>
<p>Предложение Google по использованию платформы GAE выглядит очень заманчиво, не смотря на все ограничения под нее можно как портировать существующие приложения, так и легко создавать новые. Бесплатное использование до превышения квот также не может не радовать (кстати квоты там рассчитаны на мировой рынок, превысить большинство из них в рамках рунета&nbsp;&mdash; надо постараться, мне кажется). Но закончить данное повествование мне всетаки хотелось парой недокументированных или вкратце официально упоминавшихся &laquo;ложек дегтя&raquo;. Первая неприятная особенность: процессы, обрабатывающие пользовательские запросы приложений, умирают после очень небольшого времени простоя (таймаут судя по всему секунд 20-30). По истечении таймаута система освобождает использующиеся приложением ресурсы и когда после перерыва приходит очередной пользователь система вынуждена заново инициализироваться (чуть ли не заново компилировать байткод, хотя не уверен), что занимает около 5 секунд, а то и больше, во время которых пользователю ничего не остается кроме как терпеливо ждать. Сделали данный механизм видимо в связи с тем фактом, что подавляющее большинство развернутых приложений были сделаны просто чтобы побаловаться и были сразу же заброшены, что делает неэффективным постоянное держание в готовом состоянии даже одного процесса для каждого приложения. Таким образом использование GAE для тяжелых веб-приложений с небольшой целевой аудиторией не очень эффективно.  Минус второй: существуют некоторые жесткие ограничения, которые не разрешают увеличивать даже за деньги (по крайней мере расценок не видно). В их число входят максимальное время обработки одного запроса (30 секунд, правда не ясно распространяется ли это на выполнение задач в Task Queue и местном аналоге Cron&#39;а), 30 активных процессов, обрабатывающих запросы приложения (что влечет за собой достаточно жесткое ограничение на количество запросов в секунду в районе нескольких сотен), максимальный размер HTTP запроса/ответа в 10 мегабайт и некоторые другие. В итоге &laquo;тяжелые&raquo; вычисления на GAE не погоняешь (хотя есть варианты с применением AJAX и, соответственно, большого количества запросов к GAE), от Digg-эффекта или DDOS&#39;а есть шанс не уберечься, хостинг файлов не соорудить, но... разве это ограничения? Есть масса более интересных типов веб-приложений, способных прекрасно существовать в такой среде. Да и в крайнем случае всегда можно связаться с представителями Google с просьбой в виде исключение для Вашего приложения, судя по их заявлениям все ограничения носят искусственный характер и служат лишь для защиты от потребления неоправданно большого количества вычислительных ресурсов плохо спроектированных приложениями.</p>
<p>Этот пост написан по мотивам истории сайта <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.cargobook.ru/" id="csyo" title="CargoBook"  target="_blank">CargoBook</a></noindex>, который задумывался как сообщество для логистов, с плавным выходом на корпоративный рынок с продуктом в виде логистической информационной системы, предоставляемой по принципу SaaS. Сходив по ссылке можно заценить, что можно сделать средствами сладкой парочки Django+GAE и одного студента с почти гуманитарным образованием за часов эдак 20 работы в свободное время. Сейчас в задумке кроме меня участвует всего еще один человек: на правах автора идеи, но  если Вас заинтересовал данный проект и может быть Вы хотите присоединиться в каком-либо амплуа&nbsp;&mdash; пишите об этом в комментариях или <a id="hvgv" title="по другим контактным данным" href="../author" target="_blank">по другим контактным данным</a>.</p>
<p>Кстати в американской части Интернета о GAE ходят в основном негативные мнения, мол тормозит, большое время отклика, сплошные таймауты и ошибки. На практике пока не удалось столкнуться с чем-то подобным, но реально работающего приложения с активной пользовательской базой у меня пока нет для того, чтобы делать какие-то относительно объективные выводы. Может быть со временем что-нибудь изменится и более тонкие нюансы станут выползать на поверхность&nbsp;&mdash; время покажет. Как раз будет повод написать еще один пост на эту же тему <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/masshtabiruemost/django-v-gostyakh-u-google/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>memcached на пальцах</title>
		<link>http://www.insight-it.ru/programmirovanie/memcached-na-palcakh/</link>
		<comments>http://www.insight-it.ru/programmirovanie/memcached-na-palcakh/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 12:09:06 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Memcached]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/?p=117</guid>
		<description><![CDATA[Ранее уже была сделана публикация с обзором memcached. Давайте вернемся к данной теме и рассмотрим практику работы с memcached на примерах.


К сожалению у меня по прежнему не доходят руки активно заниматься блогом, но наконец-то появился появился первый человек, откликнувшийся на мое предложение стать гостевым автором данного блога. Его имя Владислав Клименко и именно он является [...]]]></description>
			<content:encoded><![CDATA[<p>Ранее уже была сделана публикация с обзором memcached. Давайте вернемся к данной теме и рассмотрим практику работы с memcached на примерах.<br />
<span id="more-117"></span></p>
<div style="color:#eeffee; background-color:#6aa800; padding:8pt 16pt;">
<p>К сожалению у меня по прежнему не доходят руки активно заниматься блогом, но наконец-то появился появился первый человек, откликнувшийся на <a style="color:#daffda !important" href="/guest-posts">мое предложение стать гостевым автором данного блога</a>. Его имя <em>Владислав Клименко</em> и именно он является автором данного поста, а я лишь выступаю в роли редактора. Может быть данный пример подтолкнет и других читателей поучаствовать в возвращении <strong>Insight IT</strong> к жизни.</p>
<p style="text-align:right">С уважением,<br />Иван Блинков</p>
</div>
<p>Итак, пара слов о предмете разговора. memcached&nbsp;&mdash; это распределенная система кэширования объектов в оперативной памяти. Разрабатывается фирмой <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://danga.com/"  rel="nofollow">Danga Interactive</a></noindex> (кстати, они являются авторами не только memcached, но и других интересных проектов). Но о них, возможно, в следующий раз. Обычно memcached используется приложениями для временного хранения данных, которые надо часто читать. Приложения не взаимодействуют (обычно) напрямую с сервером memcached, а работают при помощи клиентских библиотек. На настоящее время созданы библиотеки для многих языков программирования (а для некоторых еще и по нескольку альтернативных) &nbsp;&mdash; полный список клиентских библиотек доступен на <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://code.google.com/p/memcached/wiki/Clients"  rel="nofollow">wiki проекта</a></noindex>. В целом, данная схема похожа на работу с БД, знакомую многим разработчикам.</p>
<p>Будем рассматривать установку и использование memcached для Linux. Так же при рассмотрении примеров на PHP и обзоре кэширования сессий потребуются PHP и Apache. Возможно, их придется установить, но мы не будем заострять внимание на вопросах установки.</p>
<h2>Сервер memcached</h2>
<p>Давайте приступим к установке memcached. Практически во всех дистрибутивах Linux memcached можно установить из репозитариев. Если есть желание собрать самую свежую версию, то можно заглянуть на <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://danga.com/memcached/"  rel="nofollow">сайт разработчика</a></noindex>  (на момент написания этих строк последняя версия&nbsp;&mdash; <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://memcached.googlecode.com/files/memcached-1.4.0.tar.gz"  rel="nofollow">1.4.0</a></noindex>).<br />
Также, возможно, понадобится установить libevent. Последняя стабильная версия&nbsp;&mdash; <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.monkey.org/~provos/libevent-1.4.11-stable.tar.gz"  rel="nofollow" rel="nofollow">1.4.11</a></noindex></p>
<p>Собираем, устанавливаем и запускаем memcached в режиме вывода сообщений. Интересно же посмотреть, что с ним происходит:</p>
<pre lang="bash">memcached -vv</pre>
<p>Процесс запускается и ждет подключений (по умолчанию на порту 11211). Серверная часть готова обрабатывать подключения клиентов и кэшировать полученные данные.</p>
<p>Но для разработчика приложений это только полпути. Необходимо поддержать работу с memcached в своем приложении. Для этого, рассмотрим некоторые существующие клиентские библиотеки memcached.</p>
<h2>Клиенты memcached</h2>
<p>Из всего многообразия клиентских библиотек рассмотрим две:</p>
<ul>
<li>libmemcached (для Си);</li>
<li>PECL extension для PHP (построенный на базе предыдущей библиотеки).</li>
</ul>
<h2>Си</h2>
<p>Библиотека libmemcached на данный момент активно развивается и представляется наиболее подходящим выбором при работе с Си и PHP. Также, в комплекте с самой клиентской библиотекой поставляются дополнительные утилиты для работы с memcached, позволяющие просматривать, устанавливать, удалять значения в кэше memcached. Кстати, удивляет, что набор утилит идет не с серверной частью, а с клиентской библиотекой.</p>
<p>Итак, приступим к установке libmemcached. На момент написания этих строк текущая версия libmemcached&nbsp;&mdash; <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://download.tangent.org/libmemcached-0.31.tar.gz"  rel="nofollow">0.31</a></noindex>. Компилируем, устанавливаем. Для начала, наслаждаемся чтением страниц man:</p>
<pre lang="bash">
man libmemcached
man libmemcached_examples
</pre>
<p>C библиотекой поставляются описание несложных примеров использования. За более интересными же способами применения имеет смысл заглянуть в исходные тексты утилит, благо все идет вместе.</p>
<p>Рекомендую обратить внимание на собранные утилиты. Наверняка многие из них станут верными помощниками при разработке приложений.</p>
<ul>
<li><b>memstat</b>&nbsp;&mdash; выдает информацию о сервере memcached</li>
<li><b>memcat</b>&nbsp;&mdash; выдает значение по ключу</li>
<li><b>memrm</b>&nbsp;&mdash; удаляет значение по ключу</li>
<li><b>memdump</b>&nbsp;&mdash; выдает список ключей</li>
</ul>
<p>Для начала посмотрим, что скажет сервер memcached, запущенный нами немного ранее в режиме выдачи сообщений. Запросим статистику сервера при помощи утилиты memstat:</p>
<pre lang="bash">
memstat --servers localhost
 Listing 1 Server
 Server: localhost (11211)
 pid: 14534
  uptime: 1950
 time: 1247390264
 version: 1.4.0
 pointer_size: 32
 rusage_user: 0.0
 rusage_system: 0.0
 curr_items: 0
 total_items: 0
 bytes: 0
 curr_connections: 10
 total_connections: 11
 connection_structures: 11
 cmd_get: 0
 cmd_set: 0
 get_hits: 0
 get_misses: 0
 evictions: 0
 bytes_read: 0
 bytes_written: 0
 limit_maxbytes: 67108864
 threads: 5
</pre>
<p>Получили статистику&nbsp;&mdash; следовательно memcached функционирует и откликается на запросы.</p>
<p>Итак, на настоящий момент готовы к использованию сервер memcached и клиентская библиотека. Осталось дело за малым&nbsp;&mdash; внедрить использование memcached в разрабатываемое приложение. Что касается приложения&nbsp;&mdash; все в руках разработчиков, а мы рассмотрим небольшой пример работы с базовыми функциями.</p>
<p>memcached предоставляет следующий набор основных функций (их, конечно, больше, но здесь приведены основные):</p>
<ul>
<li><b>set</b> - занести в кэш пару ключ-значение</li>
<li><b>add</b> - занести в кэш значение при условии, что значения с таким ключом в кэше еще нет</li>
<li><b>replace</b>&nbsp;&mdash; обновляет кэш при условии, что значение с таким ключом в кэше уже есть</li>
<li><b>get</b>&nbsp;&mdash; получает значение из кэша по указанному ключу</li>
<ul>
<h3>Пример программы на C</h3>
<pre><b>Файл mc.c</b></pre>
<pre lang="c">#include "stdio.h"
#include "string.h"
#include "memcached.h"

int main( void )
{
	char *key = "key";
	char *value = "value";
	uint32_t flags = 0;
	size_t length = 0;
	char *value2 = NULL;
	memcached_return rc;

	// 1. создать структуру для работы с кэшем
	memcached_st *memc = memcached_create(NULL);

	// 2. указать сервер с которым будем работать
	memcached_server_add(memc,"localhost",11211);

	// 3. занести пару ключ-значение в кэш
	rc = memcached_set(memc, key, strlen(key), value, strlen(value)+1, (time_t)0, flags);

	if (rc == MEMCACHED_SUCCESS) {
	} else {
		// обработать ошибку
	}

	// 4. получить значение
	value2 = memcached_get (memc, key, strlen(key),     &amp; length, &amp; flags, &amp; rc);
	if (rc == MEMCACHED_SUCCESS) {
		printf("%s\n", value2);
		free(value2);
	} else {
		// обработать ошибку
	}
	// 5. высвободить структуру
	memcached_free(memc);
	return 0;
}
</pre>
<p>Программа состоит из 5 основных операций и в особых комментариях не нуждается. Разве что можно отметить, что в пункте 2 можно добавлять много серверов, в случае использования распределенной системы.</p>
<p>Компилируем, возможно придется явно указать пути к библиотекам:</p>
<pre lang="bash">
gcc -Wall -o mc mc.c -I/usr/local/include/libmemcached/ -lmemcached
</pre>
<p>Запускаем:</p>
<pre lang="bash">
./mc
 value
</pre>
<p>Видим требуемое значение&nbsp;&mdash; должно быть, <em>заработало</em>!</p>
<p>Для уточнения деталей, смотрим сообщения на сервере memcached:</p>
<pre>
&lt;32 new auto-negotiating client connection
32: Client using the ascii protocol
32 STORED
32 sending key key
&gt;32 END
&lt;32 quit
&lt;32 connection closed.
</pre>
<p>В данном примере представлены следующие события: подключение клиента, установка пары ключ-значение, чтение данных по ключу и отключение клиента.</p>
<p>Посмотрим статистику на сервере:</p>
<pre lang="bash">
memstat --servers localhost
 Listing 1 Server
 Server: localhost (11211)
 pid: 14534
 uptime: 4659
 time: 1247392973
 version: 1.4.0
 pointer_size: 32
 rusage_user: 0.0
 rusage_system: 0.0
 curr_items: 1
 total_items: 1
 bytes: 58
 curr_connections: 10
 total_connections: 13
 connection_structures: 11
 cmd_get: 1
 cmd_set: 1
 get_hits: 1
 get_misses: 0
 evictions: 0
 bytes_read: 58
 bytes_written: 58
 limit_maxbytes: 67108864
 threads: 5
</pre>
<p>Следующие две строчки показывают, что в кэше появилось значение:</p>
<pre lang="bash">
curr_items: 1
total_items: 1
</pre>
<p>Посмотрим на данное значение:</p>
<pre lang="bash">
memcat --servers localhost key
 value
</pre>
<p>Итак, приложение, использующее memcached&nbsp;&mdash; готово.</p>
<h2>PHP</h2>
<p>Для начала установим PECL extension для PHP&nbsp;&mdash; memcached</p>
<pre lang="bash">pecl install memcached</pre>
<p>На этом этапе возможно появление сообщения об ошибке вида:</p>
<pre>ERROR: 'phpize' failed</pre>
<p>Это означает, что не установлен пакет php-dev или его аналог. Устанавливаем его и можно пробовать снова:</p>
<pre lang="bash">
pecl install memcached
 install ok: channel://pecl.php.net/memcached-1.0.0
 You should add "extension=memcached.so" to php.ini
</pre>
<p>Как нам и советуют, дописываем <b>extension=memcached.so</b> в php.ini и перезапускаем Apache.</p>
<p>Смотрим информацию об используемом PHP:</p>
<pre>
memcached support  enabled
Version  1.0.0
libmemcached version    0.31
Session support    yes
igbinary support   no
</pre>
<h3>Пример программы на PHP</h3>
<p>Можно смело использовать обращения к memcached из PHP. Как обычно, рассмотрим пример:</p>
<pre>
&lt;?php
$m = new Memcached();
$m-&gt;addServer('localhost', 11211);
$m-&gt;set('phpkey', 'phpvalue');
var_dump( $m-&gt;get('phpkey'));
?&gt;
</pre>
<p>Результат работы данного скрипта:</p>
<pre>
string(8)  "phpvalue"
</pre>
<p>Итак, PHP-приложение, использующее memcached&nbsp;&mdash; готово.</p>
<h2>Кэширование данных сессий</h2>
<p>Memcached можно использовать и как хранилище данных сессий для PHP. Такой подход часто используется в реальных приложениях. Давайте рассмотрим, что для этого надо сделать.</p>
<p>Вносим изменения в php.ini</p>
<pre>
;session.save_handler = files
session.save_handler = memcached
;session.save_path = /var/lib/php5
session.save_path = localhost:11211
</pre>
<p>Параметр session.save_handler указывает, что теперь данные будут храниться в memcached. Второй параметр&nbsp;&mdash; session.save_path указывает сервер memcached (их может быть указано несколько, через запятую) на котором будут сохранятся данные.</p>
<p>Перезапускаем Apache&nbsp;&mdash; и готово!</p>
<p>Теперь надо проверить, что теперь данные сессии реально хранятся не на диске, а в memcached.</p>
<p>Рассмотрим работу несложного скрипта, заносящего что-нибудь в сессию:</p>
<pre>
&lt;?php
session_start();
$_SESSION['intval'] = 123;
$_SESSION['strval'] = "qwe";
?&gt;
</pre>
<p>Запускаем скрипт, он заносит данные в сессию, после чего смотрим на кэш</p>
<pre lang="bash">
memdump --servers localhost
 key
 keyphp
 memc.sess.key.3ff8ccab14424082ff83a6dfbcf0941f
</pre>
<p>Итак&nbsp;&mdash; к нашим знакомым по предыдущим примерам ключам, добавился ключ с характерным именем <em>memc.sess.key.3ff8ccab14424082ff83a6dfbcf0941f</em>.</p>
<p>Хранение данных сессии перенесено в систему кэширования. Более подробную информацию по работе с memcached из PHP можно почитать <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://ru2.php.net/manual/ru/book.memcached.php"  rel="nofollow">на сайте PHP</a></noindex>.</p>
<h2>Заключение</h2>
<p>Мы рассмотрели утановку и примеры использования memcached. Следует особо подчеркнуть, что memcached&nbsp;&mdash; это не система хранения данных, поэтому на практике memcached почти всегда используется в паре с БД. Также следовало бы уделить внимание своевременной инвалидации данных в кэше и вопросам безопасности. В общем, тема интересная, и еще далека от закрытия.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/memcached-na-palcakh/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Интерфейс</title>
		<link>http://www.insight-it.ru/programmirovanie/java/interfejs/</link>
		<comments>http://www.insight-it.ru/programmirovanie/java/interfejs/#comments</comments>
		<pubDate>Sun, 04 May 2008 10:41:27 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[интерфейс]]></category>
		<category><![CDATA[ООП]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/?p=71</guid>
		<description><![CDATA[
Наверняка у многих из вас слово &#171;интерфейс&#187; ассоциируется с внешним видом любой программы, то есть кнопочками, виджетами, иконками и прочим ее оформлением. Да, несомненно графический пользовательский интерфейс является одним из значений этого понятия, но существует и масса других!
Хотите узнать больше?

В общем случае под словом интерфейс понимают правила и рамки взаимодействия двух произвольных объектов. В рамках [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/exec.png" alt="Интерфейс" style="float:left; margin:6px;" /><br />
Наверняка у многих из вас слово <em>&laquo;интерфейс&raquo;</em> ассоциируется с внешним видом любой программы, то есть кнопочками, виджетами, иконками и прочим ее оформлением. Да, несомненно графический пользовательский интерфейс является одним из значений этого понятия, но существует и масса других!</p>
<p><strong>Хотите узнать больше?</strong><br />
<span id="more-71"></span><br />
В общем случае под словом интерфейс понимают правила и рамки взаимодействия двух произвольных объектов. В рамках компьютерной терминологии такими объектами обычно выступают люди, оборудование, программное обеспечение или его компоненты, но этот термин применим и далеко за ее пределами.</p>
<p>Вернувшись к примеру из первого абзаца мы теперь можем вполне аргументированно объяснить почему GUI так часто приравнивают к слову интерфейс: он просто является частным случаем интерфейса между приложением и его пользователем. Можно было бы привести еще массу примеров различных интерфейсов, скажем сокет в качестве интерфейса между процессором и материнской платой, но целью написания этого поста было вовсе не это.</p>
<p>Уже догадались? Да, это я так неспеша плавно подводил разговор к <a href="/tag/oop">объектно-ориентированному программированию</a>. Термин <em>интерфейс</em> широко применяется и в нем. Как не трудно предположить, в роли объектов в этом случае выступают как сами классы, так и их экземпляры (которые, впрочем, тоже принято называть словом <em>объект</em>).</p>
<p>В общем случае интерфейсом класса выступает совокупность его <strong>public</strong> методов и переменных, то есть доступных для обращения из других частей приложения. Этот факт вполне логичен&nbsp;&mdash; именно благодаря им и осуществляется взаимодействие класса (или его объекта) с &laquo;внешним миром&raquo;. Но не все так просто, особенно с точки зрения <a href="/programming/design-patterns" target="_blank">шаблонов проектирования</a>, немаловажную роль в взаимодействии классов и объектов играет <strong>абстракция</strong>. Хочется обратить внимание, что формально имеется ввиду даже не сами методы, а их заголовки, то есть название, набор получаемых переменных и тип возвращаемого значения (этот набор данных принято также принято называть интерфейсом методов или функций), само тело метода (реализация) в данном случае не важно.</p>
<p>Иными словами, если один класс (будем называть его <em>клиент</em>) взаимодействует с каким-либо другим объектом, то по большому счету он абсолютно не обязан знать какого класса этот объект является экземпляром (может конечно, но это совсем не обязательно). Единственное, что интересует класс-клиент, это <em>интерфейс</em> объекта, с которым он взаимодействует, этой информации вполне достаточно для полноценной совместной работы.</p>
<p>Сразу напрашивается вполне резонный вопрос: а как же тогда клиент может быть уверен, что в классе, с которым он работает, какой-либо конкретный интерфейс реализован? Допустим ему нужен во-о-о-он тот метод, а как же узнать доступен ли он и получит ли клиент в ответ данные нужного типа? Ответ на этот вопрос реализован в каждом языке программирования по-разному: где-то  существует специальные ключевые слова для <em>обозначения</em> интерфейсов и классов, их реализующих, где-то это ненавязчиво реализуется средствами <em>наследования</em> и <em>полиморфизма</em> на более концептуальном уровне.</p>
<p>Самым наглядным языком программирования для демонстрации описания интерфейсов я считаю <strong>Java</strong> (хотя можно было бы выбрать и C#, PHP или практически любой другой по вкусу). В теории все просто:</p>
<ul>
<li>Ключевое слово <strong>interface</strong> обозначает описание интерфейса;</li>
<li>За ним следует название конкретного интерфейса, которое впоследствии можно будет использовать в коде при его упоминании (некоторые программисты на правах традиции начинают названия интерфейсов с заглавной буквы <strong>I</strong>, мне в свое время даже пытались объяснить зачем так надо делать, но аргументы не показались мне достаточно весомыми);</li>
<li>Далее идет тело интерфейса, в котором перечисляются все заголовки методов, которые должны быть в классе, реализующем данный интерфейс (никакой реализации!);</li>
<li>Впоследствии приписав к заголовку любого класса ключевое слово <strong>implements</strong> с последующим указанием названия интерфейса, можно <em>обязать</em> этот класс реализовать указанные в описания интерфейса методы. Существует небольшое исключение для абстрактных классов (то есть классов,для которых <em>не может</em> быть создан объект, обозначаются ключевым словом <strong>abstract</strong>), они <em>могут</em> и не реализовать все методы интерфейса, но тогда эта <em>обязанность</em> будет переложена на их <em>наследников</em>.</li>
</ul>
<p>В данной ситуации клиент, работающий с каким-либо произвольным объектом может просто-напросто проверить, реализован ли в нем заранее определенный интерфейс, что даст ему гарантию, что он может смело обращаться к необходимому набору методов.</p>
<p><em>Небольшое примечание:</em> сами интерфейсы и методы в их теле по-умолчанию обладают свойствами <strong>abstract</strong> и <strong>public</strong>, так что повторно указывать эти ключевые слова не нужно.</p>
<p>На практике же это выглядит это примерно следующим образом:</p>
<pre lang="Java">
// описание интерфейса
interface Renderable
{
    // обязуем реализовать метод draw
    public void draw();
}

// конкретная реализация интерфейса
class SomeText implements Renderable
{
   string text;
   public SomeText(string str)
   {
      this.text=str;
   }
   public void draw()
   {
       // вынуждены подчиниться и реализовать
       System.out.println(this.text);
   }
}
// класс-клиент
class Render
{
  public Render(Renderable obj)
  {
     // можно быть уверенным, что
     // метод draw реализован
     obj.draw();
     /*
         в качестве альтернативы можно было бы написать как-то так:
         if(obj instanceof Renderable)obj.draw();
         то есть проверить реализован ли интерфейс
         вместо использования его названия в роли типа данных
     */
  }
</pre>
<p>В данном примере ситуация тривиальна: класс-клиент <strong>Render</strong> умеет лишь визуализировать классы, которые он получает в конструктор, вызывая у них метод <strong>draw</strong>. Для обеспечения такой возможности описан интерфейс <strong>Renderable</strong>, который реализуется в классе <strong>SomeText</strong>. Хоть класс <strong>Render</strong> ничего и не знает о том, какой именно класс ему подсунут, благодаря интерфейсу он сможет вывести на экран любой объект, корректно реализующий наш интерфейс, в том числе и <strong>SomeText</strong>.</p>
<p>Как я уже упоминал: альтернативой такому подходу является использование полиморфизма и наследования. Такой подход более распространен в других языках программирования, например C++, но пример я приведу все равно на <strong>Java</strong>, основываясь на предыдущем примере, чтобы читателям было проще сравнивать.</p>
<p>В теории такой подход еще проще: создается абстрактный класс, хоть как-то реализующий наш интерфейс (теоретически реализация может быть и пустой, просто в виде метода-заглушки), а на стороне клиента достаточно лишь просто принимать только наследников этого абстрактного класса. В нашем примере достаточно лишь изменить пару ключевых слов и все:</p>
<pre lang="Java">
// теперь используем абстрактный класс
abstract class Renderable
{
    // реализуем метод draw
    public void draw()
    {
       System.out.println("Вывод на экран недоступен!");
    }
}

// реализация интерфейса (на этот раз неформального)
class SomeText extends Renderable
{
   // на этот раз используем extends (наследование)
   // вместо implements
   string text;
   public SomeText(string str)
   {
      this.text=str;
   }
   public void draw()
   {
       // переопределяем метод draw
       // но могли этого и не делать, тогда
       // использовался бы метод из Renderable
       System.out.println(this.text);
   }
}
// класс-клиент
class Render
{
  public Render(Renderable obj)
  {
     // можно быть уверенным, что
     // метод draw реализован
     obj.draw();
     /*
        на этот раз так как в крайнем случае
        в крайнем случае вызовется хотябы
        метод из класса Renderable
     */
  }
</pre>
<p>Минимальные изменения&nbsp;&mdash; суть та же. Сразу хочу отметить, что этот процесс так прост только в <strong>Java</strong>, в других языках программирования понадобилось бы использование дополнительных модификаторов для метода <strong>draw</strong> (например в <strong>C#</strong>: <strong>virtual</strong> или <strong>abstract</strong> в классе-потомке и <strong>override</strong> в классе-наследнике, это необходимо для обеспечения возможности их переопределения).</p>
<p>На этом позвольте завершить данное повествование, очень надеюсь, что мне удалось изложить суть максимально прозрачно. Эта тема будет активно подниматься в дальнейших статьях по <a href="/tag/oop" target="_blank">ООП</a>, так что очень надеюсь, что она стала для Вас элементарной и очевидной. По традиции напоминаю, что не пропустить публикацию новых постов можно <a href="/feed" target="_blank">подписавшись на RSS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/java/interfejs/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Design patterns</title>
		<link>http://www.insight-it.ru/programmirovanie/design-patterns/</link>
		<comments>http://www.insight-it.ru/programmirovanie/design-patterns/#comments</comments>
		<pubDate>Thu, 24 Apr 2008 10:03:09 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Gang of Four]]></category>
		<category><![CDATA[GoF]]></category>
		<category><![CDATA[ООП]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/design-patterns/</guid>
		<description><![CDATA[Как говорится, все новое&#160;&#8212; хорошо забытое старое. Когда я в вдруг вспомнил эту поговорку, мне пришла в голову мысль вернуться к незаслуженно забытой некоторое время назад теме объектно-ориентированного программирования. Возможно многим читателям уже поднадоели часто публикующиеся здесь статьи об устройстве уже существующих проектов, это конечно же не повод прекратить их публикацию, но, тем не менее, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/idea.png" style="float: right; margin: 16px 4px;" alt="Шаблоны проектирования" title="Шаблоны проектирования" />Как говорится, все новое&nbsp;&mdash; хорошо забытое старое. Когда я в вдруг вспомнил эту поговорку, мне пришла в голову мысль вернуться к незаслуженно забытой некоторое время назад теме объектно-ориентированного программирования. Возможно многим читателям уже поднадоели часто публикующиеся здесь <a href="/highload" target="_blank">статьи об устройстве уже существующих проектов</a>, это конечно же не повод прекратить их публикацию, но, тем не менее, немного отвлечься все же стоит.</p>
<p>Этот пост будет введением в очередную ветвь спирали повествования о теории <a href="/tag/oop" target="_blank">ООП</a>, о которой уже много было сказано различными авторами, не знаю остались ли в этой теме неосвещенные уголки, но все же я думаю, что мне найдется что сказать.<br />
<span id="more-67"></span><br />
<em><a href="/tag/design-patterns" target="_blank">Design Patterns</a></em> обычно переводят на русский фразой <em>&laquo;шаблоны проектирования&raquo;</em>, оно применимо и за рамками программирования, в таких случаях под ней подразумевают просто стандартизованное эффективное решение характерного класса задач. В рамках программирования это понятие можно несколько конкретизировать, представив его как незаконченную заготовку для будущего проекта или его части, которая не может быть напрямую реализована в коде, но зато она предоставляет некую скорее теоретическую базу для последующего решения задачи в самом проекте. Возможно у кого-то из вас возникла ассоциация с алгоритмами, она вполне предсказуема, но не совсем уместна: речь идет о проектировании, а не решении каких-либо вычислительных задач.</p>
<p>Если же говорить об объектно-ориентированных шаблонах проектирования, то зачастую помимо просто методов и средств для решения задачи или просто общей схемы организации проекта они предоставляют механизмы и схемы построения взаимоотношения классов, выполняющих определенные роли для достижения общей цели.</p>
<p>Изначально идея построения шаблонов для решения типичных задач появилась в архитектуре (имеется ввиду которая к строительству относится, а не к <a href="/highload" target="_blank">высоконагруженным системам</a> <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ). Автором ее был Cristopher Alexander, он впервые составил набор шаблонов проектирования для архитекторов во второй половине двадцатого века, но, к сожалению, в этой науке эта идея не прижилась, зато ее успешно переняли и перенесли в область программирования.</p>
<p>Основной вклад в этот процесс сделала знаменитая команда, известная как <strong>Gang of Four</strong>. Она состоит из четырех авторов не менее известной книги <em>&laquo;Design Patterns — Elements of Reusable Object-Oriented Software&raquo;</em>:</p>
<ul>
<li>Erich Gamma</li>
<li>Richard Helm</li>
<li>Ralph Jonson</li>
<li>John Vlissides</li>
</ul>
<p>Именно благодаря этим людям и их книге эта методология проектирования программного обеспечения получила такое широкое распространение. В своей книге они предоставили 23 основных шаблона проектирования, каждый из которых может использоваться для решения очень широкого класса абстрактных задач, при этом абсолютно не привязываясь к какому-либо конкретному языку программирования или стилю написания кода. Но не стоит забывать, что все они&nbsp;&mdash; просто часть теории, скорее указание на верный путь, чем тропинка, с которой нельзя сделать шаг в сторону.</p>
<p>Основным преимуществом применения шаблонов проектирования при разработке программного обеспечения является тот факт, что они помогают существенно ускорить процесс разработки и проектирования, предоставляя проверенную временем и многими разработчиками парадигму разработки. Помимо этого они существенно упрощают понимание кода при работе над ним группы программистов, а также процесс составления документации.</p>
<p>В последующих записях я планирую пройтись по основным шаблонам проектирования с более подробной информацией о сферах их применения, их востребованности, эффективности, а также с приведением примеров на каком-либо языке программирования, скорее всего на <a href="/tag/java">Java</a>, так как он позволит сделать примеры более наглядными. Как обычно для более оперативного получения информации об обновлении блога хочу предложить <a href="/feed" target="_blank">подписаться на RSS-ленту</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/design-patterns/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Comet</title>
		<link>http://www.insight-it.ru/programmirovanie/javascript/comet/</link>
		<comments>http://www.insight-it.ru/programmirovanie/javascript/comet/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 18:13:04 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Comet]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[persistent]]></category>
		<category><![CDATA[архитектура]]></category>
		<category><![CDATA[информационные технологии]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/javascript/comet/</guid>
		<description><![CDATA[Уже приготовились мыть посуду? Что ж, придется Вас разочаровать, сегодня речь пойдет вовсе не о моющем средстве, а об одноименной технологии.
Comet представляет собой архитектуру веб-приложений, основной особенностью которой является тот факт, что отправка данных от сервера к клиенту (в роли которого обычно выступает браузер) не требует какого-либо запроса данных со стороны клиента. Это позволяет пользователям [...]]]></description>
			<content:encoded><![CDATA[<p>Уже приготовились мыть посуду? Что ж, придется Вас разочаровать, сегодня речь пойдет вовсе не о моющем средстве, а об одноименной технологии.</p>
<p>Comet представляет собой архитектуру веб-приложений, основной особенностью которой является тот факт, что отправка данных от сервера к клиенту (в роли которого обычно выступает браузер) не требует какого-либо запроса данных со стороны клиента. Это позволяет пользователям приложения более оперативно реагировать на возникающие на сервере события и быть в курсе процесса работы приложения без необходимости непрерывно опрашивать сервер с помощью веб-клиента.<br />
<span id="more-58"></span><br />
Реализация этой технологии, как не сложно догадаться, основывается на JavaScript. Основной идеей является поддержание долговременных HTTP-соединений с каждым клиентом приложения и отправка новых данных клиентам с их помощью как только произошло их обновление или возникновение на сервере. Этот принцип послужил основой для альтернативных названий этой технологии: <em>Server-push</em>, <em>Reverse AJAX</em>. В случае классического AJAX (о котором тоже стоило бы сначала написать статейку, потом может быть соберусь) клиент асинхронно отправляет серверу запрос на получение какой-либо конкретной информации. В Comet же клиент с сервером как бы меняются ролями: инициатором передачи информации является сервер, а не клиент. Что же это меняет? Самым наглядным примером послужит реализация постоянного обновления какой-либо информации в реальном времени:</p>
<ul>
<li><strong>Классическая модель отправки запросов.</strong> Для решения задачи понадобится постоянно обновлять всю страницу целиком, вручную пользователем или альтернативными способами автоматически. Совсем не вариант, будет генерироваться огромное количество запросов к серверу, каждый из которых будет очень существеннен по объему. Большое количество одновременно работающих пользователей такое приложение явно не выдержит, да и доступность данных в реальном времени не обеспечит.</li>
<li><strong>AJAX.</strong> По сравнению с предыдущим вариантом AJAX предоставляет массу преимуществ: размер передаваемых данных существенно уменьшается, особенно если использовать в качестве формата данных не XML, а JSON. Но тем не менее необходимость регулярно отправлять запросы серверу для получения обновленной информации останется.   С ростом количества пользователей будет расти и количество запросов, открытие и закрытие которых будет неуклонно генерировать нагрузку на сервер. Для снижения нагрузки можно попытаться увеличивать интервал между запросами, но это лишь временная мера, обладающая существенным недостатком&nbsp;&mdash; увеличение этого промежутка времени повлечет за собой рост задержек между обновлением информации на сервере и обновлением клиентской части приложения.</li>
<li><strong>Comet.</strong> С каждым клиентом поддерживается постоянное HTTP-соединение, как только данные на сервере обновились&nbsp;&mdash; сервер сразу же отправляет по уже открытому соединению уведомление о необходимости провести изменения в клиентской части, это позволяет существенно сократить нагрузку на сервер и практически избавиться от задержек между обновлением данных на сервере и клиенте.</li>
</ul>
<p>Для написания серверной части приложения может использоваться практически любой язык программирования, наиболее распространенным решением, пожалуй, является Java Servlet, запущенный в каком-либо контейнере&nbsp;&mdash; Apache TomCat, Jetty или Sun GlassFish. Для реализации этого подхода к организации общения клиента с сервером написано достаточно большое количество framework&#39;ов и библиотек, наиболее полный список, я думаю, можно найти в <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://en.wikipedia.org/wiki/Comet_%28programming%29#Implementations"  target="_blank" rel="nofollow">английской википедии</a></noindex>.</p>
<p>Но и для Comet-приложений рано или поздно возникает вопрос масштабируемости, так как традиционные HTTP-сервера создают новый поток (thread) для обслуживания очередных нескольких очередных новых соединений. Каждый поток в состоянии обрабатывать только небольшое количество HTTP-соединений, а так как в случае с Comet соединения находятся в открытом состоянии неопределенно долго, для каждых нескольких новых пользователей веб-приложения приходится создавать новый поток. Количество одновременно существующих потоков не безгранично, что в один прекрасный момент приводит к существенному росту издержек, связанных с созданием новых и управлением существующими потоками, а также все чаще и чаще возникающим отказам потокам в предоставлении серверу необходимых вычислительных. В таких ситуациях некоторые пользователи встречаются с неприемлимыми задержками в работе приложения или непредвиденными сообщениями об ошибках. Наиболее простым и в то же время эффективным решением подобной проблемы является горизонтальное масштабирование Comet-серверов с балансировкой нагрузки на программном или аппаратном уровне.</p>
<p>Если Вас заинтересовала эта тема&nbsp;&mdash; могу посоветовать взглянуть на пару достаточно интересных статей, в котором более с практической точки зрения описывается этот подход к построению приложений:</p>
<ul>
<li><noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.ibm.com/developerworks/ru/library/j-jettydwr/"  target="_blank" rel="nofollow">Создание масштабируемых Comet-приложений с использованием Jetty и Direct Web Remoting</a></noindex></li>
<li><noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.javaworld.com/javaworld/jw-03-2008/jw-03-asynchhttp.html"  target="_blank" rel="nofollow">Asynchronous HTTP and Comet Architecture</a></noindex> (eng.)</li>
</ul>
<p>Я же надеюсь написать статью более практической на направленности по этой теме лишь в обозримом будущем, не пропустить этот момент Вам поможет <a href="/feed" target="_blank">абонемент</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/javascript/comet/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Модификация алгоритма хэширования</title>
		<link>http://www.insight-it.ru/programmirovanie/php/modifikaciya-algoritma-khehshirovaniya/</link>
		<comments>http://www.insight-it.ru/programmirovanie/php/modifikaciya-algoritma-khehshirovaniya/#comments</comments>
		<pubDate>Fri, 15 Feb 2008 10:17:20 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[md5]]></category>
		<category><![CDATA[sha1]]></category>
		<category><![CDATA[код]]></category>
		<category><![CDATA[кодинг]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[технология]]></category>
		<category><![CDATA[хранение данных]]></category>
		<category><![CDATA[хэш]]></category>
		<category><![CDATA[хэширование]]></category>
		<category><![CDATA[шифрование]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/php/modifikaciya-algoritma-khehshirovaniya/</guid>
		<description><![CDATA[Если Вы уже успели прочитать одну из моих предыдущих записей о хэшировании, то Вы уже имеете базовое представление о теме сегодняшнего разговора.
Одним из возможных способов применения хэшей является хранение аутентификационных данных пользователей интернет-приложения, об особенностях реализации формирования и проверки хэшей при регистрации и авторизации пользователей средствами PHP я и хотел бы с Вами поговорить.

Сомневаюсь, что [...]]]></description>
			<content:encoded><![CDATA[<p>Если Вы уже успели прочитать <a href="/science/kriptografiya/obratnogo-puti-net/" target="_blank">одну из моих предыдущих записей о хэшировании</a>, то Вы уже имеете базовое представление о теме сегодняшнего разговора.<br />
Одним из возможных способов применения хэшей является хранение аутентификационных данных пользователей интернет-приложения, об особенностях реализации формирования и проверки хэшей при регистрации и авторизации пользователей средствами <a href="/tag/php" target="_blank">PHP</a> я и хотел бы с Вами поговорить.<br />
<span id="more-42"></span><br />
Сомневаюсь, что Вы услышите что-то новое, если я скажу, что в <a href="/tag/php" target="_blank">PHP</a> даже в &laquo;стандартной комплектации&raquo; реализована масса алгоритмов хэширования, начиная с широкораспространенных <strong>md5 ();</strong> и <strong>sha1 ();</strong> и заканчивая модулями <strong>hash</strong> и <strong>mhash</strong>, в которых реализована еще целая масса алгоритмов. Все они давно уже стандартизованы и доступны для изучения всем желающим получить о них какую-либо информацию.</p>
<p>Допустим мы храним пароли пользователей в виде какого-то стандартного хэша, для примера&nbsp;&mdash; <strong>md5</strong>, в базе данных. Все было отлично, но в один прекрасный момент нашелся подлый злоумышленник, который неким хитрым способом получил доступ к базе данных логинов и паролей. Перед ним стоит цель&nbsp;&mdash; узнать изначальный пароль у максимального числа пользователей. Посмотрим на ситуацию с его стороны:</p>
<ul>
<li>Первым делом он бы попытался определить, какой именно хэш перед ним находится&nbsp;&mdash; чаще всего это делается либо просто взглянув на длину хэша, либо если приложение широко распространено (популярная CMS скажем)&nbsp;&mdash; покопавшись в ее исходниках, еще есть вариант найти свой собственный аккаунт&nbsp;&mdash; и зная пароль попробовать на нем разные алгоритмы, способов можно придумать множество&nbsp;&mdash; все ограничивается лишь воображением. Узнав ответ на свой вопрос ему лишь останется набрать в <a href="/tag/google" target="_blank">Google</a> фразу вроде <em>&laquo;md5 decrypt&raquo;</em>, а дальше уже дело техники.</li>
<li>Еще один вариант решения задачи&nbsp;&mdash; взглянуть на список хэшей на предмет наличия совпадений. С очень высокой степенью вероятности за значительной группой одинаковых хэшей будет скрываться какой-либо банальный пароль вроде <em>123456</em>.</li>
</ul>
<p>Задача же разработчика приложения максимально обезопасить систему от подобных ситуаций. Конечно же можно просто стараться минимизировать возможности реализации методов получения информации из базы данных, но предугадать все варианты невозможно: в любом из используемых компонентов системы может оказаться уязвимость в коде, на которую наверняка найдется умник, который напишет <em>exploit</em>, а значит полностью исключить такую вероятность не получится, в лучшем случае выйдет просто ее минимизировать.</p>
<p>Именно по этим причинам и стоит задуматься об усложнении задачи злоумышленника в случае возникновения описанной выше ситуации. Для исключения возможности просто расшифровывания хэшей по словарю (то есть первый случай, когда определяется тип хэша и соответствующий ему словарь <em>хэш =&gt; исходное значение</em>) достаточно исключить возможность идентификации алгоритма хэширования или наличия к нему заранее подготовленного словаря. Для этого достаточно лишь сделать шаг в сторону от стандартного алгоритма любым пришедшим в голову способом, например:</p>
<ul>
<li>хранить хэш не от самого пароля, а от <em>пароль + какая-либо фиксированная строка</em></li>
<li>поменять местами группы символов в получившемся стандартном хэше</li>
<li>сделать сдвиг символов в стандартном хэше (или можно даже не сами символы двигать, а с помощью битовых операций их значения)</li>
<li>комбинировать два стандартных алгоритма хэширования, или алгоритм хэширования с алгоритмом обратимого шифрования, которых доступно также множество</li>
</ul>
<p>Список этот можно было бы продолжать достаточно долго, это было лишь первое, что пришло мне в голову. Но ни один из приведенных способов не избавит от возможности второго варианта раскрывания исходного пароля. Основывается он на однозначности стандартных алгоритмов&nbsp;&mdash; одним и тем же исходным данным соответствует один и тот же хэш. Для отказа от этого свойства стандартных алгоритмов придется выполнить более сложную модификацию используемой для генерации хэша функции (которая конечно же тоже поможет и для борьбы с первым вариантом). Сразу приведу пример <a href="/tag/kod" target="_blank">кода</a>, реализующего этот механизм, а дальше попытаюсь его объяснить:</p>
<pre lang="PHP">
function generateHash($input,$salt = false)
{
  if(!$salt)$salt=randomString(2);
  $hash=md5($input.$salt);
  return $salt.substr($hash,2);
}</pre>
<p>Как не трудно заметить&nbsp;&mdash; используется самодельная функция <strong>randomString ();</strong>, которая возвращает случайную строку, состоящую из указанного количества шестнадцатеричных цифр (надеюсь Вы в состоянии написать ее своими силами). Именно этот момент и гарантирует элемент случайности при каждой новой генерации хэша. В том месте, где я прочитал про этот механизм (ссылку, к сожалению, привести не могу&nbsp;&mdash; в bookmark&#39;ах не нашел), этот случайный компонент назывался словом <strong>salt</strong>, смысл его заключается в том, что он приписывается ко входным данным, передаваемым стандартной функции хэширования, а затем им же подменяется какая-либо фиксированная часть полученного хэша.<br />
Наверняка у Вас возник вопрос: а как же потом понять, что пользователь ввел верные данные, ведь для тех же исходных данных получится другой хэш и возможности их сравнить не будет? Ответ достаточно прост, его можно было увидеть даже в коде: при повторной инициализации хэша из <a href="/tag/bd" target="_blank">базы данных</a> достается заранее известная часть хранящегося там хэша, соответствующего конкретному пользователю&nbsp;&mdash; тот самый <strong>salt</strong>, и передается нашей функции. В этом случае в механизме будет использоваться именно он, а не новое случайное значение, и, как следствие, в случае правильности введенных данных на выходе получатся совпадающие хэши. Вот такой вот простенький, но иногда достаточно полезный трюк.</p>
<p>Если Вам понравился этот пост&nbsp;&mdash; возможно Вам придутся по душе и <a href="/dzhentelmenskij-nabor-php-programmista/" target="_blank">остальные записи из этой серии статей</a>, а не пропустить публикацию новых записей Вам может помочь <a href="/feed" target="_blank">RSS feed</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/php/modifikaciya-algoritma-khehshirovaniya/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>На пути к идеалу</title>
		<link>http://www.insight-it.ru/programmirovanie/php/na-puti-k-idealu/</link>
		<comments>http://www.insight-it.ru/programmirovanie/php/na-puti-k-idealu/#comments</comments>
		<pubDate>Thu, 07 Feb 2008 12:39:34 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[online]]></category>
		<category><![CDATA[интернет]]></category>
		<category><![CDATA[информационные технологии]]></category>
		<category><![CDATA[код]]></category>
		<category><![CDATA[кодинг]]></category>
		<category><![CDATA[оптимизация]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[производительность]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/php/na-puti-k-idealu/</guid>
		<description><![CDATA[...или 15 привычек, которые помогут ускорить PHP-приложение
Практически каждый программист стремится в своих приложениях не только максимально точно реализовать требуемый функционал, но и сделать это как можно более эффективным методом. Для этого конечно же необходимо проектирование, подходящий выбор используемых технологий, возможно некоторый опыт в предметной области, этот список можно продолжать достаточно долго, но я позволю себе [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: right">...или 15 привычек, которые помогут ускорить PHP-приложение</h4>
<p>Практически каждый программист стремится в своих приложениях не только максимально точно реализовать требуемый функционал, но и сделать это как можно более эффективным методом. Для этого конечно же необходимо проектирование, подходящий выбор используемых технологий, возможно некоторый опыт в предметной области, этот список можно продолжать достаточно долго, но я позволю себе этого не делать, так как речь сегодня пойдет не об этом. Вместо этого хочу обратить Ваше внимание на более простые и &laquo;приземленные&raquo; методы <a href="/tag/optimizaciya" target="_blank">оптимизации</a> PHP-кода, которые может быть и не так эффективны по сравнению с указанными выше, но зато не требуют каких-либо усилий со стороны кодера и/или программиста, достаточно лишь воспринимать их как &laquo;не вредные&raquo; привычки.</p>
<p><span id="more-25"></span></p>
<p>Прочитав достаточно солидный объем разного рода документации по <a href="/tag/php" target="_blank">PHP</a>, я часто натыкался на статьи и тексты, так или иначе связанные с <a href="/tag/proizvoditelnost" target="_blank">производительностью</a> PHP-скриптов. Порой в такого рода источниках информации удавалось найти достаточно интересные и неочевидные факты об этом языке программирования, которые не смотря на свою простоту могли дать вполне заметный прирост к <a href="/tag/proizvoditelnost" target="_blank">производительности</a> итогового приложения. Я почему-то очень серьезно стал относиться к производительности написанных мной скриптов, и довольно часто стал испытывать на практике спорные моменты в реализации, о которых узнавал из <a href="/net" target="_blank">Сети</a> или каких-либо других источников, с помощью самописных или <a href="/tag/opensource" target="_blank">opensource</a> benchmark&#39;ов, хотя порой и просто внедряя в реальные приложения. Как ни странно, в большинстве случаев практика подтверждала теорию, и я стал постоянно пользоваться этими простыми правилами, о которых я и хочу Вам рассказать.</p>
<h4>Повышения значения индекса с помощью ++$i;</h4>
<p>Этот факт был наверное одним из самых удивительных для меня, когда я впервые о нем услышал, но действительно операция <strong>++<span style="color: blue">$i</span></strong>; выполняется несколько быстрее, чем <strong><span style="color: blue">$i</span>++;</strong>. или другие вариации на ту же тему вроде <strong><span style="color: blue">$i</span>+=<span style="color: blue">1</span>;</strong>. Привычка использовать в качестве индекса цикла переменную под названием i, казалось бы стара как Мир, мне она досталась в наследство от <strong>C</strong>, а в месте с ней &laquo;в комплекте&raquo; шла привычка писать выражение <strong>i++</strong> в заголовках циклов. Разница в скорости обработки этих выражений, насколько мне известно, обусловлена разным количеством элементарных машинных операций, которые необходимо выполнить процессору (в точных цифрах не уверен, пишу по памяти, но <strong>++<span style="color: blue">$i</span>;</strong> требует трех элементарных операций, а <strong><span style="color: blue">$i</span>++;</strong> – четырех). В справедливости этого факта не трудно убедиться, достаточно написать простенький скрипт, состоящий из цикла с достаточно большим количеством итераций, и замерить любым способом точное время его выполнения при использовании разных способов инкрементации индекса цикла.</p>
<h4>Вывод статического контента без помощи PHP</h4>
<p>Сейчас тот факт, что использование интерпретатора PHP для вывода статического контента сильно замедляет этот процесс, кажется мне очевидным, но поначалу я использовал <strong><span style="color: #17349c">echo</span></strong> там, где он был необходим, ничуть не чаще, чем там, где он лишь замедляет работу скрипта. От использования еще менее эффективного способа&nbsp;&mdash; <strong><span style="color: #17349c">print</span></strong>, меня избавила моя лень: писать каждый раз на одну букву больше дико не хотелось (в отличии от <strong><span style="color: #17349c">echo</span></strong>, <strong><span style="color: #17349c">print</span></strong> возвращает информацию об успешности выполнения своей работы, что в большинстве случаев просто-напросто не нужно). Проверить опять же не трудно&nbsp;&mdash; нужен лишь объемистый текстовый файл, который достаточно вывести в browser разными способами и засечь уходящее на это время.</p>
<h4>Вывод статического контента из отдельного файла</h4>
<p>Частенько при желании выполнить указанное в заголовке действие по привычке используют <strong><span style="color: #a3a423">include</span></strong>, <strong><span style="color: #a3a423">require</span></strong> или их <strong><span style="color: #a3a423">_once</span></strong> версии, что является далеко не самой лучшей идеей с точки зрения производительности. Самым быстрыми быстрыми и экономичными поотношению к оперативной памяти являются функции <strong><span style="color: #17349c">readfile</span></strong> и <strong><span style="color: #17349c">fpassthru</span></strong>. В качестве доказательства этого факта приведу таблицу, демонстрирующую статистику выполнения этой операции различными методами и позаимствованную с <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://www.raditha.com/wiki/Readfile_vs_include"  target="_blank" rel="nofollow">одного англоязычного сайта</a></noindex>:</p>
<table align="center" border="1" cellspacing="0" width="100%">
<tr>
<th rowspan="2" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" align="center" valign="center">Функция</th>
<th colspan="2" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" align="center">Время (сек.)</th>
<th colspan="2" style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" align="center">Оперативная память (байт)</th>
</tr>
<tr>
<td style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" align="center">32Kb файл</td>
<td style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" align="center">1Mb файл</td>
<td style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" align="center">32Kb файл</td>
<td style="background: #fcfcc0 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial" align="center">1Mb файл</td>
</tr>
<tr>
<td>file_get_contents</td>
<td align="right">0.00152</td>
<td align="right">0.00564</td>
<td align="right">52480</td>
<td align="right">1067856</td>
</tr>
<tr>
<td>fpassthru</td>
<td align="right"><strong>0.00117</strong></td>
<td align="right">0.00184</td>
<td align="right">20016</td>
<td align="right">20032</td>
</tr>
<tr>
<td>fgets</td>
<td align="right">0.00195</td>
<td align="right">0.07190</td>
<td align="right">30760</td>
<td align="right">30768</td>
</tr>
<tr>
<td>file</td>
<td align="right">0.00157</td>
<td align="right">0.06464</td>
<td align="right">87344</td>
<td align="right">2185624</td>
</tr>
<tr>
<td>require_once</td>
<td align="right">0.00225</td>
<td align="right">0.08065</td>
<td align="right">67992</td>
<td align="right">2067696</td>
</tr>
<tr>
<td>readfile</td>
<td align="right"><strong>0.00117</strong></td>
<td align="right">0.00191</td>
<td align="right"><strong>19192</strong></td>
<td align="right">19208</td>
</tr>
</table>
<h4>Вывод переменных</h4>
<p>Наверняка вам известно, что переменные можно выводить с помощью конструкции вроде <strong><span style="color: #17349c">echo</span> <span style="color: red">&laquo;</span><span style="color: blue">$var</span> <span style="color: red">text&raquo;</span>;</strong>, что является одним из самых удобных вариантов решения этой задачи благодаря минимальному количеству символов, которые необходимо набрать, но с точки зрения быстродействия этот вариант далек от идеала, так как влечет за собой достаточно серьезные преобразования в памяти сервера, эффект которых порой бывает заметен невооруженным глазом. Частично ущерб производительности можно сгладить заменой этой конструкции на <strong><span style="color: #17349c">echo</span> <span style="color: blue">$var</span>.<span style="color: red">&laquo; text&raquo;</span>;</strong>, что приводит к несколькому усложнению внешнего вида кода и несколько поправляет ситуацию со скоростью выполнения. Но как известно знак . обозначает конкатенацию двух строк, что тоже требует некоторых вычислений и затрат памяти, но и от нее можно избавиться, заменив на запятую. Выражение <strong><span style="color: #17349c">echo</span> <span style="color: blue">$var</span>,<span style="color: red">&laquo; text&raquo;</span>;</strong> ничем по своему эффекту не отличается от предложенных ранее вариантов, за исключением максимального быстрого выполнения, обусловленного отсутствием дополнительных преобразований в процессе передачи просто последовательности из константы и переменной.</p>
<h4>Избегайте выполнения лишних действий</h4>
<p>Достаточно абстрактное утверждение, но тем не мение постоянное напоминание себе о нем может избавить Вас от совершения массы ошибок. Самой широкораспространенной является наверное вызов какой-либо функции (чаще всего <strong><span style="color: #17349c">count</span>();</strong> или <strong><span style="color: #17349c">strlen</span>();</strong>) в проверке условия выхода из цикла. Когда-нибудь доводилось писать видеть в собственном или чужом коде выражение вида <strong><span style="color: #a3a423">for</span>(<span style="color: blue">$i</span> = <span style="color: #a3a423">0</span>; <span style="color: blue">$i</span> &lt; <span style="color: #17349c">count</span>(<span style="color: blue">$array</span>); ++<span style="color: blue">$i</span>) { ... }</strong>? А задумываться о последовательности выполнения действий при его обработке? Стоит только немного начать размышлять и ошибка становится очевидной: <strong><span style="color: #17349c">count</span>();</strong> выполняется при каждой итерации цикла, что приводит к подсчету количества элементов массива при каждой проверки условия выхода из цикла&nbsp;&mdash; почему бы не посчитать это значение заранее и сравнивать значения индекса с переменной, а не с результатом выполнения функции?</p>
<h4>@</h4>
<p>Использование этого оператора стоит избегать при каждой возможности. Казалось бы такое простое действие, как сокрытие вывода возможного сообщения об ошибке, влечет за собой достаточно трудоемкую последовательность действий: устанавливает значение параметра PHP-интерпретатора <strong>error_reporting = 0</strong>, выполняет указанное за этим оператором действие, возвращает значение <strong>error_reporting</strong> в исходное состояние.</p>
<h4>Маленькие мелочи</h4>
<p>Развивая тему предыдущего подраздела, хочется обратить внимания, что даже на еще более элементарных вещах можно сэкономить драгоценное процессорное время:</p>
<ul>
<li>Вместо условия <strong><span style="color: #a3a423">if</span>(<span style="color: blue">$variableOne</span> == <span style="color: blue">$variableTwo</span>) { ... }</strong> можно написать <strong><span style="color: #a3a423">if</span>(<span style="color: blue">$variableOne</span> === <span style="color: blue">$variableTwo</span>) { ... }</strong>, что избавит от проверки на соответствие типов данных и приведения их друг к другу, в некоторых случаях эти действия эти случаях эти действия конечно же и бывают необходимы, но бывает это далеко не часто.</li>
<li>Глядя на выражения вроде <strong><span style="color: #a3a423">if</span>(<span style="color: blue">$boolean</span> == true) { ... }</strong>, я чаще всего вспоминаю цитату из одного малоизвестного интернет-ресурса: <strong>if (b.ToString ().length &lt; 5) { ... }</strong>. Хоть и не имет никакого отношения к PHP, но суть проблемы отражает очень ярко.</li>
<li>Самым очевидным способом проверить попадает ли длина строки в какой-либо диапазон является использование функции <strong><span style="color: #17349c">strlen</span>();</strong> и сравнение полученного результата с фиксированными значениями, но зачем выполнять лишний вызов функции, если можно воспользоваться услугами конструкцией языка PHP <strong><span style="color: #17349c">isset</span>();</strong> для определения наличия в строке определенных символов. <strong><span style="color: #a3a423">if</span>(<span style="color: #17349c">isset</span>(<span style="color: blue">$str</span>{<span style="color: blue">5</span>})) { ... }</strong> приведет к абсолютно тем же результатам, что и <strong><span style="color: #a3a423">if</span>(<span style="color: #17349c">strlen</span>($str)&gt;4){ ... }</strong></li>
<li>Битовые операции выполняются намного быстрее относительно обычных арифметических действий. Об этом факте редко вспоминают, да и работать с ними умеет далеко не каждый, но порой они бывают очень актуальны, особенно при частой работе с числами кратными двойке.</li>
<li>Угадайте, что делает интерпретатор при виде надписи <strong><span style="color: blue">1</span>/</strong><strong><span style="color: blue">2</span></strong>? Правильно: делит <strong><span style="color: blue">1</span></strong> на <strong><span style="color: blue">2</span></strong>. Зачем лишний раз утруждать его, когда можно написать просто половину&nbsp;&mdash; <strong><span style="color: blue">0.5</span></strong>.</li>
<li>При возвращении значения переменной из функции при помощи <strong><span style="color: #17349c">global</span></strong> выполняется на порядок больше действий, чем при классическом <strong><span style="color: #17349c">return</span></strong>.</li>
<li>Конечно же фраза <strong><span style="color: blue">$array</span>[text];</strong> интерпритируется практически точно так же, как и <strong><span style="color: blue">$array</span>[<span style="color: red">'text'</span>];</strong>, но зачем выполнять лишнее преобразование из необъявленной константы в строку, проверять, что такой константы все же не существует, выводить сообщение типа <strong>E_NOTICE</strong>, если можно всего этого не делать?</li>
<li>По возможности не используйте <strong><span style="color: #17349c">require_once</span>();</strong> или <strong><span style="color: #17349c">include_once</span>();</strong> неоднократно по отношению к одному и тому же файлу. При отсутствии какого-либо эффекта, попусту тратится время на обработку повторного запроса.</li>
<li>Даже &laquo;безобидных&raquo; ошибок стоит избегать, лишняя проаерка потратит не так много процессорного времени, как генерирование достаточно длинного сообщения об ошибке и вывод его в <em>stdout</em>, <em>stderr</em> или <em>лог-файл</em>, а также не стоит забывать, что даже &laquo;безобидные&raquo; ошибки могут стать потенциальной угрозой безопасности приложения вцелом.</li>
</ul>
<h4>В заключении...</h4>
<p>...хотелось бы упомянуть одну из первых статей по <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto//tag/optimizaciya" target="_blank">оптимизации</a> <a href="/tag/php" target="_blank">PHP</a>, которые мне доводилось читать, до сих пор храню ссылку на нее в bookmark&#39;ах, именно она и выступала в роли <em><a href="http://mgccl.com/php-speed-freaks"  target="_blank" rel="nofollow">одного из основных источников информации</a></noindex></em> для этого текста. В качестве возможных вариантов продолжения чтения про <a href="/tag/php" target="_blank">PHP</a> хотелось бы предложить Вам соответствующие <a href="/php" target="_blank">раздел сайта</a>, <a href="/dzhentelmenskij-nabor-php-programmista/" target="_blank">серию статей</a>, <a href="/tag/php" target="_blank">тэг</a> и <a href="/feed" target="_blank">RSS-ленту</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/php/na-puti-k-idealu/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Обратного пути нет</title>
		<link>http://www.insight-it.ru/programmirovanie/kriptografiya/obratnogo-puti-net/</link>
		<comments>http://www.insight-it.ru/programmirovanie/kriptografiya/obratnogo-puti-net/#comments</comments>
		<pubDate>Fri, 01 Feb 2008 12:43:17 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Криптография]]></category>
		<category><![CDATA[encrypt]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[защита интернет-ресурсов]]></category>
		<category><![CDATA[информационные технологии]]></category>
		<category><![CDATA[коллизия]]></category>
		<category><![CDATA[хэш]]></category>
		<category><![CDATA[хэширование]]></category>
		<category><![CDATA[шифрование]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/science/kriptografiya/obratnogo-puti-net/</guid>
		<description><![CDATA[&#8230;или введение в хэширование
Под таким неоднозначным заголовком я решил разместить всеголишь повествование о такой неотъемлимой части криптографии как hash-функции и алгоритмы.
Не думаю, что многим из читателей будет интересен этот вопрос с математической точки зрения, а также сомневаюсь что смогу достаточно качественно осветить его в этой перспективе, так что позволю сделать более &#34;приземленный&#34; обзор возможных технологии [...]]]></description>
			<content:encoded><![CDATA[<h3 style="text-align: right;">&hellip;или введение в хэширование</h3>
<p>Под таким неоднозначным заголовком я решил разместить всеголишь повествование о такой неотъемлимой части криптографии как hash-функции и алгоритмы.</p>
<p>Не думаю, что многим из читателей будет интересен этот вопрос с математической точки зрения, а также сомневаюсь что смогу достаточно качественно осветить его в этой перспективе, так что позволю сделать более &quot;приземленный&quot; обзор возможных технологии хэширования.</p>
<p><span id="more-34"></span></p>
<h3>Введение</h3>
<p>Под словом <em>хэширование</em> обычно понимают процесс преобразования данных произвольной длины в двоичную строку фиксированной длины. Происходит он с помощью  хэш-функций, которые, в свою очередь, реализуют соответствующие им алгоритмы. Таких алгоритмов и, соответственно, функций существует достаточно много, каждый из них обладает своими свойствами, преимуществами и недостатками.</p>
<p>Общим фактом для всех хэш-функций является отсутствие <em>обратной</em> функции, то есть функции, однозначно преобразующей полученное значение (которое как раз принято называть словом <em>хэш</em> или <em>hash</em>) обратно в исходное. Факт этот достаточно очевиден&nbsp;&mdash; если бы любой объем информации можно было бы преобразовать в достаточно небольшого фиксированного размера, не зависящего от исходного объема данных, двоичную строку и при этом иметь возможность восстановить по ней исходную информацию, то это, как минимум, стало бы революцией в сфере хранения и архивирования данных.</p>
<h3>Свойства</h3>
<p>Далеко не все хэш-функции применимы в криптографии, именно из-за того, что, как Вы возможно уже знаете из <a href="/science/kriptografiya/bezopasnoe-obshhenie">предыдущей записи о криптографии</a>, основной целью криптографии изначально являлось сокрытие информации, а для ее обеспечения необходимо обладание алгоритмом хэширования рядом свойств, обеспечивающих защиту от потенциальных атак, то есть попыток раскрыть с тои или иной степенью точности исходные данные по имеющемуся хэшу.</p>
<h4>Устойчивость к коллизиям</h4>
<dl>
<dt><strong>Коллизия</strong></dt>
<dd>&ndash; пара различных прообразов, для которых значение хэша совпадает.</dd>
</dl>
<p>Устойчивость к возникновению коллизий заключается в том, что <strong>никто</strong> не может найти такую пару исходных строк, которая имела бы один и тот же хэш.</p>
<p>Если  взглянуть на это свойство с точки зрения обычного образованного человека, то нетрудно заметить, что возможных вариантов исходных данных практически бесконечное количество, а возможных хэшей&nbsp;&mdash; лишь 2 в степени фиксированной длины хэша. Из чего было бы логичным сделать вывод о том, что такие пары существуют. Но, как ни странно для всех криптографических алгоритмов, такие пары все еще кем-либо не найдены.</p>
<p>Единственный возможный способ найти такие пары&nbsp;&mdash; вычислить с помощью компьютера, сложно дать какое-либо четкое доказательство почему <em>человек</em> не в состоянии самостоятельно обнаружить коллизию, но тем не менее это так. Если не верите на слово&nbsp;&mdash; можете попробовать заняться этим сами в отношении хотябы самых простых и распространенных алгоритмов, например <strong>md5</strong>.</p>
<p>Обнаружение коллизий с помощью специализированных программ в большинстве случаев не является сложной задачей и ограниченно лишь вычислительной мощностью используемых компьютеров или кластеров. Так как рост производительность современных вычислительных систем растет семимильными шагами, требования к устойчивости хэширующим алгоритмам растут ничуть не меньшими темпами.</p>
<p>В научной литературе принята своеобразная классификация алгоритмов хэширования по устойчивости к обнаружению коллизий типов:</p>
<dl>
<dt><em>Первый тип</em></dt>
<dd>заключается в том, что при фиксированном первой двоичной строке&nbsp;&mdash; невозможно подобрать к ней вторую с таким же хэшем.</dd>
<dt><em>Второй тип</em></dt>
<dd>отличается от первого тем, что обнаружение коллизии невозможно и для произвольной пары сообщений.</dd>
</dl>
<h4>Однонаправленность</h4>
<p>Это свойство заключается в отсутствии возможности <em>эффективно</em> вычислить прообраз по хэшу и прямо вытекает из предыдущего свойства, для подтверждения этого факта существует вполне конкретное математическое доказательство, но приводить его здесь я, с Вашего позволения, не буду. Одного факта устойчивости к коллизиям недостаточно для утверждения, что алгоритм обладает свойством однонаправленности, но, как известно, большинство криптографических алгоритмов хэширования им обладают. Упомянутое выше доказательство базируется как раз на попытке воспроизведения действий потенциального злоумышленника, пытающегося опровергнуть однонаправленность алгоритма с помощью нахождения &quot;обратного пути&quot; от хэша к прообразу, и доказательства обреченности его попыток на провал.</p>
<h4>Кардинальное изменение хэша при незначительном изменении оригинала</h4>
<p>Еще одно не совсем очевидное свойств, связанное с предыдущими. Если бы хэши от отличающихся на допустим один бит прообразов практически полностью совпадали, то этот факт сильно упрощал бы вычисление возможных коллизий и, как следствие (или причина?), нарушало бы устойчивость к ним.</p>
<h3>Применение</h3>
<p>На практике криптографические хэширующие функции имеет несколько вариантов применения, вот основные из них:</p>
<ul>
<li><strong>Хранение аутентификационных данных пользователей сайтов или программных продуктов.</strong> В случае чисто теоретически возможной ошибки программистов или каких-либо других людей или просто имея доступ к базе данных на том или ином основании, потенциальный злоумышленник может получить доступ к закрытым компонентам того или иного проекта, в том числе и к базе данных пользователей. Если такого рода данные хранились бы в открытом виде, он получил бы полный доступ ко всем учетным записям пользователей. Для избежания возможности возникновения подобной ситуации принято хранить не сами логин и пароль пользователей, а их хэши. В этом случае для аутентификации введенные пользователем данные пропускаются через тот же алгоритм хэширования и полученный хэш сравнивается с хранящимся в БД.</li>
<li><strong>Проверка целостности копии данных.</strong> Чаще всего этот способ проверки соответствия копии оригиналу используется в отсутствии доступа к оригиналу. В качестве примера можно привести передачу больших объемов информации через ненадежное пространство (чаще всего Интернет), многие файловые серверы хранят рядом с большими файлами вычисленные от них хэши с использованием популярных алгоритмов, посетитель, скачав файл, может убедиться в его соответствии оригиналу, просто вычислив такой же хэш от копии и сравнив с доступным хэшем от оригинала. Но такой же принцип может использоваться и при доступном оригинале, например, многие программы для прожига образов на компакт-диски используют схожий принцип для проверки соответствия полученного диска образу.</li>
</ul>
<p>Если же слегка отвлечься от криптографии, то можно найти еще достаточно большое количество вариантов применения хэш-функций, таких как хэш-таблицы, генерация псевдо-случайных чисел, поиск текста и многие другие.</p>
<h4>Заключение</h4>
<p>Надеюсь сегодня мне успешно удалось осветить еще один компонент науки под названием криптография, в обозримом будущем я планирую написать несколько записей на эту же тему, но более практического характера, не пропустить момент их публикации вам поможет <a target="_blank" href="/feed">подписка на RSS-ленту моего блога</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/kriptografiya/obratnogo-puti-net/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Шаблонизация</title>
		<link>http://www.insight-it.ru/programmirovanie/php/shablonizaciya/</link>
		<comments>http://www.insight-it.ru/programmirovanie/php/shablonizaciya/#comments</comments>
		<pubDate>Sat, 26 Jan 2008 12:25:36 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[blitz]]></category>
		<category><![CDATA[Smarty]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[template engine]]></category>
		<category><![CDATA[интернет]]></category>
		<category><![CDATA[ООП]]></category>
		<category><![CDATA[разработка]]></category>
		<category><![CDATA[шаблон]]></category>
		<category><![CDATA[шаблонизация]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/php/shablonizaciya/</guid>
		<description><![CDATA[Наверняка Вы часто замечали, что в пределах одного сайта все (или покрайней мере большинство) страниц имеют много общего: структуру, расположение элементов, дизайн и так далее. Основным различием обычно является лишь содержание. Естественно, что делается это не спроста: именно общие компоненты сайта создают в голове посетителей тот самый образ, который производит общее подсознательное впечатление о сайте, [...]]]></description>
			<content:encoded><![CDATA[<p>Наверняка Вы часто замечали, что в пределах одного сайта все (или покрайней мере большинство) страниц имеют много общего: структуру, расположение элементов, дизайн и так далее. Основным различием обычно является лишь содержание. Естественно, что делается это не спроста: именно общие компоненты сайта создают в голове посетителей тот самый образ, который производит общее подсознательное впечатление о сайте, а также позволяет посетителям отличать сайт А от сайта Б.</p>
<p>Продолжая разговор, начатый еще в <a target="_blank" href="/programming/php/obshhaemsya-s-bazojj-dannykh/">одной</a> из <a target="_blank" href="/dzhentelmenskij-nabor-php-programmista">предыдущих статей</a>, рассмотрим организацию интерфейса между двумя другими составляющими практически любого интернет-проекта: скриптов (все так же на примере PHP) и страницами, отправляемыми посетителям посредством http-сервера.</p>
<p><span id="more-32"></span></p>
<p>С точки зрения веб-разработчика было бы как минимум не логично мешать в кучу постоянные части страниц с динамическими. Для этого существует множество причин, в том числе, например, экономия вычислительной мощности сервера на отсутствии необходимости каждый раз заново генерировать статичные элементы или неминуемое сокращение объемов кода, который необходимо написать, в случае если статический и динамический контент разделены. Отделенную подобным образом статическую часть страниц (слегка модифицированную с целью обозначить правила, по которым будет проводиться &quot;заполнение&quot; ее динамическим контентом) принято называть словом <em>&quot;шаблон&quot;</em>.</p>
<p>Наверняка у Вас уже возникло два вполне логичных вопроса:</p>
<ol>
<li>Как можно разделить таким образом контент?</li>
<li>Как потом восстановить страницу в исходном виде?</li>
</ol>
<p>Вариантов ответа на каждый из них можно придумать множество: начиная с банальных вариаций на тему применения <strong>echo</strong>, заканчивая применением достаточно серьезных готовых решений вроде широкораспространенного <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://smarty.php.net"  target="_blank" rel="nofollow"><strong>Smarty</strong></a></noindex> или существенно более эффективного <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://alexeyrybak.com/blitz/blitz_ru.html"  target="_blank" rel="nofollow"><strong>Blitz</strong></a></noindex>. Каждый из них имеет свои сильные и слабые стороны, но в целом любой из них можно оценить по двум критериям: производительности и удобстве организации кода.</p>
<p>Какие-либо цифры оценки производительности приводить не буду, так как, во-первых, в Сети можно найти много benchmark&#39;ов, посвященных этой теме, а, во-вторых, просто-напросто вовсе не о цифрах я хотел с Вами поговорить. Как известно самым производительным по крайней мере с теоретической точки зрения является метод под названием <strong>$php$ mess</strong>, заключается он в следующем: вся страница размещается в рамках одного файла, при этом статическая часть документа пишется просто &quot;как есть&quot; в соответствии с необходимым стандартом, а изменяемые части организуются размещенным в необходимых местах PHP-кодом, окруженным стандартной конструкцией <strong>&lt;?php&nbsp;&nbsp;&nbsp;?&gt;</strong>. Но огромнейший недостаток очевиден&nbsp;&mdash; огромное количество информации расположенной в одном файле, при отсутствии какого-либо более четкого разделения PHP-кода и остального содержимого, чем указанная выше конструкция, приводит к постоянной путанице в коде, а также существенным затратам времени программиста при попытках исправить ту или иную часть документа.</p>
<p>На противоположной стороне нашей шкалы <em>удобство-производительность</em> я бы расположил уже упомянутое выше решение под названием <strong>Smarty</strong>. Представляет оно собой целую систему, реализованную также на PHP, и предоставляющую огромное количество возможностей по решению нашей задачи. Шаблоны хранятся в отдельных файлах, для определения мест расположения динамического контента используется специальный синтаксис, который прост как три копейки, так как разрабатывался с расчетом не на программистов, а по принципу &quot;чем проще, тем лучше&quot;. Именно этот факт сделал <strong>Smarty</strong> одним из самых (если не самым) распространенных движков шаблонизации (или как их принято правильно называть &quot;Template Engine&quot;). Но, к сожалению, за удобство приходится платить, в этом случае производительностью: вся система сама по себе громоздка и состоит из множества файлов, между которыми все данные так или иначе передаются, а так как написано она на PHP (который является далеко не самым производительным языком программирования, в основном в силу своей интерпритируемости и некоторых других особенностей), конкуренции в плане производительности многим другим вариантам решения нашей задачи <strong>Smarty</strong> составить не в состоянии.</p>
<p>Одним из лучших &quot;компромиссных&quot; вариантов, которые доступны на данный момент, могу назвать также упомянутый выше <strong>Blitz</strong>. Реализован он в виде модуля PHP, написанного на языке <strong>C</strong>, что является залогом его отличной производительности. При этом общая его концепция близка к <strong>Smarty</strong>: шаблоны также хранятся в отдельных файлах и подчинены незамысловатому синтаксису (который вообще можно понять и запомнить буквально за 15-20 минут, прочитав статью, <noindex><a target="_blank" rel="nofollow" href="http://www.insight-it.ru/goto/http://alexeyrybak.com/blitz/blitz_ru.html"  target="_blank" rel="nofollow">ссылку на которую</a></noindex> я уже приводил выше), а в PHP-скриптах после установки становится доступен специальный класс для управления модулем. Но основное достоинство этого решения является одновременно и его основным недостатком&nbsp;&mdash; редкий хостинг имеет этот модуль в списке предустановленных (видимо в силу своей не очень обширной известности, обусловленной ), а доступ к http-серверу и PHP-интерпретатору, который необходим для установки PHP-модулей, предоставляется чаще всего только на дорогих тарифах виртуального хостинга или на различных вариантах VPS или арендуемых серверов.</p>
<p>Помимо этого некоторые энтузиасты берутся на написание &quot;собственных&quot; <em>Template Engine</em>, базирующихся на различных вариантов использования PHP-функций вроде <strong>preg_replace</strong>. Если честно такие попытки редко заканчиваются успехом: в лучшем случае удается добиться удобства использования самим разработчиком, но чаще всего в ущерб производительности. Заниматься подобными экспериментами я Вам не советую, вместо этого я предлагаю написать <em>&quot;обертку&quot;</em> к приглянувшемуся распространенному <em>Template Engine</em>, что позволит не только сделать его использование более удобным конкретно для Вас, но и позволит заменить его на другой с минимальными затратами сил и времени (например в случае, если модуль <strong>Blitz</strong> недоступен).</p>
<h3>Разрабатываем &quot;обертку&quot;</h3>
<p>Сразу скажу, что цели привести конкретный пример пригодного для реального использования кода я перед собой не ставлю в этой части моего повествования. Я лишь хочу показать направление, в котором можно провести разработку с целью облегчения собственной же жизни, т.е. предоставить Вам альтернативу простому использованию тех или иных решений в том виде, в котором они предоставлены разработчиками.</p>
<p>Если Ваш выбор всетаки пал на написание &quot;оболочки&quot;, не смотря на принесение в жертву несущественной части производительности, то стоит для начала определиться: а что же мы будем &quot;заворачивать&quot;? В качестве примера я, пожалуй, буду использовать <strong>Blitz</strong>, как самый оптимальный вариант (по крайней мере с моей точки зрения).</p>
<p>Начать стоит как обычно с пустой заготовки для класса:</p>
<pre lang="PHP">
<?php
class Template
{
  private $engine; // экземпляр оригинального класса управления модулем
  public function __construct($template)
  {
    //можно сразу указать указать путь к папке с шаблонами
    $this->engine=new Blitz('./template/'.$template.'.tpl');
  }
}
?>
</pre>
<p>Далее следует решить какие все же модификации мы будем производить для собственного удобства над стандартным решением. Попробую привести несколько примеров в отношении <strong>Blitz</strong>, для начала хочу обратить внимание, что при внимательном прочтении все той же статьи от разработчика этого шаблонизатора, можно обнаружить, что модуль показывает более высокие показатели производительности при однократном вызове метода <em>set</em>. Достичь это можно выполнением этого метода с указанием в качестве одного из входных параметров &quot;многоуровнего&quot; массива, составленного специальным образом (надеюсь Вы все же к этому моменту уже успели прочитать неоднократно упоминавшуюся статью, и представляете принцип работы модуля). Написание механизма составления такого массива позволит как сократить время разработки, так и сэкономит драгоценные миллисекунды, вычитаемые из свободного времени посетителей сайта в процессе генерации страницы.</p>
<p>В любом случае понадобится переменная для его хранения:</p>
<pre lang="PHP">
<?php
class Template
{
  private $engine; // экземпляр оригинального класса управления модулем
  private $array;  // собираемый массив
  public function __construct($template)
  {
    $this->array=array();
    //можно сразу указать указать путь к папке с шаблонами
    $this->engine=new Blitz('./template/'.$template.'.tpl');
  }
}
?>
</pre>
<p>А также метод, переопределяющий стандартный <em>set</em> на метод, добавляющий новые значения к нашему массиву (хотя можно и любое другое понравившееся название использовать):</p>
<pre lang="PHP">
function set($caption,$value)
{
  $this->array[$caption]=$value;
}
</pre>
<p>После чего оригинальный <em>set</em> можно использовать уже непосредственно перед <em>parse</em>, с указанием уже собранного массива в качестве параметра. За компанию позволю произвести себе еще одну модификацию: в подавляющем большинстве случаев <em>parse</em> используется в совокупности с <strong>echo</strong>, чтобы не указывать каждый раз это слово&nbsp;&mdash; можно включить его прямо в наш класс:</p>
<pre lang="PHP">
function parse()
{
  if(count($this->array))$this->engine->set($this->array);
  echo $this->engine->parse();
}
</pre>
<p>Еще одним возможным вариантом модификации может стать обработка всех (или какой-то части, если есть необходимость) динамических данных с помощью какой-либо функции, например это актуально для <strong>htmlspecialchars</strong>:</p>
<pre lang="PHP">
function set($caption,$value)
{
  $this->array[$caption]=$this->html($value);
}
function rawset($caption,$value)
{
  $this->array[$caption]=$value;
}
private function html($array)
{
  if(is_array($array))
  {
    foreach($array as $caption => $value)
    $value=$this->html($value);
    return $array;
  }
  else return htmlspecialchars($array,ENT_QUOTES);
}
</pre>
<p>Как нетрудно заметить, в методе используется рекурсия, так как структура передаваемых параметром массивов неизвестна.</p>
<p>Надеюсь написанный выше текст подтолкнет Вас к действию или хотябы заставит задуматься над имеющимся выбором, если же Вы читали его лишь &quot;для общего развития&quot;, то тем более хочется сказать Вам огромное <em>Спасибо</em><em> за то, что дочитали до конца это повествование.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/php/shablonizaciya/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Общаемся с базой данных</title>
		<link>http://www.insight-it.ru/programmirovanie/php/obshhaemsya-s-bazojj-dannykh/</link>
		<comments>http://www.insight-it.ru/programmirovanie/php/obshhaemsya-s-bazojj-dannykh/#comments</comments>
		<pubDate>Wed, 16 Jan 2008 19:04:09 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[БД]]></category>
		<category><![CDATA[интерфейс]]></category>
		<category><![CDATA[кодинг]]></category>
		<category><![CDATA[ООП]]></category>
		<category><![CDATA[СУБД]]></category>
		<category><![CDATA[технология]]></category>
		<category><![CDATA[хранение данных]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/php/obshhaemsya-s-bazojj-dannykh/</guid>
		<description><![CDATA[На этот раз хочется обсудить такой одновременно важный и несложный момент в реализации работы любого интернет-проекта, как координации работы Ваших скриптов с СУБД.
Если подойти к этому вопросу &#34;в лоб&#34;, то код станет очень неудобен как для понимания, так и для использования: код станет переполнен различными функциями соединения с БД, отправки запросов, преобразования результатов запросов в [...]]]></description>
			<content:encoded><![CDATA[<p>На этот раз хочется обсудить такой одновременно важный и несложный момент в реализации работы любого интернет-проекта, как координации работы Ваших скриптов с СУБД.</p>
<p>Если подойти к этому вопросу &quot;в лоб&quot;, то код станет очень неудобен как для понимания, так и для использования: код станет переполнен различными функциями соединения с БД, отправки запросов, преобразования результатов запросов в массивы PHP, подсчета строк, которые затронул запрос, а также многие и многие другие.</p>
<p>Для желающих минимизировать подобного рода издержки в процессе написания кода, хочу предложить один из, на мой взгляд, самых эффективных способов решения этой проблемы.</p>
<p><span id="more-26"></span></p>
<p>Этим способом будет являться написание класса, реализующего интерфейс между СУБД и PHP-скриптами. Для начала стоит определиться с ассортиментом функций, которые будет призван выполнять наш класс:</p>
<ul>
<li><em>установка соединения</em>, а также проверка успешности выполнения этого действия;</li>
<li><em>отправка запросов</em>, как заданных извне так и, возможно, из какого-либо ассортимента заранее написанных запросов;</li>
<li><em>обработка результатов запросов</em>, не ограничивающаяся одним SELECT, должны быть предоставлены методы обработки результатов любых видов запросов (или хотябы большинства).</li>
</ul>
<p>Вполне очевидным является тот факт, что методы этого класса будут использоваться практически повсеместно в большинстве проектов. Вследствии чего становится нецелесообразным создание объекта нашего класса и передача его по всем функциям и методам всех скриптов, в таких случае намного предпочтительнее делать владельцем методов и переменных сам класс, а не экземпляр класса, с помощью ключевого слова <strong>static</strong>. Это позволит пользоваться услугами нашего класса из любого места кода. Приступим-с собственно к кодингу, начать стоит с заготовки пустого класса:</p>
<pre lang="PHP">
<?php
class SQL
{
  private static $connection; // соединение с СУБД
  static function connect()  // установка соединения
  {

  }
  static function query($str,$bool=false) // произвольный запрос
  {

  }
?>
</pre>
<p>В зависимости от предпочитаемой Вами СУБД набор конкретных функций, используемых в реализации нашего класса, будет вариироваться. В большинстве случаев предпочитаю пользоваться PostgreSQL, на это причин у меня несколько, но это тема для отдельного разговора. Благодаря этому факту приводимый в качестве примера код будет использовать функции для работы именно с этой СУБД. Для поклонников же других этот систем вопрос в подавляющем большинстве случаев заключается лишь в замене этих функций на аналогичные из других модулей PHP, например для популярной и широкораспространенной MySQL достаточно будет всеголишь пройтись автозаменой <strong>pg_ =&gt; mysql_</strong> и слегка подредактировать параметры некоторых функций.</p>
<p>Перейдем к реализации установления соединения с СУБД, не стоит ожидать увидеть здесь ничего необычного:</p>
<pre lang="PHP">
static function connect()  // установка соединения
{
  self::$connection=pg_pconnect("host=localhost dbname=pgsql user=pgsql password=MyPassword");
  // не забываем менять указанные данные для авторизации на правильные
  if(!isset(self::$connection))
  {
    echo "Сайт не работает по техническим причинам.Просим прощения за доставленные неудобства.";
    exit;	// ни в коем случае не выводим более информативных сообщений об ошибке, чем это
  }
}
</pre>
<p>А вот с отправкой и обработкой результатов запросов ситуация далеко не так однозначна. Помимо простой передачи самого текста запроса в СУБД, необходимо правильно определить тип запроса и в соответствии с этим обработать результат. Можно конечно попытаться сделать это автоматически на основе вытаскивания первого слова из текста запроса, но мне всетаки кажется более предпочтительным определение &quot;вручную&quot; желаемого вида представление результата. Выполнение произвольных запросов может выглядеть, например, следующим образом:</p>
<pre lang="PHP">
static function query($str,$bool=false) // произвольный запрос
{
  //echo $str.""; // очень удобно на стадии разработки в процессе поиска ошибок
  $result=@pg_query(self::$connection,$str); // @ - для сокрытия теоретически возможных ошибок
  // or die('Query failed: '.pg_last_error());
  // не забываем убирать в комментарий в финальном варианте проекта
  // или совсем удалять
  if($result)  // Если получен результат, отличный от false
  {
    if($bool)  // Если выбран результат в виде boolean
    {
      return true;
    }
    else  // Если выбран результат в виде массива
    {
      $n=pg_num_rows($result);	// для создания универсального формата массива
      if($n==1)return pg_fetch_array($result,0,PGSQL_ASSOC);
      else  // даже когда результат содержит только одну строку
      {
        $j=pg_num_rows($result);
        $list=array();
        for($i=0;$i<$j;$i++)
        $list[]=pg_fetch_array($result,$i,PGSQL_ASSOC);
        return $list;
      }
    }
  }else return false;
}
</pre>
<p>Помимо базовой отправки запросов, в некоторых случаях имеет смысл написать несколько методов, отправляющих частоиспользуемые запросы, что в некоторых случаях позволяет сократить объем и уменьшить нагроможденность кода. Хоть я и предпочитаю не пользоваться такими вещами, но привести пример такого рода метода все же стоит:</p>
<pre lang="PHP">
static function selectAll($table)
{ // пример метода отправки чаcтоиспользуемых запросов
  return self::query("select * from ".$table.";");
}
</pre>
<p>Если чувствуете необходимость в подобных функциях, можно написать огромное количество, все ограничивается лишь Вашим воображением и знаниями SQL.</p>
<p>Что ж, осталось лишь собрать весь код в <a href="/wp-content/uploads/source/sql.class.phps">единый листинг</a>:</p>
<pre lang="PHP">
<?php
class SQL
{
  private static $connection; // соединение с СУБД
  static function connect()  // установка соединения
  {
    self::$connection=pg_pconnect("host=localhost dbname=pgsql user=pgsql password=MyPassword");
    // не забываем менять указанные данные для авторизации на правильные
    if(!isset(self::$connection))
    {
      echo "Сайт не работает по техническим причинам.Просим прощения за доставленные неудобства.";
      exit;	// ни в коем случае не выводим более информативных сообщений об ошибке, чем это
    }
  }
  static function query($str,$bool=false) // произвольный запрос
  {
    //echo $str.""; // очень удобно на стадии разработки в процессе поиска ошибок
    $result=@pg_query(self::$connection,$str); // @ - для сокрытия теоретически возможных ошибок
    // or die('Query failed: '.pg_last_error());
    // не забываем убирать в комментарий в финальном варианте проекта
    // или совсем удалять
    if($result)  // Если получен результат, отличный от false
    {
      if($bool)  // Если выбран результат в виде boolean
      {
        return true;
      }
      else  // Если выбран результат в виде массива
      {
         $n=pg_num_rows($result);	// для создания универсального формата массива
         if($n==1)return pg_fetch_array($result,0,PGSQL_ASSOC);
         else  // даже когда результат содержит только одну строку
         {
           $j=pg_num_rows($result);
           $list=array();
           for($i=0;$i<$j;$i++)
           $list[]=pg_fetch_array($result,$i,PGSQL_ASSOC);
           return $list;
         }
      }
    }else return false;
  }
  static function selectAll($table)
  { // пример метода отправки чаcтоиспользуемых запросов
    return self::query("select * from ".$table.";");
  }
}
?>
</pre>
<p>Вот так вот оно и выглядит в простейшем варианте, дорабатывать под собственные нужды код можно до бесконечности естественно, но в большинстве случаев даже такой реализации вполне должно хватать.</p>
<p>Эта статья является частью <a href="/dzhentelmenskij-nabor-php-programmista">серии статей &laquo;Джентельменский набор PHP программиста&raquo;</a>, если Вам понравилась эта статья то очень вероятно, что Вам придутся по душе и остальные статьи.</p>
<p>Не забываем <a href="/feed" target="_blank">подписываться на RSS блога</a>, а также на <a href="/comments/feed" target="_blank">ленту комментариев</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/php/obshhaemsya-s-bazojj-dannykh/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.737 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2010-09-10 01:50:50 -->
