<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">

<channel>
	<title>Дмитрий Нестерук</title>
	
	<link>http://nesteruk.wordpress.com</link>
	<description>Блог о программировании — C#, F#, C++, архитектура, и многое другое</description>
	<lastBuildDate>Mon, 28 May 2012 09:47:56 +0000</lastBuildDate>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain="nesteruk.wordpress.com" port="80" path="/?rsscloud=notify" registerProcedure="" protocol="http-post" />
<image>
		<url>http://0.gravatar.com/blavatar/46e0cad6558c5915dd7536a1281e4978?s=96&amp;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Дмитрий Нестерук</title>
		<link>http://nesteruk.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://nesteruk.wordpress.com/osd.xml" title="Дмитрий Нестерук" />
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/dnesteruk" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="dnesteruk" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://nesteruk.wordpress.com/?pushpress=hub" /><item>
		<title>Методы борьбы со сложностью</title>
		<link>http://nesteruk.wordpress.com/2012/05/24/%d0%bc%d0%b5%d1%82%d0%be%d0%b4%d1%8b-%d0%b1%d0%be%d1%80%d1%8c%d0%b1%d1%8b-%d1%81%d0%be-%d1%81%d0%bb%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d1%8c%d1%8e/</link>
		<comments>http://nesteruk.wordpress.com/2012/05/24/%d0%bc%d0%b5%d1%82%d0%be%d0%b4%d1%8b-%d0%b1%d0%be%d1%80%d1%8c%d0%b1%d1%8b-%d1%81%d0%be-%d1%81%d0%bb%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d1%8c%d1%8e/#comments</comments>
		<pubDate>Thu, 24 May 2012 15:55:45 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=980</guid>
		<description><![CDATA[У разработчиков &#8211; и это включает меня &#8211; полным полно отмазок на тему того, почему та или иная задача не сделана. Обычно виной тому служит компилятор, библиотека, IDE или внешние факторы вроде выход Diablo 3. На самом же деле, самая существенная, значимая, серьезная и в то же время неизученная причина, по которой мы «тормозим»&#160;&#8211; это [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=980&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>У разработчиков &ndash; и это включает меня &ndash; полным полно отмазок на тему того, почему та или иная задача не сделана. Обычно виной тому служит компилятор, библиотека, IDE или внешние факторы вроде выход Diablo 3. На самом же деле, самая существенная, значимая, серьезная и в то же время неизученная причина, по которой мы «тормозим»&nbsp;&ndash; это отсутствие вменяемого механизма для борьбы со сложностью.</p>
<p>В каком-то смысле, наша неспособность понимать и управлять витиеватыми конструктами мышления является ненавистной самой природе, которая позволяет функционировать структурам, намного превышающим по сложности какую-то там ERP-систему или сайт, который мы пишем. Наши собственные тела, обусловленные через ДНК, являются хорошим тому примером.</p>
<p>Конечно, проводить полноценные аналогии между конструкцией программного обеспечения и конструкций вроде разумных биологических существ столь же корректно, как пытаться сравнивать архитектуру ПО с архитектурой строительной. С таким подходом, можно смело редуцировать все к антропоцентризму и тем самым утверждать, что борьба со сложностью является борьбой с эго, коллективным подсознательным, или каким-нибудь еще Фрейдопорожденным психологическим конструктом.</p>
<p>Тем временем, на планете Земля, сложность реально мешает разработчикам жить и творить в полную силу. Я думаю можно смело утверждать, что конкретно языки программирования не несут сколь либо значимой вины, т.к. на сегодняшний день нам доступны различные механизмы построения собственных языков, если нам таковые нужны. Нет, я осмелюсь утверждать, что проблема сложности влияет на нас на более высоком, структурном уровне. Иначе говоря, я считаю, что причина нашей неспособности «объять необъятное» кроется в неэффективном представлении кода, вне зависимости от языка.</p>
<h3>Проблемы структуризации</h3>
<p>В .NET есть ряд весьма неприятных «канонов» в плане взаимодействия с кодом. Во-первых, у нас есть негласное правило под названием «one class per file», т.е. идея о том, что в файле может быть только один класс. Я сколько не думал, так и не мог привести вменяемых аргументов в пользу этого правила. Должен признаться, что я уже давно его не придерживаюсь, разве что для конкретных задач (например, <a href="http://devtalk.net/dotnet/dynamic-prototyping/" title="http://devtalk.net/dotnet/dynamic-prototyping/">динамического прототипирования</a>, где это критично).</p>
<p>Вторая, сопряженная, проблема заключается в том, что нынче не модно делать «композицию», т.е. вложенные классы. Опять же, мне вспоминается пример с машиной и колесами: если у вас в программе колеса есть только у машины, почему не сделать класс <code>Wheel</code> вложенным в класс <code>Car</code>? Потому что не модно. Нынче агрегирование якобы лучше чем композиция.</p>
<p>Аналогичная проблема встречается в алгоритмах, состоящих из нескольких частей. Если все эти части &ndash; внешние функции, то у нас получился не перевариваемый API. Хочется сделать функции внутренними? Пожалуйста, только вывод типов тут работать не будет. Да и то, как выглядит функция на 100 строк, где 50 из них &ndash; это какой-нибудь Action &ndash; не дает никаких особых преимуществ. Как было нечитабельно, так нечитабельно и осталось.</p>
<p>Фундаментальная проблема всего этого вовсе не в том, что мы не умеем читать код. Если бы проблема была в этом, мы бы уже все поголовно использовали идею <a href="http://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D0%BC%D0%BE%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5" title="http://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D0%BC%D0%BE%D1%82%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">грамотного программирования</a> Кнута. Проблема не в том, что код нечитабелен, а в том что мы неспособны поделить код на такие куски, которые можно было воспринимать в совокупности.</p>
<h3>Так как описать сложный алгоритм?</h3>
<p>С одной стороны, мы не можем отказаться от принципа «разделяй и властвуй», т.е. единственный шанс понять что-то сложное &ndash; разбить его на несколько кусочков, потом разбить эти кусочки, и так далее <em>ad nauseam</em>. Проблема лишь в том, как потом заставить эти 1000 кусочков не лезть нам в глаза со строк тысячестрочного файла?</p>
<p>Я предлагаю начать с простого &ndash; пересмотреть наше определение алгоритма. Мы привыкли, что алгоритм &ndash; это функция (метод). Давайте выкинем это определение в помойку. Алгоритм отныне будет классом. Если он нам вдруг понадобился, то мы инстанциируем этот класс (никакой статики, но можно положить синглтон в контейнер) и вызываем какой-то метод. Соответственно, мы уже изолировали алгоритм от той формочки или контроллера, который его использует.</p>
<p>Следующий шаг &ndash; это разбить алгоритм на отдельные классы и методы внутри этого класса, но ни в коем случае не позволять классам иметь shared state. Общее состояние &ndash; одна из причин, по которым нам не угнаться за сложностью системы. Соответственно, если наш алгоритм состоит из 2-х частей и эти части используют одни и те же данные, мы пишем что-то вроде этого:</p>
<p><pre class="brush: csharp;">
class MyAlgo
{
  MyAlgoResult Step1()
  {
    Foo foo = new Foo();
    // change foo, then
    if (foo.Baz &lt; 0) return MyAlgoResult.Fubar;
    return Step2(foo);
  }
  MyAlgoResult Step2(Foo foo)
  {
    var bar = foo.DoStuff();
    return MyAlgoResult.Ok;
  }
  enum MyAlgoResult { Ok, Fubar };
}
</pre>
<p>В качестве визуального примера этого подхода хочу показать диаграмму вызовов, сгенерированную Visual Studio. Диаграмма хоть и неидеальная, но суть подхода показывает:</p>
<p><img src="http://nesteruk.org/pix/0/51a2b28f-1d25-40e7-ad61-df85fa1cbd7e.png" alt="" style="border:0;" /></p>
<p>К сожалению, разбить алгоритм на методы &ndash; мало. Обычно нужны не только внутренние методы, но также внутренние классы. Более того, некоторые алгоритмы не делятся ровно. Например, всякие if-ы, switch-и и прочие частично ломают наш подход. Иногда их можно оставить в покое, но иногда их можно эмулировать с помощью различных ООП структур.</p>
<p>Я должен пояснить: я не предлагаю перерабатывать алгоритмы в некие аналоги Workflow Foundation. Я предлагаю лишь переписать их так, чтобы, с одной стороны, для потребителя алгоритма был один унифицированный интерфейс, но чтобы сам алгоритм являлся гибкой композиционной структурой. Это в свою очередь означает, что алгоритм может быть классом, у которого лишь один метод публичный, а остальные &ndash; приватные.</p>
<h3>Столпотворение структур</h3>
<p>У нашего подхода есть и обратная, вполне очевидная сторона: он плодит сущности. И если нам нужно в каком-то месте воспользоваться 10-ю различными сущностями, это становится проблемой &ndash; не знаю как вам, а мне не очень-то импонирует конструктор с 10 параметрами. Чтобы решить эту проблему, можно использовать т.н. «бандлы» &ndash; т.е. мы создаем класс-хранилище, который существует только для того, чтобы через конструктор инициализировать некий набор сервисов. Теперь, все что остается сделать &ndash; это инъецировать именно этот класс в нужное место и вуаля! Конечно, вложенные объекты придется вызывать через точку, что тоже не способствует экономии пространства.</p>
<p>Еще одна структура (а точнее может одна, а может у вас их несколько) &ndash; это классы для хранения методов расширения. Методы расширения нужны по ряду причин, и я уже публиковал <a href="http://nesteruk.wordpress.com/2010/03/22/extension-method-patterns/" title="http://nesteruk.wordpress.com/2010/03/22/extension-method-patterns/">пост на тему паттернов</a> которые встречаются чаще всего. Методы расширения способны существенно улучшить читаемость. Например, что проще понять &ndash; <code>Math.Round(Math.Abs(x))</code> или <code>x.AbsRound()</code>?</p>
<p>Еще одна полезная практика &ndash; это перегружать оператор индексирования <code>[]</code> для всех типов, в которых есть одна основная перечисляемая коллекция. Разница между <code>info.Points[i]</code> и <code>info[i]</code> весьма заметна, особенно если это нужно писать в 10 разных местах.</p>
<h3>Что дальше?</h3>
<p>Мне все больше и больше кажется, что использование <em>файлов</em> для хранения кода&nbsp;&ndash; это эволюционный тупик. Не существует никаких объективных причин связывать логическую и физическую структуру кода. Более того, мне кажется, что <em>вертикальность</em> файлов, т.е. тот факт, что весь код написан сверху вниз, тоже является далеко не лучшей идеей, т.к. люди имеют возможность воспринимать информацию и латерально. По вертикали, например, можно иметь основную ветку мышления, а по горизонтали&nbsp;&ndash; ответвления и зависимости.</p>
<p>Другой неразрешенной проблемой является то, что по-хорошему нужно уходить от текстового редактора к более гибкому. Меня всегда удивляло, например, почему в программировании не появилась синтаксическая нотация из математики? Ведь математики изначально и двигали эту индустрию&hellip; с перфокартами&hellip; а, ну да, ну да.</p>
<p>ОК, получился еще один «поток сознания», comments welcome!&nbsp;■</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/technology/'>Technology</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/980/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/980/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/980/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=980&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2012/05/24/%d0%bc%d0%b5%d1%82%d0%be%d0%b4%d1%8b-%d0%b1%d0%be%d1%80%d1%8c%d0%b1%d1%8b-%d1%81%d0%be-%d1%81%d0%bb%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d1%8c%d1%8e/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://nesteruk.org/pix/0/51a2b28f-1d25-40e7-ad61-df85fa1cbd7e.png" medium="image" />
	</item>
		<item>
		<title>Про книги</title>
		<link>http://nesteruk.wordpress.com/2012/05/02/on-books/</link>
		<comments>http://nesteruk.wordpress.com/2012/05/02/on-books/#comments</comments>
		<pubDate>Wed, 02 May 2012 17:52:17 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[fonts]]></category>
		<category><![CDATA[kindle]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[publishing]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=941</guid>
		<description><![CDATA[Ситуация на рынке Это мне одному кажется что по программированию как-то стало мало всего интересного выходить? Раньше помню все популярные кухни (Apress/O&#8217;Reilly/AW) штамповали достаточно интересные книги. Сейчас же, если посмотреть например на то что нового у Apress, то как-то даже ничего и читать не хочется. У меня все еще &#8220;греется&#8221; на полке их книжка по [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=941&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.bocabookbinding.com/sitebuildercontent/sitebuilderpictures/books1.gif" class="alignright" align="right" border="0" style="border:0;" /></p>
<h3>Ситуация на рынке</h3>
<p>Это мне одному кажется что по программированию как-то стало мало всего интересного выходить? Раньше помню все популярные кухни (Apress/O&#8217;Reilly/AW) штамповали достаточно интересные книги. Сейчас же, если посмотреть например на то что нового у Apress, то как-то даже ничего и читать не хочется. У меня все еще &#8220;греется&#8221; на полке их <a href="http://www.apress.com/programming/methods-and-techniques/9781430229674">книжка по TPL</a>, которая ну просто супер, с которой я в свое время слизал массу примеров. Так вот, в последнее время ничего аналогичного на рынке не появилось (или появилось, но я не заметил). Зато появилось много книг с названием &#8220;C# 2012&#8243; что есть кретинизм в высшей инстанции (ну нет такой версии языка, нету).</p>
<p>С другой стороны, периодически появляется желание написать книгу самому, но мое мнение начинает колебаться где-то между &#8220;это экономически необоснованно&#8221; и &#8220;это слишком легко&#8221;. Если экономическую необоснованность книг понимают все (даже авторы бестселлеров NY Times, оказывается, получают <a href="http://www.genreality.net/the-reality-of-a-times-bestseller">весьма скромные деньги</a>), то &#8220;слишком легко&#8221; еще нужно объяснить. Я вот вижу например сценарий в котором делается книга про Dependency Injection: берем IoC контейнер (к пр. Autofac) и линейно описываем все его возможности, начиная от самых простых и заканчивая экзотикой которая 99% пользователей никогда не понадобится. Просто, предсказуемо, но времени нужно столько что о-го-го. Сам в процессе нарабатываешь невесть-какие навыки которые самому не понадобятся. (Когда-то я написал серию блог-постов про Unity, и эффект был аналогичный.)</p>
<p>Вообще, мне кажется, что эффект книг спадающий: когда ничегошеньки не знаешь, любая книга &#8211; манна небесная. Зато когда опыту уже понабрался, то можешь что-то сам написать только в двух случаях:</p>
<ul>
<li>Очень хочется написать &#8220;что угодно&#8221; и ты начинаешь писать прописные истины. Так сейчас многие в блогах делают, фактически переписывают известные концепции в сжатой форме с некоторыми собственными наблюдениями. Я так не могу, точнее совесть не позволяет.</li>
<li>Хочется написать что-то дабы донести свой уникальный опыт и возможно даже <strong>убедить</strong> людей в своей точке зрения.</li>
</ul>
<p>Второй вариант мне определенно ближе. Я например периодически пытаюсь убеждать людей пробовать новые языки, динамическое прототипирование, realtime-программирование, создание собственных DSL-редакторов, и так далее. Результат в принципе предсказуемый: у большинства появляется просто непонимание, как если бы я начал выводить модель Блэка-Шоулза. После демонстраций, конечно, все проясняется чуть-чуть, но тогда вопрос &#8211; может стоит демонстрациями и заниматься?</p>
<h3>Читабельность, доступность, верстка</h3>
<p>Несмотря на все описаное выше, я все еще продолжаю читать массу всего на моем KDX. В связи с этим, опять же, есть масса мыслей насчет того что и как в этой сфере делается.</p>
<p>Во-первых, мне кажется разработчики всяких &#8220;читалок&#8221; окончательно забили на техническую литературу. Например, в формате MOBI (это который Kindle использует) нельзя толков верстать блоки кода. Вообще. Не говоря уже про подсветку синтаксиса и прочую муть. Я по дурости купил &#8220;The D Programming Language&#8221; в формате Киндл, и это был фейл &#8211; там код как картинки. Из доступных вариантов остаются только читалки крупного размера которые могут отражать PDF. Тогда можно купить PDF (опять же, не у всех, но паблишеры вроде Apress, слава богу, вменяемы) и попытаться прочитать на Kindle DX или аналогичном устройстве.</p>
<p>Тут тоже все непросто. Во-первых, читалка моя не A4 а все-таки поменьше, а следовательно если верстать как это делает Microsoft Press то шрифт после масштабирования получится микроскопический. Впрочем, эта же проблема влияет и на печатные издания: не знаю кто вдруг решил что человек может прочитать 200 символов в одной строке. Э-эх, MS Press.</p>
<p>Во-вторых, и это еще более существенно, некоторые издательства &#8211; например O&#8217;Reilly &#8211; верстают книги таким шрифтом который нечитабелен на электронных читалках за исключением, возможно, нового iPad&#8217;а (не знаю, не пробовал). Причина &#8211; слишком тонкий шрифт, а следовательно полное отсутствие контраста. На бумаге терпимо, на экране ну просто никак. Особенно если автор сверстал книгу в LaTeX&#8217;е и использовал дефолтный шрифт. Что кстати само по себе диагноз, т.к. у нас тут 21й век на дворе, есть <a href="http://www.lyx.org/">LyX</a> и прочие прелести, неужели читателей не жалко?</p>
<p>На самом деле интересно, я проводил исследование на тему того, как писать книжку и потом публиковать ее в разные форматы. Под разными форматами имеются в виду как минимум PDF (на самом деле есть 2 варианта &#8211; &#8220;простой&#8221; и тот который для Adobe Digital Editions), MOBI (это для Kindle), EPUB (очевидно для Nook и других систем про которые я слишком мало знаю). На самом деле, все основные вопросы появляются насчет PDF &#8211; то есть с одной стороны хочется публиковать один вариант, но с другой, начинаешь думать что:</p>
<ul>
<li>Публиковать &#8220;печатный&#8221; PDF можно только если он влезает в рамки типичной &#8220;большой&#8221; читалки вроде KDX, что накладывает порой не очень адекватные ограничения на размеры полей.</li>
<li>Использовать печатные шрифты для экрана неправильно. Да, девайсы вроде KDX или iPad 3 спокойно отрезолвят, но какой-нибудь iPad 2 например не способен качественно отображать шрифты с засечками. Следовательно, нужно использовать разные шрифты?</li>
<li>Если в книге у вас есть иллюстрации, то с большой вероятностью верстка будет привязана к размеру страницы. Что, опять же, существенно ограничивает возможность поддержки разных девайсов.</li>
</ul>
<p>Возможно, проблемы выше мною надуманы, т.к. издатели вполне успешно продают PDF-ы, пусть даже часть из них не очень корректно. Тем не менее, мне почему-то кажется что один-единственный формат PDF это &#8220;плохо для всех&#8221;.</p>
<h3>Шрифты и иллюстрации</h3>
<p>Шрифты &#8211; это наркотик. Это как автомобили или Hi-Fi системы или карточки Magic: the Gathering. Это культ, религия, предмет озабоченности. Но про шрифты говорить стоит даже если вы не культист, т.к. один и тот же текст с разным шрифтом может выглядеть читабельно и не очень. Поэтому у нас не получится их не обсуждать. Сорри.</p>
<p>Какие шрифты используются в книгах? Если кто-то из вас предложит варианты вроде Times New Roman, Arial или какой-нибудь другой предустановленный шрифт, типографические снобы косо на вас посмотрят. Если вы предложите Comic Sans, то даже я инстинктивно потянусь за ружьем. На самом же деле, насколько я понял после исследования нескольких PDF-ов, расклад примерно такой:</p>
<ul>
<li>В качестве текстового шрифта, каждый издатель использует свой собственный шрифт во всех книгах. Например, Apress использует <a href="http://www.myfonts.com/fonts/adobe/utopia/">Utopia</a>. Примечательно то, что для каждой предметной области есть свой набор шрифтов который подходит ей больше всего.</li>
<li>В качестве заголовочного шрифта используется правильный &#8220;спаренный&#8221; шрифт, то есть такой, который наиболее гармонирует с текстовым. Опять же, всякие Arial не используются, но может использоваться Helvetica (что, вообщем-то, то же самое что и Arial) или например Myriad.</li>
<li>Для верстки кода, в большинстве случаев, не используются всякие Consolas, Courier и прочие. На данный момент, самым популярным шрифтом для кода является <a href="http://www.fonthaus.com/fonts/lucasfonts/Thesis-TheSans-Mono-Condensed/LF008otW6a">TheSans Mono</a>.</li>
</ul>
<p>С другой стороны, все эти извращения хорошы только в печати: на моем киндле, все это скорее вредит. Что нужно для электронных читалок так это простой sans-serif вроде Arial Unicode. Почему именно он? Потому что большой набор символов. Я вот недавно пытался набрать <code>let 森= new List&lt;木&gt;()</code> в LyX и чуть голову себе не сломал. Не говоря уже о том, что выглядеть это все должно консистентно.</p>
<p>На самом деле, со шрифтами еще все более-менее: вы можете в крайнем случае использовать Arial для текста и какой-нибудь Consolas для кода и все должно быть хорошо. А вот с иллюстрациями совсем непонятно. В частности, непонятно их разрешение: стоит ли оставлять их как 600dpi (займет много места) или сократить т.к. все равно никто печатать с файла не будет? С одной стороны, пользователям iPad&#8217;а наверное стоит дать картинку почетче. С другой, встроенный процессор Kindle &#8211; это такая адская дурь, которая итак страницу по полсекунды рисует, а сложную картинку она еще должна будет уменьшить (наверняка с помощью кубической интерполяции, чтобы помедленнее было) прежде чем показать. Одним словом, опять нет оптимального решения. Разве что если иллюстрации векторные. Тогда проблем тоже нет, хотя опять же, если в картинке тысячи элементов, то Киндл либо будет долго думать либо вообще не отрисует.</p>
<h3>Заключение</h3>
<p>Не знаю токлом что сподвигло меня написать такой экскурс насчет книг &mdash; наверное все-таки то, что хороших книг в принципе мало, и было бы здорово если бы их было больше. С другой стороны, с учетом копеечных гонораров (а также массового пиратства), мотивации должно быть действительно мало. К тому же, не следует забывать что техническая литература &#8211; это все-таки достаточно нишевой сегмент, что только усугубляет положение.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/books/'>Books</a>, <a href='http://nesteruk.wordpress.com/category/technology/'>Technology</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/fonts-2/'>fonts</a>, <a href='http://nesteruk.wordpress.com/tag/kindle/'>kindle</a>, <a href='http://nesteruk.wordpress.com/tag/pdf-2/'>pdf</a>, <a href='http://nesteruk.wordpress.com/tag/publishing-2/'>publishing</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/941/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/941/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/941/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/941/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/941/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/941/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/941/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/941/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/941/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/941/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/941/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/941/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/941/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/941/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=941&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2012/05/02/on-books/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://www.bocabookbinding.com/sitebuildercontent/sitebuilderpictures/books1.gif" medium="image" />
	</item>
		<item>
		<title>Короткий опыт использования С++</title>
		<link>http://nesteruk.wordpress.com/2012/03/29/cpp-small-experience-report/</link>
		<comments>http://nesteruk.wordpress.com/2012/03/29/cpp-small-experience-report/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 22:01:17 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[С++]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=918</guid>
		<description><![CDATA[Хочу поделиться опытом решения задачи, для которой я вместо C# решил использовать C++. История, мне кажется, очень поучительная, т.к. хорошо иллюстрирует все казусы использования этого «древнего» языка. Сценарий В мои руки попало несколько сот гигабайт данных&#160;&#8211; если быть конкретным, по 10Гб данных за несколько месяцев. Данные поставляются в формате базы данных SQLite. Данные в основном [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=918&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Хочу поделиться опытом решения задачи, для которой я вместо C# решил использовать C++. История, мне кажется, очень поучительная, т.к. хорошо иллюстрирует все казусы использования этого «древнего» языка.</p>
<h3>Сценарий</h3>
<p>В мои руки попало несколько сот гигабайт данных&nbsp;&ndash; если быть конкретным, по 10Гб данных за несколько месяцев. Данные поставляются в формате базы данных SQLite. Данные в основном численные, но есть и некоторые нюансы:</p>
<ul>
<li>
<p>Некоторые численные значения поставлены не как число, а как строка, например <code>12345.00000</code>. Эту строку естественно надо «парсить» чтобы получить значение типа <code>double</code>.</p>
</li>
<li>
<p>Все даты в файле поставлены как строки в формате <code>1991.11.11 11:11:11.111</code>.</p>
</li>
<li>
<p>В данных много повторяющихся строковых литералов, которые можно удалить полностью.</p>
</li>
</ul>
<p>Основная проблема  с этими данными&nbsp;&ndash; их слишком много, а следовательно мне не перекинуть их на мой университетский кластер. Учитывая ужасную потерю памяти за счет кодирования всего и вся как строк, я решил что будет хорошей практикой сжать данные, удалив из них все строки.</p>
<h3>Первая попытка</h3>
<p>Первой моей попыткой было, конечно же, тупо подключить к драйверу SQLite модель на базе Entity Framework. Но из этого ничего не получилось&nbsp;&ndash; я кажется установил все драйвера которые только можно, и оно все равно не заработало.</p>
<p>Поэтому я решил написать «выдиралку» с использованием только <code>Connection/Command</code> объектов&nbsp;&ndash; это как раз тот ADO.NET подход который был популярен во времена .NET 1.1 примерно 8 лет назад.</p>
<p>Написав, я столкнулся с рядом весьма очевидных проблем, главной из которых стала производительность. Например, я понял что использование <code>BinaryFormatter</code> для сериализации структур привело к таким тормозам, что нужно было все сразу переписывать на ручную сериализацию через <code>BinaryReader/BinaryWriter</code>. Производительность увеличилась, но я понял, что если я хочу переконвертировать все данные, мне придется просто оставить компьютер работать на неделю-другую.</p>
<h3>Переход на C++</h3>
<p>В связи со всем этим, я решил что лучше написать один раз, но написать качественно и так чтобы быстро работало. Создал новый проект С++, перевел его на компилятор Intel (для тех кто не знает, я&nbsp;&ndash; ярый фанат использования Intel Parallel Studio), и начал писать. Сразу оговорюсь, что писал я с уклоном на то, что результирующие бинарные данные все равно будут использовться в .NET.</p>
<p>Первым моим шагом было найти приемлемый интерфейс для SQLite но, как ни странно, я быстро нашел <a href="http://sqlitewrapper.kompex-online.com/" title="http://sqlitewrapper.kompex-online.com/">драйвер с исходниками</a> который, будучи включенным в проект, начал работать без каких-либо особых телодвижений.</p>
<p>Второй шаг&nbsp;&ndash; это конечно подключение библиотеки Boost, которая мне потребовалась для обработки дат. И вот тут уже началось веселье. В частности, <strong>библиотека работы с датой и временем&nbsp;&mdash; апокалиптична</strong>. Неподготовленному человеку в ней не разобраться без нескольких часов читания доков. Не то что <code>System.DateTime</code>! Вот например как происходит конверсия в .NET-совместимую эпоху:</p>
<p><pre class="brush: cpp;">
static uint64_t netEpochOffset = 441481536000000000LL;
static ptime netEpoch(date(1400,1,1), time_duration(0,0,0));
static int64_t Util::TimeToTicks(ptime time)
{
  time_duration td = time - netEpoch;
  uint64_t nano = td.total_microseconds() * 10LL;
  return nano + netEpochOffset;
}
</pre>
<p>И подобная магия тут везде. Вот в .NET у нас тоже один большой <code>long</code> определяет всю дату, но <code>DateTime</code> имеет кучу методов для того чтобы получить кол-во часов, дней, и так далее. Тут все по-другому, тут дата&nbsp;&ndash; это сколько вы отсчитали от той или иной эпохи, и чтобы вычитать, например, только время из даты, придется сильно попотеть. Соответственно, для того чтобы определить определенное <em>время</em> дня мне приходилось писать вот такой код:</p>
<p><pre class="brush: cpp;">
time_duration _19_00 = time_from_string(&quot;1900/01/01 19:00:00.000&quot;).time_of_day();
</pre>
<p>Знаю что экспертам по Boost это покажется смешным, но для трезвого дот-нетчика, вся эта библиотека кажется адом. Даже Boost.Math, который я использую в другом проекте, и то порой эклектичен.</p>
<h3>Работа с коллекциями</h3>
<p>Коллекции в С++ хранятся &lsquo;by value&rsquo;, поэтому по-хорошему любой ваш список будет иметь тип <code>vector&lt;boost::shared_ptr&lt;MyObject&gt;&gt;</code> и разыменовывание надо будет делать через <code>(*itr)-&gt;DoSomething</code>, что само по себе бесит. Более того, даже работая с примитивными структурами, понимаешь что нехватает массы методов. Например, у .NETного <code>Dictionary</code> есть метод <code>ContainsKey()</code> который проверяет наличие записи с таким ключем. А что происходит с С++&lsquo;ным <code>map</code>, где такого метода нет? Вот, полюбуйтесь:</p>
<p><pre class="brush: cpp;">
boost::shared_ptr&lt;FullBarrel&gt; barrel;
auto candidate = futureBarrels.find(instrument-&gt;InstrumentID);
if (candidate != futureBarrels.end())
  barrel = candidate-&gt;second;
else {
  barrel = boost::shared_ptr&lt;FullBarrel&gt;(new FullBarrel);
  futureBarrels.insert(candidate, BarrelDictionary::value_type(instrument-&gt;InstrumentID, barrel));
}
</pre>
<p>Следующее, что убивает, это <code>const</code>-корректность&nbsp;&ndash; наивный и жалкий механизм, с помощью которого С++ пытается контролировать, какие элементы можно менять а какие нет. Выливается это в то, что например задекларированный вами <code>vector</code> внезапно нельзя менять внутри <code>for_each</code>. Понятное дело, что для «зубров» С++ эти проблемы разруливаются, да и я смог разобраться, но это еще один пример того, как устаревшая парадигма языка не привносит ничего полезного, зато добавляет массу головной боли.</p>
<h3>Сериализация</h3>
<p>Поскольку все мои данные&nbsp;&ndash; численные (в основном либо <code>double</code> либо <code>int64_t</code>), я решил использовать обычную структуру, т.е. <code>struct</code>, для хранения данных. К счастью, С++ умеет сериализовывать эту структуру в файл полностью, считывая из нее всю память:</p>
<p><pre class="brush: cpp;">
ofstream ofs(filename, ios::out | ios::binary);
ofs.write((char*)&amp;myStruct, sizeof(MyStructure));
ofs.close();
</pre>
<p>Единственный сюрприз ждал меня когда я начал читать эти данные в .NET-е. Во-первых, я не угадал сначала какой размер данных у <code>enum</code>-ов (4 байта), а во-вторых, я забыл про упаковку данных.</p>
<p>Упаковка данных (structure packing)&nbsp;&ndash; это механизм, который выравнивает структуры на границах байтов. Очень полезно для процессора, но мой .NETный <code>BinaryReader</code> естественно ничего про подобное не знает и пытается читать заглушечные данные в память переменных.</p>
<p>Решение было простое&nbsp;&ndash; добавить директиву <code>#pragma pack(1)</code> в С++ чтобы выравнивать по одному байту, т.е. не добавлять промежуточных данных вообще. Внезапно, все заработало в .NET.</p>
<h3>Оптимизации</h3>
<p>Я был поражен увеличением скорости в конечной реализации, поэтому не слишком сильно напрягался насчет профилирования. Единственное, что действительно хотелось оптимизировать&nbsp;&ndash; это механизм разбора строковых значений вроде <code>12345.000</code> и их переведения в тип <code>double</code>. Конечный результат выглядит вот так:</p>
<p><pre class="brush: cpp;">
double Util::powersOf10[] = { 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0 };
static double Util::StringToDouble(string&amp; s)
{
  auto dotPos = s.find('.');
  s.erase(s.begin() + dotPos);
  return _atoi64(s.c_str())/powersOf10[s.length() - dotPos] ;
}
</pre>
<p>В примере выше, мы просто переводим число в целое, парсим его как целое, а потом делим на степень 10-ти их заранее приготовленной таблицы.</p>
<h3>Заключение</h3>
<p>Конечный результат дал примерно 10-кратное увеличение производительности. За счет компактности С++ных <code>struct</code>ов, данные получилось ужать примерно в 100 раз. С другой стороны, производительность разработчика упала раз в 5 (а может и более). Спасает лишь то, что это единовременная проблема.</p>
<p>Мне кажется что вывод тут может быть один: нужно использовать правильный язык для правильной ситуации. Ведь анализ конечных данных я все равно буду проводить с использованием C#, т.е. работать на языке где нет LINQ&nbsp;&ndash; это как-то совсем архаично. Но многие ведь работают, не так ли?</p>
<p><strong>P.S.:</strong> для работы с данными использовался SSD &mdash; к сожалению не Revo или FusionIO, а обычный Vertex 3. Обработка велась в несколько потоков на одном физическом диске, т.е. одновременно писалось и читалось несколько файлов.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/%d1%81/'>С++</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/c-3/'>c#</a>, <a href='http://nesteruk.wordpress.com/tag/parsing/'>parsing</a>, <a href='http://nesteruk.wordpress.com/tag/sqlite/'>sqlite</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/918/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/918/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/918/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/918/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/918/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/918/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/918/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/918/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/918/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/918/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/918/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/918/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/918/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/918/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=918&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2012/03/29/cpp-small-experience-report/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Небольшой обзор Visual Studio 11 (2012) Beta</title>
		<link>http://nesteruk.wordpress.com/2012/03/04/%d0%bd%d0%b5%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be%d0%b9-%d0%be%d0%b1%d0%b7%d0%be%d1%80-visual-studio-11-2012-beta/</link>
		<comments>http://nesteruk.wordpress.com/2012/03/04/%d0%bd%d0%b5%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be%d0%b9-%d0%be%d0%b1%d0%b7%d0%be%d1%80-visual-studio-11-2012-beta/#comments</comments>
		<pubDate>Sun, 04 Mar 2012 20:38:22 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=905</guid>
		<description><![CDATA[Должен признаться, что я пишу на 11й студии (она же VS2012) уже достаточно давно, и делаю эту в силу того, что новая студия имеет неплохую обратную совместимость с 2010й: если открыть обычное решение, то 11я студия оставит .NET проекты в покое, а С++ проекты предложить переконвертировать. От этой конверсии можно отказаться, и все равно все [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=905&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Должен признаться, что я пишу на 11й студии (она же VS2012) уже достаточно давно, и делаю эту в силу того, что новая студия имеет неплохую обратную совместимость с 2010й: если открыть обычное решение, то 11я студия оставит .NET проекты в покое, а С++ проекты предложить переконвертировать. От этой конверсии можно <em>отказаться</em>, и все равно все будет работать и компилироваться. Единственное, возможно придется менять использование констант вроде <code>MSC_VER</code> или как там, для того чтобы библиотеки компилировались. Но все будет работать.</p>
<p>Этот пост&nbsp;&ndash; мои заметки о том, что новое в 2011й студии и как мне в ней работается.</p>
<h3>Поддержка WinRT&nbsp;&ndash; она есть, но не здесь</h3>
<p>Как и все, я немного ошеломлен тем, что даже в Бету Студии не попала поддержка WinRT. Microsoft в очередной раз сбила всех с толку, выпустив Visual Studio Express с поддержкой Metro-Style Apps и «полноценную» студию без такой поддержки. Наверняка на это решение повлияли сложные маркетинговые механизмы, но как бы там ни было, поддержки WinRT в основной студии пока нет.</p>
<p>Как вы понимаете поддержка WinRT&nbsp;&ndash; это основноая «фича» новой студии. Но добавлять ее в обзор VS11 пока что неуместно&nbsp;&mdash; пусть она сначала тут появится.</p>
<p><strong>Upd:</strong> как подсказал в комментариях Владимир Юнев, поддержка WinRT/Metro-Style Apps <em>присутствует</em> в VS11, но только в том случае, если вы ставите ее на Windows 8. :)</p>
<h3>Black &amp; White</h3>
<p>Новая студия, для тех кто еще не видел скриншоты&nbsp;&ndash; черно-белая. А точнее монохромная&nbsp;&ndash; в ней скорее много оттенков серого, чем чисто черный и белый цвет:</p>
<p><img src="http://nesteruk.org/pix/0/24a05efd-87ea-4ddc-95c0-e45b8f2be9c1.png" alt="" style="border:0;" /></p>
<p>В сети появилось очень много полемики насчет такого дизайнерского решения. Идея как бы понятна: берем «цветастую» студию и делаем из нее полностью нейтральный вариант. Я сам по себе фанат нейтральности: у меня нейтральный черно-белый офис, музыкальная система с самым нейтральным звучанием, а мой любимый цвет&nbsp;&ndash; белый. Но не смотря на это, работать с монохромной студией мне <em>тяжело</em>.</p>
<p>Тяжело вот почему: для меня все монохромные иконки размером 16&times;16px кажутся одинаковыми. Удалив цвет, потерялось целое «информационное измерение». Вот например раньше тип проекта (C#, F#, C++) имел свой уникальный цвет:</p>
<p><img src="http://nesteruk.org/pix/0/b499ba6c-ff63-4fed-b90d-4fee13cc8474.png" alt="" style="border:0;" /></p>
<p>Проекты можно было различить по этому цвету, в голове возникала некая «условная классификация», да и при написании собственных программ тоже было понятно, какие иконки использовать. А что теперь? Почему, например, проект C# имеет на своей прямоугольной, абсолютно невзрачной иконке просто надпись C# в то время как проект С++ имеет на своей иконке&nbsp;&ndash; внимание&nbsp;&ndash; стрелки вверх-вниз? Вся логика подобного куда-то ушла, и с ней ушло удобство.</p>
<h3>Solution Explorer</h3>
<p>Единственное новшество solution explorer&rsquo;а, которое я вижу&nbsp;&ndash; это возможность раскрывать структуру файлов чтобы смотреть что у них внутри. Работает это даже для С++ проектов:</p>
<p><img src="http://nesteruk.org/pix/0/45b3d90d-096c-404f-bf4e-b94688303666.png" alt="" style="border:0;" /></p>
<p>Что ж, похвально, только польза от этого сомнительная: обычно требуется ответить не на вопрос «что в этом файле?» а на вопрос «в каком файле лежит тип Х?», и вот тут Студия бессильна.</p>
<p>Если взять и кликнуть правой кнопкой на каком-то из представленных выше типов (например <code>Greeks</code>), Студия покажет нам вот такое меню:</p>
<p><img src="http://nesteruk.org/pix/0/e095ebbb-6c30-4144-8d7c-5f0f9b17a893.png" alt="" style="border:0;" /></p>
<p>Большинство этих пунктов приводят к замене всего контента Solution Explorer&rsquo;а, и тут-то становится ясно, что Solution Explorer&nbsp;&ndash; это некий page navigator (в терминоголии WPF), который может как набор страниц HTML показывать нам различные виды в зависимости от того где ма находимся.</p>
<p>Говоря о примере выше, <em>Scope to This</em> делает текущий элемент корнем дерева, <em>Base Types</em> и <em>Derived Types</em> ищет родителей и наследников этого типа, а вот <em>Is Used By</em> реализует полезную функцию нахождения всех мест где тип используется:</p>
<p><img src="http://nesteruk.org/pix/0/b94cc5be-3db8-431e-a280-407a9c54938e.png" alt="" style="border:0;" /></p>
<h3>Add References</h3>
<p>Add References&nbsp;&ndash; это главный <a href="http://twitter.com/#search?q=%23fail" title="fail hashtag on twitter">#fail</a> Студии всех версий включая 2010. Я с пристрастием смотрел на то, как нам обещали починить адски медленную загрузку ссылок в 2010й студии, но счастья не пришло: сделали еще хуже. В 11й студии правда все вроде получше: у меня окно при первом запуске открывалось 2 секунды, на последующих&nbsp;&ndash; моментально. Само по себе окошко теперь выглядит вот так:</p>
<p><img src="http://nesteruk.org/pix/0/f2612cc0-9203-4f8e-8270-b40c184dd1b2.png" alt="" style="border:0;" /></p>
<p>В сборки «фреймворка» попали различные сборки <code>System.*</code> и <code>Microsoft.*</code>, в то время как все сторонние сборки попали в «extensions». Что порадовало так это скорость поиска: я написал «WPF» и получил список всех нужных сборок практически моментально. Вообщем, мне кажется что инцедент изчерпан, хотя признаюсь что нынче я использую NuGet намного чаще чем Add Reference. Он кстати, судя по всему, поставляется с 11й студией, и это хорошо, т.к. я до сих пор периодически встречаю людей, которые не знают что это такое.</p>
<h3>Quick Launch или «быстрый запуск всего и вся»</h3>
<p>Те из вас кто используют Mac&rsquo;и уже знакомы с этой функцией: вы вбиваете в текстовое поле ориентировочное название того, что вы хотите сделать, и программа показывает вам все возможные варианты действий. Так вот: теперь подобное есть и в Студии. Называется эта функция Quick Launch (быстрый запуск), и находится она в правой верхней части основного приложения:</p>
<p><img src="http://nesteruk.org/pix/0/6d3d6ef4-ac10-4b7e-bce8-d7b4835574a1.png" alt="" style="border:0;" /></p>
<p>Я считаю что идея в принципе хорошая, хотя это и является как бы намеком на то, что в Студии слишком много всяких команд которые ни один человек в принципе запомнить не может. Что хорошо в списке выше, так это то что показаны шорткаты (например, для Run All Tests)&nbsp;&mdash; это позволить пользователю запомнить его и в следующий раз уже использовать шорткат вместо Quick Launch для запуска всех тестов.</p>
<h3>IntelliSense</h3>
<p>Автодополнение кода в 11 студии улучшено и даже умудряется работать в С++ с приемлимой скоростью, что особенно радует. Наконец-то дополнение сопоставляет не только начало слова, но идет все символы которые это слово содержат:</p>
<p><img src="http://nesteruk.org/pix/0/cebae365-44b0-43c3-a552-0bee3831219b.png" alt="" style="border:0;" /></p>
<p>Конечно, до полноценной реализации fuzzy string matching Студия все равно не дотягивает, но хоть какой-то прогресс виден. Да, и список дополнения выпадает теперь автоматически, после первого же напечатанного символа.</p>
<h3>Графика, GPGPU, C++ AMP</h3>
<p>Теперь мы пришли к одной из «основных» фич студии, а именно поддержки отладки программ, работающих на GPU. Ситуация на данный момент такая: Microsoft работает вместе с AMD/ATI и NVIDIA для того чтобы реализовать в поставке 2012й студии библиотеку C++ AMP (Accelerated Massive Parallelism). Эта библиотека чем-то похожа на <a href="http://code.google.com/p/thrust/" title="http://code.google.com/p/thrust/">Thrust</a>&nbsp;&mdash; ее цель дать пользователям интерфейс, сравнимый с TBB или PPL, но при этом сделать так, чтобы вычисления можно было производить не на CPU а на GPU.</p>
<p>Для тех кто не в курсе, напомню что на настоящий момент NVIDIA имеет намного более сильную позицию касаетельно вычислений на графических картах. Обусловлено это тем, что NVIDIA удосуживается поставлять качественный драйверы а также прекрасный CUDA SDK, в то время как ATI поставляет постоянно падающие драйверы и какую-то высокоуровневую несуразицу в форме OpenCL. Не удивительно, что на данный момент, большинсто библиотек и решений (Thrust, GPU.NET и так далее) поддерживают именно CUDA. Для ATI, C++ AMP&nbsp;&ndash; это наверное последний шанс вернуться в игру, т.к. иначе NVIDIA просто их раздавит.</p>
<p>К сожалению, и в этой бочке есть <strong>ложка дегтя</strong>: технология C++ AMP это некая спецификация, а реализация Microsoft использует Direct3D, что означает что шансы использовать эту технологию на не-Windows системах примерно равна нулю.</p>
<h3>Заключение</h3>
<p>На данный момент, помимо поддержки WinRT и C++ AMP, 11я студия не кажется мне чем-то особенным. Единственное что порадовало&nbsp;&ndash; это то что она работает чуть-чуть быстрее чем предыдущая, хотя она пока у меня «голая», а когда в ней будет масса плагинов&nbsp;&ndash; будет совсем другое дело. Тем не менее, на нетбуке она смотрится хорошо.</p>
<p>На данный момент мне уже ничего не препятствует в адоптации 11й студии за исключением одной вещи: наличия Intel Parallel Studio которая бы поддерживала VS11. Если вас интересует новая студия, советую скачать и начать использовать бету, т.к. «поломок» от беты, по крайней мере на моей системе, пока не наблюдается. И старая студия тоже, тьфу-тьфу, работает без проблем.</p>
<p>В целом же, мне остается только вздохнуть и заметить, что эра революций в нашей любимой IDE уже прошла. Это не значит что пора пересаживаться на Notepad, но мне кажется что сейчас самое время для какого-нибудь смелого игрока выступить с IDE которая нацелена целиком и полностью на разработку приложений для различных систем, а не на узконаправленную поддержку технологического стека Microsoft. По крайней мере, у меня такая мечта. Ведь если бы был редактор, который бы поддерживал, скажем, C# и C++ и функионал аналогичный ReSharper&rsquo;у, уверен что процентов 60 разработчиков ежесекундно пересели бы на такую IDE.</p>
<p><strong>P.S.:</strong> не упомянул MVC 4, но и не особо хотелось. Что, поддержка single-page apps, говорите? Хорошо, только зачем для этого MVC? Более того, зачем для этого IIS? Ни то ни другое не нужно для реализации парадигмы JS+REST.</p>
<p><strong>P.P.S.:</strong> а вот еще одна ложка дегтя: Microsoft сделали так, чтобы было невозможно отлаживать на Windows 7, только на Windows 8 (WTF?!?) Хотя, судя по всему, это <a href="http://blogs.msdn.com/b/nativeconcurrency/archive/2011/09/19/vs-11-developer-preview-gotchas-with-c-amp.aspx" title="http://blogs.msdn.com/b/nativeconcurrency/archive/2011/09/19/vs-11-developer-preview-gotchas-with-c-amp.aspx">можно починить</a>, но тот факт что это делается вручную через переименование DLLек&hellip; ну спасибо, Microsoft&hellip; серьезно, кто-то планирует использовать Windows 8 для разработки? А я-то думал это поделка чисто для Metro UI.</p>
<p><strong>P<sup>3</sup>S.:</strong> примечательно так же, что попытка поставить DirectX SDK (June 2010) окончилась провалом, т.к. оказываается версия C++ слишком свежая. Детали проблемы <a href="http://stackoverflow.com/questions/4102259/directx-sdk-june-2010-installation-problems-error-code-s1023" title="http://stackoverflow.com/questions/4102259/directx-sdk-june-2010-installation-problems-error-code-s1023">тут</a>.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/visual-studio/'>Visual Studio</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/905/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/905/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/905/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/905/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/905/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/905/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/905/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/905/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/905/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/905/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/905/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/905/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/905/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/905/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=905&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2012/03/04/%d0%bd%d0%b5%d0%b1%d0%be%d0%bb%d1%8c%d1%88%d0%be%d0%b9-%d0%be%d0%b1%d0%b7%d0%be%d1%80-visual-studio-11-2012-beta/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://nesteruk.org/pix/0/24a05efd-87ea-4ddc-95c0-e45b8f2be9c1.png" medium="image" />

		<media:content url="http://nesteruk.org/pix/0/b499ba6c-ff63-4fed-b90d-4fee13cc8474.png" medium="image" />

		<media:content url="http://nesteruk.org/pix/0/45b3d90d-096c-404f-bf4e-b94688303666.png" medium="image" />

		<media:content url="http://nesteruk.org/pix/0/e095ebbb-6c30-4144-8d7c-5f0f9b17a893.png" medium="image" />

		<media:content url="http://nesteruk.org/pix/0/b94cc5be-3db8-431e-a280-407a9c54938e.png" medium="image" />

		<media:content url="http://nesteruk.org/pix/0/f2612cc0-9203-4f8e-8270-b40c184dd1b2.png" medium="image" />

		<media:content url="http://nesteruk.org/pix/0/6d3d6ef4-ac10-4b7e-bce8-d7b4835574a1.png" medium="image" />

		<media:content url="http://nesteruk.org/pix/0/cebae365-44b0-43c3-a552-0bee3831219b.png" medium="image" />
	</item>
		<item>
		<title>Снова про оптимизацию математических выражений</title>
		<link>http://nesteruk.wordpress.com/2012/02/12/optimizing-math-expressions/</link>
		<comments>http://nesteruk.wordpress.com/2012/02/12/optimizing-math-expressions/#comments</comments>
		<pubDate>Sun, 12 Feb 2012 19:26:07 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=891</guid>
		<description><![CDATA[Поразительно как у меня получилось целый месяц ничего не писать в блог. Это не очень-то хорошо, так что спешу исправиться. В этом посте речь пойдет про оптимизацию и ускорение математических вычислений, что особенно актуально в контексте программ, которые генерируют код для численных расчетов. Инлайнинг возведения в степень Если ваша программа реализует как то вы оказываете [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=891&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Поразительно как у меня получилось целый месяц ничего не писать в блог. Это не очень-то хорошо, так что спешу исправиться. В этом посте речь пойдет про оптимизацию и ускорение математических вычислений, что особенно актуально в контексте программ, которые генерируют код для численных расчетов.</p>
<h3>Инлайнинг возведения в степень</h3>
<p>Если ваша программа реализует <img src='http://s0.wp.com/latex.php?latex=f%28x%29%3Dax%5E2%2Bbx%2Bc&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='f(x)=ax^2+bx+c' title='f(x)=ax^2+bx+c' class='latex' /> как</p>
<p><pre class="brush: csharp;">
double f(double a, double b, double c, double x)
{
  return a * std::pow(x, 2.0) + b*x + c;
}
</pre>
<p>то вы оказываете пользователю медвежью услугу. Для начала, следует помнить, что возведение в целочисленную степень является достаточно бессмысленной операцией, т.к. простое умножение &ldquo;инлайн&rdquo; или умножение в цикле всегда будет быстрее. Причина этого проста&nbsp;&ndash; функции вроде <code>std::pow()</code> расчитаны на подсчет степени для любых показателей, в т.ч. нецелочисленных. Как только в экспоненту ставится число вроде 2.0, строятся ряды и производительность идет лесом.</p>
<p>Решение этой проблемы весьма простое. Во-первых, для всех простых показателей вроде <img src='http://s0.wp.com/latex.php?latex=x%5E2&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='x^2' title='x^2' class='latex' />, <img src='http://s0.wp.com/latex.php?latex=x%5E3&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='x^3' title='x^3' class='latex' /> и так далее лучше все инлайнить, т.е. писать <code>x*x</code>, <code>x*x*x</code> и т.д. Что касается более крупных степеней то тут тоже все просто&nbsp;&ndash; надо чтобы степень была целым числом, т.е. имела тип <code>int</code>. Тогда будет вызвана пегрузка <code>std::pow()</code>, которая в свою очередь вызовет функцию <code>_Pow_int()</code> (по крайней мере в <code>&lt;math.h&gt;</code> от Microsoft), и все будет хорошо.</p>
<p>В .NET все не так ажурно т.к. <code>Math.Pow()</code> берет два параметра типа <code>double</code>. Очень досадное упущение, но это можно устранить самостоятельно:</p>
<p><pre class="brush: csharp;">
public static long IntPower(int x, short power)
{
  if (power == 0) return 1;
  if (power == 1) return x;
  int n = 15;
  while ((power &lt;&lt;= 1) &gt;= 0) n--;
  long tmp = x;
  while (--n &gt; 0)
    tmp = tmp * tmp *
         (((power &lt;&lt;= 1) &lt; 0) ? x : 1);
  return tmp;
}
</pre>
<p>Пример выше&nbsp;&ndash; для типа <code>short</code>, т.к. его обычно вполне достаточно. Естественно, следует также понимать что есть некий порог, после которого дешевле использовать канонический <code>pow(double,double)</code> вместо итеративного умножения.</p>
<h3>Сокращение количества умножений</h3>
<p>Допустим что мы воспользовались советом выше, и наша функция теперь выглядит вот так:</p>
<p><pre class="brush: csharp;">
double f(double a, double b, double c, double x)
{
  return a*x*x + b*x + c;
}
</pre>
<p>Мы продолжаем терять циклы, т.к. в примере выше целых три умножения, а можно было бы то же самое записать через два:</p>
<p><pre class="brush: csharp;">
double f(double a, double b, double c, double c)
{
  return x*(a*x + b) + c;
}
</pre>
<p>На самом деле, факторизация выражений, т.е. вынесение за скобки общих членов&nbsp;&mdash; задача не из легких, т.к. требует чтобы система знала уйму всяких разных правил. Например, как записать <img src='http://s0.wp.com/latex.php?latex=f%28x%2Cy%29%3Dx%5E2-y%5E2&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='f(x,y)=x^2-y^2' title='f(x,y)=x^2-y^2' class='latex' />? Вы действительно думаете, что без двух умножений не обойтись? Ничего подобного!</p>
<p><pre class="brush: csharp;">
double f(double x, double y)
{
  return (x + y) * (x - y);
}
</pre>
<p>И если равенство <img src='http://s0.wp.com/latex.php?latex=a%5E2-b%5E2%3D%28a%2Bb%29%28a-b%29&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='a^2-b^2=(a+b)(a-b)' title='a^2-b^2=(a+b)(a-b)' class='latex' /> мы еще можем запомнить, то какие-то более сложные равенства уже не получится, и придется жить без них. Хотя у пользователя всегда есть вариант использовать какой-нибудь полноценный математический пакет и собственноручно оптимизировать вычисление.</p>
<h3>Предварительные вычисления</h3>
<p>Понятное дело что выражение <img src='http://s0.wp.com/latex.php?latex=%5Cfrac%7B1%7D%7B3%7Dx&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='&#92;frac{1}{3}x' title='&#92;frac{1}{3}x' class='latex' /> превратится во что-то вроде <code>0.333333333333 * x</code> будучи оптимизированным компилятором. Но если взять выражение вроде <img src='http://s0.wp.com/latex.php?latex=%5Cfrac%7B2x%7D%7B3y%7D&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='&#92;frac{2x}{3y}' title='&#92;frac{2x}{3y}' class='latex' />, то тут уже все неоднозначно. До какой степени компилятор сможет оптимизировать и &ldquo;инлайнить&rdquo; результаты вычислений? Я думаю что в репертуар типичного компилятора не входит глубокий анализ и оптимизация вычислений.</p>
<h3>Выделение переменных</h3>
<p>Одна из проблем с генерацией кода для вычислений (к пр. на основе Excel) заключается в том, что есть большой шанс выполнить одну и ту же дорогую операцию несколько раз. Например, если напрямую конвертировать выражение <img src='http://s0.wp.com/latex.php?latex=2cos%5E3x-cos%5E2x&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='2cos^3x-cos^2x' title='2cos^3x-cos^2x' class='latex' />, то в результате можно получить весьма предсказуемый и неэффективный код:</p>
<p><pre class="brush: csharp;">
double f(double x)
{
  return 2.0*pow(cos(x),3.0) - pow(cos(x), 2.0);
}
</pre>
<p>А если еще &ldquo;проинлайнить&rdquo; степень, то будет вообще ужасно. Мораль в том, что при генерации подобных выражений, нужно уметь оценивать стоимость различных вычислений и не давать общим элементам с большой стоимостью повторяться. Например, код выше имеет смысл записать вот так:</p>
<p><pre class="brush: csharp;">
double f(double x)
{
  double u = cos(x);
  return (2*u - 1)*u*u;
}
</pre>
<p>То, что приведено выше&nbsp;&ndash; это так называемая <a href="http://ru.wikipedia.org/wiki/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%93%D0%BE%D1%80%D0%BD%D0%B5%D1%80%D0%B0" title="http://ru.wikipedia.org/wiki/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%93%D0%BE%D1%80%D0%BD%D0%B5%D1%80%D0%B0">схема Горнера</a>. Примечательно, что эта задача&nbsp;&mdash; анализ выражений на поиск общих кусков кода&nbsp;&mdash; будучи созданной ускорять код, сама по себе имеет огромную стоимость, т.к. подразумевает поиск любого поддерева с определенной стоимостью в остальных частях дерева и выделения их для последующей замены. В общем случае эта задача не решается. К счастью, при трансляции Excel&rarr;С++ ее можно решить хотя бы частично: результаты промежуточных вычислений часто хранятся в отдельных клетках, а детектировать их повторное использование легче т.к. это всего лишь сравнение cell reference&rsquo;ов.</p>
<h3>Заключение</h3>
<p>Для создания вменяемых математических моделей недостаточно просто конвертировать код &ldquo;один в один&rdquo;. В конце концов, главная цель подобных конверсий из Excel в С++&nbsp;&mdash; получить многократный прирост производительности. А сколько эта конверсия займет времени никого толком не волнует.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/mathematics/'>Mathematics</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/891/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/891/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/891/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/891/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/891/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/891/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/891/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/891/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/891/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/891/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/891/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/891/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/891/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/891/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=891&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2012/02/12/optimizing-math-expressions/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Итоги 2011 года</title>
		<link>http://nesteruk.wordpress.com/2011/12/31/year-2011-results/</link>
		<comments>http://nesteruk.wordpress.com/2011/12/31/year-2011-results/#comments</comments>
		<pubDate>Sat, 31 Dec 2011 10:36:26 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=879</guid>
		<description><![CDATA[Сейчас блоггеры усиленно подводят итоги уходящего года, и я тут подумал&#160;&#8211; а чем я хуже? Мне тоже есть что рассказать! Рассказывать я буду конечно про технические вещи, с которыми успел &#8220;поиграться&#8221; в 2011 году. Поехали&#8230; ПО, которое удалось зарелизить: JetBrains ReSharper SDK, включая онлайн документацию. Также получилось добавить одну фичу непосредственно в ReSharper. ActiveMesa R2P&#160;&#8212; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=879&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Сейчас блоггеры усиленно подводят итоги уходящего года, и я тут подумал&nbsp;&ndash; а чем я хуже? Мне тоже есть что рассказать! Рассказывать я буду конечно про технические вещи, с которыми успел &ldquo;поиграться&rdquo; в 2011 году. Поехали&hellip;</p>
<p>ПО, которое удалось зарелизить:</p>
<ul>
<li>
<p><a href="http://www.jetbrains.com/resharper/download/index.html" title="http://www.jetbrains.com/resharper/download/index.html">JetBrains ReSharper SDK</a>, включая онлайн документацию. Также получилось добавить <a href="http://blogs.jetbrains.com/dotnet/2011/03/resharper-enhances-suggestions-with-explanations/" title="http://blogs.jetbrains.com/dotnet/2011/03/resharper-enhances-suggestions-with-explanations/">одну фичу</a> непосредственно в ReSharper.</p>
</li>
<li>
<p><a href="http://activemesa.com/r2p" title="http://activemesa.com/r2p">ActiveMesa R2P</a>&nbsp;&mdash; обновления для ReSharper 6.0 и 6.1, также несколько фич по запросам пользователей (что особенно приятно). Появилось много классных вещей, без которых я и сам уже жить не могу. Впрочем, пишется в основном для себя, так что это понятно.</p>
</li>
<li>
<p><a href="http://activemesa.com/mathsharp" title="http://activemesa.com/mathsharp">ActiveMesa MathSharp</a>&nbsp;&mdash; нужно иметь много наглости чтобы просить почти 100 долларов за приложение, которое писалось максимум неделю. И покупают ведь! Первое приложение которое я выпускаю по ClickOnce, и не без факапов конечно же, но тем не менее&hellip; теперь точно понятно, что пользователи готовы качать 100-мегабайтный инсталлятор .Net 4 и их это не особо напрягает.</p>
</li>
</ul>
<p>Языки и их использование:</p>
<ul>
<li>
<p><a href="http://dlang.org/" title="http://dlang.org/">D</a>&nbsp;&mdash; открытие года для меня. Уже успел купить и прочитать книжку Александреску а также попробовать пописать на нем. Впечатления крайне позитивные, несмотря на отсутствие 64-битной поддержки а также явную &ldquo;недопиленность&rdquo; стандартной библиотеки Phobos. D&nbsp;&ndash; это язык на котором хочется писать и шипить ПО, в том числе и кросс-платформенное. Настоятельно рекомендую!</p>
</li>
<li>
<p><a href="http://en.wikipedia.org/wiki/C_Sharp_(programming_language)" title="http://en.wikipedia.org/wiki/C_Sharp_(programming_language)">C#</a>&nbsp;&mdash; продолжаю пользоваться, всем в принципе доволен. Обрастаю библиотеками с методами расширений, т.к. в любом проекте одно и то же, снова и снова. Также активно использую <a href="http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/">монаду Maybe</a> для R2P.</p>
</li>
<li>
<p><a href="http://en.wikipedia.org/wiki/C%2B%2B" title="http://en.wikipedia.org/wiki/C%2B%2B">C++</a>&nbsp;&mdash; продолжаю пользоваться, нововведения меня не очень затронули, в основном использую &ldquo;хорошо забытое старое&rdquo; а также типичный стэк&nbsp;&ndash; <a href="http://threadingbuildingblocks.org/" title="http://threadingbuildingblocks.org/">Intel TBB</a>, <a href="http://openmp.org" title="http://openmp.org">OpenMP</a>, <a href="http://msdn.microsoft.com/en-us/library/t467de55(v=VS.100).aspx" title="http://msdn.microsoft.com/en-us/library/t467de55(v=VS.100).aspx">SIMD</a>.</p>
</li>
<li>
<p><a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/" title="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/">F#</a>&nbsp;&mdash; пришел к выводу что он очень хорош для определенного круга задач, и не очень хорош для всего что требует серьезного использования ООП. При написании MathSharp, да и вообще парсеров, он очень полезен. Для математики тоже весьма неплох, хотя тут уже его приемущества чисто психологические (т.е. это приемущества для математиков, но не для меня).</p>
</li>
<li>
<p><a href="http://www.pokemon.com/" title="http://www.pokemon.com/">JavaScript</a>&nbsp;&mdash; практически не использую напрямую, пишу все на C# и транскомпилирую через SharpKit (см. ниже). За пределами <code>$.getJSON()</code> стараюсь вообще не трогать.</p>
</li>
</ul>
<p>Программы и компоненты, которые продолжают давать ощутимые бенефиты:</p>
<ul>
<li>
<p><a href="http://www.devexpress.com/Subscriptions/DXperience/winforms.xml" title="http://www.devexpress.com/Subscriptions/DXperience/winforms.xml">Контролы DevExpress (WinForms)</a>&nbsp;&mdash; использую их с 2006 года и в целом доволен, особенно доволен стилизацией, до которой конкурентам далеко. Контролы DX продолжают лидировать в плане красивости UI, а это важно для пользователей.</p>
</li>
<li>
<p><a href="http://software.intel.com/en-us/articles/intel-parallel-studio-home/" title="http://software.intel.com/en-us/articles/intel-parallel-studio-home/">Intel Parallel Studio</a>&nbsp;&mdash; до черного пояса Intel мне как до луны, но инструментарием я продолжаю пользоваться, причем весьма успешно. Как ни странно, мне намного больше импонирует использование связки C# &amp; IntelCPP чем связки C# &amp; C++/CLI.</p>
</li>
<li>
<p><a href="https://bitbucket.org/nesteruk/typografix" title="https://bitbucket.org/nesteruk/typografix">TypograFix</a> продолжает развиваться, улучшаться, и этот пост я пишу, конечно же, на нем. (Через RDC, сидя на Mac&rsquo;е.)</p>
</li>
</ul>
<p>Программы и компоненты которые понравились и стали частью процесса:</p>
<ul>
<li>
<p><a href="http://www.innovasys.com/products/dx2011/overview.aspx" title="http://www.innovasys.com/products/dx2011/overview.aspx">Innovasys Document!X</a>&nbsp;&mdash; теперь это моя стандартная тула для генерирования документации (CHM и Web) как для коммерческих, так и для OSS проектов. Действительно хороший продукт, который стоит своих денег.</p>
</li>
<li>
<p><a href="http://www.red-gate.com/products/dotnet-development/smartassembly/" title="http://www.red-gate.com/products/dotnet-development/smartassembly/">Red Gate SmartAssembly</a>&nbsp;&mdash; все любят ругать Red Gate за Reflector, но продукт SmartAssembly они выкупили у другой компании, и продукт это неплохой. SA&nbsp;&ndash; это обфускатор, <a href="http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx" title="http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx">ILMerge</a> и репортилка исключений в одном флаконе. Да, ценник &ldquo;зашкаливает&rdquo;, но мне очень нравится функционал и UI. Нет, я не страдаю любовью к обфускаторам т.к. считаю эту затею бессмысленной, но вот красивый exception reporting многого стоит.</p>
</li>
<li>
<p><a href="http://wix.sourceforge.net/" title="http://wix.sourceforge.net/">WiX</a>&nbsp;&mdash; да-да, бесплатный пакет для создания инсталляторов существует уже давно, но &ldquo;распробовал&rdquo; его я только в этом году. Теперь все инсталляторы которые не используют ClickOnce делаются именно на WiX. Единственное, чего не хватает&nbsp;&ndash; это фич автообновления. Правда автообновление уже давно перестало быть большой проблемой. Но все равно хочется иметь его &ldquo;из коробки&rdquo;.</p>
</li>
<li>
<p><a href="http://www.actiprosoftware.com/products/dotnet/windowsforms/syntaxeditor/default.aspx" title="http://www.actiprosoftware.com/products/dotnet/windowsforms/syntaxeditor/default.aspx">ActiPro Syntax Editor (WinForms)</a>&nbsp;&mdash; казалось бы, что особенного в контроле-редакторе который показывает подсветку синтаксиса и code completion для C#? А то, что процесс динамического прототипирования можно сделать более &ldquo;цивильным&rdquo;. А динамическое прототипирование дает настолько серьезный прирост производительности, что не делать его уже кажется грехом. Впрочем, мне кажется я никогда не смогу объяснить людям все его бенефиты. Что же, это не критично.</p>
</li>
<li>
<p><a href="http://sharpkit.net/" title="http://sharpkit.net/">SharpKit</a>&nbsp;&mdash; транскомпилятор из C# в JavaScript. Чтобы не писать JS, который есть зло и должен умереть, хотя кто-то и соглашается на нем писать. Тулкит имеет завязки на разные фреймворки вроде jQuery, да и свои байндинги писать на так уж сложно.</p>
</li>
</ul>
<p>Программы, которые я больше не планирую использовать:</p>
<ul>
<li>
<p>SQL Server и другие RDBMS, а также такие ORM-фреймворки как Telerik OpenAccess. <a href="http://www.mongodb.org/" title="http://www.mongodb.org/">MongoDB</a> хватает &ldquo;за глаза&rdquo;, и подход NOSQL идеален для большинства задач. Единственное исключение пока это embeddability, и тут я пожалуй продолжу пользоваться SQL CE (например в том же R2P), т.к. хороших альтернатив мало.</p>
</li>
<li>
<p>IIS и ASP.NET MVC&nbsp;&mdash; с момента моего перехода на подход <a href="http://spbaltnet.podfm.ru/solo/40/" title="http://spbaltnet.podfm.ru/solo/40/">JS+REST</a>, эти технологии оказались нерелевантными. Хотя, по правде сказать, я по-прежнему использую IIS 6 для хостинга WCF REST приложений, но по крайней мере клиентскую часть я писать на ASP.NET больше не намерен.</p>
</li>
<li>
<p><a href="http://www.ndepend.com/" title="http://www.ndepend.com/">NDepend</a>&nbsp;&mdash; в нем есть полезные фичи, но они запрятаны под слоями академичного анализа который, если честно, не очень-то полезен для анализа моего кода. Гораздо полезнее обычные механизмы статического анализа.</p>
</li>
<li>
<p><a href="http://www.typemock.com/isolator-product-page" title="http://www.typemock.com/isolator-product-page">Typemock Isolator</a>&nbsp;&mdash; я на самом деле давно забросил использование такой &ldquo;тяжелой артиллерии&rdquo;, но недавно попробовал снова и был разочарован: оказалось что в VS Ultimate Typemock генерит много багов, и умеет работать только при определенно выставленной конфигурации, которая меня не устраивает.</p>
</li>
<li>
<p>Telerik MVC поскольку его <a href="http://kendoui.com" title="http://kendoui.com">больше не существует</a> :) не говоря уже о том что я больше не буду писать под ASP.NET.</p>
</li>
</ul>
<p>Технологии, которые удивили или порадовали:</p>
<ul>
<li>
<p><a href="http://www.amazon.com/Kindle-DX-Wireless-Reader-3G-Global/dp/B002GYWHSQ" title="http://www.amazon.com/Kindle-DX-Wireless-Reader-3G-Global/dp/B002GYWHSQ">Kindle DX</a>&nbsp;&mdash; пожалуй лучшее мое приобретение года. Вопрос о покупке iPad&rsquo;а даже не стоял, а KDX я прикупил после долгих раздумий и не сожалею&nbsp;&ndash; уже прочитал на нем уйму книг. Глаза он щадит, размер вменяемый для чтения &ldquo;почти А4&rdquo;. Есть конечно фейлы&nbsp;&ndash; бесплатный 3G не работает в России и Латвии (в Скандинавии&nbsp;&ndash; на ура), браузер допотопный, WiFi нету, и книжки которые продает Amazon (типа &lsquo;Kindle Edition&rsquo;) покупать нельзя т.к. все листинги кода в них&nbsp;&ndash; битмапы, оптимизированные под &ldquo;маленький&rdquo; киндл. Что просто чудовищно. PDF FTW.</p>
</li>
<li>
<p><a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" title="http://www.microsoft.com/windowsphone/en-us/default.aspx">Windows Phone 7</a>&nbsp;&mdash; честно скажу: я ожидал увидеть очередное мертворожденное детище. А получилась операционка с уникальным, красивым user experience. Ведь могут когда захотят! Теперь остается ждать планшетов, хотя скажу сразу: если iPad 3 будет выпущен с Retina Display, куплю не задумываясь, ибо хочется, наконец-то, вменяемого разрешения. Если оно будет, можно будет и PDFы попробовать читать, и travel guides всякие, комиксы, и так далее&hellip;</p>
</li>
<li>
<p><a href="http://qt.nokia.com/products/developer-tools/" title="http://qt.nokia.com/products/developer-tools/">Qt Creator</a>&nbsp;&mdash; не совсем &ldquo;моё&rdquo;, конечно, но Qt Creator порадовал тем что он, во-первых, работает, а во-вторых даже более-менее понятен. В принципе, если приложение действительно нужно сделать кросс-платформенным, то я бы скорее смотрел на Qt чем на Java или AIR. И все это в очередной раз подчеркивает, что если хочешь чтобы твой алгоритм был кросс-платформенным, пиши его на С++. Ну или на С, это тоже сработает.</p>
</li>
</ul>
<p>Что технологического я ожидаю в 2012 году:</p>
<ul>
<li>
<p>Запуск <a href="http://www.ianquigley.com/A75_New_features_of_VS2012_revealed.html" title="http://www.ianquigley.com/A75_New_features_of_VS2012_revealed.html">Visual Studio 2012</a>, в комплекте с поддержкой Metro-style apps, AMP и отладкой на GPU, C#5 и так далее. Запуск новой Студии в Петербурге буду проводить лично, если только Microsoft не передумает и не снимет снова Прибалтийскую для эвента на 500 человек как на <a href="http://nesteruk.wordpress.com/2010/04/15/st-petersburg-vs2010launch/" title="http://nesteruk.wordpress.com/2010/04/15/st-petersburg-vs2010launch/">запуск 2010й</a>. Впрочем, я не против, так и так.</p>
</li>
<li>
<p><a href="https://groups.google.com/forum/#!topic/altnet-spb/nszzP-hy1VI" title="https://groups.google.com/forum/#!topic/altnet-spb/nszzP-hy1VI">Разработческая конференция на пароме</a>, курсирующем по скандинавии. С последующими туристическими ответвлениями. Будет весело.</p>
</li>
<li>
<p>Смерть и/или перерождение <a href="http://www.rim.com/" title="http://www.rim.com/">RIM</a>. Серьезно, что же с ними будет? Кто-нибудь может себе представить WP7 на Blackberry?</p>
</li>
</ul>
<p>Ну и наконец:</p>
<ul>
<li>
<p>В 2012м я окончательно уеду из <a href="http://lurkmore.to/%D0%AD%D1%82%D0%B0_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B0" title="http://lurkmore.to/%D0%AD%D1%82%D0%B0_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B0">России</a> (куда&nbsp;&ndash; пока секрет, скажу лишь что это не Англия и не Швеция). Впрочем, произойдет это небыстро&nbsp;&ndash; переезд это дело мутное, нужно сделать 1000 дел, все проверить-перепроверить, совершить несколько плановых полетов. Главное что это произойдет&nbsp;&ndash; понимание этого уже радует.</p>
</li>
</ul>
<p>P.S.: <strong>С Новым Годом!!!</strong></p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/life/'>Life</a>, <a href='http://nesteruk.wordpress.com/category/technology/'>Technology</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/879/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/879/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/879/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/879/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/879/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/879/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/879/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/879/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/879/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/879/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/879/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/879/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/879/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/879/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=879&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/12/31/year-2011-results/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Лайфхак с использованием строковых литералов</title>
		<link>http://nesteruk.wordpress.com/2011/12/17/string-literal-lifehack/</link>
		<comments>http://nesteruk.wordpress.com/2011/12/17/string-literal-lifehack/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 22:30:22 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[resharper]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=869</guid>
		<description><![CDATA[Хочу рассказать про лайфхак с использованием стороковых литералов. Строковый литерал сам по себе&#160;&#8211; достаточно унылая вещь, но есть один нюанс&#160;&#8211; лексер языкового сервиса (если у вас такой имеется) хорошо понимает начало и конец литерала, и может разом выдать содержимое как System.String. А получив полноценную CLR-строку, с ней можно очень много всего сделать. Да, сразу подчеркну&#160;&#8211; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=869&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Хочу рассказать про лайфхак с использованием стороковых литералов. Строковый литерал сам по себе&nbsp;&ndash; достаточно унылая вещь, но есть один нюанс&nbsp;&ndash; лексер языкового сервиса (если у вас такой имеется) хорошо понимает начало и конец литерала, и может разом выдать содержимое как <code>System.String</code>. А получив полноценную CLR-строку, с ней можно очень много всего сделать.</p>
<p>Да, сразу подчеркну&nbsp;&ndash; лайфхак этот не очень-то зависит от языка, хотя конечно я его использую в C#.</p>
<h3>Строка как магический псевдоконструктор</h3>
<p>Первое наблюдение&nbsp;&ndash; это то что <strong>многие объекты поддерживают метод <code>Parse()</code></strong>&nbsp;&ndash; не только <code>int</code> или <code>decimal</code>, но такие объекты как <code>DateTime</code>, <code>TimeSpan</code>, <code>XElement</code> и так далее. Это значит что написав строку, отдаленно похожую на дату, я могу сконвертировать ее в правильный вызов конструктора <code>DateTime</code>:</p>
<p><img src="http://activemesa.com/Images/R2P/StringToDateTime.png" alt="" style="border:0;" /></p>
<p>Особенно эффектно это выглядит для XML, где сложный кусок этого языка может превратиться в красивую цепочку из конструкторов <code>XElement</code>, <code>XAttribute</code> и так далее.</p>
<h3>Строка как неживая часть кода</h3>
<p>Языки можно мешать&nbsp;&ndash; например HTML и C# в MVCшных вьюшках. И если вы не боитесь временно&nbsp;&ndash; примерно на долю секунду которая нужна чтобы выполнить контекстное действие&nbsp;&ndash; потерять контроль над кодом, то кто мешает вам, например, делать string splicing в PHP-стиле, но в коде C#?</p>
<p>Вот что я имею ввиду:</p>
<p><img src="http://activemesa.com/Images/R2P/SpliceString.png" alt="" style="border:0;" /></p>
<p>В примере выше, мы вставили идентификаторы C# прямо в строку, а потом вызвали контекстное действие, которое заменило всю строку на правильный вызов <code>String.Format()</code>.</p>
<h3>Строка как мимолетно существующий DSL</h3>
<p>В погоне за оператором <code>?.</code> (цепочная процерка на <code>null</code>), многие сели на Roslyn и аналогичные вещи. Но ведь проблема цепочной проверки может очень просто решиться если вместо введения оператора мы дороворимся, что любое выражение в форме <code>a.b.c</code> может быть написано как строковый литерал и, мановением волшебной палочки превратиться в</p>
<p><pre class="brush: csharp;">
a == null ? null : (a.b == null ? null : a.b.c)
</pre>
<p>Ну или что-то в этом духе. Опять же, строка которая толком ничего не означает может быть развернута вот в такое. Код, конечно, не очень читабельный. Но всяко лучше чем пытаться делать то же самое руками.</p>
<p>
  <small>Внимательные читатели заметят, что то же самое можно извлечь и из вполне валидного идентификатора. Что ж, не спорю. Мне просто лень по нему гулять&nbsp;&ndash; для меня сделать <code>string.Split()</code> намного проще :)</small>
</p>
<p>Подобных встроенных DSLов можно сделать море. Например, можно взять нотацию HTML Zen и из этого строкового литерала создать декларацию XLinq которая соответсвует исходному коду. Возможности безграничны.</p>
<h3>Как это работает</h3>
<p>Сразу скажу&nbsp;&ndash; реализовать подобное <strong>тривиально</strong>. Для Решарпера, нужно просто контекстное действие, которое говорит вам что вы «на строке», создает новый кусок кода, и делает обмен:</p>
<p><pre class="brush: csharp;">
[ContextAction(Group = &quot;C#&quot;, Name = &quot;Hide string value&quot;,
  Description = &quot;Ensures the string is not human-readable in code.&quot;,
  Priority = 15)]
public class StringHideRealValueCA : IContextAction
{
  private readonly IList&lt;IBulbItem&gt; items = new List&lt;IBulbItem&gt;();
  private readonly ICSharpContextActionDataProvider provider;
  public StringHideRealValueCA(ICSharpContextActionDataProvider provider)
  {
    this.provider = provider;
  }
  public bool IsAvailable(IUserDataHolder cache)
  {
    var e = provider.GetSelectedElement&lt;ICSharpLiteralExpression&gt;(true, true);
    if (e != null &amp;&amp; e.IsConstantValue())
    {
      if (e.ConstantValue.IsString())
      {
        var s = (string)e.ConstantValue.Value;
        if (!string.IsNullOrEmpty(s))
          items.Add(new StringHideRealValueImpl(provider, e));
      }
    }
    return items.Count &gt; 0;
  }
  public IBulbItem[] Items
  {
    get { return items.ToArray(); }
  }
}
</pre>
<p>В коде выше, <code>StringHideRealValueProvider</code> прячет естественную строку, подменяя ее Base64-закодированной строкой. Вот, собственно, реализация:</p>
<p><pre class="brush: csharp;">
private class StringHideRealValueImpl
{
  // очевидные методы опущены
      protected override Action&lt;ITextControl&gt; ExecutePsiTransaction(ISolution solution, IProgressIndicator progress)
  {
    CSharpElementFactory factory = CSharpElementFactory.GetInstance(provider.PsiModule, true);
    var value = literal.ConstantValue.Value as string;
    if (value != null)
    {
      string encoded = Convert.ToBase64String(Encoding.Unicode.GetBytes(value));
      ICSharpExpression ex = factory.CreateExpressionAsIs(
        string.Format(&quot;System.Text.Encoding.Unicode.GetString(System.Convert.FromBase64String(\&quot;{0}\&quot;))&quot;, encoded));
      literal.ReplaceBy(ex);
    }
    return
      tc =&gt; provider.PsiFile.OptimizeImportsAndRefs(
        provider.Document.DocumentRange.CreateRangeMarker(provider.Document), false, true, progress);
  }
}
</pre>
<p>Если коротко, в замену существующему литералу создается выражение (через вызов <code>CreateExpressionAsIs</code>), а потом банально втыкается в замен существующей строки. На базе этого вы можете писать свои механизмы подмены&nbsp;&ndash; это тривиально!</p>
<h3>Заключение</h3>
<p>Пример выше&nbsp;&ndash; это маленький лайфхак который иногда помогает писать код быстрее. String splicing особенно полезен, хотя нужно приучить себя им пользоваться. Помните&nbsp;&ndash; эти строки только несколько секунд «магические», а потом перестают существовать совсем. Так что ничего страшного.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/resharper-2/'>resharper</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/869/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/869/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/869/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/869/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/869/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/869/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/869/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/869/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/869/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/869/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/869/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/869/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/869/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/869/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=869&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/12/17/string-literal-lifehack/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://activemesa.com/Images/R2P/StringToDateTime.png" medium="image" />

		<media:content url="http://activemesa.com/Images/R2P/SpliceString.png" medium="image" />
	</item>
		<item>
		<title>Воскрешение языка С++</title>
		<link>http://nesteruk.wordpress.com/2011/10/30/cplusplus-resurrection/</link>
		<comments>http://nesteruk.wordpress.com/2011/10/30/cplusplus-resurrection/#comments</comments>
		<pubDate>Sat, 29 Oct 2011 21:13:44 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cplusplus]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=854</guid>
		<description><![CDATA[Сдается мне, что на всей нашей круглой планете вряд ли можно найти человека, который мог бы с уверенностью сказать, в чем заключается стратегия Microsoft относительно разработки в целом. Жив ли WPF, что будет с Silverlight для веба, откуда такой ажиотаж вокруг HTML 5 и причем тут, наконец, С++? Иногда мне кажется что ни у кого [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=854&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>
  <img class="alignright" src="http://nesteruk.org/pix/0/ebb7a797-5f72-448d-8950-1b2cb8ff1f8d.png" alt="" style="border:0;" align="right" /><br />
Сдается мне, что на всей нашей круглой планете вряд ли можно найти человека, который мог бы с уверенностью сказать, в чем заключается стратегия Microsoft относительно разработки в целом. Жив ли WPF, что будет с Silverlight для веба, откуда такой ажиотаж вокруг HTML 5 и причем тут, наконец, С++? Иногда мне кажется что ни у кого нет ответов на эти вопросы, и что в погоне за добычей (добычей тут может быть, например, рынок планшетов), не возбраняется полностью смешать все карты и начать заново.
</p>
<p>Тем не менее, мы должны признать, что по крайней мере в свете анонсов касательно <a href="http://tirania.org/blog/archive/2011/Sep-15.html" title="http://tirania.org/blog/archive/2011/Sep-15.html">WinRT</a>, язык программирования С++ снова становится более актуальным чем ранее. Да и не только сам С++. Ведь фактически то, что нас ждет, это некая реинкарнация COM, правда с другими терминами и, возможно, меньшим количеством проблем. (Ведь неслучайно PIA &ndash; Primary Interop Assembly &ndash; расшифровывается также как Pain In the Ass;)</p>
<p>Если быть честно-откровенными, то тот С++ который предлагает нам Microsoft &ndash; это совсем не «стандартные» плюсы. Хотя, точно так же как и в случае с C++/CLI, остается возможность использования «труъ» кода, который был написан ранее. Но вот уже в 3й раз нам предлагают некую магию.</p>
<p>Почему в 3й? Ну, 1м разом я считаю все те изменения языка, которые не были стандартизованы. С Java/Visual J++ такое не прошло т.к. там правила ныне отошедшая на покой компания Sun, в случае же с С++ не нашлось стороны, которая единолично планировала бы получать доходы с этого языка. Поэтому Microsoft могла сделать все, что угодно &ndash; добавить поддержку свойств (да-да, свойств в стиле C#) с помощью <code>__declspec(property)</code>, замутить поддержку COM с помощью <code>#import</code>, ну и так далее. Вторым вмешательством в С++ можно считать MC++ и с последствии С++/CLI, который добавил массу ненужных ключевых слов, а также эти ненавистные шляпки (^) для классов. Ну и так далее.</p>
<p>Впрочем, создание C++/CLI было вынужденным. Я это начал понимать только тогда, когда начал встречать кросс-платформенные (!) библиотеки на С++ которые компилировались, помимо обычного С++, еще и с «управляемой прослойкой» для .Net языков. Идея в принципе оказалась правильной &ndash; дать .Net разработчикам всю мощь С++ библиотек без особого напряжения в виде P/Invoke или надобности обращать С++ библиотеки в COM.</p>
<p>Ну и наконец, шаг 3й &ndash; это полностью узаконить любые новшества в С++ сделав его одним из официальных языков разработки для Windows. Это на самом деле лицемерие &ndash; ведь для Windows итак можно писать на «плюсах» используя MFC или даже WTL. Но уверен что мало кто этим занимается. Потери от этого больше, чем потери от требования наличия .Net Framework Client Profile на компьютере. Кстати &ndash; недавно в процессе тестирования лицезрел что происходит если поставить ClickOnce-программу которая использует .Net 4 на Windows XP. Инсталлятор сам скачивает и устанавливает framework. Это конечно нехилый download, но большинство людей 100-мегабайтные файлы уже практически не пугают.</p>
<p>Так вот, хотите вы этого или нет, С++ будет использоваться Microsoft в своих целях, связанных с разработкой под Windows. Но это конечно не значит что вы не сможете получить от этого бенефиты, даже если пишете на .Net.</p>
<h3>Приемущества С++</h3>
<p>Давайте определимся с тем, что же дает нам С++ чего не может дать тот же C#.</p>
<p><strong>Ручное управление памятью.</strong> У меня в голове иногда случаются страшные баталии, связанные с тем, нужно ли делать объект структурой или классом. В принципе, в .Net нам пытаются навязать ограничение, связанное с размером объекта &ndash; дескать, если маленький то можно и структуру, а иначе ни-ни. Но это подразумевает что мы, разработчики, наивно делаем pass by value и тем самым поедаем память. Что не всегда так.</p>
<p><strong>Доступ к высокопроизводительным инструкциям процессора.</strong> Возьмем например SIMD. Думаю можно с большой степенью уверенности сказать, что JIT-компилятор не оптимизирует и никогда не будет оптимизировать код под SIMD. Соответственно, мы с Microsoft.Net начинаем проигрывать даже Mono, где есть <a href="http://tirania.org/blog/archive/2008/Nov-03.html" title="http://tirania.org/blog/archive/2008/Nov-03.html">соответствующий пакет</a>.</p>
<p><strong>Прямой доступ к намного более зрелым и продуманным библиотекам.</strong> Это более сумеречный бенефит, т.к. API таких библиотек порой ужасно. Но надо смотреть не только на API но и на производительность.</p>
<p>О да, я же забыл упомянуть о самом важном &ndash; Microsoft ныне разрабатывает свои библиотеки для С++. Примером такой библиотеки может быть вышеупомянутая <a href="http://msdn.microsoft.com/en-us/library/dd492418.aspx" title="http://msdn.microsoft.com/en-us/library/dd492418.aspx">Parallel Patterns Library</a> (PPL), которая с одной стороны может считаться «неуправляемым» аналогом .Net&rsquo;ного TPL, а с другой &ndash; конкурентом <a href="http://threadingbuildingblocks.org/" title="http://threadingbuildingblocks.org/">Intel Threading Building Blocks</a> (TBB). Но на этом все не останавливается &ndash; Microsoft работает еще на одной библиотекой под названием <a href="http://blogs.msdn.com/b/vcblog/archive/2011/06/15/introducing-amp.aspx" title="http://blogs.msdn.com/b/vcblog/archive/2011/06/15/introducing-amp.aspx">C++ Accelerated Massive Parallelism</a> (AMP), которая будет заниматься поддержкой вычислений как на CPU так и на GPU.</p>
<p>Программирование для GPU заслуживает отдельную заметку. На данный момент, графические процессоры можно программировать с помощью OpenCL (вариации языка С++ для различных устройств), <a href="http://www.nvidia.ru/object/cuda_home_new_ru.html" title="http://www.nvidia.ru/object/cuda_home_new_ru.html">CUDA C</a> (подобия С++ для чипов NVidia, кстати с прекрасным тулсетом для Visual Studio). Существуют также решения на .Net, такие как исследовательский проект <a href="http://research.microsoft.com/en-us/projects/accelerator/" title="http://research.microsoft.com/en-us/projects/accelerator/">Microsoft Accelerator</a> (который, насколько я знаю, также работает с FPGA) или коммерческое решение <a href="http://www.tidepowerd.com/" title="http://www.tidepowerd.com/">GPU.NET</a>.</p>
<h3>Недостатки С++</h3>
<p>С++ архаичен. Использовать его для ООП &ndash; делать себе плохо. Даже со всеми новшествами C++ 2011 является динозавром, пусть и динозавром который пока не думает вымирать. С другой стороны, С++ прекрасно подходит для производительных алгоритмов.</p>
<p>Приведу пример. Мне в <a href="http://bitbucket.org/nesteruk/typografix" title="http://bitbucket.org/nesteruk/typografix">TypograFix</a> нужно обрабатывать <code>Bitmap</code>&rsquo;ы. Если использовать .Net, то единственная возможность получить более-менее вменяемую скорость по обработке картинок &ndash; это использовать <code>unsafe</code>. Что как бы само по себе не очень эффективно, но даже если у вас получится, вы не сможете эффективно настроить параллелизацию unsafe кода. (Автор пробовал использовать TPL и <code>unsafe</code>, с весьма мутными результатами.)</p>
<p>Еще одна проблема &ndash; это нехватка инструментария. Отладчики конечно есть, но вот анализа кода в стиле Решарпера мне очень нехватает. А ведь это как раз тот «небезопасный» язык, в котором так нужны всяческие проверки, причем чем их больше, тем лучше.</p>
<p>Это основные недостатки, но есть и масса других. <a href="http://drdobbs.com/blogs/cpp/228701711" title="http://drdobbs.com/blogs/cpp/228701711">Скорость компиляции</a>, неинформативность ошибок, итд, итп. Масса компромиссов, на которые можно пойти в погоне за производительностью.</p>
<h3>AMP</h3>
<p>У инициативы AMP есть одно существенное приемущество &ndash; над этой технологией работают AMD и NVidia, две компании которые держат рынок графических карт (лично я тяготею к AMD потому что у них есть <a href="http://www.amd.com/us/products/technologies/amd-eyefinity-technology/Pages/eyefinity.aspx" title="http://www.amd.com/us/products/technologies/amd-eyefinity-technology/Pages/eyefinity.aspx">Eyefinity</a>). Работают они над ней, конечно, с Microsoft, т.к. у всех трех компаний есть уклон в сторону различных процессоров. Кстати, в случае с Microsoft, это конечно же ARM, о котором вы все уже наверняка наслышаны. Соответственно идея, как мне кажется, в том, чтобы иметь код (возможно даже код низкого уровня &ndash; драйвера, кодеки, и т.п.) который мог бы выжать максимум возможностей из любого процессора.</p>
<p>С другой стороны, по крайней мере для GPU, поддержка идет по наименьшему знаменателю, и этот знаменатель называется <a href="http://en.wikipedia.org/wiki/DirectCompute" title="http://en.wikipedia.org/wiki/DirectCompute">DirectCompute</a>. Поэтому неизвестно, будет ли AMP настолько эффективен как например CUDA C или кросскомпиляция, скажем, C# в NVidia <a href="http://en.wikipedia.org/wiki/Parallel_Thread_Execution" title="http://en.wikipedia.org/wiki/Parallel_Thread_Execution">PTX</a> (именно это делает GPU.NET). Также непонятно, придется ли писать fallback-код для CPU в случае отсутствия девайса с поддержкой DirectCompute &ndash; если это придется делать, то часть шарма данного подхода пропадет, т.к. это точно не «write once, run everywhere».</p>
<h3>Intel C++</h3>
<p>Microsoft не является единственной компанией, которая выпускает компилятор С++. Intel тоже делает компилятор, в большей степени заточенный на свои процессоры, с неплохой интеграцией в Visual Studio. Важен не только сам компилятор (а он хорош), но и тулсет &ndash; отладчик, профилировщик, библиотеки. Все это на высоте. Библиотеки, например, работают более резво на процессорах AMD чем библиотеки самой AMD.</p>
<p>На сегодняшний день я готов работать только с компилятором Intel. Я не использую C++/CLI, мне хватает P/Invoke. На самом деле, технология P/Invoke &ndash; настолько простая и понятная, что я не чувствую особого стеснения когда пишу часть проекта на C# а часть на С++. Что P/Invoke не поддерживает так это, конечно же, ООП и возможность передавать туда-сюда классы, но тут я скажу вот что: если вы используете С++ именно для ООП (или для взаимодействия с .Net) &ndash; вы делаете что-то не так. На С++ нужно писать производительные алгоритмы, или использовать уже существующие библиотеки (например, Intel TBB, <a href="http://software.intel.com/ru-ru/articles/intel-mkl/" title="http://software.intel.com/ru-ru/articles/intel-mkl/">MKL</a> или <a href="http://software.intel.com/en-us/articles/intel-ipp/#support" title="http://software.intel.com/en-us/articles/intel-ipp/#support">IPP</a>). Потреблять ООП-структуры там бесполезно, но с другой стороны, не возбраняется потреблять оттуда COM. Например, когда только вышли библиотеки Direct2D/DirectWrite, я захотел ими воспользоваться в WPF-проекте и просто написал C++ DLL&rsquo;ку, которая рисовала в «залоченый» <code>System.Drawing.Bitmap</code>. Никаких проблем.</p>
<h3>OpenMP</h3>
<p><a href="http://en.wikipedia.org/wiki/OpenMP" title="http://en.wikipedia.org/wiki/OpenMP">OpenMP</a> &ndash; это поддержка декларативной параллелизации на С++. Это может показаться шуткой, но на самом деле это старая, проверенная временем технология, которая работает. Для большинства случаев data-level параллелизации в стиле <code>parallel_for()</code> подходит именно OpenMP. Я много где использую именно OpenMP, оставляя Intel TBB для более сложных задач, где автоматический подход не сработает.</p>
<p>Конечно, в .Net есть некий аналог &ndash; использование TPL и надежда на то, что JIT-компилятор магическим способом оптимизирует и «векторизует» сгенерированный код. Но это достаточно наивно. Пока вы проверяете индекс элемента доступа к массиву, вы теряете в производительности. Как только вы это отключите, у вас начнутся уже другие проблемы.</p>
<p>Если честно, я не большой фанат TPL. Для простеньких случаев в которые не хочется вникать, я просто пишу <code>Parallel.Invoke</code> или вставляю <code>AsParallel()</code> в цепочку LINQ-запроса и надеюсь на лучшее. Но если мне нужно почитать <a href="http://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D1%81%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%9B%D0%B5%D0%B2%D0%B5%D0%BD%D1%88%D1%82%D0%B5%D0%B9%D0%BD%D0%B0" title="http://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D1%81%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%9B%D0%B5%D0%B2%D0%B5%D0%BD%D1%88%D1%82%D0%B5%D0%B9%D0%BD%D0%B0">дистанцию Левенштейна</a> на огромном наборе данных, то я даже напрягаться не буду &ndash; отошлю все данные в неуправляемый код, а там уж сделаю все «правильно».</p>
<h3>Заключение</h3>
<p>Я надеюсь, что повышенное внимание к С++ приведет к улучшению редактора. Правильный IntelliSense уже будет достижением. А что еще надо &ndash; ах да, возможно какой-нибудь генератор P/Invoke оберток и соответствующей документации для того чтобы упростить процесс.</p>
<p>К слову скажу, что недавно пытался найти нормальный блог по С++ путем вбивания &ldquo;с++ блог&rdquo; в гугле. Гугл выдал какой-то мусор. Если кто-то знает интересные блоги на русском, дайте ссылочку в комментариях. Спасибо.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/programming/'>Programming</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/cplusplus/'>cplusplus</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/854/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/854/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/854/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/854/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/854/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/854/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/854/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/854/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/854/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/854/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/854/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/854/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/854/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/854/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=854&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/10/30/cplusplus-resurrection/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://nesteruk.org/pix/0/ebb7a797-5f72-448d-8950-1b2cb8ff1f8d.png" medium="image" />
	</item>
		<item>
		<title>Язык программирования D</title>
		<link>http://nesteruk.wordpress.com/2011/08/28/d-programming-language/</link>
		<comments>http://nesteruk.wordpress.com/2011/08/28/d-programming-language/#comments</comments>
		<pubDate>Sun, 28 Aug 2011 18:14:49 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[D]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=834</guid>
		<description><![CDATA[У любого вменяемого программиста который сталкивается с языком программирования С++ должно рано или поздно возникать чувство отвращения и полной богозабытости. И если в случае с Java кто-то еще может поспорить что &#8220;светлое будущее впереди&#8221; (фиаско с Java 7 как бы намекает), то с С++ мне кажется определились все: и те кто недавно перешли или решили [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=834&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://nesteruk.org/pix/0/661674fe-a3a7-455b-8277-93fadb714b33.png" class="alignright" align="right" alt="" style="border:0;" />У любого вменяемого программиста который сталкивается с языком программирования С++ должно рано или поздно возникать чувство отвращения и полной богозабытости. И если в случае с Java кто-то еще может поспорить что &ldquo;светлое будущее впереди&rdquo; (фиаско с Java 7 как бы намекает), то с С++ мне кажется определились все: и те кто недавно перешли или решили просто попробовать, и те кто с ним работают десятилетиями.</p>
<p>С++ устарел. Программы на С++, как бы красиво они не выглядели, не соответствуют современным реалиям. Попытки пропатчить C++ под 0x/2011 выглядят трезвыми только на фоне того, что в &ldquo;плюсах&rdquo; появились лямбда-выражения, а в Java 7 у Oracle нехватило силенок их сделать.</p>
<p>Вообще, мне по большому счету все равно. Все равно насчет Java-стека т.к. на Java я не пишу, на Scala меня не тянет (синтаксис F# на порядок лучше, имхо). С другой стороны, у меня есть небольшие &ldquo;вкрапления&rdquo; С++ в проекты, поэтому о них наверное стоит рассказать.</p>
<h3>Зачем нужен С++?</h3>
<p>Конкретно мне С++ нужен для параллелизации. Нет, поймите меня правильно, я ни в коей случае не против TPL и всяких прелестей вроде <code>Parallel.For</code> или <code>AsParallel()</code>. Более того, все что я сейчас делаю с коллекциями обычно содержит использование TPL т.к. это достаточно безопасный способ ускорить программу.</p>
<p>Но есть ряд областей где .Net-а мало. Возьмем например обработку изображений &ndash; даже если вы напишете обработку Bitmap&rsquo;а в <code>unsafe</code> режиме на C#, это все равно будет существенно медленнее чем использование C++. Особенно если учесть, что в плюсах есть доступ к SSE (<code>__mm_mul_ps</code> и все такое). И самое главное, что манипуляций-то никаких особо не нужно, т.к. класс <code>System.Drawing.Bitmap</code> может выдать указатель на фиксированный блок памяти, который в последствии можно через P/Invoke передать в тело метода на C++. А дальше можно использовать все прелести OpenMP, Threading Building Blocks, а также мощный инструментарий.</p>
<p>Кстати о&hellip; думаю стоит пояснить, что я религиозно использую <strong>стек Intel</strong>, т.е. <a href="http://software.intel.com/en-us/articles/intel-parallel-studio-home/" title="http://software.intel.com/en-us/articles/intel-parallel-studio-home/">Intel Parallel Studio</a> со всеми прелестями. Это важно потому что инструментарий этот достаточно хороший и много чего умеет, компилятор С++ от Microsoft в былые годы (до Intel) был ооочень слабоват &ndash; в те времена, чтобы заработали примеры из <a href="http://www.amazon.com/Generative-Programming-Methods-Tools-Applications/dp/0201309777" title="http://www.amazon.com/Generative-Programming-Methods-Tools-Applications/dp/0201309777">Generative Programming</a>, нужно было использовать KAI C++, Metrowerks или еще какой-то сторонний компилятор. Мне правда повезло &ndash; на шаблонное метапрограммирование я так и не подсел, хотя идея конечно заманчива.</p>
<p>Итак, если прорезюмировать то, зачем мне С++ нужен, должен сказать, что нужен он для производительности в параллелизуемых алгоритмах. Для нативных библиотек С++ не критичен, т.к. всегда можно написать P/Invoke обертку или скачать уже готовую, а вот для новых, свежих алгоритмов &ndash; при условии что они не требуют качественного библиотечного окружения &ndash; С++ очень даже подходит.</p>
<h3>А причем тут D?</h3>
<p>Я уже давно хотел попробовать D, но все нехаватало времени. Теперь же у меня получилось истратить день на изучение особенностей языка и выборочное читание частей <a href="http://www.amazon.com/D-Programming-Language-Andrei-Alexandrescu/dp/0321635361" title="http://www.amazon.com/D-Programming-Language-Andrei-Alexandrescu/dp/0321635361">The D Programming Language Александреску</a>. Книга, кстати, классная &ndash; объем информации большой, написано с долей весьма своеобразного юмора.</p>
<p>Собственно использование D под Windows требует от вас две вещи.</p>
<p>Во-первых, нужно скачать компилятор. Инсталлятор (MSI) все делает сам, напрягаться толком не нужно.</p>
<p>Во-вторых, хоть это и опционально, можно скачать IDE или пакет поддержки уже существующей IDE. Я конечно же скачал <a href="http://dsource.org/projects/visuald" title="http://dsource.org/projects/visuald">Visual D</a> &ndash; пакет для Visual Studio. Особенности пакета:</p>
<ul>
<li>
<p>Позволяет создавать проекты на языке D и конфигурировать их</p>
</li>
<li>
<p>Весьма слабо поддерживает IntelliSense &ndash; можно сказать что поддержки практически нет</p>
</li>
<li>
<p>Есть отладка (YMMV, конечно же)</p>
</li>
<li>
<p>Все это, увы, 32-bit</p>
</li>
</ul>
<p>Одна из фееричных особенностей использования D &ndash; это то, что <strong>компиляция практически моментальна</strong>. Всем кто привык работать со студией это должно выносить мозг. Вы нажали F6, и программа скомпилировалась &ndash; вот так, просто.</p>
<h3>D vs. C++</h3>
<p>В чем же приемущества D? Попробую перечислить то, что бросилось в глаза:</p>
<ul>
<li>
<p>Нет этого бреда с заголовочными файлами, <code>#pragma once</code> и т.п. Порядок файлов в проекте тоже не важен (F#, я смотрю на тебя). Пишешь <code>module foo</code> в одном файле и <code>import foo</code> в другом.</p>
</li>
<li>
<p>Строки&hellip; строки вменяемы, почти как в C#. Почти потому что остались извраты с UTF-16 и UTF-32 для тех кто знает в этом толк. Да, естественно что до .Net в плане глобализации не дотянуть &ndash; но цель не в этом.</p>
</li>
<li>
<p>Сборка мусора. При этом можно выделять память собственноручно если вдруг у вас приступ мазахизма.</p>
</li>
<li>
<p>Свойства! Java и С++ могут убить себя об стену, <code>__declspec(property)</code> идет лесом. Свойства, имхо, должны быть в любом современном языке программирования. И тут они есть, и ими приятно пользоваться.</p>
</li>
<li>
<p>Piece de resistance: ключевое слово <code>mixin</code>. Самый вменяемый подход к метапрограммированию, который просто ставит в угол Boo, Nemerle и иже с ними.</p>
</li>
</ul>
<p>Язык D отличается очень продуманным, вменяемым дизайном и при этом не несет с собой кучу устаревшей/спорной идеологии на тему того что, например, публичные поля это плохо, надо делать свойства.</p>
<h3>Mixin</h3>
<p>Как работает метапрограммирование в языках вроде Boo? Там с помощью цитирования создается объектная модель кода &ndash; например <code>[| x + y |]</code> превращается в <code>BinaryExpression</code>. Вставки из реального мира делаются с помощью splice-оператора <code>$</code>. Тем самым, чтобы <em>хоть что-то</em> сгенерировать, нужно уметь создавать объектную модель нужного кода.</p>
<p>В большинстве случаев это вообще не нужно. Гораздо проще взять и сгенерировать строку (на подобии T4), которая создает текстовое представление и добавляет его в исходный код на этапе компиляции. Это в 100 раз проще чем мучаться с объектной моделью компилятора.</p>
<p>В языке D, инструкция <code>mixin</code> просто принимает строку. Напишите <code>mixin("string Name;")</code> и вы добавили в класс поле <code>Name</code>. Тривиально. Естественно что строки можно не только передавать напрямую, но и создавать отдельные функции, которые <em>исполняются на этапе компиляции</em>. Это решает проблему метапрограммирования в большинстве случаев.</p>
<h3>Недостатки</h3>
<p>Куда же без них. Вот то, что я успел заметить:</p>
<ul>
<li>
<p>Дебаггер порой идет совсем не туда куда нужно. Вложенные функции и делегаты дебажатся &ldquo;с грехом пополам&rdquo;.</p>
</li>
<li>
<p>Конкретно под Windows, D компилируется только в 32-bit.</p>
</li>
<li>
<p>Стандартные библиотеки конечно не дотягивают до какой-нть STL но они намного более вменяемы. Так что это палка о двух концах.</p>
</li>
<li>
<p>Стандартных библиотек на самом деле две &ndash; Phobos и Tango. Какую использовать &ndash; непонятно. В Phobos я уже столкнулся с недопиленностью &ndash; например <code>std.xml</code> сейчас переписывается.</p>
</li>
<li>
<p>Никто пока не воспринимает D серьезно. Даже у F# больше exposure чем у D, что собственно понятно &ndash; ведь F# продвигает Microsoft и этот язык активно используется в quant finance.</p>
</li>
<li>
<p>IntelliSense не работает в Visual D. Надо будет еще глянуть на D-IDE которая, кстати, написана под .Net 4 :)</p>
</li>
</ul>
<h3>Впечатления</h3>
<p>Мне D <em>очень понравился</em>. Это язык с максимальным уровнем вменяемости и достаточно низким уровнем шума. Если вам не нужно завязок на 100 библиотек, D позволит вам быстро разрабатывать и компилировать ваш код. При этом вы не теряете в выразительности &ndash; тут и делегаты, и события, и вложенные функции, функциональные литералы (= лямбда-выражения), не говоря уже о совсем продвинутых вещах вроде вариадичных шаблонов.</p>
<p>Резюмируя, должен сказать что D меня очаровал, и в ближайшее время я планирую его использовать к некритичных, non-production проектах дабы прочувствовать все его возможности. А они, судя по первичным наблюдениям, весьма обширны.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/d/'>D</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/834/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/834/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/834/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/834/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/834/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/834/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/834/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/834/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/834/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/834/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/834/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/834/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/834/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/834/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=834&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/08/28/d-programming-language/feed/</wfw:commentRss>
		<slash:comments>66</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://nesteruk.org/pix/0/661674fe-a3a7-455b-8277-93fadb714b33.png" medium="image" />
	</item>
		<item>
		<title>Нужен ли математикам статический анализ?</title>
		<link>http://nesteruk.wordpress.com/2011/08/18/do-quants-need-static-analysis/</link>
		<comments>http://nesteruk.wordpress.com/2011/08/18/do-quants-need-static-analysis/#comments</comments>
		<pubDate>Thu, 18 Aug 2011 19:22:54 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[quant]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=825</guid>
		<description><![CDATA[Есть такая профессия, в которой люди на 50% процентов занимаются программированием, но при этом сидят на порой весьма &#8220;несовременных&#8221; технологиях, пишут в основном на С++, и никаких особых бенефитов от IDE вообще не имеют. И при этом не жалуются. В этом посте &#8211; про то, кто эти люди, чем они заниматся и чем мы можем [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=825&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Есть такая профессия, в которой люди на 50% процентов занимаются программированием, но при этом сидят на порой весьма &ldquo;несовременных&rdquo; технологиях, пишут в основном на С++, и никаких особых бенефитов от IDE вообще не имеют. И при этом не жалуются. В этом посте &ndash; про то, кто эти люди, чем они заниматся и чем мы можем сделать их жизнь лучше.</p>
<h3>Знакомьтесь &ndash; квонты</h3>
<p><a href="http://ru.wikipedia.org/wiki/%D0%9A%D0%B2%D0%BE%D0%BD%D1%82" title="http://ru.wikipedia.org/wiki/%D0%9A%D0%B2%D0%BE%D0%BD%D1%82">Квонт</a>, он же quant (quantitative analyst &ndash; численный, так сказать, аналитик) &mdash; это человек, который занимается применением математики в финансах, часто &ndash; для создания торговых систем, т.е. программ, которые занимаются автоматизированной торговлей на бирже. Эти люди &ndash; чаще всего магистры или PhD в области физики (да-да) или математики (в частности, с дипломами вроде MFE &ndash; Masters in Financial Engineering), в некоторых случаях, с дипломом <a href="http://www.cqf.com/" title="http://www.cqf.com/">CQF</a> (один из очень небольшого кол-ва &ldquo;неакадемических&rdquo; дипломов) или даже с MBA Finance или а ля.</p>
<p>Квонты (я бы называл их кв<em>а</em>нтами) программируют в очень узком ключе &ndash; их в большинстве случаев не волнуют новые тренды в Asp.Net или новых языках вроде Scala или D. Они живут в совершенно другой реальности, где доминантным маст-хэв языком был, есть и будет С++. Конечно, есть варинты (например, вспомним <a href="http://www.janestcapital.com/" title="http://www.janestcapital.com/">Jane Street</a> и их любовь к OCaml), но суть остается одна &ndash; эти разработчики привыкли работать с достаточно ограниченным tool support, и не особо от этого страдают. Ведь согласитесь, для того чтобы эффективно выполнять математические рассчеты нужно лишь чтобы у вас худо-бедно работал intellisense, и то, это не так критично если нужно вызвать что-то вроде <code>std::min()</code>.</p>
<p>Соответственно, текущее положение вещей наводит на мысль, что людям которые используют в основном C++ (а также MATLAB, VBS, R, ну и другие языки на вкус) tool support как бы не очень нужен.</p>
<h3>И все же&hellip;</h3>
<p>Приведу конкретный пример. На многих графических устройствах, операция <code>a*x+b</code> оптимизирована и проходит быстрее, чем умножение и сложение отдельно. Соответственно, когда я работаю с GPU.NET, у меня есть в <a href="http://activemesa.com/r2p" title="http://activemesa.com/r2p">R2P</a> контекстное действие, которое превращает все, что похоже на &ldquo;умножение-в-сложении&rdquo; на вызов вроде <code>DeviceMath.MultiplyAdd(a, x, b)</code>. Мелочь, а приятно, и программу ускоряет.</p>
<p>И это далеко не частный случай. Вот еще пример &ndash; допустим что вы попросили студента за еду реализовать вам ряд формул в коде, и студент в качестве реализации написал что-то вроде <code>y = a * Math.Pow(x, 2.0) + b * x</code>. Бред, не так ли?</p>
<p>И тут снова можно включить &ldquo;электронный мозг&rdquo; статического анализатора и начать помогать несчастному разработчику. Для начала ему нужно объяснить, что считать ряды Тэйлора в подобном случае раз, эээ, в 50 медленнее чем сделать <code>x*x</code>. Но даже объяснив это, вы получите вот такой результат:</p>
<p><pre class="brush: csharp;">
y = a * x * x + b * x;
</pre>
<p>Это тоже не очень-то эффективно. Ведь тут целых 3 умножения, хотя можно обойтись двумя:</p>
<p><pre class="brush: csharp;">
y = x * (a * x + b);
</pre>
<p>Опаньки, а это факторизация, задачка уже посложнее, особенно в контексте статического анализа. Тем не менее, она решабельна, и позволит квонту хоть немного но ускорить вычисления.</p>
<h3>А это имеет смысл?</h3>
<p>Действительно, кому нужна скорость? Ну, наблюдения показывают что ряд задач (например, Монте-Карло симуляции) очень любят кушать CPU. Микрооптимизация вычислений &ndash; это как раз то, что позволит аналитику протестировать свою стратегию быстрее, на большем объеме данных.</p>
<p>Еще одна полезная, хотя и тривиальная вещь &ndash; это рефакторинги с уклонов в сторону параллелизации &ndash; например рефакторинг <code>for</code> и <code>foreach</code> циклов в параллельные с сохранением правильной семантики. То есть, если разработчик написал</p>
<p><pre class="brush: csharp;">
int [] elems = new int[] { ⋮ };
int sum = 0;
foreach (var e in elems) sum += e;
</pre>
<p>то почему бы нам не дать ему возможность отрефакторить этот цикл в параллельный:</p>
<p><pre class="brush: csharp;">
Parallel.ForEach(elems, () =&gt; 0, 
                 (n, loopState, localSum) =&gt; 
                 {
                   localSum += n;
                   return localSum;
                 },
                 localSum =&gt; Interlocked.Add(ref sum, localSum));
</pre>
<p>У меня в R2P уже реализованы некоторые приведения простых циклов в параллельные, но это большая задача, и за один день ее не решить.</p>
<h3>Другие языки?</h3>
<p>Я привел пример поддержки C#, т.к. не знаю доступной инфраструктуры для написания рефакторингов для С++ или (это было бы еще интересней) для CUDA C. Было бы интересно услышать мнение читателей насчет применимости всех этих идей.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/c-2/'>c++</a>, <a href='http://nesteruk.wordpress.com/tag/math/'>math</a>, <a href='http://nesteruk.wordpress.com/tag/quant/'>quant</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/825/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=825&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/08/18/do-quants-need-static-analysis/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Управление подписками на события</title>
		<link>http://nesteruk.wordpress.com/2011/08/02/managing-event-subscriptions/</link>
		<comments>http://nesteruk.wordpress.com/2011/08/02/managing-event-subscriptions/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 03:27:48 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[rx]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=818</guid>
		<description><![CDATA[Итак, небольшая заметка на тему того, как я работаю с подписками на события. Проблема такая: у меня есть XMPP-клиент, он генерирует тучу событий, которые хочется отловить, но помимо этого, еще иногда нужно делать reset этому клиенту, напрочь удаляя все подписки и создавая новые. Для начала, я создаю класс DisposableCollection который умеет вызывать Dispose() на каждом [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=818&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Итак, небольшая заметка на тему того, как я работаю с подписками на события. Проблема такая: у меня есть XMPP-клиент, он генерирует тучу событий, которые хочется отловить, но помимо этого, еще иногда нужно делать reset этому клиенту, напрочь удаляя все подписки и создавая новые.</p>
<p>Для начала, я создаю класс <code>DisposableCollection</code> который умеет вызывать <code>Dispose()</code> на каждом элементе коллекции:</p>
<p><pre class="brush: csharp;">
public sealed class DisposableCollection : Collection&lt;IDisposable&gt;, IDisposable
{
  public void Dispose()
  {
    foreach (var obj in this)
      obj.SafeDispose();
  }
}
</pre>
<p><code>SafeDispose()</code> в коде выше &ndash; это всего лишь <code>Dispose()</code> с проверкой на <code>null</code>. Метод также возвращает «флаг успешности», что порой бывает полезно.</p>
<p><pre class="brush: csharp;">
public static bool SafeDispose(this IDisposable thіs)
{
  if (thіs != null)
  {
    thіs.Dispose();
    return true;
  }
  return false;
}
</pre>
<p>Еще один extension method &mdash; это инверсия потока управления для добавления элементов в коллекцию:</p>
<p><pre class="brush: csharp;">
public static T AddTo&lt;T&gt;(this T thіs, Collection&lt;T&gt; coll)
{
  coll.Add(thіs);
  return thіs;
}
</pre>
<p>А теперь всем этим можно пользоваться. Для подписок используем ReactiveExtensions.</p>
<p><pre class="brush: csharp;">
public sealed class XmppConnectionManager : IResetable
{
  private XmppClient client;
  private DisposableCollection subscriptions;
  private void InitializeEvents()
  {
    // wire up events
    Observable.FromEventPattern&lt;ExceptionEventArgs&gt;(x =&gt; client.OnError += x, x =&gt; client.OnError -= x)
      .Subscribe(x =&gt; OnError(x.EventArgs))
      .AddTo(subscriptions);
    Observable.FromEventPattern&lt;EventArgs&gt;(x =&gt; client.OnLogin += x, x =&gt; client.OnLogin -= x)
      .Subscribe(x =&gt; OnLogin(x.EventArgs))
      .AddTo(subscriptions);
    ...
  }
}
</pre>
<p>Соответственно, если нужно вдруг отписаться от всех подписок, это делается очень быстро:</p>
<p><pre class="brush: csharp;">
subscriptions.SafeDispose();
</pre>
<p><strong>А теперь загадка</strong>: почему методы расширения, приведенные выше, компилируются несмотря на название параметра <code>thіs</code>? Дам намек: как ключевое слово имя параметра не подсветилось.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a>, <a href='http://nesteruk.wordpress.com/category/c/'>C#</a>, <a href='http://nesteruk.wordpress.com/category/net/rx/'>rx</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/818/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/818/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/818/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/818/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/818/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/818/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/818/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/818/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/818/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/818/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/818/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/818/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/818/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/818/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=818&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/08/02/managing-event-subscriptions/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Оптимизация математических выражений для CPU и GPU</title>
		<link>http://nesteruk.wordpress.com/2011/07/14/math-parsing-optimization/</link>
		<comments>http://nesteruk.wordpress.com/2011/07/14/math-parsing-optimization/#comments</comments>
		<pubDate>Thu, 14 Jul 2011 19:47:53 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=803</guid>
		<description><![CDATA[Когда я создавал MathSharp, я преследовал вполне простую цель &#8212; мне нужно было чтобы уравнения, которые записали инженеры, могли быть точно и аккуратно переведены из языка формул на язык C#. На практике, это означает, что написав красивое уравнение вроде его можно автоматически сконвертировать во что-то подобное: Код выше, как вы видите, оптимизирует количество умножений, и [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=803&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Когда я создавал <a href="http://activemesa.com/mathsharp" title="http://activemesa.com/mathsharp">MathSharp</a>, я преследовал вполне простую цель &mdash; мне нужно было чтобы уравнения, которые записали инженеры, могли быть точно и аккуратно переведены из языка формул на язык C#. На практике, это означает, что написав красивое уравнение вроде <img src='http://s0.wp.com/latex.php?latex=y+%3D+ax%5E2%2Bbx%2Bc&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='y = ax^2+bx+c' title='y = ax^2+bx+c' class='latex' /> его можно автоматически сконвертировать во что-то подобное:</p>
<p><pre class="brush: csharp;">
public void y(double a, double b, double c, double x)
{
  return x*(a*x + b) + c;
}
</pre>
<p>Код выше, как вы видите, оптимизирует количество умножений, и в общем случае, MathSharp старается срезать стоимость вычислений к абсолютному минимуму, не прибегая в этом к <a href="http://en.wikipedia.org/wiki/Fast_inverse_square_root" title="http://en.wikipedia.org/wiki/Fast_inverse_square_root">особо извращенным методам</a>.</p>
<p>Код выше легко генерить, и созданное AST позволит вам создать код на любом языке, будь то на C#, F# или C++. Но зачем останавливаться на этом?</p>
<p>Недавно, я начал работать с <a href="http://www.tidepowerd.com/" title="http://www.tidepowerd.com/">GPU.NET</a>. Несмотря на наблюдения автора одной не особо хорошо отрецензированной <a href="http://www.rsdn.ru/article/dotnet/CudaLibs.xml" title="http://www.rsdn.ru/article/dotnet/CudaLibs.xml">статьи</a> на RSDN, библиотека работает, и подход мне нравится. А поэтому, мне пришла в голову (гениальная?) мысль &mdash; MathSharp может оптимизировать код не только для CPU но и для GPU! В результате, наша функция выше может выглядеть вот так:</p>
<p><pre class="brush: csharp;">
public void y(double a, double b, double c, double x)
{
  return DeviceMath.MultiplyAndAdd(DeviceMath.MultiplyAndAdd(a, x, b), x, c);
}
</pre>
<p>Суть тут в том, что некоторые GPU обрабатывают вычисление <img src='http://s0.wp.com/latex.php?latex=ax%2Bb&amp;bg=ffffff&amp;fg=1c1c1c&amp;s=0' alt='ax+b' title='ax+b' class='latex' /> еще быстрее, чем эти операции отдельно (типа <a href="http://en.wikipedia.org/wiki/Multiply-accumulate_operation" title="http://en.wikipedia.org/wiki/Multiply-accumulate_operation">пруф</a>). И это только вершина айсберга &mdash; по-хорошему, вариантов для оптимизации &ndash; масса.</p>
<p>Кстати, MathSharp &mdash; это такой небольшой пруф того, что приложение может быть написано на F#, использовать функциональные фишки (алгебраические типы, рекурсивный частичный паттерн-матчинг) и при этом жить, продаваться, развиваться. Правда если хотите tool support то вам скорее <a href="https://github.com/ActiveMesa/FSharper" title="https://github.com/ActiveMesa/FSharper">сюда</a> &mdash; увы, я решил что делать из FSharper коммерческий продукт &ndash; слишком сложно. Основная причина &ndash; что F# не &ldquo;тянет&rdquo; чтобы парсить сам себя. По скорости не тянет. На GPU может и можно, но это нужно исследовать.</p>
<p>Ну и напоследок &ndash; кто-нибудь может посоветовать workflow engine для коротких операций? Не workflow foundation со всем его багажом, а что-нибудь легковесное, чтобы можно было &ldquo;самодокументировать&rdquo; алгоритмы через какой-нть fluent interface или dsl. Заранее спасибо.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/technology/'>Technology</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/803/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/803/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/803/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=803&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/07/14/math-parsing-optimization/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Распределенная разработка и проект FreeSpace</title>
		<link>http://nesteruk.wordpress.com/2011/06/16/distributed-development-project-freespace/</link>
		<comments>http://nesteruk.wordpress.com/2011/06/16/distributed-development-project-freespace/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 20:00:08 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Computation]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[freespace]]></category>
		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=784</guid>
		<description><![CDATA[Пришло время рассказать про тот проект, про который я говорил в моем последнем подкасте. Проект называется FreeSpace (рабочее название, но мне нравится) и затрагивает, конечно же, вопрос распределенного управления программным кодом. Иначе говоря, я строю инфраструктуру для эффективной разработки с использованием большого количества машин. С чего все начиналось Когда я обитал в сфере финансового программирования [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=784&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Пришло время рассказать про тот проект, про который я говорил в моем <a href="http://spbaltnet.podfm.ru/solo/36/" title="http://spbaltnet.podfm.ru/solo/36/">последнем подкасте</a>. Проект называется FreeSpace (рабочее название, но мне нравится) и затрагивает, конечно же, вопрос распределенного управления программным кодом. Иначе говоря, я строю инфраструктуру для эффективной разработки с использованием большого количества машин.</p>
<h3>С чего все начиналось</h3>
<p>Когда я обитал в сфере финансового программирования (было же такое), одна из задач была в том, чтобы &ldquo;сливать&rdquo; воедино финансовые показатели из различных источников. Начиналось все достаточно просто &ndash; берем какую-то котировку, делаем для нее квантизацию (это когда нужно подсчитать агрегированные значения за последнюю минуту/час/день и т.п.) а потом начинаем считать всякие показатели (к пр. движимое среднее). Сейчас такие задачи делаются с помощью Reactive Extensions, под которым, должен сказать, аггрегаторы и квантизаторы выглядят не лучшим образом. Тогда же это делалось более примитивными методами. Но не суть&hellip;</p>
<p>Так вот, в те времена подход <a href="http://gpgpu.org/" title="http://gpgpu.org/">GPGPU</a> был не ахти какой популярный, и соответственно все утыкалось в слабый перформанс моего одноядерного процессора. И, естественным путем, я набрел на то, что по-хорошему нужно использовать <em><font face="Candara" />несколько машин</font></em> чтобы все эффективно считать. Механизмы общения между компьютерами в те времены были ни ахти какие, соответственно использовались такие извращения как <a href="http://www.nservicebus.com/" title="http://www.nservicebus.com/">NServiceBus</a>/MSMQ которые, конечно, имеют свои приемущества, но все же &ldquo;не айс&rdquo;.</p>
<p>Самым прикольным было написать <a href="http://bitbucket.org/nesteruk/mdxconsole" title="http://butbucket.org/nesteruk/mdxconsole">консоль</a>, которая показывала бы как моя сеть в realtime обсчитывала те или иные показатели. Более того, в те времена я также использовал нейронные сети (MLPs w/backpropagation) и у меня даже остался код, которые по объектным моделям сетей генерировал диаграммы в PowerPoint. Забавное было зрелище.</p>
<h3>Сети &ndash; это же так соблазнительно!</h3>
<p>Качество работы на среднестатистической &ldquo;винде&rdquo; прогрессивно снижается. Когда я начинал программировать на Visual Studio 97, в моем компьютере было 16Мб (мегабайт!!!) RAM, но при этом все работало. Сейчас такой experience можно получить разве что скачав EVC++ 4 (завидую эмбедщикам!). У нас же в плане разработки все плохо &ndash; сплошные тормоза. Вон только вчера коллега рассказал, что получил удовольствие от использования Visual Studio 2008 для части ReSharper SDK. Когда я его спросил что у него за машина, оказалось что и 16Gb RAM и SSD у него присутствуют. Так что делаем выводы&hellip;</p>
<p>Все это наводит на достаточно печальные мысли. Компьютеры будут становиться быстрее, но &ldquo;затыки&rdquo; в производительности будут, и со временем они будут все больше и больше. А нам нужно разрабатывать, а не ждать 15 минут пока полсотни референсов в проект добавятся (таргет-файлы рулят!).</p>
<p>Поэтому единственная вменяемая стратегия, к которой я на данный момент пришел сводится к следующим вещам.</p>
<p>Во-первых, я ратую за <strong>экологичное программирование</strong>, т.е. если вы используете машину для разработки, не стоит на ней ставить доменный контроллер, IIS, AppFabric и еще 100500 различных сервисных примочек. Ни в коем случае не стоит ставить серверные технологии которые используют SQL Server т.к. эта штука сама по себе съест 1-2Gb оперативки, так она еще и будет диск дергать даже когда никто к ней не обращается. А потом, в один прекрасный день, вы увидите что вместо того чтобы разрабатывать, вы думаете как бы засунуть SQL Server&rsquo;ный кэш в RAM. Или что-то в этом духе.</p>
<p>Во-вторых, я за <strong>распределенную разработку</strong>. Писать код можно и на одном компьютере. Но держите свои затраты к минимуму. Ставьте десктопную ось (да-да, сейчас модно ставить 2008R2 везде где не попадя, я тоже на это попался в свое время). Если можете себе это позволить &ndash; ставьте XP. Windows, VS и ReSharper/dotTrace/dotCover/TortoiseXxx &ndash; плагины, естественно по вкусу. Остальное &ndash; в топку! А точнее на другой компьютер.</p>
<h3>Что это дает?</h3>
<p>Я уже слышу крики в стиле &ldquo;мне всего и так хватает!&rdquo;. Что же, если вам итак хорошо, рад за вас. Это как <a href="http://www.codinghorror.com/blog/2004/06/multiple-monitors-and-productivity.html" title="http://www.codinghorror.com/blog/2004/06/multiple-monitors-and-productivity.html">извечная дискуссия про мониторы</a> &ndash; каждому свое. Но если говорить о <em><font face="Candara" />приемуществах</font></em> такого подхода, то их масса.</p>
<p>Главное приемущество &ndash; это <strong>моментальный фидбэк</strong>. Представьте, что у вас есть солюшн который собирается, скажем, две минуты. Две минуты &ndash; это <em><font face="Candara" />вечность</font></em>. Особенно если билд провалился с какой-то дурацкой ошибкой которую не отловил статический анализатор. Да, мы говорим не про простенькие проектики, мы говорим например про системы где смешан С++ (адски медленная компиляция), C# и Java (да-да, Java &ndash; она примешана тут осознанно). Если учесть сложность cross-VM конфигов, все это дело работает не так быстро как хотелось бы.</p>
<p>Так вот, представьте себе систему, где фидбэк по сборке, тестам, и даже покрытию (хотя с покрытием сложнее) получается <em><font face="Candara" />моментально</font></em>. Причем он никак не затрагивает ваш разработческий комп, т.к. мы договорились держать его стерильным. Моментальный фидбэк стоит многого! Особенно это затрагивает такую проблему как тестирование на staging-серверах. На Хабре был <a href="http://habrahabr.ru/blogs/net/120755/" title="http://habrahabr.ru/blogs/net/120755/">пост</a> про то, надо ли стабить репозитарии. Так вот что я думаю &ndash; <em><font face="Candara" />если вы можете себе это позволить, тестируйте на staging-базах</font></em>! Главное чтобы эти тесты не вызывали затыков. А если вызывает затыки &ndash; просто добавьте <del>воды</del> машин!</p>
<p>Второе приемущество &ndash; это то, что <strong>ничего не отвлекает</strong>. Я категорически против подхода, когда люди в свою Студию устанавливают 1000 различных дополнений для всяких микро-фич которые, особенно если они используют визуальные элементы, тормозят все до такого состояния, что работать невозможно. Но я не столько про стороннии фичи говорю, сколько про два основных источника потери времени &ndash; компиляцию и тестирование. Давайте обсудим их более детально.</p>
<h3>Компиляция</h3>
<p>Разработчики С++ уже давно поняли что сборка проектов должна быть распределенной, и на рынке есть для этого <a href="http://www.electric-cloud.com/" title="http://www.electric-cloud.com/">соответствующие</a> <a href="http://www.xoreax.com/" title="http://www.xoreax.com/">решения</a>. Но если вы думаете, что в .Net все лучше, то вы правы только отчасти. Да, .Net собирается быстрее, хотя я <em><font face="Candara" />уверен</font></em> что новый C#5 компилятор будет намного медленнее в силу своей managed структуры. Опять же, еще один аргумент в том, что де нынче MSBuild поддерживает параллелизацию напрямую, и тем самым грамотное использование MSBuild вместе с правильной, loosely coupled архитектурой, как бы избавляет нас от проблем с медленной компиляцией.</p>
<p>А вот и нет!</p>
<p>На практике все сводится к следующим моментам. Во-первых, <strong>стоимость компиляции связана не только с созданием сборок</strong> &ndash; компиляция как таковая включает в себя массы различных процессов, таких как кастомные task-и которые вы используете. Например, процесс XSLT-трансформации путем какого-нть <a href="http://msbuildtasks.tigris.org/" title="http://msbuildtasks.tigris.org/">community task</a>&lsquo;а может стоить намного больше чем компиляция.</p>
<p>Во-вторых, этот аргумент <strong>не применим на mixed-mode проектах</strong>. С++ играет по своим правилам, особенно если вы делаете что-то сложное. Да, ваша сборка <em><font face="Candara" />может</font></em> скомпилироваться параллельно с другими. Но это не покрывает изначальную проблему &ndash; она скомпилируется медленно. Это, кстати, влияет не только на С++ &mdash; даже тот же F# компилируется медленнее (что понятно), не говоря уже про языки вроде Scala (reminder: Scala компилируется в <strong>10</strong> раз медленнее Java).</p>
<p>В третьих, все как-то забыли что <strong>некоторым проектам нужно собирать несколько конфигураций</strong>. В этом случае параллелизация на уровне конфигураций имеет смысл &ndash; тут мы билдим staging, а тут &ndash; production. Естественно, никто не мешает настроить разные конфигурации на разных build-системах. Действительно, на практике многие разработчики используют TeamCity для параллелизации подобных задач. Одна из самых популярных &ndash; параллелизация тестирования. Кстати о нем&hellip;</p>
<h3>Тестирование</h3>
<p>Тестирование бывает разным. Одно дело когда вы нажали F5 на проекте, который открывает VS в дебаг-режиме. Если у вас комп с 4Gb RAM и Раптором &ndash; вы попали. Можете смело идти за кофе/чаем/печеньками. Отладочный экспириенс будет адским. Да &ndash; и не думайте что удаленная отладка вам поможет. Во-первых, вы замахаетесь ее настраивать (у меня на это полдня ушло), но даже настроив, вы сразу поймете, что игра не стоит свеч &ndash; идея неплохая, но скорость &ndash; улиточная. Snail speed. Если действительно хочется делать отладку на другой машине, более вменяемым решением <em><font face="Candara" />мне лично</font></em> кажется использование VMWare Workstation. Но так или иначе, тормоза будут.</p>
<p>Но я сейчас немного не про это, а скорее про банальное unit/integration-тестирование. Сейчас в этой сфере ведется работы по разным направлениям &ndash; например работы связанные с автопрогоном только тех тестов, которые были затронуты изменениями в коде. Примеры таких программ &ndash; <a href="http://www.ncrunch.net/" title="http://www.ncrunch.net/">NCrunch</a> и <a href="http://continuoustests.com/" title="http://continuoustests.com/">Mighty Moose</a>. А теперь угадайте, какой основной смысл этих программ? Правильно &ndash; экономия ресурсов. Вызывать только те тесты которые <em><font face="Candara" />были затронуты</font></em>. А не все подряд.</p>
<p>На самом деле, это очень сложная задача. В чем проблема вызова абсолютно всех тестов? Правильно, в том, что эти тесты могут задевать сотню различных систем. Да-да, я не только про юнит-тесты говорю, но и про интеграционные тесты &ndash; включая те, которые например дергают реальные базы или устройства. Их-то тоже хочется тестировать, причем опять же вопрос ставится так: если мы можем тестировать постоянно &ndash; почему бы не делать это? Лично я &ndash; ярый сторонник <a href="http://devtalk.net/dotnet/continuous-testing/" title="http://devtalk.net/dotnet/continuous-testing/">непрервыного тестирования</a>. И не только по комиту &ndash; а например по любому компилу. Сделал тестовую сборку &ndash; она <em><font face="Candara" />сразу же</font></em> ушла в тестирование. Если что упало &ndash; результаты <em><font face="Candara" />сразу же</font></em> возвращаются к разработчику.</p>
<h3>Так что там про FreeSpace?</h3>
<p>FreeSpace &ndash; это мое новое детище. FreeSpace &ndash; это Windows-сервис который можно устанавливать на любые машины где угодно. Фактически, этот сервис объединяет машины в ботнет, который умеет заниматься распределенной компиляцией, тестированием, развертыванием, и так далее. FreeSpace работает как на реальных так и на виртуальных машинах, неприхотлив (дружит с ХР) и требует <em><font face="Candara" />минимальное кол-во конфигурирования</font></em>.</p>
<p>FreeSpace использует XMPP (в частности &ndash; библиотеку <a href="http://www.ag-software.de/matrix-xmpp-sdk/" title="http://www.ag-software.de/matrix-xmpp-sdk/">MatriX</a>) и механизмы облачной синхронизации файлов. XMPP гарантирует что машины могут беспрепятственно коммуницировать между собой, при условии что у вас стоит XMPP-сервер (поставить какой-нть <a href="http://www.ejabberd.im/" title="http://www.ejabberd.im/">ejabberd</a> занимает полминуты). А механизмы облачной синхронизации позволяют гарантировать, что на всех инстансах одни и те же файлы. Поскольку сервис работает через MEF, файлы можно обновлять динамически.</p>
<p>Основная цель FreeSpace &ndash; <strong>балансировка нагрузки</strong>, т.е. составление сбалансированных планов исполнения. Собственно выполнение задач на себя берут уже готовые тулзы. Для компиляции, например, это может быть MSBuild, для тестирования &ndash; <a href="http://gallio.org/" title="http://gallio.org/">Gallio</a>. Суть в том, что имея информацию о всех нодах в сети, а также агентах на этих нодах (на одной ноде можно бегать более одного агента), можно сформировать сбалансированный план компиляции или тестирования, который оптимально использует все доступные ресурсы и при этом <em><font face="Candara" />уважает предпочтения самого нода</font></em>, т.е. знает что нельзя перегружать нод, который уже занят или имеет какие-то другие обязанности.</p>
<p>Одно из приемуществ FreeSpace &ndash; системе полностью плевать на домены. Синхронизация через XMPP способна игнорировать все firewall&rsquo;ы и протаскивать трафик <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol#XMPP_via_HTTP_transport" title="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol#XMPP_via_HTTP_transport">через порт 80</a>, если это надо (ну, это теоретически&hellip; это нужно тестировать). При этом трафик можно шифровать, так что идея о том что де кто-то украдет контрольные данные в транзите или подменит их тоже отпадает. А сами файлы синхронизуются с помощью изначально безопасной системы (так по крайней мере нам говорят), поэтому кроме как на нодах к ним не достучаться. И даже достучавшись, система-то распределенная, так что всей картины все равно не получите &ndash; хотя конечно подразумевается, что нодам вы доверяете.</p>
<h3>Более сложные задачи</h3>
<p>Есть более сложные задачи, которые пока не решить ну никак. Во-первых, было бы здорово вынести за пределы компьютера разработчика весь статический анализ и сделать некий &lsquo;FxCop/R#/whatever as a service&rsquo;. Если это сделать, и если это хоть как-то параллелизуемо (есть подозрение что не очень), это позволит делать намного более глубокий/затратный анализ и тем самым получать намного более умные эвристические подсказки.</p>
<p>Покрытие &ndash; запредельно затратная операция, поэтому вынести его наружу тоже хотелось бы. Это, правда, менее приоритетная задача, т.к. я не большой фанат покрытия. Но с другой стороны, имея уже готовый механизм для измерения покрытия (к пр., <a href="http://www.jetbrains.com/dotcover/" title="http://www.jetbrains.com/dotcover/">dotCover</a>), я не вижу никаких причин не применять измерение покрытия, скажем, к разным тестовым фиксчам на разных машинах. Главное чтобы можно было слить все результаты воедино и как-то их продемонстрировать. (Прошу заметить, что в отличии от результатов тестирования, результаты покрытия таки требуют наличие локальной Visual Studio для подсветки и навигации. То же отчасти верно и для обычного юнит-тестирования, хотя там и не нужно вклиниваться в редактор.)</p>
<p>Зато что я люблю так это всякий спекулятивный процессинг. Я бы с удовольствием воспользовался, например, механизмами <a href="http://msdn.microsoft.com/en-us/magazine/hh148145.aspx" title="http://msdn.microsoft.com/en-us/magazine/hh148145.aspx">мутационного тестирования</a>. Ну или например я бы с радостью гонял тесты на производительность параллельных алгоритмов варьируя разные параметры, такие как, к примеру, degree of parallelism.</p>
<h3>Вместо заключения</h3>
<p>FreeSpace разрабатывается в первую очередь не как коммерческий продукт, а как система, которая сможет, при наличии достаточного количества машин, существенно сэкономить количество времени, требуемое для работы с крупными проектами. Соответственно, пишу я ее в основном для себя, с уклоном в те проблемы (например, тестирование в виртуальной среде &ndash; VMM/HyperV) которые являются для меня наиболее насущными.</p>
<p>Я давно не писал в этот блог, но теперь буду писать почаще, особенно если кому-то данная тема покажется интересной. И естественно, я выпущу дистрибутив системы как только у меня будет что релизить. Основной concern в данном случае в том, что я очень хочу сделать систему обновляемой, чтобы она и ее плагины (я использую плагин-архитектуру на основе MEF) могли автоматически обновляться по мере выхода новых версий.</p>
<p>А пока всё! Comments welcome!&nbsp;■</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a>, <a href='http://nesteruk.wordpress.com/category/computation/'>Computation</a>, <a href='http://nesteruk.wordpress.com/category/development/'>Development</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/freespace/'>freespace</a>, <a href='http://nesteruk.wordpress.com/tag/xmpp/'>xmpp</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/784/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/784/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/784/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/784/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/784/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/784/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/784/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/784/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/784/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/784/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/784/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/784/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/784/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/784/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=784&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/06/16/distributed-development-project-freespace/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Хранение preset-ов в setting-ах</title>
		<link>http://nesteruk.wordpress.com/2011/06/05/presets-in-settings/</link>
		<comments>http://nesteruk.wordpress.com/2011/06/05/presets-in-settings/#comments</comments>
		<pubDate>Sun, 05 Jun 2011 20:22:37 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=780</guid>
		<description><![CDATA[Сегодня я зарелизил версию 1.7.2 Типографикса, добавив всего одну фичу &#8211; возможность держать несколько наборов настроек. Сделал я это для того, чтобы можно было сохранять настройки редактора для разных платформ &#8211; в моем случае, для этого блога и devtalk, а также для Хабра, ГДН, CodeProject&#8217;а и других систем. Примечательно то, что простенькая задача сохранить в [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=780&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Сегодня я зарелизил версию 1.7.2 Типографикса, добавив всего одну фичу &ndash; возможность держать несколько наборов настроек. Сделал я это для того, чтобы можно было сохранять настройки редактора для разных платформ &ndash; в моем случае, для этого блога и devtalk, а также для Хабра, ГДН, CodeProject&rsquo;а и других систем.</p>
<p>Примечательно то, что простенькая задача сохранить в словарике несколько пресетов и потом записать все это в <code>Properties.Settings</code> превратилась в непростую затею.</p>
<h3>Первая попытка</h3>
<p>Сначала я сделал все правильно: создал <code>Dictionary&lt;string, ConversionOptions&gt;</code>, то есть мэп названий пресетов на их значения, и тупо попробовал записать все это в настройки. Ничего не получилось. Оказывается, большое количество классов в WPF (такие как <code>Color</code> или <code>Thickness</code>) не сериализуются! Это значит, что по сути дела чтобы сериализовать тип мне нужно их выкинуть!</p>
<p>Следующей проблемой оказалось то, что .Net бросал исключение при попытке сериализовать событие <code>PropertyChanged</code>. Это правда очень быстро релилось прописыванием <code>[field: NonSerialized]</code>, но толком делу не помогло.</p>
<h3>Вторая попытка</h3>
<p>Проблема в том, что несмотря на то, что все работало, настройки отказались записывать <code>Dictionary&lt;&gt;</code>. Никаких исключений не было, тип просто не сохранялся в <code>Properties.Settings</code> и воответственно при попытке считать, возвращался <code>null</code>.</p>
<p>Самое простое в этом случае (точно так же как и в случае с несериализуемыми типами) &ndash; это сконвертировать структуру не в XML а в&hellip; JSON! (Формат выбран произвольно.) Соответственно, я скачал <a href="https://github.com/ServiceStack/ServiceStack.Text" title="https://github.com/ServiceStack/ServiceStack.Text">ServiceStack.Text</a> и заменил тип свойств в <code>Settings</code> на <code>string</code>. В результате, сериализация происходит вот так:</p>
<p><pre class="brush: csharp;">
Settings.Default[&quot;OptionPresets&quot;] =
  JsonSerializer.SerializeToString(OptionPresets, typeof (Dictionary&lt;string, ConversionOptions&gt;));
</pre>
<p>Ну а что касается тех «несериализуемых» полей то, увы, приходится делать строковые или аналогичные backing fields, со всемы вытекающими последствиями.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a>, <a href='http://nesteruk.wordpress.com/category/c/'>C#</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/780/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/780/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/780/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=780&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/06/05/presets-in-settings/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Бесшумный компьютер для разработчика</title>
		<link>http://nesteruk.wordpress.com/2011/05/21/noiseless-computer-for-developers/</link>
		<comments>http://nesteruk.wordpress.com/2011/05/21/noiseless-computer-for-developers/#comments</comments>
		<pubDate>Sat, 21 May 2011 13:11:19 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[Hardware]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=767</guid>
		<description><![CDATA[В процессе разработки я готов слушать любой шум, при условии что этот шум создал я и дал на него согласие. В идеале же я предпочитаю тишину, а следовательно шумные компьютеры не для меня. Только вот проблема: мне банально лень исследовать вопросы шумоизоляции и строить кастомные решения.[1] К счастью есть подход который масштабируется. Бесшумый источник питания [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=767&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>В процессе разработки я готов слушать любой шум, при условии что этот шум создал я и дал на него согласие. В идеале же я предпочитаю тишину, а следовательно шумные компьютеры не для меня. Только вот проблема: мне банально лень исследовать вопросы шумоизоляции и строить кастомные решения.[<a href="#Reference1" title="Поправка: рано или поздно я буду строить систему с водяным охлаждением &ndash; только для того чтобы разобраться как это работает и насколько это сложно. Но это хобби и к делу не относится." name="BackReference1">1</a>] К счастью есть подход который масштабируется.</p>
<h3>Бесшумый источник питания</h3>
<p>До поры до времени, источники питания без вентиляторов были мусором &ldquo;по показателям&rdquo;, и приходилось терпеть[<a href="#Reference2" title="На самом деле &ndash; не совсем. Я недавно выкинул систему 5-летней давности которая была фактически бесшумной поскольку использовала внешний адаптер вместо полноценного PSU и была построена на базе Pentium M (да-да, десктоп на ноутбучной платформе). К сожалению, когда я еще был идиотом и не обвешал все бесперебойниками, один перепад напряжения спалил мне трансформатор в этом компьютере, и с тех пор этот комп жил в кладовке с воткнутым в него убогим 350W PSU. Недавно я набрался смелости и снес этот &ldquo;проваленный эксперимент&rdquo; на помойку." name="BackReference2">2</a>]. Это время прошло. Теперь качественные и тихие PSU доступны всем и каждому. Конечно, основная их польза &ndash; при построении HTPC, но для офиса они тоже идеально подходят (а вот для геймеров &ndash; нет, ибо максимум 400W).</p>
<p>Безвентиляторные (fanless) PSU предсказуемо используют радиатор. Лучший по моему субъективному ощущению (после прочтения обзоров) &ndash; <a href="http://www.scan.co.uk/products/400w-silverstone-st40nf-s-nightjar-80-plus-bronze-86-eff-fanless-0db-atx-23" title="http://www.scan.co.uk/products/400w-silverstone-st40nf-s-nightjar-80-plus-bronze-86-eff-fanless-0db-atx-23">Silverstone Nightjar</a>.</p>
<p align="center"><img src="http://www.overclockers.ua/news/power/104138-silverstone-nightjar-st40nf.jpg" alt="" style="border:0;" /></p>
<p>Полный обзор, если кто сомневается, можно почитать <a href="http://www.hardwaresecrets.com/article/869" title="http://www.hardwaresecrets.com/article/869">тут</a>. Стоимость &ndash; около $180. В России, естественно, не продается.</p>
<h3>Бесшумный кулер</h3>
<p>Я сам не очень верил в то что можно иметь беззвучное неводяное охлаждение. Оказывается можно. Порыскав на <a href="http://www.frostytech.com/top5heatsinks.cfm" title="http://www.frostytech.com/top5heatsinks.cfm">Frosty&#8217;s</a> я увидел в лидерах по уровню шума кулер <a href="http://www.scythe-usa.com/product/cpu/036/scorc1000_detail.html" title="http://www.scythe-usa.com/product/cpu/036/scorc1000_detail.html">Scythe Orochi</a>. Пошел, купил, установил и доволен.</p>
<p align="center"><img src="http://alienbabeltech.com/main/wp-content/uploads/2009/04/scythe-orochi-cpu-cooler-04.jpg" alt="" style="border:0;" /></p>
<p>С кулером поставляется 14-сантиметровый вентилятор но мне он не нужен (да и в корпус не поместится). Обзор сего чуда можно почитать <a href="http://www.frostytech.com/articleview.cfm?articleID=2258" title="http://www.frostytech.com/articleview.cfm?articleID=2258">тут</a>. Стоимость &ndash; около $60. В России было очень сложно найти. Сейчас его в России не найти, да и на Западе тоже &ndash; он discontinued и его заменят обновленной моделью. Ждем-с.</p>
<h3>Бесшумное все остальное</h3>
<p>Тут все как бы тривиально &ndash; например, графических карт без вентиляторов масса. Неигровых, конечно, но мы про офисные компьютеры говорим. Если у вас несколько мониторов, то вам подойдет что-то вроде этого:</p>
<p align="center"><img src="http://images.nvidia.com/products/quadro_nvs_450/quadro_nvs_450_3qtr_low.png" alt="" style="border:0;" /></p>
<p>Это <a href="http://www.nvidia.com/object/product_quadro_nvs_450_us.html" title="http://www.nvidia.com/object/product_quadro_nvs_450_us.html">nVidia Quadro NVS 450</a>. Такая карта тянет 4 монитора и не жужжит.[<a href="#Reference3" title="Я тут сильно лукавлю: сам работаю на 3-х мониторах (4-й стоит в сторонке и пока ничего не делает). Более того, не все мои экраны подключены к одному компьютеру, хотя и управляются одной с одной пары мышь-клавиатура. Но это уже тянет на отдельный пост :)" name="BackReference3">3</a>] (Да, 4 монитора, если надо больше, можно добавить Quadro NVS 295 &ndash; <a href="http://superuser.com/questions/257571/is-there-a-pcix1-video-card-that-plays-nice-with-pcix16-video-cards" title="http://superuser.com/questions/257571/is-there-a-pcix1-video-card-that-plays-nice-with-pcix16-video-cards">почти пруфлинк</a>.) Карточка стоит $550.[<a href="#Reference4" title="Такая сумма за графическую карточку &ndash; это дороговато, особенно если учесть что Eyefinity 6 поддерживает сразу 6 мониторов а карточки стоят где-то $500 на Амазоне. Тем не менее, такие монстрообразные карты откровенно шумят, что как бы портит всю идею этого поста." name="BackReference4">4</a>] В России&hellip; да, что там говорить, берите <a href="http://www.amazon.com/PNY-Quadro-NVS-Graphics-Card/dp/B001QVPG8I/ref=sr_1_4?ie=UTF8&amp;s=miscellaneous&amp;qid=1305979217&amp;sr=8-4" title="http://www.amazon.com/PNY-Quadro-NVS-Graphics-Card/dp/B001QVPG8I/ref=sr_1_4?ie=UTF8&amp;s=miscellaneous&amp;qid=1305979217&amp;sr=8-4">на Амазоне</a>.[<a href="#Reference5" title="Товарищ Суворов и его коллеги, которые работают на 3-х мониторах (за одно это респект), исповедуют другой подход: основной графической карточкой поддерживают 2 экрана, а третий&mdash;с помошью подпиленной x16 карточки, воткнутой в x4 слот. Да-да, это реально, хотя судя по всему не везде работает." name="BackReference5">5</a>]</p>
<p>Насчет жестких дисков тут все понятно. Либо вы берете SSD и проблема отпадает, либо ставите диск на 5200RPM и проблема тоже отпадает (только работать становится намного сложнее). Главное не баловаться дешевыми неопробованными дисками (у меня тут есть Hitachi на 1Gb &ndash; такой слона разбудит) и не пытаться думать что какой-нибудь Raptor (даже под RAID) &ndash; хорошее решение.[<a href="#Reference6" title="Рапторы &ndash; имеется ввиду Western Digital VelociRaptor &ndash; производительные 10kRPM диски которые, тем не менее, адски жужжат и тем самым меня бесят." name="BackReference6">6</a>]</p>
<p align="center"><img src="http://exempt.files.wordpress.com/2010/08/intel_x25-m_ssd1.jpg?w=700" alt="" style="border:0;" /></p>
<p>Диск выше &ndash; Intel X25-M на 160Gb &ndash; стоит $430 <a href="http://www.amazon.com/Intel-2-5-Inch-X25-M-Mainstream-SSDSA2MH160G2C1/dp/B002IGT7IU/ref=sr_1_4?ie=UTF8&amp;qid=1305979892&amp;sr=8-4" title="http://www.amazon.com/Intel-2-5-Inch-X25-M-Mainstream-SSDSA2MH160G2C1/dp/B002IGT7IU/ref=sr_1_4?ie=UTF8&amp;qid=1305979892&amp;sr=8-4">на Амазоне</a>. В России, впрочем, найти его тоже <a href="http://scorpion.ru/descr1921140387" title="http://scorpion.ru/descr1921140387">не проблема</a>.</p>
<p>Да, и&hellip; если у вас жужжит DVD- или BR-драйв, советом помочь не смогу ибо такого добра у меня уже несколько лет не водилось. Впрочем, уверен что для дисководов сущуствуют всякие антивибрационные решения.</p>
<h3>Заключение</h3>
<p>Вот собственно и всё. Я надеюсь что мне удалось показать то, как &ldquo;малой кровью&rdquo; сделать компьютер бесшумным. Конечно, сделать это не так-то просто хотя бы потому что в &ldquo;этой стране&rdquo; компьютерное оборудование а) в основном ширпотреб; и b) с неприличной наценкой, но по крайней мере, предложенное мною решение может масштабироваться и не требует огромных временных затрат.</p>
<h3>Заметки</h3>
<ol>
<li><a name="Reference1"></a><a href="#BackReference1" title="Back to text">&uarr;</a> Поправка: рано или поздно я буду строить систему с водяным охлаждением &ndash; только для того чтобы разобраться как это работает и насколько это сложно. Но это хобби и к делу не относится.</li>
<li><a name="Reference2"></a><a href="#BackReference2" title="Back to text">&uarr;</a> На самом деле &ndash; не совсем. Я недавно выкинул систему 5-летней давности которая была фактически бесшумной поскольку использовала внешний адаптер вместо полноценного PSU и была построена на базе Pentium M (да-да, десктоп на ноутбучной платформе). К сожалению, когда я еще был идиотом и не обвешал все бесперебойниками, один перепад напряжения спалил мне трансформатор в этом компьютере, и с тех пор этот комп жил в кладовке с воткнутым в него убогим 350W PSU. Недавно я набрался смелости и снес этот &ldquo;проваленный эксперимент&rdquo; на помойку.</li>
<li><a name="Reference3"></a><a href="#BackReference3" title="Back to text">&uarr;</a> Я тут сильно лукавлю: сам работаю на 3-х мониторах (4-й стоит в сторонке и пока ничего не делает). Более того, не все мои экраны подключены к одному компьютеру, хотя и управляются одной с одной пары мышь-клавиатура. Но это уже тянет на отдельный пост :)</li>
<li><a name="Reference4"></a><a href="#BackReference4" title="Back to text">&uarr;</a> Такая сумма за графическую карточку &ndash; это дороговато, особенно если учесть что Eyefinity 6 поддерживает сразу 6 мониторов а карточки стоят где-то $500 <a href="http://www.amazon.com/Diamond-Radeon-Eyefinity-PCI-Express-5870PE52G/dp/B003EYV0PI/ref=sr_1_1?ie=UTF8&amp;qid=1305982067&amp;sr=8-1" title="http://www.amazon.com/Diamond-Radeon-Eyefinity-PCI-Express-5870PE52G/dp/B003EYV0PI/ref=sr_1_1?ie=UTF8&amp;qid=1305982067&amp;sr=8-1">на Амазоне</a>. Тем не менее, такие монстрообразные карты откровенно шумят, что как бы портит всю идею этого поста.</li>
<li><a name="Reference5"></a><a href="#BackReference5" title="Back to text">&uarr;</a> Товарищ <a href="http://alexeysuvorov.wordpress.com">Суворов</a> и его коллеги, которые работают на 3-х мониторах (за одно это респект), исповедуют другой подход: основной графической карточкой поддерживают 2 экрана, а третий&mdash;с помошью подпиленной x16 карточки, воткнутой в x4 слот. Да-да, это реально, хотя судя по всему не везде работает.</li>
<li><a name="Reference6"></a><a href="#BackReference6" title="Back to text">&uarr;</a> Рапторы &ndash; имеется ввиду <a href="http://scorpion.ru/descr1916524787" title="http://scorpion.ru/descr1916524787">Western Digital VelociRaptor</a> &ndash; производительные 10kRPM диски которые, тем не менее, адски жужжат и тем самым меня бесят.</li>
</ol>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/computer/'>Computer</a>, <a href='http://nesteruk.wordpress.com/category/hardware/'>Hardware</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/767/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/767/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/767/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=767&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/05/21/noiseless-computer-for-developers/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://www.overclockers.ua/news/power/104138-silverstone-nightjar-st40nf.jpg" medium="image" />

		<media:content url="http://alienbabeltech.com/main/wp-content/uploads/2009/04/scythe-orochi-cpu-cooler-04.jpg" medium="image" />

		<media:content url="http://images.nvidia.com/products/quadro_nvs_450/quadro_nvs_450_3qtr_low.png" medium="image" />

		<media:content url="http://exempt.files.wordpress.com/2010/08/intel_x25-m_ssd1.jpg" medium="image" />
	</item>
		<item>
		<title>Новости (Апрель 2011)</title>
		<link>http://nesteruk.wordpress.com/2011/04/17/news-april-2011/</link>
		<comments>http://nesteruk.wordpress.com/2011/04/17/news-april-2011/#comments</comments>
		<pubDate>Sun, 17 Apr 2011 14:53:46 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[freespace]]></category>
		<category><![CDATA[mathsharp]]></category>
		<category><![CDATA[spbaltnet]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=755</guid>
		<description><![CDATA[Этот пост новостного типа &#8211; расскажу про то, что произошло и про то, что происходит. С удовольствием написал бы технический пост, но пока все очень туманно &#8211; может чуть позже. Итак&#8230; Релиз MathSharp Давным-давно я попал на проект, где при разработке программ нужно было переводить математические формулы в код. Тогда я только и думал о [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=755&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Этот пост новостного типа &ndash; расскажу про то, что произошло и про то, что происходит. С удовольствием написал бы технический пост, но пока все очень туманно &ndash; может чуть позже. Итак&hellip;</p>
<h3>Релиз MathSharp</h3>
<p>Давным-давно я попал на проект, где при разработке программ нужно было переводить математические формулы в код. Тогда я только и думал о том, как все это автоматизировать дабы конвертировать формулы в код автоматически. И вот спустя несколько лет, я создал проект <strong>ActiveMesa MathSharp</strong>. MathSharp &ndash; это программа, которая умеет переводить контент из формата MathML (который можно получить из Microsoft Word 2007/2010, MathType, Maple и других систем) в код на языках C# или F#.</p>
<p>Вот небольшой видеоролик, в котором показано как работает MathSharp:</p>
<p style="text-align:center;"><div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/22251021' width='640' height='480' frameborder='0'></iframe></div></p>
<p>Если коротко &ndash; вы пишете</p>
<p align="center">
  <img src="http://www.codeproject.com/KB/recipes/mmlsharp/MmlSharp2.jpg" alt="" style="border:0;" />
</p>
<p>а оно переводит это в</p>
<p><pre class="brush: csharp;">
p = rho*R*T + (B_0*R*T-A_0-((C_0) / (T*T))+((E_0) / (Math.Pow(T, 4))))*rho*rho +
    (b*R*T-a-((d) / (T)))*Math.Pow(rho, 3) +
    alpha*(a+((d) / (t)))*Math.Pow(rho, 6) +
    ((c*Math.Pow(rho, 3)) / (T*T))*(1+gamma*rho*rho)*Math.Exp(-gamma*rho*rho);
</pre>
<p>Если вам понравилась идея, само приложение можно найти тут:&nbsp;<a href="http://activemesa.com/mathsharp" title="http://activemesa.com/mathsharp">http://activemesa.com/mathsharp</a>. Стоит оно $95 &ndash; дешевле чем один инженерный час, так что если оно кому-то сэкономит хоть час работы, значит выгода уже есть.</p>
<p>P.S.: этот релиз позволил мне получить следующие &quot;ачивменты&quot;:</p>
<ul>
<li>Зарелизил проект написанный на F# (есть соблазн накатать статейку для <a href="http://fprog.ru" title="http://fprog.ru">fprog.ru</a>)</li>
<li>Зарелизил самообновляемое приложение</li>
</ul>
<h3>Возобновление встреч Spbalt.net</h3>
<p><img src="http://spbalt.net/content/spbalt.net.jpg" alt="" class="alignright" style="border:0;" />После небольшого перерыва мы возобновляем наши встречи &ndash; уже в другом месте, в помещении которое любезно предоставляет нам компания <a href="http://dataart.ru" title="http://dataart.ru">DataArt</a>. Первые мои семинары проводились именно в DataArt под флагом их DataArt Way. Собственно там все и началось. Так что я доволен что мы сможем снова там встречаться.</p>
<p>Следующая встреча пройдет в четверг 21го. Будет рассказ про создание back-end&rsquo;а для MMO RPG. Подробности тут: <a href="http://spbalt.net/home/meetings/27">http://spbalt.net/home/meetings/27</a></p>
<h3>Новый проект</h3>
<p>После релиза MathSharp нужно чем-то снова заняться, поэтому я решил написать что-то посложнее. Сейчас я в стадии R&amp;D экспериментирую с идеей code provider&rsquo;ов (по аналогии с type provider&rsquo;ами). Идея в том, чтобы иметь распределенные сервисы, которые могли бы заниматься не столько анализом сколько порождением нового кода на основе декларативных моделей.</p>
<p>Для тех из вас кому интересно что стало с <a href="http://activemesa.com/fsharper" title="http://activemesa.com/fsharper">FSharper</a>&rsquo;ом, могу сказать что на данный момент проект приостановлен &ndash; в основном потому, что надо было делать MathSharp &ndash; но возможно я и вернусь к нему. &ldquo;Ничего обещать не буду.&rdquo;</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/life/'>Life</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/freespace/'>freespace</a>, <a href='http://nesteruk.wordpress.com/tag/mathsharp/'>mathsharp</a>, <a href='http://nesteruk.wordpress.com/tag/spbaltnet/'>spbaltnet</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/755/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/755/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/755/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/755/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/755/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/755/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/755/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/755/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/755/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/755/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/755/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/755/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/755/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/755/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=755&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/04/17/news-april-2011/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://www.codeproject.com/KB/recipes/mmlsharp/MmlSharp2.jpg" medium="image" />

		<media:content url="http://spbalt.net/content/spbalt.net.jpg" medium="image" />
	</item>
		<item>
		<title>Коротко про type forwarding</title>
		<link>http://nesteruk.wordpress.com/2011/04/06/on-type-forwarding/</link>
		<comments>http://nesteruk.wordpress.com/2011/04/06/on-type-forwarding/#comments</comments>
		<pubDate>Wed, 06 Apr 2011 11:33:29 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[type forwarding]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=748</guid>
		<description><![CDATA[Представьте, что у вас есть SDK, состоящий из огромного количества библиотек, и что любому пользователю вашего SDK нужно для нормальной работы подключить штук 15-20 DLLек, причем конечный пользователь может даже не знать заранее, какие именно библиотеки нужны. Эта ситуация &#8211; весьма неприятная. Все мы знаем, что Visual Studio 2010 добавляет новые ссылки на библиотеки с [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=748&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Представьте, что у вас есть SDK, состоящий из огромного количества библиотек, и что любому пользователю вашего SDK нужно для нормальной работы подключить штук 15-20 DLLек, причем конечный пользователь может даже не знать заранее, какие именно библиотеки нужны. Эта ситуация &ndash; весьма неприятная. Все мы знаем, что Visual Studio 2010 добавляет новые ссылки на библиотеки с черепашьей скоростью, и что трудозатраты по добавлению ссылок равны факториалу (!!!) от количества ссылок которые вы добавляете.</p>
<p>Очевидно, нужно искать возможность как-то улучшить user experience. Не имея возможности просто сделать <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=22914587-b4ad-4eae-87cf-b14ae6a939b0&amp;displaylang=en" title="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=22914587-b4ad-4eae-87cf-b14ae6a939b0&amp;displaylang=en">ILMerge</a> на все сборки, у нас тем не менее есть возможность сделать нечто не менее эффективное &ndash; а именно создать прокси-сборку для всех типов внутри сборок, и воспользоваться фичей под названием type forwarding, для того чтобы вызывались именно конечные сборки нашего SDK.</p>
<h3>Как работает type forwarding?</h3>
<p>Поддержка <a href="http://msdn.microsoft.com/en-us/library/ms404275.aspx" title="http://msdn.microsoft.com/en-us/library/ms404275.aspx">type forwarding</a> была добавлена в .Net 2.0 для того чтобы авторы библиотек могли мигрировать типы из одной сборки в другую, не ломая в процессе код пользователей и не требуя перекомпиляции.</p>
<p>Вот как это работает. Есть у меня сборка <code>FirstAssembly</code>, а в ней тип <code>С</code>:</p>
<p><pre class="brush: csharp;">
// FirstAssembly.dll
public class С {}
</pre>
<p>Далее, другой пользователь пишет свой код, ссылаясь на <code>FirstAssembly.dll</code>:</p>
<p><pre class="brush: csharp;">
С с = new С();
</pre>
<p>Все хорошо, но вдруг я решил передвинуть мой тип <code>C</code> в сборку <code>SecondAssembly.dll</code>, при этом не меняя пространства имен и имени самого типа. Тогда я делаю следующее:</p>
<ul>
<li>Удаляю реализацию класса <code>С</code> в <code>FirstAssembly.dll</code> и переношу его в <code>SecondAssembly.dll</code></li>
<li>Добавляю ссылку на <code>SecondAssembly.dll</code> в <code>FirstAssembly.dll</code></li>
<li>Иду в <code>FirstAssembly</code>, открываю там <code>AssemblyInfo.cs</code> и в нем пишу магическую строчку<br />
<pre class="brush: csharp;">
[assembly: TypeForwardedTo(SomeNamespace.C)]
</pre>Эта директива намекает пользователям, что де тип <code>C</code> переехал, и теперь находится в другой сборке.
</li>
</ul>
<p>Атрибут сборки на момент компиляции <code>FirstAssembly.dll</code> превращается в следующую директиву:</p>
<p><pre class="brush: csharp;">
.class extern forwarder SomeNamespace.C
{
  .assembly extern SecondAssembly
}
</pre>
<p>Иначе говоря, все, что у нас получается &ndash; это лишняя директива которая подсказывает, что если клиент ищет в нашей сборке тип <code>Somenamespace.C</code> но не находит его, имеет смысл поискать этот тип в сборке <code>SecondAssembly.dll</code>.</p>
<h3>Обсуждение</h3>
<p>Во-первых, следует заметить что какой-то особой поддержки type forwarding со стороны Visual Studio не существует &ndash; в лучшем случае, при попытке сослаться на тип из сборки который «переехал», помимо обычной ошибки Visual Studio намекнет вам, что тип «мигрировал» и что для успешной компиляции вам стоит добавить ссылку на <code>SecondAssembly.dll</code>.</p>
<p>В контексте SDK, следует заметить, что</p>
<ul>
<li>Вы не можете просто поставлять набор из огромного количества директив <code>TypeForwardedTo</code> и компилировать код. В момент компиляции нужны ссылки на реальные сборки или же на некие прокси, которые в точности повторяют структуру тех сборок, на которые нужно ссылаться.</li>
<li>В момент исполнения, мы не можем «выкинуть» прослойку, т.к. тогда непонятно откуда брать информацию о местоположении реальных сборок.</li>
<li>Фактически, требуются две прокси-сборки. Одна &ndash; это прокси для компиляции, вторая &ndash; с набором директив type forwarding для исполнения.</li>
</ul>
<p>Теперь я пытаюсь понять, правильный ли это подход, и если да &ndash; как заставить <a href="http://www.mono-project.com/Cecil" title="http://www.mono-project.com/Cecil">Mono.Cecil</a> делать из «реальных» сборок прокси с пустышками вместо методов. ▪</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/type-forwarding/'>type forwarding</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/748/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/748/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/748/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/748/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/748/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/748/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/748/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/748/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/748/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/748/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/748/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/748/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/748/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/748/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=748&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/04/06/on-type-forwarding/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Создание сервиса WCF REST с поддержкой JSONP</title>
		<link>http://nesteruk.wordpress.com/2011/03/24/create-wcf-rest-jsonp-service/</link>
		<comments>http://nesteruk.wordpress.com/2011/03/24/create-wcf-rest-jsonp-service/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 16:58:35 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[jsonp]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[wcf]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=741</guid>
		<description><![CDATA[Мне всегда импонировали фреймворки и языки, которые делались для того, чтобы сделать &#8220;простые вещи простыми, а сложные вещи возможными&#8221;. Надеясь именно на подобный расклад вещей, я решил посмотреть на то, как нынче делаются REST сервисы в WCF без помощи каких-либо библиотек (OpenRasta, MindTouch DReAM) или шаблонов вроде WCF REST Starter Kit. В этом посте &#8211; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=741&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Мне всегда импонировали фреймворки и языки, которые делались для того, чтобы сделать &ldquo;простые вещи простыми, а сложные вещи возможными&rdquo;. Надеясь именно на подобный расклад вещей, я решил посмотреть на то, как нынче делаются REST сервисы в WCF без помощи каких-либо библиотек (<a href="http://trac.caffeine-it.com/openrasta" title="http://trac.caffeine-it.com/openrasta">OpenRasta</a>, <a href="http://www.mindtouch.com/products/dream" title="http://www.mindtouch.com/products/dream">MindTouch DReAM</a>) или шаблонов вроде <a href="http://aspnet.codeplex.com/wikipage?title=WCF%20REST" title="http://aspnet.codeplex.com/wikipage?title=WCF%20REST">WCF REST Starter Kit</a>. В этом посте &ndash; мои заметки насчет того, как все вышло.</p>
<h3>Мотивация</h3>
<p>Почему REST? Все очень просто &ndash; мне нынче импонируют идеи сайтов, которые находятся полностью на клиенте и работают с серверами именно через REST а не через <code>WS-*</code> или какие-то кастомные RPC-байндинги. REST &ndash; это тривиальная парадигма и, казалось бы, любой более менее продвинутый фреймворк должен позволять быстро и эффективно создавать REST-сервисы.</p>
<p>Поэтому я решил испробовать простенький сценарий &ndash; взять мой <a href="http://devtalk.net/fsharp/conversation-engine-websharper/" title="http://devtalk.net/fsharp/conversation-engine-websharper/">диалоговый фреймворк</a> написанный на WebSharper и перетащить все данные на сервер, осуществив взаимодействие через REST.</p>
<h3>Сущности</h3>
<p>Первое что я обычно делаю в проекте который хранит данные &ndash; это конечно <code>Install-Package norm</code> дабы добавить драйвер NoRM для MongoDB. Коллега Суворов конечно <a href="http://alexeysuvorov.wordpress.com/2011/03/11/mongodb-csharp-driver-part2/" title="http://alexeysuvorov.wordpress.com/2011/03/11/mongodb-csharp-driver-part2/">рекоммендует</a> якобы официальный драйвер от 10gen, но у меня итак все работает, в т.ч. Linq, поэтому зачем напрягаться?</p>
<p>Как вы помните, NoRM немного замусоривает наш объект, но он все еще остается &ldquo;почти POCO&rdquo;. WCF же в долгу не остается, и &ldquo;домусоривает&rdquo; объект еще больше, прописывая свои аттрибуты. В результате получаем классы подобные этому:</p>
<p><pre class="brush: csharp;">
[DataContract]
public class ConversationItem
{
  public ConversationItem()
  {
    Id = ObjectId.NewObjectId();
  }
  [DataMember, MongoIdentifier] public string Id { get; set; }
  [DataMember] public string PartyId { get; set; }
  [DataMember] public string Speech { get; set; }
  [DataMember] public List&lt;string&gt; EnableList { get; set; }
  [DataMember] public List&lt;string&gt; DisableList { get; set; }
}
</pre><br />
<h3>Начинаем писать сервис</h3>
<p>Первое что нужно сделать &ndash; удалить к черту сгенерировнный интерфейс &ndash; сервис проживет и без него, а <code>[ServiceContract]</code> можно навесить прямо на класс сервиса. Далее, можно создавать методы, но на них тоже нужно навесить аттрибуты, в частности:</p>
<ul>
<li><code>OperationContract</code> для того чтобы пометить что это часть сервиса.</li>
<li><code>WebGet</code> дабы прописать шаблон вызова а также форматы запроса и ответа.</li>
<li><code>JSONPBehavior</code>, но он из коробки не поставляется, и мы о нем поговорим попозже.</li>
</ul>
<p>Вот пример декорированного метода:</p>
<p><pre class="brush: csharp;">
[OperationContract]
[WebGet(UriTemplate = &quot;/c/{id}&quot;, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = &quot;callback&quot;)]
public Conversation GetInitialConversationItems(string id)
{
  ...
}
</pre>
<p>Итак, &ldquo;из коробки&rdquo; мы получаем достаточно простой метод, но не хватает двух вещей &ndash; обработки ошибок и поддержки JSONP, без которой вы ничего кроссдоменно не вызовете.</p>
<h3>Обработка ошибок</h3>
<p>Для того чтобы возвращать всякие статус коды вроде Not Found, нужно перехватить выходящий ответ из <code>WebOperationContext</code> и прописать в него информацию о том, что собственно пошло не так. Например:</p>
<p><pre class="brush: csharp;">
using (var db = GetDB())
{
  var conversation = db.Query&lt;Conversation&gt;().FirstOrDefault();  
  if (conversation == null)
  {
    var resp = WebOperationContext.Current.OutgoingResponse;
    resp.StatusCode = HttpStatusCode.NotFound;
    resp.StatusDescription = &quot;Could not find conversation with id='{0}'.&quot;.ƒ(id);
    return null;
  } 
  else
  {
    return conversation;
  }
}
</pre><br />
<h3>JSONP</h3>
<p>Феноменально, но факт &ndash; WCF не поставляется с поддержкой JSONP. К счастью, Microsoft дает такую поддержку в примерах, и то как она выглядит является хорошей демонстрацией того, как гибок WCF в плане расширения.</p>
<p>Всего для поддержки JSONP нужно добавить 5 классов. Детально я описывать их не буду, опишу только вкратце.</p>
<ol>
<li>Во-первых, нужна реализация аттрибута <code>JSONPBehavior</code> который я уже описывал. Фактически, этот аттрибут навешивает на операцию объект типа <code>IParameterInspector</code>, который перед вызовом прописывает в свойства исходящего сообщение свойство типа <code>IMessageProperty</code> для JSON.</li>
<li>Класс <code>JSONMessageProperty</code> &ndash; это всего лишь обертка для лишнего кусочка метаданных который поставляются поведением. Применим этот довесок только для callback-параметра. Для тех кто забыл, callback-параметр это то с помошью чего данные <code>data</code> возвражаются через запрос <code>http://somewhere.com/x?callback=y</code> как <code>y(data)</code>, прописываются в <code>&lt;script&gt;</code> и исполняются.</li>
<li>Далее формируется фабрика <code>JSONPEncoderFactory</code>, которая производит энкодеры типа <code>JSONPEncoder</code>. Сам энкодер, казалось бы, тривиален &ndash; все, что он должен сделать так это обернуть вызов в название callback&rsquo;а и вернуть его. Но поскольку его метод <code>WriteMessage()</code> перегружен, его приходится вызывать в нескольких местах.</li>
</ol>
<p>Для того чтобы получить всю поддержку JSONP полностью, нужно скачать <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=35ec8682-d5fd-4bc3-a51a-d8ad115a8792&amp;displaylang=en" title="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=35ec8682-d5fd-4bc3-a51a-d8ad115a8792&amp;displaylang=en">набор примеров по WCF</a> c MSDN.</p>
<h3>Web.config</h3>
<p>Несмотря на то, что все, в принципе можно сделать в коде, на практике приходится достаточно сильно шаманить с <code>Web.config</code> ом дабы все заработало. В частности, нужно прописать новый binding:</p>
<p><pre class="brush: csharp;">
&lt;bindings&gt;
  &lt;customBinding&gt;
    &lt;binding name=&quot;jsonpBinding&quot;&gt;
      &lt;jsonpMessageEncoding/&gt;
      &lt;httpTransport manualAddressing=&quot;true&quot;/&gt;
    &lt;/binding&gt;
  &lt;/customBinding&gt;
&lt;/bindings&gt;
</pre>
<p>А также добавить расширение для кодировки JSONP:</p>
<p><pre class="brush: csharp;">
&lt;extensions&gt;
  &lt;bindingElementExtensions&gt;
    &lt;add name=&quot;jsonpMessageEncoding&quot;
    type=&quot;ConversationServer.JsonpSupport.JsonpBindingExtension, ConversationServer&quot;/&gt;
  &lt;/bindingElementExtensions&gt;
&lt;/extensions&gt;
</pre><br />
<h3>Удаление .svc</h3>
<p>Для REST-сервисов окончание <code>.svc</code> на конце сервиса как-то нелепо. К счастью его очень просто удалить. Для этого, мы можем создать свой собственный модуль который игнорирует это окончание:</p>
<p><pre class="brush: csharp;">
public class RestModule : IHttpModule
{
  public void Init(HttpApplication context)
  {
    context.BeginRequest += (sender, args) =&gt;
    {
      var ctx = HttpContext.Current;
      var path = ctx.Request.AppRelativeCurrentExecutionFilePath;
      int i = path.IndexOf('/', 2);
      if (i &gt; 0)
      {
        var svc = path.Substring(0, i) + &quot;.svc&quot;;
        var rest = path.Substring(i, path.Length - i);
        var qs = ctx.Request.QueryString.ToString();
        ctx.RewritePath(svc, rest, qs, false);
      }
    };
  }
  public void Dispose()
  {
  }
}
</pre>
<p>А далее просто прописываем его в секцию <code>system.web</code> в <code>Web.config</code>:</p>
<p><pre class="brush: csharp;">
&lt;system.web&gt;
  &lt;compilation debug=&quot;true&quot; targetFramework=&quot;4.0&quot; /&gt;
  &lt;customErrors mode=&quot;Off&quot;/&gt;
  &lt;httpModules&gt;
    &lt;add name=&quot;NoMoreSVC&quot; type=&quot;ConversationServer.RestModule, ConversationServer&quot;/&gt;
  &lt;/httpModules&gt;
&lt;/system.web&gt;
</pre>
<p>Вот собственно и все.</p>
<h3>Заключение</h3>
<p>Мой небольшой эксперимент по использованию WCF REST показал что, как и во многих других случаях, приходится даже для простенького сервиса городить громозкие структуры. К счастью, сделав это один раз, можно потом копировать реализацию в различные проекты.</p>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/jsonp/'>jsonp</a>, <a href='http://nesteruk.wordpress.com/tag/rest/'>rest</a>, <a href='http://nesteruk.wordpress.com/tag/wcf/'>wcf</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/741/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=741&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/03/24/create-wcf-rest-jsonp-service/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Парсим HTML Zen на F#, FsLex и FsYacc</title>
		<link>http://nesteruk.wordpress.com/2011/03/03/parsing-htmlzen-fsharp-fslex-fsyacc/</link>
		<comments>http://nesteruk.wordpress.com/2011/03/03/parsing-htmlzen-fsharp-fslex-fsyacc/#comments</comments>
		<pubDate>Thu, 03 Mar 2011 12:22:51 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[f#]]></category>
		<category><![CDATA[fslex]]></category>
		<category><![CDATA[fsyacc]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=733</guid>
		<description><![CDATA[Все наверное так или иначе слышали про HTML Zen и про то, как он спасает при написании HTML. Но мало кому приходит в голову написать свою собственную реализацию, когда есть готовая на Python&#8217;е. На самом деле, собственная реализация позволяет добавлять собственные конструкты, нужные только вам. Давайте попробуем реализовать базовые конструкты HTML Zen. Для этого мы [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=733&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Все наверное так или иначе слышали про HTML Zen и про то, как он спасает при написании HTML. Но мало кому приходит в голову написать свою собственную реализацию, когда есть готовая на Python&rsquo;е. На самом деле, собственная реализация позволяет добавлять собственные конструкты, нужные только вам.</p>
<p>Давайте попробуем реализовать базовые конструкты HTML Zen. Для этого мы воспользуемся языком F#, библиотекой тестирования <a href="http://fsunit.codeplex.com/" title="http://fsunit.codeplex.com/">FSunit</a>. Будем писать программу в стиле TDD. Я пожалуй назову ее FSharpZen, так интересней.</p>
<p>Исходный код можно найти тут: <a href="https://bitbucket.org/nesteruk/fsharpzen">https://bitbucket.org/nesteruk/fsharpzen</a></p>
<h3>Базовые случаи</h3>
<p>Весь HTML Zen &ndash; это набор трансформаций. Например, на входе <code>a</code>, а на выходе <code>&lt;a href="|"&gt;&lt;/a&gt;</code>, где <code>|</code> обозначает финальное положение каретки. Следовательно, можно как минимум написать следующий тест:</p>
<p><pre class="brush: fsharp;">
[&lt;TestFixture&gt;]
type ``Basic transformation tests`` ()=
  [&lt;Test&gt;] member test.
    ``Empty input should yield empty output`` () =
      Zen.html &quot;&quot; |&gt; should equal &quot;|&quot;
</pre>
<p>Это счастье совсем не компилируется, поэтому нам придется как минимум предоставить хоть какую-то реализацию, например:</p>
<p><pre class="brush: fsharp;">
module FSharpZen.Zen
let html input = &quot;&quot;
</pre>
<p>В результате, конечно, получим &ldquo;красный&rdquo; тест:</p>
<p><pre class="brush: fsharp;">
Expected string length 1 but was 0. Strings differ at index 0.
Expected: &quot;|&quot;
But was:  &lt;string.Empty&gt;
-----------^
</pre>
<p>Ну а дальше мы &ldquo;жульничаем&rdquo; и наш тест проходит. Не забываем сказать спасибо Решарперу, который поддерживает F#-тесты out-of-the-box.</p>
<h3>Пустые тэги</h3>
<p>Дефолтное поведение HTML Zen такое, что при написании, скажем, буквы <code>z</code> разворачивается шаблон <code>&lt;z&gt;|&lt;/z&gt;</code>. С другой стороны, <code>hr</code> определенно превращается в <code>&lt;hr/&gt;|</code>, а <code>img</code> &ndash; в <code>&lt;img src="|"&gt;&lt;/img&gt;</code>.</p>
<p><pre class="brush: fsharp;">
[&lt;Test&gt;] member test.
  ``Simple entity should be in a closed tag`` () =
    Zen.html &quot;c&quot; |&gt; should equal &quot;&lt;c&gt;|&lt;/c&gt;&quot;
[&lt;Test&gt;] member test.
  ``Self-closing entity should yield a self-closing tag`` () =
    Zen.html &quot;br&quot; |&gt; should equal &quot;&lt;br/&gt;|&quot;
[&lt;Test&gt;] member test.
  ``Entity should have appropriate attributes generated and placeholder set accordingly`` () =
    Zen.html &quot;a&quot; |&gt; should equal &quot;&lt;a href=\&quot;|\&quot; title=\&quot;\&quot;&gt;&lt;/a&gt;&quot;
</pre>
<p>Теперь у нас есть 3 use-case&rsquo;а: просто тэги, тэги которые не нуждаются в закрывающем тэге, и тэги которые имеют сложную начинку. Второй и третий случай &ndash; специальные, поэтому мы можем попробовать их выделить&hellip;</p>
<p><pre class="brush: fsharp;">
let singularEntities = [&quot;hr&quot;; &quot;br&quot;; &quot;img&quot;]
let neededAttributes = [
                         &quot;a&quot;, [&quot;href&quot;, &quot;title&quot;];
                         &quot;img&quot;, [&quot;src&quot;, &quot;alt&quot;]
                       ]
</pre>
<p>TDD по наивности своей рекоммендует &ldquo;самое простое работающее решение&rdquo; которое в нашем случае выглядит примерно вот так:</p>
<p><pre class="brush: fsharp;">
let html input =
  if input |&gt; String.IsNullOrEmpty then &quot;|&quot;
  else
    let sb = StringBuilder()
    sb.Append (&quot;&lt;&quot; + input) |&gt; ignore
    for a in neededAttributes do
      match a with
      | i, attributes when i = input -&gt;
        let firstAtt = List.head attributes
        sb.Append(&quot; &quot; + firstAtt + &quot;=\&quot;|\&quot;&quot;) |&gt; ignore
        attributes |&gt; List.tail 
                   |&gt; List.iter (fun f -&gt; sb.Append(&quot; &quot; + f + &quot;=\&quot;\&quot;&quot;) |&gt; ignore)
      | _ -&gt; ()
    // see if this is a self-closing tag
    let isSelfClosing = List.exists (fun f -&gt; f = input) singularEntities
    let pipe = if sb.ToString().Contains(&quot;|&quot;) then &quot;&quot; else &quot;|&quot;
    sb.Append(if isSelfClosing then &quot;/&gt;&quot; + pipe else &quot;&gt;&quot; + pipe + &quot;&lt;/&quot; + input + &quot;&gt;&quot;) |&gt; ignore
    sb.ToString()
</pre>
<p>До элегантности тут как до Китая. Вывода напрашивается два:</p>
<ul>
<li>Нужны какие-то структуры для того чтобы отражать структуру тэгов, особенно когда будут вложенные, с аттрибутами, и т.д.</li>
<li>Нужно учиться лучше парсить строки. То, что мы делаем выше &ndash; &ldquo;не по паттернам&rdquo;.</li>
</ul>
<h3>FsLex и FsYacc</h3>
<p>Лучший способ парсить &ndash; это взять что-то уже готовое (хотя до меня это иногда туго доходит). Поэтому для парсинга наших магических строк мы возьмем <a href="http://fsharppowerpack.codeplex.com/" title="http://fsharppowerpack.codeplex.com/">F# Power Pack</a>, и скачаем через VS Extension Manager шаблон проекта под названием <a href="http://visualstudiogallery.msdn.microsoft.com/a075ff98-7e6f-47ce-a23c-838c1e488046/" title="http://visualstudiogallery.msdn.microsoft.com/a075ff98-7e6f-47ce-a23c-838c1e488046/">F# Parser Language Starter</a>. Это позволит нам получить пример, в котором есть три важных файла, а именно:</p>
<ul>
<li><code>Ast.fs</code> &mdash; определение синтактического дерева. В нашем случае оно достаточно простое.</li>
<li><code>Lexer.fsl</code> &mdash; определение &ldquo;лексем&rdquo;, т.е. различных кусков строки, которые формируют выражение HTML Zen.</li>
<li><code>Parser.fsy</code> &mdash; собственно парсер, который определяет то, как лексемы становятся чем-то осмысленным.</li>
</ul>
<p>В сгенерированном примере получается калькулятор<sup><a href="#Reference1" title="Кстати, пример кривой &ndash; попробуйте например ввести 2-2 и у вас парсер моментально накроется &ndash; а все из-за попытки взять минус перед 2кой как префикс-оператор. :)" name="BackReference1">1</a></sup>, нам же остается только поменять его чтобы начали поддерживаться наши собственные структуры.</p>
<h3>AST</h3>
<p>Итак, для нашего магического синтаксиса нам нужно определить тот набор элементов дерева, который мы фактически готовы подерживать. Это включает в себя как минимум следующие конструкции<sup><a href="#Reference2" title="Тут я немного отклонился от &ldquo;кошерного&rdquo; HTML Zen который, на мой взгляд, достаточно избыточен. В частности, я заменил &gt; на + а &ldquo;оригинальный&rdquo; + попросту проигнорировал." name="BackReference2">2</a></sup>:</p>
<ul>
<li>Идентификаторы, такие как <code>div</code>, <code>href</code> и так далее. Они парсятся &ldquo;как есть&rdquo;.</li>
<li>Классы, т.е. при при написании <code>a.b</code> мы получаем <code>&lt;a href="|" class="b"&gt;&lt;/a&gt;</code>.</li>
<li>Идентификаторы, т.е. <code>a#b</code> ставовится <code>&lt;a id="b" href="|"&gt;&lt;/a&gt;</code>.</li>
<li>Множители, т.е. <code>hr*2</code> дает нам <code>&lt;hr/&gt;&lt;hr/&gt;</code>. Между тэгами, между прочим, фигурирует <code>\n</code> &ndash; это вынужденная мера для таких ситуаций как <code>ol&gt;li*2</code>.</li>
<li>Вложенные тэги &ndash; например, <code>ol+li</code> становится <code>&lt;ol&gt;&lt;li&gt;|&lt;/li&gt;&lt;/ol&gt;</code>, с соответствующими переносами и отступами.</li>
</ul>
<p>Теперь попробуем перевисти все эти идеи на структуры F#. У меня получилось примерно следующее:</p>
<p><pre class="brush: fsharp;">
type ZenExpression =
  | ZenExpression of Expression list
and Expression =
  | Expression of Identifier * Qualifier list
and Identifier =
  | Identifier of string
and Qualifier =
  | ClassQualifier of string
  | IdentityQualifier of string
  | CardinalityQualifier of int
</pre>
<p>Строго говоря, то, что вы видите выше &ndash; уродство. С этим очень сложно работать. К тому же, нет никаких ограничений на количество идентификатов или показателей размерности (а ведь элемент может иметь только один квалификатор каждого типа). Ну да ладно, эту проблему мы разрулим позже.</p>
<h3>Лексер</h3>
<p>Лексер у нас будет простенький. Во-первых, нужно определить регулярные выражения для всех полезных конструктов:</p>
<p><pre class="brush: fsharp;">
let digit = ['0'-'9']
let letter = ['a'-'z'] | ['A'-'Z']
let letterOrDigit = letter | digit
let whitespace = [' ' '\t' ]
let newline = ('\n' | '\r' '\n')
</pre>
<p>Ну а теперь, нужно определить какие конструкты будут производится из регулярных выражений. Нам нужны:</p>
<ul>
<li>Строки (возможно с числами) для идентификаторов и квалификаторов.</li>
<li>Операторы для разделения квалификаторов (<code>.</code>, <code>#</code>, <code>+</code> и <code>*</code>)</li>
<li>Числа для квалификатора размерности</li>
</ul>
<p>Следовательно, получаем следующее определение:</p>
<p><pre class="brush: fsharp;">
rule tokenize = parse
| whitespace	   { tokenize lexbuf }
| newline        { tokenize lexbuf }
| letterOrDigit+ { STRING(lexeme lexbuf) }
| digit+         { INT32(Int32.Parse(lexeme lexbuf)) }
// Operators
| &quot;+&quot;            { PLUS }
| &quot;#&quot;            { HASH }
| &quot;*&quot;            { TIMES }
| &quot;.&quot;            { DOT }
// EOF
| eof   { EOF }
</pre><br />
<h3>Парсер</h3>
<p>Определив лексемы, нам нужно научиться парсить их и превращать их комбинации в элементы AST. Для этого пойдет следующее определение:</p>
<p><pre class="brush: fsharp;">
start: exprs { ZenExpression($1) }
exprs:
  | exp PLUS exprs EOF { Expression($1) :: $3 }
  | exp EOF { [Expression($1)] }
exp:
  | STRING quals { (Identifier($1), $2) }
  | STRING { (Identifier($1), []) }
quals:
  | qual quals { $1 :: $2 }
  | qual { [$1] }
qual:
  | DOT STRING  { ClassQualifier($2) }
  | HASH STRING { IdentityQualifier($2) }
  | TIMES INT32 { CardinalityQualifier($2) }
</pre>
<p>Помимо того, что списки чего бы то ни было создаются рекурсивно, тут нет ничего необычного.</p>
<h3>Принтер</h3>
<p>Ну а теперь самое сложное. Помните я сказал, что та структура в которую мы парсим &ndash; убогая и избыточная? Так вот, сейчас вы увидите насколько неудобно такую штуку печатать.</p>
<p>Во-первых, код забрасывается кучей вспомогательных функций для поиска квалификаторов определенного типа. Например:</p>
<p><pre class="brush: fsharp;">
let rec private getId qualifierList =
  match qualifierList with
  | IdentityQualifier(id) :: t -&gt; Some(id)
  | h :: t -&gt; getId t
  | [] -&gt; None
</pre>
<p>Потом, приходится (не знаю в какой уже раз) делать вменяемый билдер для кода:</p>
<p><pre class="brush: fsharp;">
type CodeBuilder() =
  let sb = StringBuilder()
  let mutable indent = 0;
  member this.GetIndent() =
    System.String.Empty.PadRight(indent * 2)
  member this.AppendWithIndent (text:string) = 
    sb.Append(this.GetIndent()).Append(text) |&gt; ignore
  member this.Append (text:string) = 
    sb.Append(text) |&gt; ignore
  member this.NewLine() = sb.AppendLine() |&gt; ignore
  member this.Indent() = indent &lt;- indent + 1
  member this.Unindent() = indent &lt;- indent - 1
  override this.ToString() = sb.ToString()
</pre>
<p>Потом нужен поистине гигантский кусок кода для того чтобы распарсить все кейсы &ndash; конструкция весьма громоздкая:</p>
<p><pre class="brush: fsharp;">
let rec private print expressions (builder:CodeBuilder) =
  match expressions with
  | h :: t -&gt;
    builder.AppendWithIndent &quot;&lt;&quot;
    match h with
    | Expression(name, qual) -&gt;
      builder.Append name
      // id it if has any
      match getId qual with
      | Some(id) -&gt; builder.Append(&quot; id=\&quot;&quot; + id + &quot;\&quot;&quot;)
      | _ -&gt; ()
      // needed attributes
      let needed = getNeededAttributes name
      needed |&gt; List.iter(fun n -&gt; builder.Append(&quot; &quot; + n + &quot;=\&quot;|\&quot;&quot;))
      // classes
      let classes = getClasses qual
      if classes &lt;&gt; List.empty then
        builder.Append(&quot; class=\&quot;&quot;)
        builder.Append(System.String.Join(&quot; &quot;, classes))
        builder.Append(&quot;\&quot;&quot;)
      // if self-closing, then close it
      let selfClosing = singularEntities |&gt; List.exists(fun f -&gt; f = name)
      if selfClosing then builder.Append &quot;/&gt;|&quot;
      else builder.Append &quot;&gt;&quot;
      // if there's more stuff in there, add it
      if t &lt;&gt; List.empty then
        builder.Indent()
        builder.NewLine()
        print t builder
        builder.NewLine()
        builder.Unindent()
        
      if not selfClosing then
        builder.Append(&quot;|&lt;/&quot; + name + &quot;&gt;&quot;)
  | _ -&gt; 
    builder.Append &quot;|&quot;
</pre>
<p>А вот собственно как все запускается:</p>
<p><pre class="brush: fsharp;">
let html input = 
  let lexbuf = LexBuffer&lt;char&gt;.FromString(input)
  let parsed = Parser.start Lexer.tokenize lexbuf
  let builder = new CodeBuilder()
  match parsed with
  | ZenExpression(items) -&gt; print items builder
  let pre = builder.ToString() |&gt; Seq.toList
  let rec clean input metBar =
    match input with
    | '|' :: t when not metBar -&gt; '|' :: clean t true
    | '|' :: t when metBar -&gt; clean t true
    | h :: t -&gt; h :: clean t metBar
    | [] -&gt; []
  let lst = clean pre false
  System.String(lst |&gt; List.toArray)
</pre>
<p>Излишние телодвижения у нас от того, что мы в принтере генерируем избыточное число кареток. Нужно удалить все кроме первой, а более элегантного способа я не знаю (хотя не исключаю что он существует).</p>
<h3>Заключение</h3>
<p>В очередной раз у меня сомнения. Количество телодвижений для того чтобы реализовать парсер примерно в 10 раз больше чем когда я все это писал &ldquo;в лоб&rdquo; на C#. FxLex и FsYacc обладают практически нулевой диагностичностью, никакого IntelliSense нет, такое впечатление что блуждаешь в потемках. Что касается принтера, опять же, структура на которую все было &ldquo;замэплено&rdquo; очень неудобна; намного быстрее было бы использовать ООП. Плюшки FP вроде паттерн-матчинга и прочего тут совсем не амортизировались.</p>
<h3>Заметки</h3>
<ol>
<li><a name="Reference1"></a><a href="#BackReference1" title="Back to text">&uarr;</a> Кстати, пример кривой &ndash; попробуйте например ввести <code>2-2</code> и у вас парсер моментально накроется &ndash; а все из-за попытки взять минус перед 2кой как префикс-оператор. :)</li>
<li><a name="Reference2"></a><a href="#BackReference2" title="Back to text">&uarr;</a> Тут я немного отклонился от &ldquo;кошерного&rdquo; HTML Zen который, на мой взгляд, достаточно избыточен. В частности, я заменил <code>&gt;</code> на <code>+</code> а &ldquo;оригинальный&rdquo; <code>+</code> попросту проигнорировал.</li>
</ol>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a>, <a href='http://nesteruk.wordpress.com/category/net/f/'>f#</a> Tagged: <a href='http://nesteruk.wordpress.com/tag/fslex/'>fslex</a>, <a href='http://nesteruk.wordpress.com/tag/fsyacc/'>fsyacc</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/733/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/733/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=733&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/03/03/parsing-htmlzen-fsharp-fslex-fsyacc/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>
	</item>
		<item>
		<title>Уравнения на F# проще чем на C#?</title>
		<link>http://nesteruk.wordpress.com/2011/02/05/are-fsharp-equations-easier-than-csharp/</link>
		<comments>http://nesteruk.wordpress.com/2011/02/05/are-fsharp-equations-easier-than-csharp/#comments</comments>
		<pubDate>Sat, 05 Feb 2011 07:52:32 +0000</pubDate>
		<dc:creator>Dmitri</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[f#]]></category>

		<guid isPermaLink="false">http://nesteruk.wordpress.com/?p=718</guid>
		<description><![CDATA[На недавней встрече, посвещенной языку F#, я показал как якобы «элегантно» можно описывать математические функции на F#. А сейчас сел и задумался &#8211; так ли это на самом деле? Давайте разберемся. Квадратное уравнение Начнем с примера, приведенного мною на встрече &#8211; решения квадратного уравнения. Казалось бы &#8211; что может быть проще? Сразу можно сделать несколько [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=718&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>На <a href="http://spbalt.net/Home/Meetings/25" title="http://spbalt.net/Home/Meetings/25">недавней встрече</a>, посвещенной языку F#, я показал как якобы «элегантно» можно описывать математические функции на F#. А сейчас сел и задумался &ndash; так ли это на самом деле? Давайте разберемся.</p>
<h3>Квадратное уравнение</h3>
<p>Начнем с примера, приведенного мною на встрече &ndash; решения квадратного уравнения. Казалось бы &ndash; что может быть проще?</p>
<p align="center"><img src="http://nesteruk.org/pix/0/4d155c02-150c-48b9-a862-c6ac1cfb5d6b.png" alt="" style="border:0;" align="center" class="aligncenter" /></p>
<p>Сразу можно сделать несколько сравнений C# и F# для этого примера:</p>
<ul>
<li>Возвращаются 2 значения, а следовательно F# выигрывает за счет того что не надо писать <code>Tuple.Create</code>, а тому кто эти значения получит не надо использовать абсолютно ничего не значащие свойства <code>Item1</code> и <code>Item2</code></li>
<li>Математические binding&rsquo;и у F# намного «ближе» чем у C#, а следовательно в этом случае (да и в общем), ваш код на F# не будет испачкан явным вызовом статических функций вроде <code>Math.Sqrt</code>. Меня всегда это бесило в C# т.к. сложные вычисления становится еще сложнее читать.</li>
<li>Ни C# ни F# не умеют работать с оператором ±. Но если в C# нам придется тупо вызывать вычисления дважды, в F# мы можем просто определить функцию конечного вычисления, а потом передать в нее операторы <code>(+)</code> и <code>(-)</code>.</li>
</ul>
<p>В результате получим следующее сравнение:</p>
<p>
  <strong>C#</strong>
</p>
<p><pre class="brush: csharp;">
public Tuple&lt;double,double&gt; SolveQuadraticEquation(double a, double b, double c)
{
  double discRoot = Math.Sqrt(b*b-4.0*a*c);
  double x1 = (-b + discRoot) / (2 * a);
  double x2 = (-b - discRoot) / (2 * a);
  return Tuple.Create(x1, x2);
}
</pre>
<p>
  <strong>F#</strong>
</p>
<p><pre class="brush: fsharp;">
let solveQuadratic a b c =
  let disc = b * b - 4.0 * a *c
  let calc op = (op (-b) (sqrt disc)) / (2.0*a)
  (calc (+), calc(-))
</pre>
<p>Пока что разница небольшая &ndash; в одну строчку, если не считать фигурных скобок. А спорим я могу сократить эту разницу практически до нуля? Вот, пожалуйста:</p>
<p>
  <strong>C#</strong>
</p>
<p><pre class="brush: csharp;">
public Tuple&lt;double, double&gt; SolveQuadraticEquation(double a, double b, double c)
{
  double q = -0.5 * (b + Math.Sign(b) * Math.Sqrt(b * b - 4 * a * c));
  return Tuple.Create(q / a, c / q);
}
</pre>
<p>
  <strong>F#</strong>
</p>
<p><pre class="brush: fsharp;">
let solveQuadraticEquation a b c =
  let q = -0.5 * (b + (sign b |&gt; float) * sqrt(b * b - 4.0 * a * c))
  (q / a, c / q) //           ^^^^^^^^ WTF?!?
</pre>
<p>Пример на F# должен вызвать у вас возмущение &ndash; с какой это радости результат <code>(sign b)</code> должен быть приведен к типу <code>float</code>?<sup><a href="#Reference1" title="Напоминаю, что float в F# &ndash; это double в C#. А C#-ный float в F# называется float32." name="BackReference1">1</a></sup> А дело все в непродуманности API, согласно которому <code>sign(x)</code> &ndash; это всегда <code>int</code> (могли бы сделать тем же типом что и аргумент), а также крайне жесткой системе типов в которой <code>float + int * float</code> не воспринимается и никак не вычисляется.</p>
<p>Такое странное поведение F# унаследовано из OCaml и требуется для правильного вывода типов. Если вам действительно интересны причины &ndash; можно <a href="http://cs.hubfs.net/forums/thread/3391.aspx" title="http://cs.hubfs.net/forums/thread/3391.aspx">почитать тут</a>. Мне же это лишь палки в колеса. Да, и я знаю что можно было бы написать <code>sign(float b)</code> или что-то в этом роде. Тут как бы без разницы, все равно «не очень».</p>
<h3>Комплексные решения</h3>
<p>Ну да ладно, а вот вопрос &ndash; что будет если дискриминанта (&Delta;) меньше нуля? С одной стороны, и C# и F# поддерживает комплексные типы данных (см. System.Numerics). Если сделать вид что мы все будем передавать как комплексные числа (так проще?), то получим вот такой вот код:</p>
<p>
  <strong>C#</strong>
</p>
<p><pre class="brush: csharp;">
public Tuple&lt;Complex, Complex&gt; SolveQuadraticEquation3(double a, double b, double c)
{
  double det = b * b - 4 * a * c;
  double absRoot = Math.Sqrt(Math.Abs(det));
  Complex root = det &lt; 0 ? new Complex(0, absRoot) : new Complex(absRoot, 0);
  Complex q = -0.5 * (b + Math.Sign(b) * root);
  return Tuple.Create(q / a, c / q);
}
</pre>
<p><strong>F#</strong></p>
<p><pre class="brush: fsharp;">
let solveQuadratic3 a b c =
  let complex v = Complex(v, 0.0)
  let det = b * b - 4.0 * a * c
  let absRoot = sqrt(det |&gt; abs)
  let root = if det &lt; 0.0 then Complex(0.0, absRoot)
                          else Complex(absRoot, 0.0)
  let q = -(complex 0.5) * ((complex b) + (sign b |&gt; float |&gt; complex) * root)
  (q / complex(a), complex(c) / q)
</pre>
<p>Эээ, ну что я могу сказать? F# определенно превносит массу головной боли. Проблема тут как раз в том, что в C# нам доступны операторы автоконверсии вроде <code>float</code>&rarr;<code>Complex</code>, но в F# они попросту не работают! Поэтому вы можете либо определить их как функции (благо у них есть имя <code>op_Implicit</code>), либо же просто вызвать конструктор как делаю я.<sup><a href="#Reference2" title="Тут еще хочется заметить что if который выбирает какой Complex создавать как бы не нужно &mdash; можно было вместо этого написать Complex.Sqrt(new Complex(b*b-4*a*c, 0.0)). Проблема только в том что в результате этого вычисления Real-значение будет чуточку отличаться от нуля. Например sqrt(Complex(-4.0, 0.0)) равен (1.22460635382238E-16, 2)." name="BackReference2">2</a></sup></p>
<h3>Заключение</h3>
<p>То ли я чего-то недопонимаю, то ли F# действительно неудобен для работы с математикой? Ведь если нужно каждый <code>int</code> кастовать во <code>float</code>, а каждый <code>float</code> в <code>Complex</code>, и так далее, то это же сколько лишнего, никому не нужного и мешающего восприятию кода надо написать?</p>
<p>Критика welcome! А то может я что не так написал?</p>
<h3>Заметки</h3>
<ol>
<li><a name="Reference1"></a><a href="#BackReference1" title="Back to text">&uarr;</a> Напоминаю, что <code>float</code> в F# &ndash; это <code>double</code> в C#. А C#-ный <code>float</code> в F# называется <code>float32</code>.</li>
<li><a name="Reference2"></a><a href="#BackReference2" title="Back to text">&uarr;</a> Тут еще хочется заметить что <code>if</code> который выбирает какой <code>Complex</code> создавать как бы не нужно &mdash; можно было вместо этого написать <code>Complex.Sqrt(new Complex(b*b-4*a*c, 0.0))</code>. Проблема только в том что в результате этого вычисления Real-значение будет <em><font face="Trebuchet MS" />чуточку</font></em> отличаться от нуля. Например <code>sqrt(Complex(-4.0, 0.0))</code> равен <code>(1.22460635382238E-16, 2)</code>.</li>
</ol>
<br />Filed under: <a href='http://nesteruk.wordpress.com/category/net/'>.NET</a>, <a href='http://nesteruk.wordpress.com/category/c/'>C#</a>, <a href='http://nesteruk.wordpress.com/category/net/f/'>f#</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/718/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nesteruk.wordpress.com/718/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nesteruk.wordpress.com/718/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nesteruk.wordpress.com/718/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nesteruk.wordpress.com/718/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nesteruk.wordpress.com/718/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nesteruk.wordpress.com/718/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=718&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://nesteruk.wordpress.com/2011/02/05/are-fsharp-equations-easier-than-csharp/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;r=G" medium="image">
			<media:title type="html">nesteruk</media:title>
		</media:content>

		<media:content url="http://nesteruk.org/pix/0/4d155c02-150c-48b9-a862-c6ac1cfb5d6b.png" medium="image" />
	</item>
	</channel>
</rss>

