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

<channel>
	<title>DoK. Мысли из жизни.</title>
	<atom:link href="http://smarty.ru/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://smarty.ru</link>
	<description>Всё интересное, что не тянет на статью, но требует обсуждения.</description>
	<lastBuildDate>Sat, 08 Oct 2011 17:58:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Optimizing Insert in PostgreSQL: index locality</title>
		<link>http://smarty.ru/?p=65</link>
		<comments>http://smarty.ru/?p=65#comments</comments>
		<pubDate>Sat, 08 Oct 2011 17:58:08 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=65</guid>
		<description><![CDATA[There are tons of materials around there on how to optimize selects, how plans work and so, but almost no information on how to optimize insert/update/delete operations. At least I haven&#8217;t found what I needed so I wish to tell my story. First of all a bit of environment: I have a large part of [...]]]></description>
			<content:encoded><![CDATA[<p>There are tons of materials around there on how to optimize selects, how plans work and so, but almost no information on how to optimize insert/update/delete operations. At least I haven&#8217;t found what I needed so I wish to tell my story.</p>
<p>First of all a bit of environment: I have a large part of database for search (well it counts in tens of millions of records) with need for<br />
a) fast search (so there must be some indexes).<br />
b) fast update with lots of data (again several millions of records of updates a day are usual).<br />
c) some sort of uniqueness so that cache contains only latest record for some condition.  </p>
<p>Actually insert/update/delete optimization is pretty simple: every index you have slows updates down, so don&#8217;t make too much of them. But there is another case to consider: how much pages of index would be updated in case of data update.</p>
<p>In my situation the goal c) was achieved by using md5(of some fields), this is quite a good key it has perfect distribution (there are no repeating numbers and also they are spred very well). It&#8217;s also quite usefull in operations: single field in index, single equality in join.</p>
<p>But there was one problem: when I tried to insert let&#8217;s say 100K rows with new equality keys it distributed almost to every page of an index, so operation was very sloowww. Thanks to good distribution of equality_key <img src='http://smarty.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Sadly situation get only worse over time as overall size grows, because updates are still very random.</p>
<p>Solution in my case was to &laquo;group&raquo; this index in a manner it is updated (in my case it is hotel_id, departure_date, and only then equality_key). This gives much better locality in updates and little impact in search perfomance (actually due to locality impcat should be even positive). I have some numbers but they wouldn&#8217;t say much and it&#8217;s not a purpose of this post. In my case update perfomance was boosted by an order of magnitude, and it should degrade so much with growth of DB size, so now I&#8217;m happy <img src='http://smarty.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>The overall rule to consider in optimizing inserts/updates/deletes is to look on how many index pages would be updated in typical update situation (i.e. index could be thought as table records sorted in index order (actually it&#8217;s a lot different, but still model is very nice in many situations)). Ideally only pages, related to new data should be updated almost fully, and other should not be touched.</p>
<p>This might be very very simple and obvious when you know about it. But some people (like me) don&#8217;t know this. I hope this would help.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=65</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Получение пути к свойству, несколько мыслей, QueryDSL</title>
		<link>http://smarty.ru/?p=61</link>
		<comments>http://smarty.ru/?p=61#comments</comments>
		<pubDate>Mon, 04 Oct 2010 18:25:32 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cglib]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=61</guid>
		<description><![CDATA[Наткнулся тут на http://blog.mysema.com/2010/07/querying-hibernate-with-querydsl.html &#8211; по своему интересная игрушка . Тут описан вариант с кодогенерацией через процессор анотаций, но в доках есть вариант и без него, примерно так: Cat c = alias&#40;Cat.class, &#34;cat&#34;&#41;; List&#60;String&#62; names = from&#40;$&#40;c&#41;,cats&#41; &#160; .where&#40;$&#40;c.getKittens&#40;&#41;&#41;.size&#40;&#41;.gt&#40;0&#41;&#41; &#160; .list&#40;$&#40;c.getName&#40;&#41;&#41;&#41;; &#160; for &#40;String name : names&#41;&#123; &#160; &#160; System.out.println&#40;name&#41;; &#125; Порывшись в исходниках нашёл [...]]]></description>
			<content:encoded><![CDATA[<p>Наткнулся тут на http://blog.mysema.com/2010/07/querying-hibernate-with-querydsl.html &#8211; по своему интересная игрушка <img src='http://smarty.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Тут описан вариант с кодогенерацией через процессор анотаций, но в доках есть вариант и без него, примерно так:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">
<ol>
<li class="li1">
<div class="de1">Cat c = alias<span class="br0">&#40;</span>Cat.<span class="kw2">class</span>, <span class="st0">&quot;cat&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">List&lt;String&gt; names = from<span class="br0">&#40;</span>$<span class="br0">&#40;</span>c<span class="br0">&#41;</span>,cats<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; .<span class="me1">where</span><span class="br0">&#40;</span>$<span class="br0">&#40;</span>c.<span class="me1">getKittens</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">gt</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; .<span class="me1">list</span><span class="br0">&#40;</span>$<span class="br0">&#40;</span>c.<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">for</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> name : names<span class="br0">&#41;</span><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
</div>
<p>Порывшись в исходниках нашёл способ, как оно работает (меня ещё со времён squeryl эта магия интересовала, но там так и не докопал сырцы)&#8230; там походу дела alias при помощи cglib генерирует класс-прокси (в отличии от JDK Proxy, которые только для интерфейсов, cglib позволяет генерить и класс-прокси). А вот что с ним дальше делать? А тут похоже всё просто &#8211; хранится &laquo;глобальный&raquo; (видимо для алиаса) путь, соответственно вызовы прокси этот путь увеличивают, например, c.getKittens() кладёт нужную запись в локальный путь, а $(&#8230;) тупо выдёргивает весь последний путь, немного контролируя типы и сбрасывает память пути. Вуаля, получаем обработку вызовов object.getSomething().getSomethingElse().getSomethingMore(), которая компилируется, а в рантайме генерирует путь.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=61</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Проблема редактирования и состояния объектов</title>
		<link>http://smarty.ru/?p=59</link>
		<comments>http://smarty.ru/?p=59#comments</comments>
		<pubDate>Mon, 19 Apr 2010 15:44:44 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[недодумано]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=59</guid>
		<description><![CDATA[Как работает абстрактный редактор в GUI? Очень просто &#8211; ему даётся некоторый объект, он его хавает, заполняет по нему то, что должен сейчас редактировать, дальше ОК/Отмена, если ОК &#8211; проверяет, всё ли правильно введено и если всё верно &#8211; применяет редактирование к объекту. И тут всё просто и хорошо. А вот что, если отмена? По [...]]]></description>
			<content:encoded><![CDATA[<p>Как работает абстрактный редактор в GUI?</p>
<p>Очень просто &#8211; ему даётся некоторый объект, он его хавает, заполняет по нему то, что должен сейчас редактировать, дальше ОК/Отмена, если ОК &#8211; проверяет, всё ли правильно введено и если всё верно &#8211; применяет редактирование к объекту. И тут всё просто и хорошо.</p>
<p>А вот что, если отмена? По идее ничего, просто не надо ничего применять. Объект остаётся в исходном состоянии.</p>
<p>И вот тут начинаются сложности, как бы так не изгадить исходный объект. Вариант первый, можно использовать своего рода &laquo;патчи&raquo; &#8211; т.е. редактор накапливает изменения и применяет их _всегда_ только, если все проверки пройдены.</p>
<p>Проблемы:<br />
- Если какие-то проверки целостности завязаны на совокупное состояние объекта (скажем, что поле А меньше поля Б), то логику проверки придётся продублировать в диалоге. Нельзя использовать зашитое в объекте, т.к. нельзя в него записать (вдруг проверка не пройдёт и будет &laquo;отмена&raquo;).</p>
<p>- И это бы ладно, но что делать, если редактор в том числе вносит изменения в списковое поле? </p>
<p>Пример:<br />
Редактируем партнёра<br />
+ гридик с его юр-лицами.</p>
<p>Соответственно в процессе редактирования партнёра юр. лица могут добавляться, удаляться, изменяться. При изменении юр. лица показывается редактор юр. лица (так или иначе) и он вообще говоря знать не знает про то, что он показан в контексте редактирования партнёра и ему надо накопить изменения, но не применять (т.к. редактирование партнёра может и отмениться).</p>
<p>В общем на списках у меня эта стратегия работы с накоплением изменений и загнулась.</p>
<p>Альтернативно сейчас думаю над вариантом, когда редактор начиная что-то править делает себе полную копию того, что ему дали (а это ой как не просто, сделать полную копию <img src='http://smarty.ru/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  ), и делает с ней что хочет, если всё успешно &#8211; возвращает и это уже обязанность вызвавшего правильно &laquo;пристроить&raquo; эту копию &#8211; записать себе в список, сохранить в БД или ещё чего с ней сотворить.</p>
<p>Отдельно есть сложность составления копии&#8230; тут уже весёлости Java. В общем, с clone всё очень непросто, там и жёсткие проверки не сделаешь и с теми же коллекциями хлопот много.</p>
<p>В общем из способов не слишком обременительных пока нарыл Serializable + засериализовать/рассериализовать&#8230; криво, сначала даже думать не хотел в эту сторону, но всё остальное ещё хуже.</p>
<p>В общем это так, поток мысли в процессе. Кто что скажет?</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=59</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Пустячок с LEFT JOIN или NULL != NULL is false и NULL = NULL is false</title>
		<link>http://smarty.ru/?p=57</link>
		<comments>http://smarty.ru/?p=57#comments</comments>
		<pubDate>Wed, 10 Feb 2010 16:05:19 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[мелочи]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=57</guid>
		<description><![CDATA[Довольно таки интересная штука, помоему в жизни каждый программист на неё пару раз напоролся. Если не помнит, значит ему повезло.. я в своё время хорошо налетел на часик отладки. Простой запрос: SELECT o.*, m.* FROM &#160; orders o &#160; LEFT JOIN manager m ON m.id = o.manager_id WHERE &#160; m.is_active = true Запрос простой, тут [...]]]></description>
			<content:encoded><![CDATA[<p>Довольно таки интересная штука, помоему в жизни каждый программист на неё пару раз напоролся. Если не помнит, значит ему повезло.. я в своё время хорошо налетел на часик отладки.</p>
<p>Простой запрос:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">
<ol>
<li class="li1">
<div class="de1"><span class="kw1">SELECT</span> o.*, m.*</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">FROM</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; orders o</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">LEFT</span> <span class="kw1">JOIN</span> manager m <span class="kw1">ON</span> m.id = o.manager_id</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">WHERE</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; m.is_active = true</div>
</li>
</ol>
</div>
</div>
<p>Запрос простой, тут нестыковка очевидна &#8211; несмотря на то, что хочу я получить все заказы, с активными менеджерами, либо заказы без менеджера (т.к. LEFT JOIN), получу я только лишь заказы с активными менеджерами. Проблема в том, что там где менеджер не найдётся (предположим это необязательное поле), m.is_active будет NULL, а когда я сравню NULL c true, я получу ложь. И такие записи меня не устроят.</p>
<p>Решение? Обходное &#8211; m.is_active is null or m.is_active = true. Правильное? Вероятно здесь надо просто перенести условие в условие JOIN-а (на самом деле в зависимости от того, что я имел ввиду).</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=57</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Область видимости переменных</title>
		<link>http://smarty.ru/?p=55</link>
		<comments>http://smarty.ru/?p=55#comments</comments>
		<pubDate>Mon, 08 Feb 2010 11:23:26 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=55</guid>
		<description><![CDATA[Думал с чего начать, это показалось самым простым. Собственно речь о том, где и как хранить и передавать информацию между частями программы. Самое простое в программе – локальные переменные. Почему? Они живут на стэке =&#62; существует один экземпляр для одного вызова функции. Вся работа с ними у нас перед глазами – все изменения и чтения [...]]]></description>
			<content:encoded><![CDATA[<p>Думал с чего начать, это показалось самым простым. Собственно речь о том, где и как хранить и передавать информацию между частями программы.</p>
<p>Самое простое в программе – <strong>локальные переменные</strong>. Почему? Они живут на стэке =&gt; существует один экземпляр для одного вызова функции. Вся работа с ними у нас перед глазами – все изменения и чтения =&gt; мы можем легко добавлять новые, менять и убирать старые. Всё у нас в руках. Есть полная уверенность, что ни одна другая часть программы не может влиять на них.</p>
<p>Второе – <strong>параметры функции и возвращаемое значение</strong>. Также простая штука. Они у нас перед глазами. Они также живут на стэке, т.е. в рамках одного вызова мы можем быть уверены, что они полностью в нашей власти (никто снаружи не залезет и не изменит их). Единственная проблема с ними – могут дать не то, что надо, но и от этого можно обезопаситься: заставить компилятор проверить правильность типа, да и самим проверить значения/тип на допустимость, и после этого работать с ними спокойно.</p>
<p>Прелесть локальных переменных и параметров в том, что работая с ними надо держать в голове только лишь один метод, про всё остальное можно забыть. Нам что-то дали и мы должны что-то вернуть, это описано в начале и больше нас ничего не волнует.</p>
<p><strong>Поля экземпляра.</strong> Тут уже всё несколько сложнее. Проблем несколько:</p>
<ol>
<li>Чтобы понять, какие 	поля использует метод надо прочитать 	его. Т.е. нигде в его заголовке это не 	описано.</li>
<li>Доступ к полям имеют 	все методы, а значит они могут их менять. 	Это означает, что на протяжении работы 	нашего метода, если он не дай бог вызывает 	что-то ещё, значение поля может измениться.</li>
<li>Значение поля одно 	на один экземпляр, а значит при рекурсии 	могут быть проблемы.</li>
</ol>
<p>Таким образом, при работе с неконстантными полями объекта в голове надо держать уже весь класс целиком (все методы, работающие с полем), всех предков (если поле унаследовано) и всех потомков (если поле не private). А это довольно сильно повышает нагрузку на мозг. Не всё так страшно, если использовать несколько правил:</p>
<ul>
<li>Не надо использовать 	поля объекта для передачи параметров 	в фукции, для этого есть… параметры 	функций.</li>
<li>Тоже самое с результатом 	работы метода (за исключением редких 	случаев).</li>
<li>Поля объекта удобно 	использовать для настройки объекта, 	которая задаётся в конструкторе и не 	меняется на протяжении всей жизни 	объекта (либо меняется в очень понятных 	точках).</li>
<li>Поля лучше делать 	private, от греха подальше 	(область которую надо держать в голове 	сразу сокращается до одного класса), 	аналогигчно, public заставляет 	помнить про всех пользователей класса.</li>
</ul>
<p><strong>Глобальные переменные</strong>. Тут вообще в голове надо держать всё глобально – всё, что может писать в переменную. Да ещё и экземпляр всего один. Реально они нужны довольно редко. Кстати, на заметку, Singleton == глобальная переменная (почти). И тоже нужен крайне редко (инъекция зависимостей – наше всё).</p>
<p>Маленькое итого. Надо стараться по максимуму использовать передачу данных функциям. Параметры – значит параметры функций, результат – значит результат. Параметры должны быть явными (по максимуму типизированными) и понятными, что не понятно компилятору/парсеру должно проверяться на входе. После этого можно выбросить из головы происхождение параметров и писать только логику функции.</p>
<p>Поля объекта – для настройки объекта (вообще говоря, для состояния объекта, но состояние должно поминимуму включать временные переменные). И private, чтобы меньше заботиться.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=55</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Мы ограниченные, и это нормально</title>
		<link>http://smarty.ru/?p=53</link>
		<comments>http://smarty.ru/?p=53#comments</comments>
		<pubDate>Mon, 08 Feb 2010 11:20:19 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[разработка]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=53</guid>
		<description><![CDATA[Программист – существо ограниченное, я например – точно: Я не могу держать в голове более 7 +/- 2 вещей. У меня хорошая память, но я не могу запомнить все переменные, выражения, методы и классы в программе. Также я не могу помнить все зависимости в коде. Я плохо читаю запутанный код (и не хочу этого делать). [...]]]></description>
			<content:encoded><![CDATA[<p>Программист – существо ограниченное, я например – точно:</p>
<ul>
<li>Я не могу держать в 	голове более 7 +/- 2 вещей.</li>
<li>У меня хорошая память, 	но я не могу запомнить все переменные, 	выражения, методы и классы в программе.</li>
<li>Также я не могу 	помнить все зависимости в коде.<span style="background-color: #ffffff;"> </span></li>
<li>Я плохо читаю запутанный код (и не хочу этого делать).</li>
</ul>
<p>Т.е. я на самом деле слышал, что существует лишь одно существо, неподвластное этим ограничениям… правда его зовут по разному, и с доказательствами туго. Но тем не менее, это не означает, что мы не можем писать большие хорошие работающие программы.</p>
<p>Нужно всего то:</p>
<ul>
<li>Сократить  объём 	вещей в памяти до необходимого количества 	( = сделать остальное ненужным для 	решения конкретной задачи).</li>
<li>Использовать средства, 	готовые в любой момент заменить мою 	дырявую память (IDE), 	использовать максимальное количество 	проверок (компилятор, тесты), 	а также делать названия настолько 	очевидными, чтобы я не помнил название, 	а правильно его составлял каждый раз.</li>
<li>Максимально упрощать зависимости = делать их очень явными 	и локальными.</li>
</ul>
<p>Собственно на решение этих задач направлено всё искусство программирования, все методы, будь то выделение процедур из алгоритмов, выделение объектов из сложного взаимодействия или преобразование алгоритма в более декларативный, более понятный вид.</p>
<p>Что интересно, для того чтобы программировать быстро и качественно необходимо всего лишь победить эти проблемы, т.е. программировать понятно, а это даст всё остальное.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=53</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Разработка</title>
		<link>http://smarty.ru/?p=51</link>
		<comments>http://smarty.ru/?p=51#comments</comments>
		<pubDate>Mon, 08 Feb 2010 11:17:50 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=51</guid>
		<description><![CDATA[Давно я не писал. Не знаю, получится ли цикл заметок, как хотелось бы, или нет, но что-то хотелось бы. Цель – всё та же, структурировать текущую картину мира, для себя – чтобы в очередной раз всё вспомнить и для других, чтобы этим поделиться. Заметка первая, зачем всё это нужно. Мы никогда ничего не пишем только [...]]]></description>
			<content:encoded><![CDATA[<p>Давно я не писал. Не знаю, получится ли цикл заметок, как хотелось бы, или нет, но что-то хотелось бы. Цель – всё та же, структурировать текущую картину мира, для себя – чтобы в очередной раз всё вспомнить и для других, чтобы этим поделиться.</p>
<p>Заметка первая, зачем всё это нужно.</p>
<p>Мы никогда ничего не пишем только чтобы написать. Пишем мы, чтобы оно работало, развивалось, цвело и пахло. Ещё нельзя исключать такую вещь, как итеративность. Как бы нам ни хотелось, реалии таковы, что задачи не ставятся целиком, что сделали и всё. Нет, мы делаем макет, потом делаем пробную версию, потом делаем рабочую версию, потом делаем рабочую рабочую версию… ну вы поняли, и так раз 5, 10, 20, 100, в зависимости от длины жизни проекта (что самое забавное – чем живучее проект, тем больше раз мы будем в нём что-то менять/дорабатывать).</p>
<p>Ах да, ещё есть такая проблема, что всё надо делать а) быстро и б) хорошо. Казалось бы несовместимо. Совместимо. Причём иногда оказывается, что быстро и плохо сделать не получается. Парадокс.</p>
<p>Я отвлёкся. Суть такая, что основная задача – быстро писать качественный код, при чём такой, который потом можно будет также быстро дорабатывать, менять, убирать и т.п. Важно – чтобы потом можно было не выкинуть всё и начать заново, а именно использовать максимум наработок.</p>
<p>Собственно об этом всё дальше и будет.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=51</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ОО программирование, как я его сейчас понимаю</title>
		<link>http://smarty.ru/?p=44</link>
		<comments>http://smarty.ru/?p=44#comments</comments>
		<pubDate>Tue, 19 May 2009 13:38:39 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[ООП]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=44</guid>
		<description><![CDATA[Вообще меня, как и многих едва ли не в школе научили, что вот, есть такая штука, как объектно-ориентированное программирование. Есть объекты и всё такое. Потом тому же учили в институте. Но как-то так вышло, что моё понимание ООП со времён института очень сильно изменилось, и хочется это изменение зафиксировать. Поэтому &#171;сейчас&#187; означает &#171;не так, как [...]]]></description>
			<content:encoded><![CDATA[<p>Вообще меня, как и многих едва ли не в школе научили, что вот, есть такая штука, как объектно-ориентированное программирование. Есть объекты и всё такое. Потом тому же учили в институте. Но как-то так вышло, что моё понимание ООП со времён института очень сильно изменилось, и хочется это изменение зафиксировать. Поэтому &laquo;сейчас&raquo; означает &laquo;не так, как тогда&raquo;, впрочем, видимо через год-два можно будет написать новое &laquo;сейчас&raquo;, которое также будет отличаться.</p>
<h2>Итак, что было</h2>
<p>Нас учили, что основные понятия ООП, это:</p>
<ul>
<li>Инкапсуляция</li>
<li>Наследование</li>
<li>Полиморфизм</li>
</ul>
<p>При этом инкапсуляция &#8211; сокрытие всего так, чтобы снаружи знали поменьше о классе; наследование &#8211; возможность создавать новые классы на базе существующих, заменять в них методы, дополнять, и использовать части предка; полиморфизм &#8211; возможность использовать один класс вместо другого (как правило из той же иерархии)&#8230; ну в общем тут был совершенно замечательный пример про рисование &#8211; фигура &#8211; линия, фигура &#8211; квадрат.</p>
<p>То, что я извлёк (это вероятно относится и ко мне и к программе, т.к. очень многие после той же программы думают также) &#8211; это то, что я могу написать в резюме &laquo;я знаю ООП&raquo;, что в итоге сводится к тому, что я умею записывать процедурный код в классы, и моим любимыми паттернами являются недоделанный Template Method и God Object (не в крайнем проявлении, но как направление).</p>
<h2>Что надо было вбить или услышать</h2>
<p><strong>Инкапсуляция </strong>- это не только то, что можно сокрыть часть данных и методов, но сам принцип, что мы ограничиваем внешнее знание об объекте с целью уменьшения количества зависимостей. А также важны примеры, как это делать или не делать&#8230; без фанатизма &laquo;все свойства должны быть закрытыми&raquo;, но с пониманием того, что надо задумываться &laquo;а по сути это ожидается снаружи?&raquo;.</p>
<p>Простите крамольную мысль необразованного человека, но интерфейсы &#8211; тоже форма инкапсуляции, потому что оставяют от всего интерфейса класса только несколько согласованных методов, уменьшая зависимости.</p>
<p><strong>Наследование </strong>- о да! Наследование решает все проблемы <img src='http://smarty.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . И на следующем шаге порождает в два раза больше, если использовать неправильно. Особенно прикольны рассуждения &laquo;этот метод нужен в 3 из 5 наследников, давайте поднимем его в родителя&raquo;. Вообще наверное корень зла в том, что наследование у меня в своё время спозиционировалось, как способ повторного использования кода, хотя таковым не является. Наследования &#8211; это отношение &laquo;является&raquo; и очень сильная связь между двумя классами. Если нужно повторное использование кода &#8211; есть масса других механизмов.</p>
<p>Мой любимый Template Method хотя и имеет право на жизнь в принципе, но в тех объёмах, в которых он использовался (и используется порой :-Р) &#8211; страшное зло, потому что исполнение неявно скачет из одного класса в другой и когда что произойдёт предсказать сложно (как и что обрушится, если что-то изменить). (З.Ы. Там надо было его ограничивать и делать более строгим, никаких реализаций по умолчанию, которые потом опционально перекрываются).</p>
<p>Ещё про наследование &#8211; очень важная вещь &#8211; принцип подстановки Лискоу. Что объект порождённого класса должен использоваться везде где используется его предок без нарушения интерфейса (в частном) и вообще обещаний (в целом). Является ли правильной цепочка наследования Фигура &#8211; Прямоугольник &#8211; Квадрат? В общем нет, потому что с точки зрения программирования Квадрат часто не является Прямоугольником (как &laquo;честно&raquo; реализовать методы setWidth/setHeight в квадрате?).</p>
<p><strong>Полиморфизм</strong> &#8211; вот тут интересно, пусть это моё имхо, но полиморфизм надо рассказывать на базе интерфейсов (каждый класс &#8211; неявно порождает интерфейс, который наследуют предки, так что для классов и наследников всё верно).  И это тоже к принципу подстановки Лискоу &#8211; кто реализует интерфейс &#8211; реализует его полностью и соблюдая обещания, если нельзя полностью &#8211; то что-то не так, возможно нужно два интерфейса вместо одного.</p>
<p>А сюда кстати завязана инкапсуляция с другого конца &#8211; каждый код должен очень чётко и минимально сформулировать, что ему надо от других объектов, и больше ничего не спрашивать. Именно поэтому я считаю, что интерфейс должен предоставляться &laquo;потребителем&raquo; объекта. Т.е. если есть алгоритм сортировки, то он даёт интерфейс &laquo;Сортируемое&raquo; &#8211; и уже задача пользователя реализовать его или адаптер, если они хотят сортироваться этим алгоримом. Можно пойти и дальше, отвязав для нескольких потребителей общий интерфейс, важно, не столкнуться с ситуацией, когда интерфейс распухает, а каждый потребитель использует только часть &#8211; тогда нужны разные интерфейсы. // Лирическое отступление <img src='http://smarty.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Вообще</strong>. Наверное одна из причин была в том, что на ОО программирование смотрелось со статической позиции &#8211; как распихать код по классам, и не было никакого понимания, что классы должны взаимодействовать и основная собака здесь &#8211; это должно быть понятно, гибко и эффективно.</p>
<p><strong>З.Ы. повторное использование.</strong> Написал выше, что без наследования, а как иначе? Мы создали объект, вызвали метод &#8211; вот мы и использовали код повторно. Надо поменять? Сделаем, чтобы метод (или конструктор объекта, это зависит от ситуации) принимал другой объект, реализующий меняющуюся часть &#8211; вот у нас появился &laquo;набор&raquo; методов &#8211; для каждого нового объекта это новый метод (это и есть полиморфизм). Код использовался повторно, а мы не обременили себя жёсткой связью &laquo;наследуется&raquo;, код гибкий.</p>
<h2>Что ещё</h2>
<p>А ещё очень интересно расширить применение и показать альтернативы. Расширить применение &#8211; показать, что такое TDD, объяснить, зачем и дать попробовать&#8230; ещё при обучении. Это классная лакмусовая бумажка, показывающая закрепощённость и неправильность ОО-кода.</p>
<p>Альтернативы &#8211; мне очень понравилось познакомиться с миром функционального программирования, не могу сказать, что я по нему спец, но это однозначно добавило новых подходов в моё программирование. Об этом тоже надо рассказать.</p>
<p>Функциональное программирование &#8211; всё функция. В применении к вебу страница &#8211; это функция от GET, POST, FILES, COOKIES. <em>Функция не имеет состояния</em> &#8211; т.е. результат всегда зависит только от параметров, и это один из полезных принципов. Функция может быть суперпозицией других функций, функции могут передаваться как параметры, может быть замыкание &#8211; функция, принимающая в качестве параметров часть того места, где она быа создана (не знаю, правильно ли это теоретически, там carrying и всё такое, но по сути так).</p>
<p>Что это даёт в моём ООП? <img src='http://smarty.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  То, что в объектах не должно быть состояния помимо их настройки, да, настройка может меняться, но при этом вся динамика &#8211; отдельно. Пример. Есть класс, обрабатывающий ввод данных, должен ли этот класс сам хранить введённые данные и ошибки ввода? Нет, они не имеют к нему отношение &#8211; они являются результатом проверки. Он хранит настройку &laquo;как проверять&raquo;, её можно менять по ходу, но он не хранит сами результаты, желательно даже во время обработки.</p>
<p>Ещё одна штука &#8211; связь вызовов методов. Имхо желательно минимизировать зависимости &laquo;вызови метод А, получи результат, добавь и вызови метод Б&raquo;, и не дай бог метод А что-то меняет внутри объекта и без него метод Б вызвать нельзя это совсем ужас&#8230; Да и вообще, начинал писать абзац к тому, что очень многие вещи решаются паттерном &laquo;Команда&raquo;, что является ничем иным, как замыканием в функциональном программировании &#8211; это объект, который можно настроить при создании, а дальше у него есть только один метод с определёнными параметрами&#8230; такой аналог функции-параметра.</p>
<p><strong>Итого</strong> &#8211; сейчас очень тянет к архитектуре, где объекты хранят только то, что определяет их работу, но не промежуточные данные, сами объекты маленькие, фактически близки к функции с несколькими предзаданными параметрами&#8230; возможно к семейству функций с одинаковыми настройками. А результат работы программы &#8211; некий прогон входных данных через сеть связанных объектов. Сама сеть от этого меняется только если входные данные заставляют её измениться, все же временные эффекты после выполнения забываются. И этот подход транслируется на каждый отдельный кусочек выполнения.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=44</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Отпуск (Крым, май 2009)</title>
		<link>http://smarty.ru/?p=37</link>
		<comments>http://smarty.ru/?p=37#comments</comments>
		<pubDate>Tue, 12 May 2009 05:07:30 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Крым]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=37</guid>
		<description><![CDATA[В двух словах, как это было &#8211; было здорово. Мы сходили в поход в районе Демерджи. С погодой повезло не особенно &#8211; первую часть путешествия был мелкий дождик (а стоянка в районе агнарского перевала так и вообще проходила в облаке &#8211; тот же мелкий дождь + сильный туман). Потом всё более-менее раздуло и облачка чередовались [...]]]></description>
			<content:encoded><![CDATA[<p>В двух словах, как это было &#8211; было здорово. Мы сходили в поход в районе Демерджи.</p>
<p>С погодой повезло не особенно &#8211; первую часть путешествия был мелкий дождик (а стоянка в районе агнарского перевала так и вообще проходила в облаке &#8211; тот же мелкий дождь + сильный туман). Потом всё более-менее раздуло и облачка чередовались с чистым небом.</p>
<p>Вообще по походу можно многое написать, это мой первый поход и впечатлений масса, из целей &#8211; мы почти забрались на Чатыр-Даг (как позже выяснилось забрались мы на более низкую вершину, Ангар-Бурун), на Южный Демерджи у меня в этом году забраться не вышло &#8211; пришлось остаться в лагере. Так что есть для чего возвращаться.</p>
<p>Вторая часть отдыха проходила в Коктебели&#8230; тут можно много рассказать &#8211; отличная еда &#8211; солёности, местная (мясная!) колбаса, вкуснейшие кисломолочные продукты (такой сметаны я ещё не ел)&#8230; и конечно же вина. Дегустация в Солнечной Долине, портвейн 90-го года, и куча куча всего другого. Жаль, в моём городе нет фирменного магазина, с ним жизнь была бы веселее <img src='http://smarty.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).</p>
<p>Вот. В общем пора работать, а рассказывать можно очень долго.</p>
<p>З.Ы. едва не забыл самое важное! Самое классное в этом походе &#8211; это компания, &laquo;старейшие&raquo; члены которой ходят в эти места едва ли не 20 лет. Именно компания сделала интересный поход по интересным местам действительно офигенным и незабываемым.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=37</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Пара идей по отладке</title>
		<link>http://smarty.ru/?p=30</link>
		<comments>http://smarty.ru/?p=30#comments</comments>
		<pubDate>Thu, 05 Feb 2009 07:53:43 +0000</pubDate>
		<dc:creator>DoK</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://smarty.ru/?p=30</guid>
		<description><![CDATA[Очень много раз порывался написать такую заметку и как-то каждый раз или не выходило, или выходило криво, так, что не нравилось. Сейчас есть настроение, попробую снова. На самом деле, я наверное больше хочу сделать акцент на теории, нежели чем на практике, дать несколько советов, а по практике &#8211; опыт ничто не заменит. Что такое отладка? [...]]]></description>
			<content:encoded><![CDATA[<p>Очень много раз порывался написать такую заметку и как-то каждый раз или не выходило, или выходило криво, так, что не нравилось. Сейчас есть настроение, попробую снова.</p>
<p>На самом деле, я наверное больше хочу сделать акцент на теории, нежели чем на практике, дать несколько советов, а по практике &#8211; опыт ничто не заменит.</p>
<h2>Что такое отладка?</h2>
<p>Начинается всё с поиска ошибки. И здесь мы должны пройти путь от &laquo;ничего не работает&raquo; к тому, что ошибочной является одна строка и то, зачастую, ошибочна она только при определённых внешних условиях. В принципе весь процесс поиска ошибки заключается в сужении контекста ошибки.</p>
<p>Как сужать контекст ошибки? В целом это всегда уменьшение размера кода, в котором потенциально находится ошибка, а также условий, значений ввода и т.п. Т.е. пришёл менеджер &laquo;ничего не работает&raquo; &#8211; контекст &#8211; весь код. Что не работает? Такая-то страница. Что там? Форма не сохраняется. А что вводили? &#8230;</p>
<p>Эта часть очевидна, я просто хочу подчеркнуть, что это всего навсего сужение контекста ошибки. Дальше процесс точно такой же &#8211; формулируем некоторую гипотезу &laquo;на входе в скрипт данные правильны&raquo; &#8211; смотрим данные $_POST, ага, всё, про ошибки в хтмл можно забыть, это не там. Или наоброт. Т.е. дальше процесс идёт также, последовательным уменьшением контекста ошибки, пока она не станет ясна.</p>
<h2>Что может помочь?</h2>
<p>Сначала вопрос, а как мы определяем верность того или иного утверждения? Мы смотрим на какие-то значения в разных участках программы. Соответственно чем эффективнее мы будем смотреть, тем быстрее сможем искать.</p>
<ul>
<li>Расстановка var_dump-ов будет очень неэффективной (хотя приемлимой для начала). </li>
<li>Могут помочь различные встроенные трассировки (например, у нас есть режимы, когда по параметру в адресе хорошим людям выводятся все SQL запросы, все удалённые ошибки и т.п.). Это позволяет проконтролировать несколько точек сразу, даже не касаясь кода.</li>
<li>Не забываем про firebug &#8211; это очень хорошее средство контроля вывода, ввода (можно смотреть что постилось, какие куки, какие заголовки) и взаимодействия &#8211; вкладка &laquo;net&raquo;. </li>
<li>Наконец, последнее по порядку не по значению, интерактивная отладка на сервере (пусть даже локальном). Интерактивным отладчиком однозначно стоит овладеть, он позволяет смотреть все переменные, проходить о всем вызовам и т.д., т.е. если сравнивать с вардампом &#8211; это возможность посмотреть вардамп любой желаемой переменной на любой строке без перезагрузки страницы и правки кода. Это очень быстрое средство при отладке средних и сложных ошибок.</li>
</ul>
<p>А ещё?</p>
<ul>
<li>Ещё надо поменьше доверять и побольше проверять. Я не раз попадал на часовую отладку ошибки в рабочем коде просто потому, что подумал &laquo;я знаю, ошибки в этом месте нет, надо смотреть там&raquo; &#8211; подумал и не проверил, на самом ли деле нет ошибки. Просто надо держать глаза открытыми.</li>
<li>А ещё при отладке, как это ни странно, помогает грамотно написанный код. Как заметил один мой умный знакомый, нет режима &laquo;убирания ошибок&raquo;, есть режим &laquo;скрытия ошибок&raquo;, но они никуда не уходят. Т.е. приложение должно быть написано так, чтобы максимально сообщать о том, что что-то пошло не так, сразу же, как пошло не так. Очень хороший материал &#8211; МакКоннелл, &laquo;Совершенный код&raquo;, глава про защитное программирование.</li>
</ul>
<h2>Ошибку нашли, что дальше?</h2>
<p>Дальше её надо исправлять. Здесь тоже пара моментов:</p>
<ul>
<li>Если ошибка сложная, очень желательно её не заткнуть, а понять суть проблемы (для сложных ошибок обычно надо искать проблему в понимании логики приложения/предметной области). Такое исправление будет более сложным, зато снимет проблемы в будущем.</li>
<li>Модульные, браузерные и прочие тесты. Если они есть &#8211; исправлять сложные ошибки, переписывать большие куски и т.п. &#8211; удовольствие &#8211; код становится лучше и ты знаешь, что можешь проверить, чтобы ничего не сломать.</li>
<li><strong>Подобные ошибки.</strong> Исправив одну ошибку, часто даже уже коммитя её, я задаю себе вопрос &laquo;а где может быть такая же ошибка?&raquo;&#8230; и исправляю ещё пару мест, которые вылезли бы с такими же страданиями через неделю-две.</li>
</ul>
<h3>Учимся или стоим на месте?</h3>
<p>Если мы хотим не просто исправить ошибку, а чему-то научиться: надо подумать, как не совершать таких ошибок в будущем. Т.е. как писать код, который бы или исключал подобные ошибки, или делал их менее вероятными, или просто лучше предупреждал бы о них. Это сложный процесс &#8211; от исправления сообщений об ошибках на более внятные до изменения стиля программирования. Но это один из способов развития программиста, и далеко не самый последний.</p>
]]></content:encoded>
			<wfw:commentRss>http://smarty.ru/?feed=rss2&amp;p=30</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

