<?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>Tue, 31 Jan 2012 09:34:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Реальная ситуация в мире языков программирования</title>
		<link>http://www.insight-it.ru/programmirovanie/realnaya-situaciya-v-mire-yazykov-programmirovaniya/</link>
		<comments>http://www.insight-it.ru/programmirovanie/realnaya-situaciya-v-mire-yazykov-programmirovaniya/#comments</comments>
		<pubDate>Mon, 21 Mar 2011 00:29:25 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Программирование]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/?p=1041</guid>
		<description><![CDATA[Наверняка у всех &#171;гражданских&#187; на слуху сплошные PHP да C++, но на них все, естественно, не заканчивается. Популярность языков программирования можно объяснить массой причин, начиная от &#171;так исторически сложилось&#187; и заканчивая, скажем, условно низким порогом входа. Но далеко не всегда лучшие технологии становятся мэйнстримом, по крайней мере в первые годы, а то и десятилетия, их [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.insight-it.ru/wp-content/uploads/2011/03/programming.jpeg" alt="" title="programming" width="628" height="421" class="alignnone size-full wp-image-1202" /><br />
Наверняка у всех &#171;гражданских&#187; на слуху сплошные PHP да C++, но на них все, естественно, не заканчивается. Популярность языков программирования можно объяснить массой причин, начиная от &#171;так исторически сложилось&#187; и заканчивая, скажем, условно низким порогом входа. Но далеко не всегда лучшие технологии становятся мэйнстримом, по крайней мере в первые годы, а то и десятилетия, их существования.</p>
<p>Так как нас <a href="/life/wordpress/nebolshojj-soc-opros/" target="_blank">здесь много разработчиков собралось</a>, давайте составим рейтинг самых распространенных и перспективных языков программирования. Посмотрим на реальную ситуацию на сегодняшний день &#8212; какие языки сейчас широко распространены, какие заслуживают более детального внимания, а в каких мы видим перспективы.</p>
<p>Для просмотра результатов и участия в опросе &#8212; прошу под кат. В комментариях предлагаю устроить маленький холивар и обсудить сферы применения каждого из языков на практике <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> <span id="more-1041"></span></p>
<div style="float:left; width:33%;">[poll id="16"]</div>
<div style="float:left; width:34%;">[poll id="17"]</div>
<div style="float:left; width:33%;">[poll id="18"]</div>
<div style="float:left; width:100%;">&nbsp;</div>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/realnaya-situaciya-v-mire-yazykov-programmirovaniya/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>3 мифа об эффективности SSL</title>
		<link>http://www.insight-it.ru/programmirovanie/kriptografiya/3-mifa-ob-effektivnosti-ssl/</link>
		<comments>http://www.insight-it.ru/programmirovanie/kriptografiya/3-mifa-ob-effektivnosti-ssl/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 16:52:11 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Криптография]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[шифрование]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/?p=868</guid>
		<description><![CDATA[К использованию SSL для защиты передаваемых через Интернет данных все относятся по-разному: кто-то пренебрегает и гоняет даже пароли пользователей в незашиврованном виде, а у кого-то паранойя и он готов пройти через все круги ада для получения Extended Validation сертификата от крупного вендора. В результате в народе рождаются различные мифы по этой тематике, которые я и [...]]]></description>
			<content:encoded><![CDATA[<p>К использованию SSL для защиты передаваемых через Интернет данных все относятся по-разному: кто-то пренебрегает и гоняет даже пароли пользователей в незашиврованном виде, а у кого-то паранойя и он готов пройти через все круги ада для получения Extended Validation сертификата от крупного вендора. В результате в народе рождаются различные мифы по этой тематике, которые я и предлагаю сегодня обсудить.<span id="more-868"></span></p>
<h2>МИФ №1: Использование HTTPS &#8212; гарантия безопасности сайта</h2>
<p>Вроде бы все просто: все данные передаются между сервером и браузером в зашифрованном виде и украсть их &#171;по пути&#187; невозможно. На практике же запросто могут возникать нюансы&#8230;</p>
<p>Во-первых сам ключ: в большинстве компаний он просто лежит на жестком диске веб-сервера и доступен если не каждому сотруднику, то каждому системному администратору точно (причем вместе с паролем &#8212; перезапускать HTTP-сервера начальству же не положено). Про потенциальный ущерб от попавшего не в те руки SSL-сертификата более-менее серьезной интернет-компании, наверное, рассказывать не стоит &#8212; у всех и так хватит воображения.</p>
<p>Решением чаще всего становится использование аппаратных решений (так называемых <a href="http://en.wikipedia.org/wiki/Hardware_security_module" target="_blank">HSM</a>), соответствующих стандарту <a href="http://en.wikipedia.org/wiki/FIPS_140-2" target="_blank">FIPS 140-2</a>. Они предотвращают как несанкционированный доступ к ключам, так и любые формы его экспорта в незашифрованном виде (даже при резервном копировании и смене аппаратных модулей).</p>
<p>Вторым моментом, на который стоит обратить внимание, является тот факт, что шифрования трафика защищает только от перехвата данных: вирусы, фишинг и опасный для пользователей код остаются таковыми даже в зашифрованном виде. Если сайт генерирует вредоносные ответы через HTTPS они попадут в браузеры пользователей-жертв еще более безопасно для себя <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  В такой ситуации маршрутизаторы с защитой от вторжения (IDS/IPS) и прочие системы безопасности, основанные на &#171;глубоком анализе пакетов&#187;, становятся бессильными, если не настроить дешифрование и повторное шифрование.</p>
<p>Для избежания подобных казусов максимальное внимание стоит уделять работе отдела QA, грамотной настройке всех компонентов инфраструктуры и регулярным проверкам на предмет возможных эксплойтов на сайте.</p>
<h2>МИФ №2: SSL сегодня не является значительной статьей расходов серверных вычислительных ресурсов</h2>
<p>Если бы это было так, то F5, Juniper, Cisco и прочие не ставили бы такие ценники на свои решения. Да, вычислительные мощности среднестатистического сервера растут не по дням, а по часам, но эти же самые вычислительные ресурсы используются и для взлома сертификатов. Не смотря на то, что на взлом  1024-битного ключа по-прежнему требуются многие годы и неплохие финансовые вложения, <a href="http://en.wikipedia.org/wiki/National_Institute_of_Standards_and_Technology" target="_blank">NIST</a> рекомендует переходить на более криптостойким решениям (от 2048 бит), так как теоретически подбор 1024-битного ключа сейчас вполне возможен.</p>
<p>Для разгрузки центрального процессора веб-серверов существует два основных пути:</p>
<ul>
<li>SSL-акселерация на уровне маршрутизатора (чаще всего от вышеупомянутых вендоров)</li>
<li>Использование HSM с встроенным криптографическим процессором</li>
</ul>
<p>Вопрос вычислительных мощностей сегодня решается очень лекго, были бы деньги.</p>
<h2>МИФ №3: Расходы на управление сертификатами не растут с увеличением количества веб-серверов</h2>
<p>Вполне очевидно, что чем больше веб-серверов используется, тем больше SSL-сертификатов должно быть установлено. Еще дополнительные SSL-сертификаты возникают и когда используется несколько виртуальных хостов на одном сервере. До до сих пор часто встречаются люди, которые не знают, что веб-сервер не может определить каким ключом расшифровывать запрос, если на одном IP-адресе расположены несколько доменов, использующих SSL.</p>
<p>Чтобы позволить спокойно масштабировать HTTP-уровень веб-приложения, необходимо рано прерывать HTTPS-соединение для определения сервера, где запрос будет собственно обработан. Такую архитектуру намного легче поддерживать, так как нет необходимости конфигурировать абсолютно каждый HTTP-сервер с отдельными IP-адресами для каждого шифруемого поддомена.</p>
<p>Особенно это актуально для виртуализированных окружений: облачные решения подразумевают наличие образа операционной системы, полностью готового к работе после автоматического старта, настройка SSL в таком случае достаточно проблематична даже в обычном режиме, не говоря уже об использование аппаратных модулей.</p>
<h2>Заключение</h2>
<p>Полностью технический подход к архитектурным решениям, касающихся использования как SSL, так и других технологий, чаще всего абсолютное неприемлем для ИТ-организаций, пытающихся соответствовать требованиям бизнеса. Подобные решения могут сильно влиять на возможность компании разрабатывать, развертывать и контролировать бизнес приложения и решения. Они не могут приниматься чисто из технических или бизнес соображений, только полностью понимая все аспекты можно сделать верный шаг.</p>
<p>Вообще мифы получились достаточно спорные, но на эту тему недавно прошла довольно горячая волна дискуссии в западной блогосфере, даже с участием довольно крупных игроков в этой сфере (<a href="http://devcentral.f5.com/weblogs/macvittie/archive/2011/01/31/dispelling-the-new-ssl-myth.aspx" target="_blank">в частности F5</a>). Может быть у читателей Insight IT тоже найдется что добавить, жду в комментариях <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>По традиции напоминаю про <a href="/feed" target="_blank">подписку на обновления</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/kriptografiya/3-mifa-ob-effektivnosti-ssl/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Piccolo &#8212; построение распределенных систем в 11 раз быстрее Hadoop</title>
		<link>http://www.insight-it.ru/masshtabiruemost/piccolo-postroenie-raspredelennykh-sistem-v-11-raz-bystree-hadoop/</link>
		<comments>http://www.insight-it.ru/masshtabiruemost/piccolo-postroenie-raspredelennykh-sistem-v-11-raz-bystree-hadoop/#comments</comments>
		<pubDate>Sat, 12 Feb 2011 20:49:46 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Масштабируемость]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[piccolo]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[вычисления]]></category>
		<category><![CDATA[разработка]]></category>
		<category><![CDATA[распределенные вычисления]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/?p=731</guid>
		<description><![CDATA[Piccolo &#8212; это система для распределенных вычислений, использующая новую ориентированную на данные модель программирования для разработки приложений по параллельным вычислениям в памяти в масштабах дата-центров. В отличии от существующих моделей, основывающихся на потоках данных, Piccolo позволяет вычислениям выполняться на различных машинах, при этом имея общее изменяющееся состояния через интерфейс таблиц пар &#171;ключ-значение&#187;. Традиционные ориентированные на [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste">
<p><a href="http://piccolo.news.cs.nyu.edu/" target="_blank">Piccolo</a> &#8212; это система для распределенных вычислений, использующая новую ориентированную на данные модель программирования для разработки приложений по параллельным вычислениям в памяти в масштабах дата-центров. В отличии от существующих моделей, основывающихся на <em>потоках</em> данных, Piccolo позволяет вычислениям выполняться на различных машинах, при этом имея общее изменяющееся состояния через интерфейс таблиц пар &#171;ключ-значение&#187;. Традиционные ориентированные на данные модели (такие как используются в <a href="/tag/hadoop/" target="_blank">Apache Hadoop</a>) предоставляют пользователю для работы лишь единственный объект в определенный момент времени, когда в Piccolo используется глобальная таблица состояний, одновременно доступная для всех частей вычисления. Это позволяет пользователям указывать алгоритм вычисления в интуитивно-понятной манере, очень похожей на разработку программ для одного компьютера.<span id="more-731"></span></p>
<p style="margin-bottom: 1em; margin-top: 0em;">Использование хранилища, позволяющего хранить в памяти пары &#171;ключ-значение&#187;, сильно отличается от канонического подхода <a href="/tag/mapreduce/" target="_blank">map-reduce</a>, который основан на распределенных файловых системах. Результаты впечатляют:</p>
<blockquote style="font-family: Georgia, 'Times New Roman', serif; font-style: italic;">
<p style="margin-bottom: 1em; margin-top: 0em;">Эксперименты показали, что Piccolo очень быстр и отличные возможности по масштабируемости для многих прикладных задач. Производительность вычисления PageRank и k-средних выросла в 11 и 4 раза, соответственно, по сравнению с Hadoop. Вычисление PageRank для связанного графа из 1 миллиарда страниц заняло лишь 70 секунд на 100 машинах в <a href="/tag/ec2/" target="_blank">Amazon EC2</a>. Распределенная система по скачиванию веб-страниц легко может полностью загрузить 100Мбит интернет-канал при работе на 12 машинах.</p>
</blockquote>
<div id="_mcePaste">При разработке на Piccolo программисты создают наборы прикладных функций, которые принято называть ядром. Функции ядра запускаются параллельно на нескольких вычислительных узлах, при этом у них есть доступ к общему изменяемому состоянию, которое реализовано в виде набора таблиц, располагающихся в оперативной памяти различных узлов системы. Для доступа к этому состоянию используется примитивный интерфейс, позволяющий узнать <em>(get)</em> и изменить <em>(put)</em> то или иное состояние. Процесс отправки сообщений удаленным узлам, непосредственно имеющим в памяти требуемые данные, полностью берет на себя сам код Piccolo.</div>
<div>Предоставляя разработчикам доступ к глобальному общему состоянию, Piccolo предлагает несколько привлекательных возможностей:</div>
<div>
<ul>
<li>Алгоритмы, основанные на общем промежуточном состоянии, могут быть реализованы естественным, логичным и эффективным образом</li>
<li>Асинхронные online приложения получают возможность иметь <em>оперативный</em> доступ к новым и изменившимся данным, расположенным на других узлах системы</li>
</ul>
</div>
<div>В Piccolo используется ряд оптимизаций, обеспечивающий не только удобное использование интерфейса к таблице состояний, но и его быстроту:</div>
<div id="_mcePaste">
<ul style="list-style-type: square; margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 2em;">
<li><strong>Локальность</strong> &#8212; для обеспечения выполнения локальности исполнения, таблицы явным образом разбиваются на части, располагающиеся на разных машинах. В пользовательском коде при взаимодействии с таблицами доступна настройка локальности, обеспечивающая выполнение кода на том же узле, где располагаются даннын.</li>
<li><strong>Балансировка нагрузки</strong> &#8212; далеко не вся нагрузка равномерна, часто какая-то часть вычислений требует намного больше ресурсов, чем все остальные. Ожидание без дела пока такая задача будет выполнена впустую тратит ценное время и ресурсы. Для решения данной проблемы Piccolo может мигрировать часть задач с загруженных машин на простаивающие, при этом сохраняя настройки локальности и корректность выполнения программы.</li>
<li><strong>Обработка сбоев </strong>- сбои оборудования неизбежны и обычно они случаются в самые критические моменты. Piccolo делает создание контрольных точек и восстановление простым и быстрым, обеспечивая быстрое восстановление в случае сбоев.</li>
<li><strong>Синхронизация </strong>- управление корректной синхронизацией и обновлениями в условиях распределенной системы может быть сложным и медленным. Piccolo позволяет пользователям поручить реализацию логики синхронизации системе. Вместо явной блокировки таблиц при выполнении обновлении данных, пользователи могут присоединять аккумулирующие функции к таблицам: они используются автоматически системой для корректного комбинирования параллельных обновлений ячеек таблиц.</li>
</ul>
</div>
<p>Проект реализован в виде библиотеки для <a href="/tag/python/" target="_blank">Python</a> и <a href="/tag/c/" target="_blank">C++</a>. Более детально примеры использования и принципы работы системы разбираются в источниках информации (правда на английском), не поленитесь &#8212; загляните. Вместо заключения хотелось бы по традиции порекомендовать подписаться на <a href="/feed" target="_blank">RSS блога</a>, если Вы еще этого не сделали.</p>
<h2><strong>Источники информации</strong></h2>
<ul style="list-style-type: square; margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 2em;">
<li><a href="http://www.cs.nyu.edu/~power/" target="_blank">Russell Power</a> &#8212; автор проекта Piccolo</li>
<li><a href="http://www.usenix.org/event/osdi10/tech/full_papers/Power.pdf" target="_blank">Piccolo: Building Fast, Distributed Programs with Partitioned Tables</a></li>
<li>
<p style="margin-bottom: 1em; margin-top: 0em;">Проект был презентован на <a href="http://www.usenix.org/event/osdi10/tech/" target="_blank">OSDI10</a>: <a href="https://docs.google.com/viewer?url=http%3A%2F%2Fwww.usenix.org%2Fevent%2Fosdi10%2Ftech%2Fslides%2Fpower.pdf" target="_blank">презентация</a> и <a href="http://piccolo.news.cs.nyu.edu/osditalk.mp4" target="_blank">видео</a></p>
</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/masshtabiruemost/piccolo-postroenie-raspredelennykh-sistem-v-11-raz-bystree-hadoop/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
<enclosure url="http://piccolo.news.cs.nyu.edu/osditalk.mp4" length="118199420" type="video/mp4" />
		</item>
		<item>
		<title>ООП или не ООП</title>
		<link>http://www.insight-it.ru/programmirovanie/oop-ili-ne-oop/</link>
		<comments>http://www.insight-it.ru/programmirovanie/oop-ili-ne-oop/#comments</comments>
		<pubDate>Thu, 23 Sep 2010 09:07:41 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[ООП]]></category>
		<category><![CDATA[парадигма]]></category>
		<category><![CDATA[языки программирования]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/?p=550</guid>
		<description><![CDATA[Вчера мне на почту пришло письмо от коллеги с просьбой прокомментировать статью, видимо его же перевода или авторства, о судьбе объектно-ориентированного программирования в современном мире: Почему объектно-ориентированное программирование провалилось?. Собственно говоря, пишу ответ в своем блоге скорее чтобы несколько растопить образовавшийся здесь лед, да и возможно снова затянет &#8212; продолжу дальше активно писать в Insight [...]]]></description>
			<content:encoded><![CDATA[<p>Вчера мне на почту пришло письмо от коллеги с просьбой прокомментировать статью, видимо его же перевода или авторства, о судьбе объектно-ориентированного программирования в современном мире: <a href="http://blogerator.ru/page/oop_why-objects-have-failed" target="_blank">Почему объектно-ориентированное программирование провалилось?</a>. Собственно говоря, пишу ответ в своем блоге скорее чтобы несколько растопить образовавшийся здесь лед, да и возможно снова затянет &#8212; продолжу дальше активно писать в Insight IT.</p>
<p><span id="more-550"></span></p>
<p>Для начала хочу вкратце пересказать саму статью. Написана она по мотивам мнений различных экспертов в области разработки, в частности <a href="http://www.dreamsongs.com/ObjectsHaveFailedNarrative.html" target="_blank">Objects Have Failed</a> by Richard P. Gabriel, November 6, 2002 и holywar&#8217;а на конференции <a href="http://en.wikipedia.org/wiki/OOPSLA" target="_blank">OOPSLA</a> с участием именитых специалистов. Аргументы у обоих сторон &#171;за и против&#187;  были довольно странноватыми и по сути были подтверждениями и опровержениями различных мифов об ООП, например о том, что с использованием парадигмы ООП разработка идет быстрее/проще/понятнее/удобнее, что ОО языки программирования не соответствуют требованиям вычислительных процессов будущего и не адекватно отражают предметную область, что повторное использование кода есть в любом языке программирование &#8212; как минимум в виде библиотек. Сторонники ООП же в основном настаивают на справедливости мифов и твердо отстаивают <a href="http://www.insight-it.ru/programmirovanie/java/tri-osnovnyx-komponenta-paradigmy-obektno-orientirovannogo-programmirovaniya/" target="_blank">три основных столпа их парадигмы</a>. На вышеупомянутой конференции по мнению аудитории вверх взяла сторона &#171;против ООП&#187; из-за натиска сторонников языка Lisp и растерянности сторонников ООП касательно своей же теории.</p>
<p>Что же касается моего мнения касательно данного вопроса, то я не являюсь ни приверженцем, ни противником объектно-ориентированного подхода к программированию. В целом мой взгляд на ситуацию довольно прост: все языки программирования &#8212; лишь инструмент для решения вполне определенного круга задач. Выбор инструмента и способа работы с ним определяется в основном лишь самой конкретной постановкой задачи, требованиям к ней, а также имеющимися в наличии ресурсами &#8212; в первую очередь человеческими и финансовыми.  Не нужно смотреть на программирование чисто с технической точки зрения &#8212; в первую очередь программисты решают бизнес-задачи и проблемы людей, а каким именно образом и с использованием каких инструментов &#8212; заказчиков и потребителей программных продуктов волнует меньше всего. Для них намного важнее итоговые показатели получившегося продукта: себестоимость разработки и поддержки, сроки исполнения, соответствие требованиям, а также в зависимости  от типа продукта масштабируемость, производительность, стабильность, безопасность.</p>
<p>Да, в десятках и сотнях тысяч готовых классов в .NET или Java легко запутаться, но они позволяют не разрабатывать реализуемые ими вещи самим. Объектно-ориентированные языки программирования дают возможность оперировать более высокоуровневыми понятиями и не тратить время на возню с памятью напрямую (от утечек правда это не избавляет, но все же), указателями, типовыми алгоритмами, реализацией протоколов и прочими нормальными для низкоуровневых языков программирования вещами. Уделяя меньше внимания деталям, можно создавать крупные проекты большими мазками &#8212; возможно в ущерб качеству, но для многих ситуаций это приемлемо.</p>
<p>Когда речь идет о разработке крупной корпоративной системы с большим количеством пользователей и разнородной информации, на первый план выходят чаще всего масштабируемость и сроки реализации, а вовсе не производительность и эффективность алгоритмов. В таких системах разработка выглядит скорее как склейка требуемого продукта из различных готовых компонентов, чем реализация собственных алгоритмов и оптимизация производительности. Для подобных проектов чаще более уместен объектно-ориентированный подход с использованием широкого спектра готовых классов, библиотек и системных компонентов. Да, в данном случае пострадает производительность, но купить несколько дополнительных серверов дешевле, чем изобретать велосипед и писать с нуля реализацию всех необходимых составных частей системы.</p>
<p>Если же разрабатывается скажем какая-нибудь библиотека для расчета инверсной кинематики, то скорее всего использование ОО-подхода в ней будет излишним и после реализации всех алгоритмов на низкоуровневом языке в функциональном/процедурном стиле будет достаточно создать обертки для всех требуемых языков программирования.</p>
<p>Плюс не стоит забывать и о том, какие люди участвуют в разработке: бывают разработчики, которые фанатеют от ООП, всю жизнь занимаются &#171;сборкой&#187; проектов из библиотек на Java или C#, являются ярыми поклонниками <a href="http://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5" target="_blank">TDD</a> и Agile-разработки, а бывают разработчики, которые предпочитают Assembler/C/Fortran/Cobol/Lisp/Haskell/Erlang (нужное подчеркнуть), любят реализовывать очень сложные  алгоритмы, оптимизировать их, добиваясь выиграша в несколько миллисекунд во времени или пару килобайт в использованной оперативной памяти. Естественно это лишь крайние или почти крайние случаи, большинство разработчиков скорее всего находятся где-то посередине (к сожалению, у меня нет такой статистики), предпочитая универсальные языки программирования, на которых можно писать код как объектно-ориентированно, так и нет (C++/Python/PHP/etc). Хочется порекомендовать руководителям не заставлять имеющихся в наличии людей заниматься тем, что им не по душе, просто так как Вам кто-то вчера рассказал, что &#171;Ruby on Rails &#8212; это круто&#187; или так как во-о-он тот известный проект реализован с использованием во-он тех технологий, языков программирования или парадигм разработки. Используемые технологии и подходы к написанию кода, должны соответствовать поставленным задачам, а команда должна быть готова реализовать проект именно так, как это необходимо, при этом очень большое значение имеет распределение ролей между разработчиками &#8212; чтобы каждый занимался своим любимым делом.</p>
<p>Коллеги, копайте ямы лопатами и забивайте гвозди молотками, а не наоборот <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/programmirovanie/oop-ili-ne-oop/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<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[Давным-давно, в далекой-предалекой галактике&#8230; Хотя да, достаточно давно уже 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;">Давным-давно, в далекой-предалекой галактике&#8230;</span></p>
<p>Хотя да, достаточно давно уже Google выпустили в свет платформу <a id="ix89" title="Google App Engine" href="http://www.appspot.com/" target="_blank" rel="external nofollow">Google App Engine</a>. Описание этого продукта меня заинтересовало еще до открытия публичного доступа к системе и я даже записался на полу-закрытое тестирование. Вскоре пришло подтверждение, что мол &#171;мы рады сообщить, что Ваша учетная запись активирована и теперь у Вас есть возможность попробовать наш новый продукт, для этого нажмите ссылку такую-то&#187;. Но пришло оно как-то не очень удачно, когда ни лишнего свободного времени не было, да и идеи подходящей для создания чего-нибудь эдакого на новой платформе тоже на горизонте не наблюдалось. В общем зашел на их сайт, посмотрел админку, поставил демо-приложение, поигрался чуток и забросил. Но с тех пор руки так и не прекращали чесаться от желания попробовать GAE на каком-нибудь более приближенном к реальности приложении, что мне совсем недавно и довелось сделать. Спешу поделиться впечатлениями.<br />
<span id="more-213"></span><br />
Если Вы даже краем уха не слышали о платформе <span style="font-family: Courier New;">Google App Engine</span> и после прочтения вступления не удосужились скопировать это название в свою любимую поисковую систему, чтобы почитать по-подробнее, то Вам повезло: для порядка я все-таки расскажу чуть-чуть о тех вкусностях, которые так долго поддерживали мой интерес к данному проекту.</p>
<p>Если взглянуть издалека, то GAE представляет собой условно-бесплатный хостинг для веб-приложений, для разработчиков предоставляется все необходимое: начиная от минимально-необходимого <a id="t39e" title="SDK" href="http://code.google.com/appengine/downloads.html" target="_blank" rel="external nofollow">SDK</a> со встроенным веб-сервером, локально эмулирующим саму платформу, заканчивая неплохой документацией по самой системе и доступным из нее API от Google. Почему условно-бесплатный? Бесплатно приложениям выделяется лишь ограниченное количество вычислительных ресурсов, при превышении которых по выбору владельца приложения либо взимается вполне <a id="ly53" title="скромная плата" href="http://code.google.com/appengine/docs/quotas.html" target="_blank" rel="external nofollow">скромная плата</a>, либо всем пользователям начинают показывать &#171;извиняйте, заходите завтра&#187; (в прямом смысле, счетчики потребления ресурсов сбрасываются ежедневно).</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 и библиотеки, использующие нативный, платформозависимый код, также стоит забыть. Но не все так плохо, как кажется: для реализации всех &#171;отобранных&#187; у разработчиков функциональных компонент 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> (лишь отдаленно). Продукт в обращении достаточно своеобразен, как оказалось самый простой способ привыкнуть к работе с ним &#8212; выкинуть из головы все знания о традиционных СУБД и взглянуть на процесс хранения данных с чистого листа. Разномастные JOIN&#8217;ы и прочие изыски лишь мешают думать в терминах подобных систем.</p>
<p>Закончив тему с рекламой GAE, позвольте перейти к моим личным впечатлениям. Попробовал я данную платформу на вполне конкретном примере (в конце поста дам ссылочку на частично-готовый результат, если кому интересно), надо же в конце-концов на что-то с пользой убивать внезапно появившееся свободное время. ОтJava и прочей компании языков, основанных на JVM, я невероятно устал на теперь уже &#171;прошлой&#187; работе, так что взор мой упал на Python и давно находящийся у меня на слуху (в основном благодаря  <a id="vdse" title="Ивану Сагалаеву" href="http://www.softwaremaniacs.org/" target="_blank" rel="external nofollow">Ивану Сагалаеву</a>) фреймворк <a id="mnk8" title="Django" href="http://www.djangoproject.com/" target="_blank" rel="external nofollow">Django</a>. Ни с тем, ни с другим я ранее почти не был знаком на практике, разве что когда-то пытался помогать своим очень хорошим подругам с прохождением Python в университете (пользуясь случаем, передаю привет Полине, Кате и Юле, очень по вам скучаю <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). Стоит упомянуть, что существует несколько сборок Django, адаптированных под GAE, наиболее продуманным и готовым к эксплуатации мне показался проект под названием  <a id="u899" title="app engine patch" href="http://code.google.com/p/app-engine-patch/" target="_blank">app engine patch</a>, которым я и воспользовался для экспериментов.</p>
<p>Django, как известно, является вполне традиционным веб-фрейморком, пропагандирующим свою вариацию на тему MVC (именуемую <strong>MVT</strong> &#8212; <span style="font-family: Courier New;">Model-View-Template</span>, но по сути абсолютно то же самое), а также целый ряд философских верований (вроде <em>DRY, Don&#8217;t repeat yourself</em>), которым даже отведена <a id="m71-" title="отдельная страница на сайте" href="http://docs.djangoproject.com/en/dev/misc/design-philosophies/" target="_blank" rel="external nofollow">отдельная страница на официальном сайте</a>. Адаптированная под GAE версия фреймворка отличается от стандартной по большому счету лишь замененной частью <span style="font-family: Courier New;">Model</span>, в которую очень неплохо вписался предоставляемый API к уже упоминавшемуся хранилищу данных. По всем остальным компонентам системы официальная документация по Django практически полностью актуальна и сильно помогла понять всю картину разработки веб-приложений с использованием данных технологий.</p>
<p>Пересказывать функциональные возможности Django как-то не входило в мои планы, все кому интересно и так уже в курсе или знают где посмотреть. Хочу лишь сказать, что со своей задачей упрощения и ускорения процесса разработки веб-приложений он полностью справляется: все основные функциональные компоненты реализуются просто, легко и быстро, при этом особой необходимости (да и желания) вникать в то, как оно в итоге работает не возникает. Если же взглянуть на Django в совокупности с возможностями GAE &#8212; вопросы масштабируемости также по большей части с плеч разработчика снимаются (если не забыть прочитать документацию по хранилищу и не творить глупостей). В общем что-что, а количество человекочасов, требуемых на создание качественного масштабируемого веб-приложения, эта парочка способна сократить изрядно.</p>
<p>Предложение Google по использованию платформы GAE выглядит очень заманчиво, не смотря на все ограничения под нее можно как портировать существующие приложения, так и легко создавать новые. Бесплатное использование до превышения квот также не может не радовать (кстати квоты там рассчитаны на мировой рынок, превысить большинство из них в рамках рунета &#8212; надо постараться, мне кажется). Но закончить данное повествование мне всетаки хотелось парой недокументированных или вкратце официально упоминавшихся &#171;ложек дегтя&#187;. Первая неприятная особенность: процессы, обрабатывающие пользовательские запросы приложений, умирают после очень небольшого времени простоя (таймаут судя по всему секунд 20-30). По истечении таймаута система освобождает использующиеся приложением ресурсы и когда после перерыва приходит очередной пользователь система вынуждена заново инициализироваться (чуть ли не заново компилировать байткод, хотя не уверен), что занимает около 5 секунд, а то и больше, во время которых пользователю ничего не остается кроме как терпеливо ждать. Сделали данный механизм видимо в связи с тем фактом, что подавляющее большинство развернутых приложений были сделаны просто чтобы побаловаться и были сразу же заброшены, что делает неэффективным постоянное держание в готовом состоянии даже одного процесса для каждого приложения. Таким образом использование GAE для тяжелых веб-приложений с небольшой целевой аудиторией не очень эффективно.  Минус второй: существуют некоторые жесткие ограничения, которые не разрешают увеличивать даже за деньги (по крайней мере расценок не видно). В их число входят максимальное время обработки одного запроса (30 секунд, правда не ясно распространяется ли это на выполнение задач в Task Queue и местном аналоге Cron&#8217;а), 30 активных процессов, обрабатывающих запросы приложения (что влечет за собой достаточно жесткое ограничение на количество запросов в секунду в районе нескольких сотен), максимальный размер HTTP запроса/ответа в 10 мегабайт и некоторые другие. В итоге &#171;тяжелые&#187; вычисления на GAE не погоняешь (хотя есть варианты с применением AJAX и, соответственно, большого количества запросов к GAE), от Digg-эффекта или DDOS&#8217;а есть шанс не уберечься, хостинг файлов не соорудить, но&#8230; разве это ограничения? Есть масса более интересных типов веб-приложений, способных прекрасно существовать в такой среде. Да и в крайнем случае всегда можно связаться с представителями Google с просьбой в виде исключение для Вашего приложения, судя по их заявлениям все ограничения носят искусственный характер и служат лишь для защиты от потребления неоправданно большого количества вычислительных ресурсов плохо спроектированных приложениями.</p>
<p>Этот пост написан по мотивам истории сайта <a id="csyo" title="CargoBook" href="http://www.cargobook.ru/" target="_blank">CargoBook</a>, который задумывался как сообщество для логистов, с плавным выходом на корпоративный рынок с продуктом в виде логистической информационной системы, предоставляемой по принципу SaaS. Сходив по ссылке можно заценить, что можно сделать средствами сладкой парочки Django+GAE и одного студента с почти гуманитарным образованием за часов эдак 20 работы в свободное время. Сейчас в задумке кроме меня участвует всего еще один человек: на правах автора идеи, но  если Вас заинтересовал данный проект и может быть Вы хотите присоединиться в каком-либо амплуа &#8212; пишите об этом в комментариях или <a id="hvgv" title="по другим контактным данным" href="../author" target="_blank">по другим контактным данным</a>.</p>
<p>Кстати в американской части Интернета о GAE ходят в основном негативные мнения, мол тормозит, большое время отклика, сплошные таймауты и ошибки. На практике пока не удалось столкнуться с чем-то подобным, но реально работающего приложения с активной пользовательской базой у меня пока нет для того, чтобы делать какие-то относительно объективные выводы. Может быть со временем что-нибудь изменится и более тонкие нюансы станут выползать на поверхность &#8212; время покажет. Как раз будет повод написать еще один пост на эту же тему <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>17</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 &#8212; это распределенная система кэширования объектов в оперативной памяти. Разрабатывается фирмой <a href="http://danga.com/" rel="nofollow">Danga Interactive</a> (кстати, они являются авторами не только memcached, но и других интересных проектов). Но о них, возможно, в следующий раз. Обычно memcached используется приложениями для временного хранения данных, которые надо часто читать. Приложения не взаимодействуют (обычно) напрямую с сервером memcached, а работают при помощи клиентских библиотек. На настоящее время созданы библиотеки для многих языков программирования (а для некоторых еще и по нескольку альтернативных)  &#8212; полный список клиентских библиотек доступен на <a href="http://code.google.com/p/memcached/wiki/Clients" rel="nofollow">wiki проекта</a>. В целом, данная схема похожа на работу с БД, знакомую многим разработчикам.</p>
<p>Будем рассматривать установку и использование memcached для Linux. Так же при рассмотрении примеров на PHP и обзоре кэширования сессий потребуются PHP и Apache. Возможно, их придется установить, но мы не будем заострять внимание на вопросах установки.</p>
<h2>Сервер memcached</h2>
<p>Давайте приступим к установке memcached. Практически во всех дистрибутивах Linux memcached можно установить из репозитариев. Если есть желание собрать самую свежую версию, то можно заглянуть на <a href="http://danga.com/memcached/" rel="nofollow">сайт разработчика</a>  (на момент написания этих строк последняя версия &#8212; <a href="http://memcached.googlecode.com/files/memcached-1.4.0.tar.gz" rel="nofollow">1.4.0</a>).<br />
Также, возможно, понадобится установить libevent. Последняя стабильная версия &#8212; <a href="http://www.monkey.org/~provos/libevent-1.4.11-stable.tar.gz" rel="nofollow" rel="nofollow">1.4.11</a></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 &#8212; <a href="http://download.tangent.org/libmemcached-0.31.tar.gz" rel="nofollow">0.31</a>. Компилируем, устанавливаем. Для начала, наслаждаемся чтением страниц man:</p>
<pre lang="bash">
man libmemcached
man libmemcached_examples
</pre>
<p>C библиотекой поставляются описание несложных примеров использования. За более интересными же способами применения имеет смысл заглянуть в исходные тексты утилит, благо все идет вместе.</p>
<p>Рекомендую обратить внимание на собранные утилиты. Наверняка многие из них станут верными помощниками при разработке приложений.</p>
<ul>
<li><b>memstat</b> &#8212; выдает информацию о сервере memcached</li>
<li><b>memcat</b> &#8212; выдает значение по ключу</li>
<li><b>memrm</b> &#8212; удаляет значение по ключу</li>
<li><b>memdump</b> &#8212; выдает список ключей</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>Получили статистику &#8212; следовательно memcached функционирует и откликается на запросы.</p>
<p>Итак, на настоящий момент готовы к использованию сервер memcached и клиентская библиотека. Осталось дело за малым &#8212; внедрить использование memcached в разрабатываемое приложение. Что касается приложения &#8212; все в руках разработчиков, а мы рассмотрим небольшой пример работы с базовыми функциями.</p>
<p>memcached предоставляет следующий набор основных функций (их, конечно, больше, но здесь приведены основные):</p>
<ul>
<li><b>set</b> - занести в кэш пару ключ-значение</li>
<li><b>add</b> - занести в кэш значение при условии, что значения с таким ключом в кэше еще нет</li>
<li><b>replace</b> &#8212; обновляет кэш при условии, что значение с таким ключом в кэше уже есть</li>
<li><b>get</b> &#8212; получает значение из кэша по указанному ключу</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>Видим требуемое значение &#8212; должно быть, <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 &#8212; готово.</p>
<h2>PHP</h2>
<p>Для начала установим PECL extension для PHP &#8212; 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 &#8212; готово.</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. Второй параметр &#8212; session.save_path указывает сервер memcached (их может быть указано несколько, через запятую) на котором будут сохранятся данные.</p>
<p>Перезапускаем Apache &#8212; и готово!</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>Итак &#8212; к нашим знакомым по предыдущим примерам ключам, добавился ключ с характерным именем <em>memc.sess.key.3ff8ccab14424082ff83a6dfbcf0941f</em>.</p>
<p>Хранение данных сессии перенесено в систему кэширования. Более подробную информацию по работе с memcached из PHP можно почитать <a href="http://ru2.php.net/manual/ru/book.memcached.php" rel="nofollow">на сайте PHP</a>.</p>
<h2>Заключение</h2>
<p>Мы рассмотрели утановку и примеры использования memcached. Следует особо подчеркнуть, что memcached &#8212; это не система хранения данных, поэтому на практике 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>&#171;интерфейс&#187;</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> методов и переменных, то есть доступных для обращения из других частей приложения. Этот факт вполне логичен &#8212; именно благодаря им и осуществляется взаимодействие класса (или его объекта) с &#171;внешним миром&#187;. Но не все так просто, особенно с точки зрения <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>Минимальные изменения &#8212; суть та же. Сразу хочу отметить, что этот процесс так прост только в <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[Как говорится, все новое &#8212; хорошо забытое старое. Когда я в вдруг вспомнил эту поговорку, мне пришла в голову мысль вернуться к незаслуженно забытой некоторое время назад теме объектно-ориентированного программирования. Возможно многим читателям уже поднадоели часто публикующиеся здесь статьи об устройстве уже существующих проектов, это конечно же не повод прекратить их публикацию, но, тем не [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/idea.png" style="float: right; margin: 16px 4px;" alt="Шаблоны проектирования" title="Шаблоны проектирования" />Как говорится, все новое &#8212; хорошо забытое старое. Когда я в вдруг вспомнил эту поговорку, мне пришла в голову мысль вернуться к незаслуженно забытой некоторое время назад теме объектно-ориентированного программирования. Возможно многим читателям уже поднадоели часто публикующиеся здесь <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>&#171;шаблоны проектирования&#187;</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>&#171;Design Patterns — Elements of Reusable Object-Oriented Software&#187;</em>:</p>
<ul>
<li>Erich Gamma</li>
<li>Richard Helm</li>
<li>Ralph Jonson</li>
<li>John Vlissides</li>
</ul>
<p>Именно благодаря этим людям и их книге эта методология проектирования программного обеспечения получила такое широкое распространение. В своей книге они предоставили 23 основных шаблона проектирования, каждый из которых может использоваться для решения очень широкого класса абстрактных задач, при этом абсолютно не привязываясь к какому-либо конкретному языку программирования или стилю написания кода. Но не стоит забывать, что все они &#8212; просто часть теории, скорее указание на верный путь, чем тропинка, с которой нельзя сделать шаг в сторону.</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. Но тем не менее необходимость регулярно отправлять запросы серверу для получения обновленной информации останется.   С ростом количества пользователей будет расти и количество запросов, открытие и закрытие которых будет неуклонно генерировать нагрузку на сервер. Для снижения нагрузки можно попытаться увеличивать интервал между запросами, но это лишь временная мера, обладающая существенным недостатком &#8212; увеличение этого промежутка времени повлечет за собой рост задержек между обновлением информации на сервере и обновлением клиентской части приложения.</li>
<li><strong>Comet.</strong> С каждым клиентом поддерживается постоянное HTTP-соединение, как только данные на сервере обновились &#8212; сервер сразу же отправляет по уже открытому соединению уведомление о необходимости провести изменения в клиентской части, это позволяет существенно сократить нагрузку на сервер и практически избавиться от задержек между обновлением данных на сервере и клиенте.</li>
</ul>
<p>Для написания серверной части приложения может использоваться практически любой язык программирования, наиболее распространенным решением, пожалуй, является Java Servlet, запущенный в каком-либо контейнере &#8212; Apache TomCat, Jetty или Sun GlassFish. Для реализации этого подхода к организации общения клиента с сервером написано достаточно большое количество framework&#8217;ов и библиотек, наиболее полный список, я думаю, можно найти в <a href="http://en.wikipedia.org/wiki/Comet_%28programming%29#Implementations" target="_blank" rel="nofollow">английской википедии</a>.</p>
<p>Но и для Comet-приложений рано или поздно возникает вопрос масштабируемости, так как традиционные HTTP-сервера создают новый поток (thread) для обслуживания очередных нескольких очередных новых соединений. Каждый поток в состоянии обрабатывать только небольшое количество HTTP-соединений, а так как в случае с Comet соединения находятся в открытом состоянии неопределенно долго, для каждых нескольких новых пользователей веб-приложения приходится создавать новый поток. Количество одновременно существующих потоков не безгранично, что в один прекрасный момент приводит к существенному росту издержек, связанных с созданием новых и управлением существующими потоками, а также все чаще и чаще возникающим отказам потокам в предоставлении серверу необходимых вычислительных. В таких ситуациях некоторые пользователи встречаются с неприемлимыми задержками в работе приложения или непредвиденными сообщениями об ошибках. Наиболее простым и в то же время эффективным решением подобной проблемы является горизонтальное масштабирование Comet-серверов с балансировкой нагрузки на программном или аппаратном уровне.</p>
<p>Если Вас заинтересовала эта тема &#8212; могу посоветовать взглянуть на пару достаточно интересных статей, в котором более с практической точки зрения описывается этот подход к построению приложений:</p>
<ul>
<li><a href="http://www.ibm.com/developerworks/ru/library/j-jettydwr/" target="_blank" rel="nofollow">Создание масштабируемых Comet-приложений с использованием Jetty и Direct Web Remoting</a></li>
<li><a href="http://www.javaworld.com/javaworld/jw-03-2008/jw-03-asynchhttp.html" target="_blank" rel="nofollow">Asynchronous HTTP and Comet Architecture</a> (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> даже в &#171;стандартной комплектации&#187; реализована масса алгоритмов хэширования, начиная с широкораспространенных <strong>md5();</strong> и <strong>sha1();</strong> и заканчивая модулями <strong>hash</strong> и <strong>mhash</strong>, в которых реализована еще целая масса алгоритмов. Все они давно уже стандартизованы и доступны для изучения всем желающим получить о них какую-либо информацию.</p>
<p>Допустим мы храним пароли пользователей в виде какого-то стандартного хэша, для примера &#8212; <strong>md5</strong>, в базе данных. Все было отлично, но в один прекрасный момент нашелся подлый злоумышленник, который неким хитрым способом получил доступ к базе данных логинов и паролей. Перед ним стоит цель &#8212; узнать изначальный пароль у максимального числа пользователей. Посмотрим на ситуацию с его стороны:</p>
<ul>
<li>Первым делом он бы попытался определить, какой именно хэш перед ним находится &#8212; чаще всего это делается либо просто взглянув на длину хэша, либо если приложение широко распространено (популярная CMS скажем) &#8212; покопавшись в ее исходниках, еще есть вариант найти свой собственный аккаунт &#8212; и зная пароль попробовать на нем разные алгоритмы, способов можно придумать множество &#8212; все ограничивается лишь воображением. Узнав ответ на свой вопрос ему лишь останется набрать в <a href="/tag/google" target="_blank">Google</a> фразу вроде <em>&#171;md5 decrypt&#187;</em>, а дальше уже дело техники.</li>
<li>Еще один вариант решения задачи &#8212; взглянуть на список хэшей на предмет наличия совпадений. С очень высокой степенью вероятности за значительной группой одинаковых хэшей будет скрываться какой-либо банальный пароль вроде <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>Список этот можно было бы продолжать достаточно долго, это было лишь первое, что пришло мне в голову. Но ни один из приведенных способов не избавит от возможности второго варианта раскрывания исходного пароля. Основывается он на однозначности стандартных алгоритмов &#8212; одним и тем же исходным данным соответствует один и тот же хэш. Для отказа от этого свойства стандартных алгоритмов придется выполнить более сложную модификацию используемой для генерации хэша функции (которая конечно же тоже поможет и для борьбы с первым вариантом). Сразу приведу пример <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>Как не трудно заметить &#8212; используется самодельная функция <strong>randomString();</strong>, которая возвращает случайную строку, состоящую из указанного количества шестнадцатеричных цифр (надеюсь Вы в состоянии написать ее своими силами). Именно этот момент и гарантирует элемент случайности при каждой новой генерации хэша. В том месте, где я прочитал про этот механизм (ссылку, к сожалению, привести не могу &#8212; в bookmark&#8217;ах не нашел), этот случайный компонент назывался словом <strong>salt</strong>, смысл его заключается в том, что он приписывается ко входным данным, передаваемым стандартной функции хэширования, а затем им же подменяется какая-либо фиксированная часть полученного хэша.<br />
Наверняка у Вас возник вопрос: а как же потом понять, что пользователь ввел верные данные, ведь для тех же исходных данных получится другой хэш и возможности их сравнить не будет? Ответ достаточно прост, его можно было увидеть даже в коде: при повторной инициализации хэша из <a href="/tag/bd" target="_blank">базы данных</a> достается заранее известная часть хранящегося там хэша, соответствующего конкретному пользователю &#8212; тот самый <strong>salt</strong>, и передается нашей функции. В этом случае в механизме будет использоваться именно он, а не новое случайное значение, и, как следствие, в случае правильности введенных данных на выходе получатся совпадающие хэши. Вот такой вот простенький, но иногда достаточно полезный трюк.</p>
<p>Если Вам понравился этот пост &#8212; возможно Вам придутся по душе и <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[&#8230;или 15 привычек, которые помогут ускорить PHP-приложение Практически каждый программист стремится в своих приложениях не только максимально точно реализовать требуемый функционал, но и сделать это как можно более эффективным методом. Для этого конечно же необходимо проектирование, подходящий выбор используемых технологий, возможно некоторый опыт в предметной области, этот список можно продолжать достаточно долго, но я позволю [...]]]></description>
			<content:encoded><![CDATA[<h4 style="text-align: right">&#8230;или 15 привычек, которые помогут ускорить PHP-приложение</h4>
<p>Практически каждый программист стремится в своих приложениях не только максимально точно реализовать требуемый функционал, но и сделать это как можно более эффективным методом. Для этого конечно же необходимо проектирование, подходящий выбор используемых технологий, возможно некоторый опыт в предметной области, этот список можно продолжать достаточно долго, но я позволю себе этого не делать, так как речь сегодня пойдет не об этом. Вместо этого хочу обратить Ваше внимание на более простые и &#171;приземленные&#187; методы <a href="/tag/optimizaciya" target="_blank">оптимизации</a> PHP-кода, которые может быть и не так эффективны по сравнению с указанными выше, но зато не требуют каких-либо усилий со стороны кодера и/или программиста, достаточно лишь воспринимать их как &#171;не вредные&#187; привычки.</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&#8217;ов, хотя порой и просто внедряя в реальные приложения. Как ни странно, в большинстве случаев практика подтверждала теорию, и я стал постоянно пользоваться этими простыми правилами, о которых я и хочу Вам рассказать.</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>, а в месте с ней &#171;в комплекте&#187; шла привычка писать выражение <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> там, где он был необходим, ничуть не чаще, чем там, где он лишь замедляет работу скрипта. От использования еще менее эффективного способа &#8212; <strong><span style="color: #17349c">print</span></strong>, меня избавила моя лень: писать каждый раз на одну букву больше дико не хотелось (в отличии от <strong><span style="color: #17349c">echo</span></strong>, <strong><span style="color: #17349c">print</span></strong> возвращает информацию об успешности выполнения своей работы, что в большинстве случаев просто-напросто не нужно). Проверить опять же не трудно &#8212; нужен лишь объемистый текстовый файл, который достаточно вывести в 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>. В качестве доказательства этого факта приведу таблицу, демонстрирующую статистику выполнения этой операции различными методами и позаимствованную с <a href="http://www.raditha.com/wiki/Readfile_vs_include" target="_blank" rel="nofollow">одного англоязычного сайта</a>:</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">&#171;</span><span style="color: blue">$var</span> <span style="color: red">text&#187;</span>;</strong>, что является одним из самых удобных вариантов решения этой задачи благодаря минимальному количеству символов, которые необходимо набрать, но с точки зрения быстродействия этот вариант далек от идеала, так как влечет за собой достаточно серьезные преобразования в памяти сервера, эффект которых порой бывает заметен невооруженным глазом. Частично ущерб производительности можно сгладить заменой этой конструкции на <strong><span style="color: #17349c">echo</span> <span style="color: blue">$var</span>.<span style="color: red">&#187; text&#187;</span>;</strong>, что приводит к несколькому усложнению внешнего вида кода и несколько поправляет ситуацию со скоростью выполнения. Но как известно знак . обозначает конкатенацию двух строк, что тоже требует некоторых вычислений и затрат памяти, но и от нее можно избавиться, заменив на запятую. Выражение <strong><span style="color: #17349c">echo</span> <span style="color: blue">$var</span>,<span style="color: red">&#187; text&#187;</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>) { &#8230; }</strong>? А задумываться о последовательности выполнения действий при его обработке? Стоит только немного начать размышлять и ошибка становится очевидной: <strong><span style="color: #17349c">count</span>();</strong> выполняется при каждой итерации цикла, что приводит к подсчету количества элементов массива при каждой проверки условия выхода из цикла &#8212; почему бы не посчитать это значение заранее и сравнивать значения индекса с переменной, а не с результатом выполнения функции?</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>) { &#8230; }</strong> можно написать <strong><span style="color: #a3a423">if</span>(<span style="color: blue">$variableOne</span> === <span style="color: blue">$variableTwo</span>) { &#8230; }</strong>, что избавит от проверки на соответствие типов данных и приведения их друг к другу, в некоторых случаях эти действия эти случаях эти действия конечно же и бывают необходимы, но бывает это далеко не часто.</li>
<li>Глядя на выражения вроде <strong><span style="color: #a3a423">if</span>(<span style="color: blue">$boolean</span> == true) { &#8230; }</strong>, я чаще всего вспоминаю цитату из одного малоизвестного интернет-ресурса: <strong>if (b.ToString().length &lt; 5) { &#8230; }</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>})) { &#8230; }</strong> приведет к абсолютно тем же результатам, что и <strong><span style="color: #a3a423">if</span>(<span style="color: #17349c">strlen</span>($str)&gt;4){ &#8230; }</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>. Зачем лишний раз утруждать его, когда можно написать просто половину &#8212; <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>Даже &#171;безобидных&#187; ошибок стоит избегать, лишняя проаерка потратит не так много процессорного времени, как генерирование достаточно длинного сообщения об ошибке и вывод его в <em>stdout</em>, <em>stderr</em> или <em>лог-файл</em>, а также не стоит забывать, что даже &#171;безобидные&#187; ошибки могут стать потенциальной угрозой безопасности приложения вцелом.</li>
</ul>
<h4>В заключении&#8230;</h4>
<p>&#8230;хотелось бы упомянуть одну из первых статей по <a href="/tag/optimizaciya" target="_blank">оптимизации</a> <a href="/tag/php" target="_blank">PHP</a>, которые мне доводилось читать, до сих пор храню ссылку на нее в bookmark&#8217;ах, именно она и выступала в роли <em><a href="http://mgccl.com/php-speed-freaks" target="_blank" rel="nofollow">одного из основных источников информации</a></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>32</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>) обратно в исходное. Факт этот достаточно очевиден &#8212; если бы любой объем информации можно было бы преобразовать в достаточно небольшого фиксированного размера, не зависящего от исходного объема данных, двоичную строку и при этом иметь возможность восстановить по ней исходную информацию, то это, как минимум, стало бы революцией в сфере хранения и архивирования данных.</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>Если  взглянуть на это свойство с точки зрения обычного образованного человека, то нетрудно заметить, что возможных вариантов исходных данных практически бесконечное количество, а возможных хэшей &#8212; лишь 2 в степени фиксированной длины хэша. Из чего было бы логичным сделать вывод о том, что такие пары существуют. Но, как ни странно для всех криптографических алгоритмов, такие пары все еще кем-либо не найдены.</p>
<p>Единственный возможный способ найти такие пары &#8212; вычислить с помощью компьютера, сложно дать какое-либо четкое доказательство почему <em>человек</em> не в состоянии самостоятельно обнаружить коллизию, но тем не менее это так. Если не верите на слово &#8212; можете попробовать заняться этим сами в отношении хотябы самых простых и распространенных алгоритмов, например <strong>md5</strong>.</p>
<p>Обнаружение коллизий с помощью специализированных программ в большинстве случаев не является сложной задачей и ограниченно лишь вычислительной мощностью используемых компьютеров или кластеров. Так как рост производительность современных вычислительных систем растет семимильными шагами, требования к устойчивости хэширующим алгоритмам растут ничуть не меньшими темпами.</p>
<p>В научной литературе принята своеобразная классификация алгоритмов хэширования по устойчивости к обнаружению коллизий типов:</p>
<dl>
<dt><em>Первый тип</em></dt>
<dd>заключается в том, что при фиксированном первой двоичной строке &#8212; невозможно подобрать к ней вторую с таким же хэшем.</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>9</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>, заканчивая применением достаточно серьезных готовых решений вроде широкораспространенного <a href="http://smarty.php.net" target="_blank" rel="nofollow"><strong>Smarty</strong></a> или существенно более эффективного <a href="http://alexeyrybak.com/blitz/blitz_ru.html" target="_blank" rel="nofollow"><strong>Blitz</strong></a>. Каждый из них имеет свои сильные и слабые стороны, но в целом любой из них можно оценить по двум критериям: производительности и удобстве организации кода.</p>
<p>Какие-либо цифры оценки производительности приводить не буду, так как, во-первых, в Сети можно найти много benchmark&#8217;ов, посвященных этой теме, а, во-вторых, просто-напросто вовсе не о цифрах я хотел с Вами поговорить. Как известно самым производительным по крайней мере с теоретической точки зрения является метод под названием <strong>$php$ mess</strong>, заключается он в следующем: вся страница размещается в рамках одного файла, при этом статическая часть документа пишется просто &quot;как есть&quot; в соответствии с необходимым стандартом, а изменяемые части организуются размещенным в необходимых местах PHP-кодом, окруженным стандартной конструкцией <strong>&lt;?php&nbsp;&nbsp;&nbsp;?&gt;</strong>. Но огромнейший недостаток очевиден &#8212; огромное количество информации расположенной в одном файле, при отсутствии какого-либо более четкого разделения 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 минут, прочитав статью, <a href="http://alexeyrybak.com/blitz/blitz_ru.html" target="_blank" rel="nofollow">ссылку на которую</a> я уже приводил выше), а в PHP-скриптах после установки становится доступен специальный класс для управления модулем. Но основное достоинство этого решения является одновременно и его основным недостатком &#8212; редкий хостинг имеет этот модуль в списке предустановленных (видимо в силу своей не очень обширной известности, обусловленной ), а доступ к 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>, чтобы не указывать каждый раз это слово &#8212; можно включить его прямо в наш класс:</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">серии статей "Джентельменский набор PHP программиста"</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>
		<item>
		<title>Защита интернет-ресурсов в картинках</title>
		<link>http://www.insight-it.ru/programmirovanie/php/zashhita-internet-resursov-v-kartinkax/</link>
		<comments>http://www.insight-it.ru/programmirovanie/php/zashhita-internet-resursov-v-kartinkax/#comments</comments>
		<pubDate>Sun, 13 Jan 2008 19:30:00 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[OCR]]></category>
		<category><![CDATA[online]]></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/zashhita-internet-resursov-v-kartinkax/</guid>
		<description><![CDATA[Этой статьей мне хотелось бы открыть мою первую серию статей &#34;Джентельменский набор PHP программиста&#34;. Как и во всей остальной серии здесь пойдет речь о программировании на PHP для интернет-проектов, но в каждой статье я буду выбирать один узкий аспект и на протяжении всей статьи буду стараться показать возможные варианты его реализации и применения. Сегодня таким [...]]]></description>
			<content:encoded><![CDATA[<p>Этой статьей мне хотелось бы открыть мою первую <a href="/dzhentelmenskij-nabor-php-programmista/" target="_blank">серию статей &quot;Джентельменский набор PHP программиста&quot;</a>. Как и во всей остальной серии здесь пойдет речь о программировании на PHP для интернет-проектов, но в каждой статье я буду выбирать один узкий аспект и на протяжении всей статьи буду стараться показать возможные варианты его реализации и применения.</p>
<p>Сегодня таким аспектом станет защита интернет-ресурса от возможного возникновения нежелательного контента со стороны пользователей с помощью технологии captcha (точнее о &quot;графическом&quot; варианте ее реализации), о которой уже <a href="/net/otkuda-voznikaet-spam-i-kak-s-nim-borotsya/" target="_blank">неоднократно шла речь</a>.</p>
<p><span id="more-23"></span></p>
<p>Начать имеет смысл с небольшого напоминания о принципе работы этой технологии: перед потенциальным посетителем ставится некое препятствие, которое ему необходимо преодолеть для  продолжения работы с интернет-ресурсом. Существует множество <a target="_blank" href="/net/7-sposobov-zashhitit-svoj-internet-resurs-ot-nezhelatelnoj-informacii/">вариантов такого рода препятствий</a>. Как уже упоминалось, сегодня мы будем реализовывать только один наиболее распространенный тип &#8212; &quot;графический&quot;. В простейшем случае он представляет собой просьбу переписать с изображения некий набор символов. В процессе генерирования изображения, символы сильно искажаются с целью предотвращения возможности их распознавания любой программой с помощью технологии OCR.</p>
<h3>Подготовка</h3>
<p>Прежде чем начать писать код стоит более детально осознать какая же цель перед нами стоит: нам необходимо написать скрипт, генерирующий искаженное изображение некоторого набора символов и незаметно для пользователя передающее этот набор какому-либо другому скрипту, который нас пока мало интересует, но ясно лишь, что собственно проверкой будет заниматься именно он на основе данных полученных от пользователя и нашего скрипта. Способов исказить текст существует огромное количество, в ходе написания статьи постараюсь упомянуть несколько самых эффективных и широкоиспользуемых из них.</p>
<p>В первую очередь стоит подготовить некий каркас кода, который мы будем впоследствии заполнять. Он будет состоять из двух частей:</p>
<ol>
<li>Описание класса, генерирующего изображение</li>
<li>Файл, который будет вызываться browser&#8217;ом. В нем будет подключено описание нашего класса, выбор настроек данного конкретного изображения и выполнено создание объекта класса, в соответствии с выбранными настройками.</li>
</ol>
<p>Для начала давайте определимся со списком параметров, которые будет иметь наш класс. Во-первых, нужно решить какой текст будет генерироваться, самый простой и распространенный вариант &#8212; просто четыре цифры, я в примере на нем и остановлюсь, а реально же можно использовать абсолютно любые приходящие в голову варианты. Во-вторых, размеры изображения и текста &#8212; их лучше подобрать фиксированными так, чтобы было максимально читабельно, при минимальных размерах изображения, но при желании можно сделать и возможность изменения их извне. Последним в списке параметров будет цвет фона и текста &#8212; их как раз лучше задавать вне класса, так как основным действием, необходимым при переносе этого скрипта с одного сайт на другой &#8212; подбор используемых цветов таким образом, чтобы изображение смотрелось не очень ужасно при текущем варианте дизайна, изменения в других параметрах требуются на порядок реже.</p>
<p>Итак, создание объекта будем производить максимально простым способом, параметрами укажем белый и черный цвета.</p>
<pre lang="php">
<?php
require_once('captcha.class.php');	// указываем правильный путь к описанию класса
new Captcha(array(255,255,255),array(0,0,0));
?>
</pre>
<p style="font-size: 75%;">(для удобного чтения таких вставок исходного кода достаточно нажать на нее один раз левой кнопкой мыши и использовать стрелки &larr; и &rarr; на клавиатуре)</p>
<p>Заготовка для самого класса будет выглядеть примерно следующим образом (предположим, что он хранится в файле <u>captcha.class.php</u>):</p>
<pre lang="PHP">
<?php
class Captcha
{
   private $string;	// генерируемый текст
   private $bgcol;	// основной цвет фона
   private $fgcol;	// основной цвет текста
   private $height;	// высота изображения
   private $width;	// ширина изображения
   function __construct($bgcol,$fgcol)  // конструктор, вызывается при создании экземпляра класса
   {

   }
}
?>
</pre>
<h3>Задаем параметры</h3>
<p>Первым делом при создании объекта необходимо задать остальные параметры, размеры изображения можно указать прямо в конструкторе, а для генерации текста лучше написать отдельную функцию:</p>
<pre lang="PHP">
<?php
class Captcha
{
   private $string;	// генерируемый текст
   private $bgcol;	// основной цвет фона
   private $fgcol;	// основной цвет текста
   private $height;	// высота изображения
   private $width;	// ширина изображения
   function __construct($bgcol,$fgcol)  // конструктор, вызывается при создании экземпляра класса
   {
	$this->width=250;
	$this->height=80;
	$this->fgcol=$fgcol;
	$this->bgcol=$bgcol;
	$this->generateSymbols();
   }
   private function generateSymbols()   // генерация четырех цифр
   {
      $this->string=$this->leadingZero(rand()%10000,4);
   }
   private function leadingZero($num,$length) // дополнения числа num лидирующими нулями
   {						// до длины length
	$str=strrev($num);
	for($i=strlen($str);$i<$length;++$i)$str.="0";
	return strrev($str);
   }
}
?>
</pre>
<p>Этих данных нам должно хватить для написания функции, генерирующей изображение.</p>
<h3>Генерируем изображение</h3>
<p>Если забыть, что текст необходимо искажать, то функция, генерирующая изображение выглядела бы просто как:</p>
<pre lang="PHP">
private function generateImage()  // генерация изображения
{
   $im=@imagecreatetruecolor($this->width,$this->height);
   $bcol=imagecolorallocate($im,$this->bgcol[0],$this->bgcol[1],$this->bgcol[2]);
   $fcol=imagecolorallocate($im,$this->fgcol[0],$this->fgcol[1],$this->fgcol[2]);
   imagefill($im,0,0,$bcol);
   imagettftext($im,40,10,20,25,$fcol,"./font/font_name.ttf",$this->string));
   header('Content-Type: image/png');
   imagepng($im);
   imagedestroy($im);
}
</pre>
<p><span style="background-color: Yellow;">В данном методе используются функции модуля PHP под названием GD, основывающегося на одноименной библиотеке, убедитесь, что на Вашем хостинге этот модуль установлен.</span></p>
<p>Реально же ей пользоваться не стоит &#8212; такое изображение с легкостью поддается OCR. Полученный текст необходимо тем или иным образом исказить. Для вывода изображения используется формат PNG, но никто не мешает воспользоваться JPEG или GIF, для этого достаточно заменить везде png на название соответствующего формата.</p>
<h3>Искажаем текст</h3>
<p>Вот списочек тех, способов искажения текста, которыми я буду пользоваться в примере, пользоваться всеми сразу естественно никто не заставляет, да и включив воображение можно придумать много модификаций приведенных мной способов или абсолютно других:</p>
<ul>
<li><i>использование нестандартных шрифтов</i> &#8212; функция imagettftext позволяет использовать произвольный шрифт в формате Truetype, чем и необходимо воспользоваться. В Сети можно найти огромное количество бесплатных шрифтов в этом формате. По возможности стоит выбирать шрифты, максимально не похожие на любой стандартный, но при этом легко читающиеся.</li>
<li><i>использование нескольких шрифтов</i> &#8212; сделав подборку подходящих шрифтов, можно не останавливаться на каком-то одном, а сделать выбор текущего шрифта случайным из списка.</li>
<li><i>случайный выбор цветов</i> &#8212; усложняет работу OCR и в большинстве случаев не сильно мешает восприятию человеком.</li>
<li><i>случайное расположение символов</i> &#8212; еще один способ усложнить работу программам, пытающимся прочитать текст.</li>
<li><i>неравномерный фон</i> &#8212; изобразив на фоне какой-либо абстрактный набор любых фигур, можно заставить программу-посетителя подумать что какая-то часть из них является символом. Например, пересечение двух прямых линий часто распознается как буква T или L. Неплохим вариантом является написание на фоне других символов другим цветом, сильно отличающимся от основного и близким к цвету фона.</li>
</ul>
<p>Для начала этого вполне хватит, перейдем к реализации, в комментариях постараюсь указывать все особенности:</p>
<pre lang="PHP">
private function generateImage() // генерация изображения
{
   $im=@imagecreatetruecolor($this->width,$this->height);  // создаем пустое изображение
   $mcol=imagecolorallocate($im,$this->fgcol[0]+rand()%100+80,$this->fgcol[1]+rand()%30+150,$this->fgcol[2]-rand()%55); // выбираем случайным образом
   $kcol=imagecolorallocate($im,$this->fgcol[0]+rand()%100+80,$this->fgcol[1]+rand()%30+150,$this->fgcol[2]-rand()%20); // несколько цветов
   $lcol=imagecolorallocate($im,$this->bgcol[0]-rand()%20,$this->bgcol[1]-rand()%20,$this->bgcol[2]-rand()%20);
   $bcol=imagecolorallocate($im,$this->bgcol[0],$this->bgcol[1],$this->bgcol[2]);
   $fcol=imagecolorallocate($im,$this->fgcol[0],$this->fgcol[1],$this->fgcol[2]);
   imagefill($im,0,0,$bcol);  // заполняем изображение фоном
   $array=array(6,7,6,6,20,20,25,26,31,32,37,39,41); // список названий подходящих шрифтов
   $n=$array[rand()%count($array)];  // наугад выбираем из них один
   $m=rand()%50+1;
   $k=rand()%50+1;
   for($i=0;$i<$m;++$i)
   imageline($im,0,rand()%$this->height,$this->width,rand()%$this->height,$lcol); // создаем на фоне несколько линий
   for($i=0;$i<$k;++$i)
   imageline($im,rand()%$this->width,0,rand()%$this->width,$this->height,$lcol); // и еще несколько
   /*
   Генерируем текст: две строки на фон, а также интересующие нас символы по одному.
   */
   imagettftext($im,rand()%20+40,rand()%100-50,rand()%$this->height*0.8,rand()%50+25,$kcol,"./font/".$k.".ttf",$this->randomString(rand()%15));
   imagettftext($im,rand()%40+35,rand()%70-35,rand()%$this->height*0.8,rand()%25+25,$mcol,"./font/".$m.".ttf",$this->randomString(5+rand()%4));
   for($i=0;$i<strlen($this->string);++$i)
   imagettftext($im,rand()%10+33,rand()%70-35,15+$i*$this->width/5*1.1+rand()%5,rand()%7+$this->height*0.73,$fcol,"./font/".$n.".ttf",$this->string[$i]);
   for($i=0;$i<$m/10;++$i)
   imageline($im,0,rand()%$this->height,$this->width,rand()%$this->height,$mcol); // еще линии
   for($i=0;$i<$k/4;++$i)
   imageline($im,rand()%$this->width,0,rand()%$this->width,$this->height,$mcol);  // и еще немного
   for($i=0;$i<$k/6;++$i)
   imageline($im,rand()%$this->width,0,rand()%$this->width,$this->height,$fcol);  // и еще чуть-чуть
   header('Content-Type: image/png');
   imagepng($im);
   imagedestroy($im);
}
private function randomString($length)  // генерируем случайный набор символов заданной длины
{
  $list="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ!@#$%^&#038;**()-=_+.,<>/\|;:";
  for($i=0,$str="";$i<$length;++$i)$str.=substr($list,mt_rand(0,strlen($list)-1),1);
  return $str;
}
</pre>
<p>Стоит заметить, что конкретные цифры необходимо подбирать индивидуально, в примере они указаны абсолютно произвольно. Использование конкретно этих же цифр приведет к далеко не самым лучшим результатам.</p>
<h3>Сборка</h3>
<p>Не стоит забывать, что помимо генерации самого изображения, необходимо передать написанный текст другому скрипту, который будет сверять данные. Удобнее всего это делать через глобальный массив <span style="color: rgb(0, 0, 255);">$_SESSION</span>.</p>
<p>Собрав все написанное выше, и учтя передачу текста, можно получить следующий класс:</p>
<pre lang="PHP">
class Captcha
{
   private $string;	// генерируемый текст
   private $bgcol;	// основной цвет фона
   private $fgcol;	// основной цвет текста
   private $height;	// высота изображения
   private $width;	// ширина изображения
   function __construct($bgcol,$fgcol)  // конструктор, вызывается при создании экземпляра класса
   {
      $this->width=250;
      $this->height=80;
      $this->fgcol=$fgcol;
      $this->bgcol=$bgcol;
      $this->generateSymbols();
      $this->generateImage();
   }
   private function generateImage() // генерация изображения
   {
      $im=@imagecreatetruecolor($this->width,$this->height);  // создаем пустое изображение
      $mcol=imagecolorallocate($im,$this->fgcol[0]+rand()%100+80,$this->fgcol[1]+rand()%30+150,$this->fgcol[2]-rand()%55); // выбираем случайным образом
      $kcol=imagecolorallocate($im,$this->fgcol[0]+rand()%100+80,$this->fgcol[1]+rand()%30+150,$this->fgcol[2]-rand()%20); // несколько цветов
      $lcol=imagecolorallocate($im,$this->bgcol[0]-rand()%20,$this->bgcol[1]-rand()%20,$this->bgcol[2]-rand()%20);
      $bcol=imagecolorallocate($im,$this->bgcol[0],$this->bgcol[1],$this->bgcol[2]);
      $fcol=imagecolorallocate($im,$this->fgcol[0],$this->fgcol[1],$this->fgcol[2]);
      imagefill($im,0,0,$bcol);  // заполняем изображение фоном
      $array=array(6,7,6,6,20,20,25,26,31,32,37,39,41); // список названий подходящих шрифтов
      $n=$array[rand()%count($array)];  // наугад выбираем из них один
      $m=rand()%50+1;
      $k=rand()%50+1;
      for($i=0;$i<$m;++$i)
      imageline($im,0,rand()%$this->height,$this->width,rand()%$this->height,$lcol); // создаем на фоне несколько линий
      for($i=0;$i<$k;++$i)
      imageline($im,rand()%$this->width,0,rand()%$this->width,$this->height,$lcol); // и еще несколько
      /*
      Генерируем текст: две строки на фон, а также интересующие нас символы по одному.
      */
      imagettftext($im,rand()%20+40,rand()%100-50,rand()%$this->height*0.8,rand()%50+25,$kcol,"./font/".$k.".ttf",$this->randomString(rand()%15));
      imagettftext($im,rand()%40+35,rand()%70-35,rand()%$this->height*0.8,rand()%25+25,$mcol,"./font/".$m.".ttf",$this->randomString(5+rand()%4));
      for($i=0;$i<strlen($this->string);++$i)
      imagettftext($im,rand()%10+33,rand()%70-35,15+$i*$this->width/5*1.1+rand()%5,rand()%7+$this->height*0.73,$fcol,"./font/".$n.".ttf",$this->string[$i]);
      for($i=0;$i<$m/10;++$i)
      imageline($im,0,rand()%$this->height,$this->width,rand()%$this->height,$mcol); // еще линии
      for($i=0;$i<$k/4;++$i)
      imageline($im,rand()%$this->width,0,rand()%$this->width,$this->height,$mcol);  // и еще немного
      for($i=0;$i<$k/6;++$i)
      imageline($im,rand()%$this->width,0,rand()%$this->width,$this->height,$fcol);  // и еще чуть-чуть
      header('Content-Type: image/png');
      imagepng($im);
      imagedestroy($im);
   }
   private function generateSymbols()   // генерация четырех цифр
   {
      $this->string=$this->leadingZero(rand()%10000,4);
   }
   private function leadingZero($num,$length) // дополнения числа num лидирующими нулями
   {						// до длины length
      $str=strrev($num);
      for($i=strlen($str);$i<$length;++$i)$str.="0";
      return strrev($str);
   }
   private function randomString($length)  // генерируем случайный набор символов заданной длины
   {
      $list="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ!@#$%^&#038;**()-=_+.,<>/\|;:";
      for($i=0,$str="";$i<$length;++$i)$str.=substr($list,mt_rand(0,strlen($list)-1),1);
      return $str;
   }
}
</pre>
<p>Слегка доработав его и приведя в более подходящий вид, можно добиться генерации изображений, выглядящих например вот так:</p>
<p> <img style="margin: 6px; float: left;" title="Пример получающегося изображения" alt="CAPTCHA Sample" src="/wp-content/uploads/captcha-sample.png" />
<p>Специально не выкладываю уже доведенный до ума класс, чтобы у читателей не возникало желания просто взять и воспользоваться им, это приведет лишь к очередной серии captcha-клонов.</p>
<p>Для Вашего удобства предлагаю скачать используемые в примере <a href="/wp-content/uploads/source/captcha.class.phps">код класса</a> и <a href="/wp-content/uploads/source/captcha.phps">код вызываемого browser'ом файла</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/php/zashhita-internet-resursov-v-kartinkax/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Безопасное общение</title>
		<link>http://www.insight-it.ru/programmirovanie/kriptografiya/bezopasnoe-obshhenie/</link>
		<comments>http://www.insight-it.ru/programmirovanie/kriptografiya/bezopasnoe-obshhenie/#comments</comments>
		<pubDate>Wed, 09 Jan 2008 14:34:33 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Криптография]]></category>
		<category><![CDATA[decrypt]]></category>
		<category><![CDATA[encrypt]]></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>
		<category><![CDATA[шифр]]></category>
		<category><![CDATA[шифрование]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/science/kriptografiya/bezopasnoe-obshhenie/</guid>
		<description><![CDATA[&#8230;или введение в криптографию Представим, что два человека хотят общаться, но при этом хотят сохранить свой разговор в секрете. Для этого у них есть идеальный канал связи, который представляет собой цельную, непроницаемую для внешних воздействий трубу, что приводит к тому, что когда один из них шепчет что-либо в нее то только второй человек сможет получить [...]]]></description>
			<content:encoded><![CDATA[<h3 style="text-align: right;">&#8230;или введение в криптографию</h3>
<p>Представим, что два человека хотят общаться, но при этом хотят сохранить свой разговор в  секрете. Для этого у них есть идеальный канал связи, который представляет собой цельную, непроницаемую для внешних воздействий трубу, что приводит к тому, что когда один из них шепчет что-либо в нее то только второй человек сможет получить сообщение, приложив ухо к противоположному концу трубы. Общение по такому каналу связи сравнимо с ситуацией, когда помимо них во всем мире не существовало бы других людей.</p>
<p>Но, к сожалению, таких каналов связи не существует, но это не мешает стремиться снабжать существующие каналы связи свойствами, приближающими их к идеальному, об этом мы сегодня и поговорим.</p>
<p><span id="more-21"></span></p>
<p>Как известно, наукой, посвященной теории и практике сокрытия данных, является криптография (из греческого: &kappa;&rho;&upsilon;&pi;&tau;ό&sigmaf; &#8212; скрытый и &gamma;&rho;ά&phi;&omega; &#8212; писать). Несмотря на свою историю, насчитывающую не одну тысячу лет, эта наука и в современном мире нашла множество применений.&nbsp; С применением этой науки возможно решение самых разнообразных проблем, но основной задачей, с которой призвана справляться современная криптография является как раз относительно безопасная передача данных через ненадежное пространство.</p>
<p>Для максимального приближения реальных каналов связи к идеальному, необходимо выделить основные цели, к которым необходимо стремиться, в нашем случае их две:</p>
<ul>
<li><b>приватность</b> &#8212; сокрытие содержимого передаваемых данных от возможных злоумышленников, с целью предотвращения возможности их получения или изменения</li>
<li><b>аутентификация</b> &#8212; возможность получателя данных убедиться, что принятые им данные действительно были переданы отправителем и не претерпели в процессе никаких изменений</li>
</ul>
<p>Для реализации этих целей криптография предоставляет отправителю и получателю <i>протокол</i>, в общем случае он представляет собой совокупность программ и алгоритмов. Протокол должен предоставлять как минимум по одному алгоритму (реализованному в программе) каждому участнику процесса передачи данных, в нашем случае получателю и отправителю. Отправителю должна быть предоставлена возможность упаковать данные, предназначенные для отправки, именно таким образом, чтобы получатель с помощью своей программы мог не только распаковать данные в первоначальную форму, но и убедиться, что они были отправлены именно в таком виде.</p>
<p>Залогом уверенности в том, что передача данных безопасна, является наличие чего-либо что знает или может сделать получатель, но не знает или не может сделать. Использование этой формы <i>асимметрии</i> и является основой для большинства современных методов шифрования информации. Этот объект, обуславливающий возникновение асимметрии, принято называть словом <i>ключ</i>. Формально говоря ключ является одним из параметров шифрования, определяющим каким именно образом были преобразованы данные заранее известным алгоритмом. Основная классификация алгоритмов шифрования основывается на том, кто изначально владеет ключом, принято разделять их на алгоритмы с симметричным (т.е. секретным) и асимметричным (т.е. публичным) ключами.</p>
<h3 style="text-align: right;">Алгоритмы с симметричным ключом</h3>
<p>В самом простом случае получатель и отправитель являются владельцами одного и того же ключа, представляющего собой случайно выбранную строку, то есть последовательность бит заданной длины. С помощью этого ключа они получают возможность исключить вмешательство посторонних лиц в передачу данных <span style="font-size: smaller;">(будем считать что ключи хранятся на компьютерах отправителя и получателя, и какая-либо возможность получения их оттуда третьими лицами отсутствует).</span> Логичным было бы возникновение вопроса о том как же изначально ключ попал в их распоряжение, не попав в руки злоумышленников, но ответ на него выходит за рамки этого повествования, для нас намного важнее сам процесс использования ключа<span style="font-size: smaller;">.</span></p>
<p>Сам процесс передачи достаточно прост: с помощью первого предоставленного протоколом алгоритма и имеющегося ключа, отправитель <i>шифрует (<a href="/tag/encrypt" target="_blank">encrypt</a>)</i> сообщение, и получает на выходе зашифрованное сообщение, которое и будет отправлено получателю через ненадежный канал. Получатель же в свою очередь, применив второй алгоритм и все тот же ключ, <i>расшифровывает (<a href="/tag/decrypt" target="_blank">decrypt</a>)</i> полученное сообщение и в идеале получает исходное сообщение.</p>
<p>Приватность в этом случае достигается за счет того, что даже зная алгоритм и перехватив передаваемое сообщение восстановление исходного текста без ключа невозможно. Но в некоторых случаях даже не имея возможности точно расшифровать сообщения, злоумышленник может с некоторой ненулевой вероятностью предположить содержимое исходного сообщения, основываясь на длине передаваемого сообщения (вполне очевидно, что в большинстве случаев длина сообщения и длина исходного текста &#8212; величины зависимые). Но такая вероятность чаще всего ничтожно мала, но если злоумышленник знает что-либо о структуре исходного сообщения и о том что оно собой представляет, этот факт может позволить ему предполагать с более высоким шансом на успех.</p>
<p>Аутентификация реализуется несколько более сложным образом: для того чтобы предоставить гарантию что сообщение было передано именно отправителем, протокол предоставляет еще два алгоритма (которые правда могут совпадать) алгоритма. Помимо самого сообщения отправитель вычисляет &quot;метку&quot; &#8212; результат выполнения некой функции, аргументами которой являются ключ и исходное сообщение. Метка отправляется вместе с зашифрованным сообщением, и когда&nbsp; получатель применяет свой второй алгоритм на полученной метке и сообщении, он может точно определить обладал ли составитель этого сообщения ключом и, как следствие, не являлся ли он &quot;злоумышленником&quot;.</p>
<h3 style="text-align: right;">Алгоритмы с асимметричным ключом</h3>
<p>Главной особенностью этого класса алгоритмов является использование <b>пары</b> ключей: <i>публичного</i> и <i>секретного</i>. Их названия говорят сами за себя: публичный ключ участника передачи данных предоставляется им в свободный доступ и привязывается к его личности, а секретный так и остается известен только его владельцу.</p>
<p>Передача сообщения происходит следующим образом: отправитель получает копию публичного ключа <i>получателя</i> из какого-либо общедоступного источника, с его помощью зашифровывает по заранее известному алгоритму сообщение и отправляет получателю. Получатель же, обладая <i>секретным</i> ключом, предназначенным для расшифровывания сообщений, которые были составлены с помощью <i>его же</i> публичного ключа, получает исходное сообщение.</p>
<p>В отличии от алгоритмов с симметричным ключом получатель и отправитель могут даже быть незнакомы, но это все равно позволяет отправителю передавать сообщения получателю и быть точно уверенным, что <i>только</i> получатель сможет получить из переданного сообщения исходное, другими словами этот механизм реализует <i>приватность</i> передачи данных.</p>
<p>Передача сообщений по тому же принципу может быть организована и с помощью пары ключей отправителя, в этом случае идет речь о так называемой <b>цифровой подписи</b>. Отправитель прикрепляет к сообщению последовательность бит, которая является результатом функции от его секретного ключа и исходного сообщения, получатель же имеет возможность с помощью публичного ключа отправителя проверить действительно ли сообщение было составлено именно им и не притерпело никаких изменений в процессе передачи, что говорит о наличии <i>аутентификации</i> в этом методе.</p>
<p>В отличии от алгоритмов с симметричным ключом, цифровая подпись может быть при необходимости использована в суде как доказательство того, что сообщение было отправлено именно им, ведь возможность подделать ее отсутствует как у получателя так и у всех остальных лиц не обладающих секретным ключом (если секретный ключ был бы известен получателю, как в ситуации с симметричным ключом, то была бы возможность подделки со стороны получателя). Даже если отправитель заявит что секретный ключ был украден, этот факт расценивается как проблема отправителя и ответственности за документы подписанные этим ключом с него не снимает.</p>
<h3>В качестве заключения&#8230;</h3>
<p>&#8230;хотелось бы сказать, что каждый упомянутый подход к обеспечению безопасности передачи информации имеет свое право на существование, что легко подтверждается тем, что каждый из них нашел свое применение в жизни. Надеюсь этот теоритический обзор дал Вам возможность получить общее представление о принципах современного обеспечения безопасности передачи данных через ненадежное пространство, которым в большинстве случаев является международная сеть Интернет.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/kriptografiya/bezopasnoe-obshhenie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Unix way</title>
		<link>http://www.insight-it.ru/unix-way/unix-way/</link>
		<comments>http://www.insight-it.ru/unix-way/unix-way/#comments</comments>
		<pubDate>Sun, 06 Jan 2008 16:30:16 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Unix way]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[идеология]]></category>
		<category><![CDATA[программное обеспечение]]></category>
		<category><![CDATA[философия]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/unix-way/</guid>
		<description><![CDATA[На эту тему в Сети можно найти несметное количество статей и обсуждений, не удивлюсь если Вам уже доводилось читать что-либо подобное в прошлом или может быть работать в одной из множества операционных систем, разработанных с использованием этой идеологии. За этим словосочетанием скрывается целая философия разработки программного обеспечения, начавшая свое развитие в середине 90-х годов прошлого [...]]]></description>
			<content:encoded><![CDATA[<p>На эту тему в Сети можно найти несметное количество статей и обсуждений, не удивлюсь если Вам уже доводилось читать что-либо подобное в прошлом или может быть работать в одной из множества операционных систем, разработанных с использованием этой идеологии. За этим словосочетанием скрывается целая философия разработки программного обеспечения, начавшая свое развитие в середине 90-х годов прошлого века и воплощенная в огромном количестве операционных систем и в еще большем количестве <a href="/tag/opensource" target="_blank">opensource</a> проектов. В этом тексте я хочу поведать Вам свой взгляд на эту философию с двух точек зрения: программиста и пользователя.</p>
<p>Наиболее точно охарактеризовать то, о чем пойдет речь можно лишь процитировав одного из основателей традиций <a href="/tag/unix" target="_blank">Unix</a> и разработчика <a href="/tag/tekhnologiya" target="_blank">технологии</a> под названием &quot;Unix pipes&quot; &#8212; <a href="http://www.cs.dartmouth.edu/~doug/" target="_blank" rel="nofollow">Douglas&#8217;а Mcllroy&#8217;а</a>:</p>
<blockquote><p>&quot;This is the Unix philosophy:</p>
<dl>
<dd>Write programs that do one thing and do it well.</dd>
<dd>Write programs to work together.</dd>
<dd>Write programs to handle text streams, because that is a universal interface.&quot;</dd>
</dl>
</blockquote>
<p> <span id="more-15"></span></p>
<p>Для начала воспроизведу суть цитаты для тех читателей, кто возможно не знает в достаточной степени английского языка:</p>
<p><cite>Философия написания программ для <a href="/tag/unix" target="_blank">Unix</a> заключается в написании программ, качественно решающих строго одну задачу, но при этом тесно работающих вместе. В качестве стандартного универсального интерфейса между ними предлагается использование стандартных потоков текстовых данных.</cite></p>
<p>Сразу же позволю себе слегка отойти от темы, упомянув что существует также и абсолютно противоположный подход к написанию программного обеспечения, который стоит упомянуть для того, чтобы &quot;почувствовать разницу&quot;. Он используется в большинстве <abbr title="Платное программное обеспечение с закрытым кодом">проприетарных</abbr> программ и заключается в нагромождении максимального количества функционала внутри одного программного продукта, в большинстве случаев с целью получения дополнительных возможностей для построения рекламной компании и, как следствие, более выгодного ведения продаж. К сожалению, при таком подходе разработчики часто забывают о качестве ПО, о возможностях расширение, удобстве использования, возможностях модификации со стороны пользователя и многом другом, но зато в итоге получают продукт, о котором можно указать &quot;установил &#8212; и сразу что-то как-то работает&quot;, но что именно, как оно работает, и как долго еще сможет работать до тех пор пока не начнутся неполадки, и как с ними бороться в случае если они появятся &#8212; остается загадкой для  как для подавляющего большинства пользователей, так и не редко для самих разработчиков тоже.</p>
<p>Закончив лирическое отступление, хочется взглянуть на нашу философию с точки зрения программиста.</p>
<h3 style="text-align: right;">Взгляд с точки зрения программиста</h3>
<p>Философия <a href="/tag/unix" target="_blank">Unix</a> предлагает программисту набор элементарных правил, соблюдение которых не только упростит работу программиста, но и позволит расширить сферу применения получившегося программного продукта с помощью различных вариантов интеграции с другими программами.</p>
<p>Как же это выглядит?</p>
<h4>Одна задача &#8212; одна программа</h4>
<p>С помощью этого правила список действий, требуемых от программиста для написания готовой программы, резко сокращается до двух позиций, одной из которых является собственно реализация задачи. Задачи эти чаще всего элементарны до безобразия и заключается в переработки входных данных, например: вывод содержимого указанного каталога, подсчет длины указанного файла, фильтрация входных данных, отправка локального электронного письма на удаленный сервер (да-да, для приема, сортировки, хранения, чтения, редактирования и отправки электронных писем могут использоваться отдельные программы).</p>
<p>Подобное множество программ решающих элементарные задачи делает количество способов решения какой-либо комплексной задачи стремящимся к бесконечности, ведь при наличии стандартизованного интерфейса комбинировать программы можно в любой последовательности. Для расширения возможностей такого рода комбинирования используются различные скриптовые языке, которых существует достаточно много, наиболее распространенным из которых являются bash скрипты, основанные на командах одноименной оболочки командной строки, используемой по-умолчанию во всех (хотя возможно стоило не использовать громких слов и написать &quot;в большинстве&quot;) дистрибутивах <a href="/tag/linux" target="_blank">Linux</a>.</p>
<h4>Unix pipes</h4>
<p>Этот механизм является основным способом реализации столько раз упоминавшегося выше интерфейса между элементарными программами.  Реализация его поддержки является как раз второй задачей, которая ставится перед программистом, идущим по пути <a href="/tag/unix" target="_blank">Unix</a>. С использованием большинства языков программирования она является тривиальной, особенно это справедливо для C.</p>
<p>На подробностях реализации останавливаться не будем, по этому позволю себе плавно перейти к следующему разделу и продолжить эту тему уже там.</p>
<h3 style="text-align: right;">Взгляд с точки зрения пользователя</h3>
<p>Слово pipes можно переводить по-разному, мне больше нравится вариант <em>потоки</em>,  но также часто используется и дословный перевод &#8212; <em>трубы</em>. Также имеет смысл сразу сказать, что его реализация полностью основывается на командной строке и командах различных ее оболочек, а также тесно интегрирована с устройствами компьютера и файловой системой.</p>
<p>У каждой элементарной программы, соответствующей этой идеологии, должен быть входной и выходной стандартные текстовые потоки &#8212; stdin и stdout соответственно. Механизм unix pipes позволяет перенаправлять эти потоки любой программы произвольным образом с помощью трех простых операторов: |, &gt; и &lt;. Первый из них &#8212; | перенаправляет stdout команды слева от него в stdin команды справа, а &gt; и &lt; предназначены для перенаправление потоков в/из файлы по схожему принципу.</p>
<p>Предлагаю рассмотреть  этот механизм на примерах. Возьмем несколько базовых утилит, имеющихся на практически любой unix-like системе:</p>
<ul>
<li><em>cat</em> &#8212; вывод содержимого указанного первым параметром файла в stdout (по умолчанию stdout в большинстве программ направляется  в консоль)</li>
<li><em>less</em> &#8212; постраничный вывод текста, полученного в stdin в stdout (переключение страниц и некоторые другие функции производятся с клавиатуры, возможны и другие варианты использования, но они нам не нужны)</li>
<li><em>grep</em> &#8212; построчная фильтрация текста, полученного в stdin, вывод только строк, содержащих текст, указанный первым аргументом, и вывод результата в stdout.</li>
</ul>
<p>Начнем с примера, позволяющего прочитать постранично любой файл:</p>
<pre lang="bash">
cat readme.txt | less</pre>
<p>Не смотря на наличие более простых методов достижения той же цели, этот пример наглядно демонстрирует процесс перенаправления ввода-вывода, другими словами с помощью оператора | была создана так называемая pipe, которая и дала название этому механизму. Пример, демонстрирующий перенаправление в файл будет столь же элементарным, хотя может быть с первого взгляда покажется &quot;пострашнее&quot;:</p>
<pre lang="bash">
cat readme.txt | grep unix > readme.txt
</pre>
<p>Этот пример должен был бы удалить из файла все строки, где нет слова &quot;unix&quot;. <em>Маленькое замечание:</em> при использовании такого перенаправления, перед началом передачи данных файл обнуляется. В этом и заключается ошибка данного примера: файл очищается до того, как поток данных успел пройти через фильтрацию <strong>grep</strong>, что приводит к просто очистке файла. Если же Вам все же нужен отфильтрованный список строк &#8212; стоит разместить в другом файле (которым можно было бы подменить исходный при необходимости), просто поменяв его название:</p>
<pre lang="bash">
cat readme.txt | grep unix > meread.txt
</pre>
<p>Если же Вы хотите избежать очищения файла, в который производится запись, необходимо написать символ &gt; дважды, тогда новые данные припишутся в конец:</p>
<pre lang="bash">
cat readme.txt | grep unix >> readme.txt</pre>
<p>В unix-like системах есть еще одна интересная особенность, косвенно связанная с этим механизмом: <em>все устройства являются файлами</em> и соответственно, прикреплены к файловой системе, для них выделена отдельная директория, по традиции называемая /dev. Работа с ними также ведется на тех же правах что и с обычными файлами, например набрав в консоли:</p>
<pre lang="bash">
cat readme.txt > /dev/dsp</pre>
<p>в ответ от компьютера Вы услышите некоторый звук, издаваемый из колонок или наушников.</p>
<h4>Подводим итоги</h4>
<p>С точки зрения простого пользователя использование opensource решений, построенных на базе философии unix, является как минимум нетривиальной задачей &#8212; ведь от него требуется как минимум понимание насколько мощная и гибкая система попала ему/ей в руки.  Отсутствие единственного верного способа решения той или иной задачи ставит большинство людей попросту в тупик, у них начинают разбегаться глаза от десятков тысяч программ, доступа к которым есть у всех пользователей unix-like операционных систем, с помощью набора простой волшебной команды в консоли, состоящей не более чем из трех-четырех слов.</p>
<p>Но если пользователь находит в себе силы понять что за зверь попал ему в руки, он сможет превратить любой компьютер в универсальное устройство по решению любых задач именно тем способом, который удобен <em>пользователю</em>, а не который навязали ему <em>производители</em> <abbr title="Платное программное обеспечение с закрытым кодом">проприетарного</abbr> програмного обеспечения.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/unix-way/unix-way/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Три основных компонента парадигмы объектно-ориентированного программирования</title>
		<link>http://www.insight-it.ru/programmirovanie/java/tri-osnovnyx-komponenta-paradigmy-obektno-orientirovannogo-programmirovaniya/</link>
		<comments>http://www.insight-it.ru/programmirovanie/java/tri-osnovnyx-komponenta-paradigmy-obektno-orientirovannogo-programmirovaniya/#comments</comments>
		<pubDate>Sat, 05 Jan 2008 19:28:51 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<category><![CDATA[Java]]></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>
		<category><![CDATA[программное обеспечение]]></category>

		<guid isPermaLink="false">http://www.insight-it.ru/programming/tri-osnovnyx-komponenta-paradigmy-obektno-orientirovannogo-programmirovaniya/</guid>
		<description><![CDATA[Представьте: Россия, солнце только-только начинает свой путь по бескрайним просторам неба, Вы находитесь на одной из самых оживленных улиц своего города и вокруг Вас нетрудно заметить множество людей, спешащих по своим делам. И вот, Вы видите как один человек зашел в большое офисное здание. Вы спросите у меня: как это все может быть связано с [...]]]></description>
			<content:encoded><![CDATA[<p>Представьте: Россия,  солнце только-только начинает свой путь по бескрайним просторам неба, Вы находитесь на одной из самых оживленных улиц своего города и вокруг Вас нетрудно заметить множество людей, спешащих по своим делам. И вот, Вы видите как один человек зашел в большое офисное здание.</p>
<p>Вы спросите у меня: как это все может быть связано с темой этой записи? &#8212; об этом я и собираюсь Вам поведать.</p>
<p><span id="more-12"></span><br />
<hr width="100%" size="2" />
<font size="1" face="courier new,courier">Перед тем как продолжить чтение этой записи, очень рекомендую сначала ознакомиться с <a href="/programming/obektno-orientirovannoe-programmirovanie-a-chto-zhe-eto">введением в объектно-ориентированное програмирование</a>, если Вы еще не успели этого сделать.</font><br />
<hr width="100%" size="2" />
<img style="float: right;" src="/wp-content/uploads/cubes.png" alt="" /></p>
<p>Человек, которого Вы, надеюсь, успешно представили в процессе прочтения вступления к этой записи, будет служить нам примером в процессе обсуждения трех базовых вещей, на которых основывается вся концепция <strong>ООП</strong>, которые имеет сразу обозначить прямо сейчас:</p>
<ul>
<li>наследование</li>
<li>инкапсуляция</li>
<li>полиморфизм</li>
</ul>
<p>Все они являются равнозначными и перечислены они просто в порядке их упоминания в этом посте. Но прежде чем перейти к их рассмотрению по отдельности было бы не лишним несколько конкретизировать пример, упомянутый чуть выше. Основной акцент в этой записи делается на теорию, но для упрощения понимания я буду стараться приводить элементарные примеры реализации на языке <em>Java</em> (выбранный как наиболее характерный представитель языков программирования, приспособленных для ООП), которые правда будут лишь иллюстрировать повествование, но не будут нести за собой никакой практической пользы.</p>
<p align="justify">Для начала можно рассматривать этого человека просто &quot;со стороны&quot;: с этой точки зрения можно определить его рост, возраст, пол, цвет волос и глаз, и возможно какие-либо внешние признаки. Помимо этого можно предположить, что он обладает элементарными навыками, которые он успел продемонстрировать, проходя мимо Вас: он умеет ходить и еще, видимо, работать, правда не ясно кем.</p>
<p align="justify">Теперь посмотрим на него, как на объект, который необходимо смоделировать внутри программы. Внешние данные, перечисленные в предыдущем абзаце, станут <em>состоянием</em>, которое необходимо будет описать примерно следующим образом в описании класса, экземпляром которого и будет впоследствии являться наш человек:</p>
<pre lang="Java">
class Human
{
   public int height; // рост
   public int age; // возраст
   public String gender; // пол
   public String eyesColor; // цвет глаз
   public String hairColor; // цвет волос
}</pre>
<p align="justify">Помимо этого мы говорили о его навыках, которые тоже необходимо здесь же упомянуть, для простоты не будем ничего сложного придумывать в плане реализации:</p>
<pre lang="Java">
class Human
{
   public int height; // рост
   public int age; // возраст
   public String gender; // пол
   public String eyesColor; // цвет глаз
   public String hairColor; // цвет волос
   public void walk()
   {
      System.out.println(&quot;Я иду!&quot;);
   }
   public void work()
   {
      System.out.println(&quot;Я работаю в большом офисном здании&quot;);
   }
}</pre>
<p align="justify">Пожалуй этого будет достаточно для перехода собственно к обсуждению первого из трех компонентов парадигмы.</p>
<h3>Наследование</h3>
<p align="justify">В отличии от реальной жизни, в рамках данной концепции наследование относится не к материальным вещам, а к  переменным и методам класса. Тот класс, который передает &quot;наследство&quot;, принято называть <strong>базовым</strong>, а получателя &quot;наследства&quot;, соответственно &#8212; <strong>наследующим</strong>. Наследующий класс в дополнение к собственным методам и переменным получает еще и полный доступ ко всем переменным и методам базового класса (за некоторым исключением, о котором пойдет речь при разговоре об инкапсуляции, но обо всем по порядку).</p>
<p align="justify">Для иллюстрации этого механизма предлагаю предположить кем же мог работать наш человек. Для примера возьмем три варианта: менеджер, программист и директор. Менеджер будет уметь командовать подчиненными, программист писать код, а директор &#8212; ничего не делать. но не будем забывать, что человек, обладающий каждой из этих трех профессий, все же остается просто человеком и может выполнять все стандартные действия, которые мог бы выполнять обычный безработный, и обладать теми же признаками.</p>
<p align="justify">Конечно же можно было бы написать для каждой из профессии класс, просто добавив по одному методу, это выглядело бы примерно так:</p>
<pre lang="Java">
class Director
{
   public int height; // рост
   public int age; // возраст
   public String gender; // пол
   public String eyesColor; // цвет глаз
   public String hairColor; // цвет глаз
   public void walk()
   {
      System.out.println(&quot;Я иду!&quot;);
   }
   public void work()
   {
      System.out.println(&quot;Я работаю в большом офисном здании&quot;);
   }
   public void idle()
   {
      System.out.println(&quot;Я ничего не делаю!&quot;);
   }
}</pre>
<p align="justify">Но такой подход годится только для людей даже краем уха не слышавших об ООП, ведь он далеко не самый эффективный, особенно с точки зрения затрачиваемого на написание кода времени. Воспользовавшись механизмом наследования, можно сократить как объем кода, так и время, затраченное на его написание. В используемом для примеров языке программирования Java, для этого достаточно лишь указать в заголовке наследующего класса ключевое слово <em>extends</em> и название базового класса. Аналогичный предыдущему класс с использованием этого механизма существенно упрощается:</p>
<pre lang="Java">
class Director extends Human
{
   public void idle()
   {
      System.out.println(&quot;Я ничего не делаю!&quot;);
   }
}</pre>
<p align="justify">Как не трудно заметить объем кода существенно сократился, но это далеко не единственное преимущество. Помимо этого, например, если появится необходимость произвести изменения во всех профессиях &#8212; нужно будет произвести их один раз в базовом классе, а не три раза, как было бы в случае не использования наследования. А в некоторых случаях базовый класс может быть уже написан разработчиками языка программирования и для того чтобы им воспользоваться останется лишь написать пару волшебных слов.</p>
<h3>Полиморфизм</h3>
<p align="justify">Это слово пришло к нам из греческого языка, понимания этого термина легко достичь, просто переведя его на русский язык: <span lang="grc" style="font-family: palatino linotype,new athena unicode,athena,gentium,code2000,serif; font-size: 110%;" xml:lang="grc">&pi;&omicron;&lambda;ύ&mu;&omicron;&rho;&phi;&omicron;&sigmaf;</span> &#8212; многоформенность. То есть в наиболее простом случае подразумевается использование одной и той же переменной (или массива) для хранения информации об объектах, описываемых разными классами. Представим, что нам необходим стандартизованный способ узнать кем же работает тот или иной человек, естественно для этого необходимо описание соответствующего метода для выполнения этой функции в каждом классе, причем он должен одинаково называться в каждом из них. Для реализации этого примера на языке Java нет необходимости использовать дополнительных ключевых слов (в отличие от, например, C#, где необходимо использование слова virtual в заголовке метода в базовом классе и override &#8212; в производных). Продолжая приводить примеры на Java имеем три производных класса (для упрощения опустим дополнительные методы, которые могли бы присутствовать):</p>
<pre lang="Java">
class Director extends Human
{
   public void work()
   {
      System.out.println(&quot;Я работаю директором!&quot;);
   }
}</pre>
<pre lang="Java">
class Programmer extends Human
{
   public void work()
   {
      System.out.println(&quot;Я работаю программистом!&quot;);
   }
}</pre>
<pre lang="Java">
class Manager extends Human
{
   public void work()
   {
      System.out.println(&quot;Я работаю менеджером!&quot;);
   }
}</pre>
<p align="justify">Для того, чтобы воспользоваться механизмом полиморфизма достаточно лишь написать функцию, которая будет создавать экземпляры наших классов и &quot;спрашивать&quot; к них кем они работают, выглядит это ничуть не сложнее, чем и описания классов, хочу лишь обратить Ваще внимание на то, что полиморфная переменная должна иметь тип базового класса:</p>
<pre lang="Java">
class AskHuman
{
   public static void main(String[] args)
   {
      public Human person;
      person = new Director();
      person.work();
      person = new Manager();
      person.work();
      person = new Programmer();
      person.work();
}</pre>
<p align="justify">В ответ на выполнение этого мы метода мы получим каждую фразу из всех четырех классов, то есть не смотря на то, что у переменной заявлен тип базового класса, будут вызываться методы производных:</p>
<p><code> Я работаю директором! Я работаю менеджером! Я работаю программистом! </code></p>
<p align="justify">Этот механизм расширяет возможности использования классов, позволяя более гибко использовать переменные и методы (да, этот механизм справедлив и для методов), а также позволяет писать более абстрактные программы и существенно упрощает работу программ, имеющих модульную структуру.</p>
<p align="justify">Также имеет смысл упомянуть, что в некоторых языках программирования существует такое понятие как <strong>интерфейс</strong>, предназначенное именно для стандартизации механизма полиморфизма. Смысл интерфейса состоит в том, что он предоставляет классу список методов, которые класс <em>обязан</em> реализовать (ключевое слово в Java &#8212; <strong>implements</strong>), при этом сам интерфейс не содержит какой-либо реализации и может быть только определен. Выглядит примерно следующим образом:</p>
<pre lang="Java">
interface Worker
{
   public void work();
}</pre>
<pre></pre>
<pre lang="Java">
class Director extends Human implements Worker
{
   public void work()
   {
      System.out.println(&quot;Я работаю директором!&quot;);
   }
}</pre>
<pre lang="Java">
class Programmer extends Human implements Worker
{
   public void work()
   {
      System.out.println(&quot;Я работаю программистом!&quot;);
   }
}</pre>
<pre lang="Java">
class Manager extends Human implements Worker
{
   public void work()
   {
      System.out.println(&quot;Я работаю менеджером!&quot;);
   }
}</pre>
<p align="justify">В этом случае производные классы будут <em>обязаны</em> иметь метод work, что даст гарантию классу AskHuman, что он не вызовет несуществующий метод.</p>
<h3>Инкапсуляция</h3>
<p align="justify">Наверняка Вы уже задавались вопросом о том, что же значит слово <strong>public</strong> во всех предыдущих примерах. Это ключевое слово является частью реализации механизма инкапсуляции в языке Java, суть его состоит в том, чтобы дать возможность определить <em>область видимости</em> для составных частей класса, это очень актуально при написании ПО, использующего библиотеки, plug-in&#8217;ы или при написании программы группой людей. Ведь если Ваш класс подразумевает какие-либо ограничения для переменных или методов (например &#8212; возраст не может быть отрицательным), то их легко обойти воспользовавшись прямым доступом к ним из-за пределов класса или просто выполнив наследование.</p>
<p align="justify">Для предотвращения этого используется система параметров, назначаемых переменным и методам внутри класса для присвоения им &quot;уровней доступа&quot; (на примере опять же Java, но в большинстве известных мне высокоуровневых языков используется та же система):</p>
<ul>
<li><strong>public</strong> &#8212; назначается по-умолчанию &#8212; полностью свободный доступ</li>
<li><strong>private</strong> &#8212; доступ предоставляется <em>только</em> другим компонентам класса</li>
<li><strong>protected</strong> &#8212; доступ предоставляется остальным компонентам класса, а также всем <em>наследникам</em> данного класса</li>
</ul>
<p align="justify">Данный механизм является незаменимым помощником разработчиков любых более-менее крупных проектов, следующих принципам ООП.</p>
<h4>Вместо заключения</h4>
<p align="justify">Казалось бы бестолковая история про человека, идущего на работу, позволила Вам получить базовое представление об основах объектно-ориентированного программирования. Надеюсь у меня не раз еще найдется повод вернуться к обсуждению этой парадигмы. А на последок, хотелось бы Вас попросить, если вам понравилась эта статья, <a href="http://technorati.com/faves?sub=addfavbtn&amp;add=http://www.insight-it.ru">добавить этот блог в Ваши закладки сервиса Tehnorati</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/java/tri-osnovnyx-komponenta-paradigmy-obektno-orientirovannogo-programmirovaniya/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Объектно-ориентированное программирование: а что же это?</title>
		<link>http://www.insight-it.ru/programmirovanie/obektno-orientirovannoe-programmirovanie-a-chto-zhe-eto/</link>
		<comments>http://www.insight-it.ru/programmirovanie/obektno-orientirovannoe-programmirovanie-a-chto-zhe-eto/#comments</comments>
		<pubDate>Fri, 04 Jan 2008 18:39:53 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<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/obektno-orientirovannoe-programmirovanie-a-chto-zhe-eto/</guid>
		<description><![CDATA[Находишься в поисках способов облегчить свой труд в процессе написания программного обеспечения? &#8212; об одном из них мы сегодня и поговорим. Сама концепция этого подхода к программированию достаточно проста для понимания, и заключается она в&#8230; &#8230;совокупности достаточно большого количества факторов, о которых и пойдет речь ниже (надеюсь Вы не ожидали увидеть пост, состоящий из двух [...]]]></description>
			<content:encoded><![CDATA[<p>Находишься в поисках способов облегчить свой труд в процессе написания программного обеспечения?  &#8212; об одном из них мы сегодня и поговорим.</p>
<p>Сама концепция <a href="/tag/oop" target="_blank">этого подхода</a> к программированию достаточно проста для понимания, и заключается она в&#8230;</p>
<p><span id="more-7"></span></p>
<p>&#8230;совокупности достаточно большого количества факторов, о которых и пойдет речь ниже (надеюсь Вы не ожидали увидеть пост, состоящий из двух предложений).</p>
<p> Хочется верить, что Вам уже доводилось иметь хоть какой-либо опыт в программировании, иначе я не могу гарантировать что значения всех слов, которыми я буду оперировать в процессе написания, будет для Вас очевидным.</p>
<p>Для начала напомню тот факт, что в языках высокого уровня простейшими элементами, доступными программисту, являются:</p>
<ul>
<li><em>переменная</em> и <em>константа</em> &#8212; указатель на ячейку памяти заранее определенной длинны, содержащую какие-либо данные. Различие в том, что константа обычно заранее определена, а содержимое переменных вычисляется в процессе работы программы.</li>
<li><em>функция, процедура и оператор</em> &#8212; по сути представляют собой логически обособленную часть программы. Точную границу между этими тремя терминами провести сложно, да и не важна она, могу лишь упомянуть, что процедуры не возвращают значения и, как следствие,не могут использоваться внутри выражений.</li>
</ul>
<p>Ни для кого не секрет, что набор ноликов и единичек, содержащийся в переменной, должен каким-то образом интерпретироваться программой. Способы интерпретации данных программой принято называть <strong>тип данных</strong>. Помимо базовых типов, которые можно найти в практически любом языке программирования высокого уровня (в основном числовые и символьные данные разных видов), большинство из них позволяют программистам определять собственные типы данных, которые<br />
могут представлять собой практически что угодно, но на одной категории определяемых программистом типов данных стоит остановиться по-подробнее:</p>
<h3>Класс</h3>
<p>У многих из вас это слово наверняка вызывает множество ассоциаций, связанных как минимум со школой, и возможно с какими-либо науками, ведь это слово имеет достаточно много значений.</p>
<p>Если же по смотреть на слово класс с точки зрения программирования, то он представляет собой тип данных, состоящий из совокупности переменных, констант, и функций (которые принято называть <em>методами</em>). Все вместе они служат общей цели &#8212; смоделировать возможное поведение некоторого <strong>объекта</strong>. Не сомневаюсь, что у большинства из вас возник вопрос: что же имеется в виду под этим словом в программировании?</p>
<h3 align="right">Объект</h3>
<p>Для простоты понимания это слово можно воспринимать буквально &#8212; как некую сущность, находящуюся в каком-либо состоянии и имеющую возможность совершать некий набор действий. Также как и реальные объекты, объекты &#171;компьютерные&#187; живут своей <em>жизнью</em>: рождением считается создание объекта (выделение памяти), а смертью &#8212; уничтожение (освобождение памяти). Промежуток между этими двумя событиями принято называть <em>временем жизни</em> объекта.</p>
<p>Если же есть желание взглянуть на объект с технической точки зрения, то он представляет собой экземпляр какого-либо класса, то есть как раз указатель на область оперативной памяти, данные по которому подчиняются &#171;правилам&#187;, установленными в соответствующем классе. То есть для него могут выполняться заранее определенные функции, что будет приводить к определенным изменениям в его состоянии (то есть совокупности переменных).</p>
<p>Все написанное выше можно считать лишь неким подобием введения в ООП, дающим поверхностное  представление о том, что же понимают под этой странновато звучащей фразой, и на какие же &#171;<a href="/tag/obekt" target="_blank">&#171;объекты&#187;</a> нужно &#171;ориентироваться&#187;. Сама же теория является намного более обширной, и я собираюсь еще не раз вернуться к ее обсуждению в теории и с более практической точки. Например, возможно для многих остался не ясным вопрос: какие же преимущества предоставляет использование ООП перед более традиционным функциональным программированием? Ответить на него я и собираюсь в одном из следующих постов, не пропустить публикацию которого можно с помощью <a href="/feed">RSS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/obektno-orientirovannoe-programmirovanie-a-chto-zhe-eto/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Пара простых способов повысить эффективность написания кода</title>
		<link>http://www.insight-it.ru/programmirovanie/para-prostyx-sposobov-povysit-effektivnost-napisaniya-koda/</link>
		<comments>http://www.insight-it.ru/programmirovanie/para-prostyx-sposobov-povysit-effektivnost-napisaniya-koda/#comments</comments>
		<pubDate>Thu, 03 Jan 2008 17:52:05 +0000</pubDate>
		<dc:creator>Иван Блинков</dc:creator>
				<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/paru-prostyx-sposobov-povysit-effektivnost-napisaniya-koda/</guid>
		<description><![CDATA[Начнем, пожалуй, издалека: если рассматривать процесс программирования чуть более глобально, чем просто как дальний синоним слова coding, то нетрудно прийти к выводу, что реализация хоть сколько-нибудь большого проекта невозможна просто с помощью следования банальному алгоритму: сесть за компьютер, бросить взгляд на ТЗ, открыть любимый текстовый редактор, взять в зубы клавиатуру и написать. Если говорить о [...]]]></description>
			<content:encoded><![CDATA[<p>Начнем, пожалуй, издалека: если рассматривать процесс программирования чуть более глобально, чем просто как дальний синоним слова <em><a href="/tag/koding" target="_blank">coding</a></em>, то  нетрудно прийти к выводу, что реализация хоть сколько-нибудь большого проекта невозможна просто с помощью следования банальному алгоритму: сесть за компьютер, бросить взгляд на ТЗ, открыть любимый текстовый редактор, взять в зубы клавиатуру и написать. Если говорить о проектах уровня &quot;Hello, world!&quot; такой алгоритм вполне пригоден для реального использования, но как только речь заходит о чем-либо более серьезном и полномасштабным, такой подход сразу начинает порождать несметное количество проблем.</p>
<p><span id="more-5"></span></p>
<p>Основными причинами этого явления я бы назвал ограниченность ресурсов одного человека и отсутствие какой-либо стандартизации. Количество строк кода, которые кодер в состоянии писать в единицу времени ограниченно не только скоростью набора символов на клавиатуре, но и аналитическими способностями: начиная с какого-то момента человек тупо начинает забывать где у него находилась, например, та или иная функция или что значит та или иная переменная / константа.</p>
<p>Временным спасением от подобного рода проблем может послужить привычка грамотно оформлять код:</p>
<ul>
<li>Размещение строго по одному выражению на строке в комбинации с поддающимся хоть какой-либо логике расставления отступов в начале строки позволяет избежать потерянных выражений и четко понимать: а где же заканчивает вон то-о-от цикл?</li>
<li>Осмысленные названия переменных резко сокращают время, необходимое для осознавания ответа на вопрос &quot;а что же она значила?&quot; Мне доводилось не раз сталкивался с кодом, написанным с использованием в качестве абсолютно всех переменных разнообразных букв латинского алфавита &#8212; мало того что изменить их на что-либо другое как автозаменой, так и RegExp&#8217;ами проблематично, так и на разобраться что к чему ушло очень продолжительный период времени. Существует большое количество более адекватных способов названия переменных и функций, перечислять их все смысла не вижу, по-этому кратенько расскажу о том, которым предпочитаю пользоваться сам: алгоритм прост как три копейки &#8212; название соответствует переведенному на английский смыслу (переменную, содержащую чье-либо имя называем name), в случае если слов требуется более одного слова &#8212; пишем их слитно, начиная все кроме первого с заглавной буквы (например: veryLongName), и по старинной традиции делаем исключение для индексов циклов, которые называем буквами латинского алфавита начиная с <em>i</em> и далее по списку. Вот собственно говоря банальный способ, позволяющий в очень сжатые сроки вспомнить как называлась переменная, содержащее имя <img src='http://www.insight-it.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li>Подавляющее большинство языков программирования поддерживает <em>разбавление </em>кода комментариями, что существенно упрощает ориентирование в <em>объемистых </em>листингах как самим автором, так и всеми остальными персонами, которым по тем или иным причинам доведется в последствии читать <em>произведение. </em>Особенно этот способ актуален для низкоуровневых языков программирования, так как с первого взгляда на код даже его автору порой проблематично определить его значение.</li>
</ul>
<p>Все вышесказанное хоть и упрощает процесс программирования (хотя в этом предложении более подходящим является слово <em><a href="/tag/koding" target="_blank">кодинг</a></em>), но не позволяет избежать большей части потенциальных проблем, связанных с крупномасштабными проектами. Существует множество способов борьбы с издержками от масштаба проекта, такие как компонентно-ориентированное и объектно-ориентированное программирование, различные формы анализа и проектирования.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.insight-it.ru/programmirovanie/para-prostyx-sposobov-povysit-effektivnost-napisaniya-koda/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

