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

<channel>
	<title>Блоги &#187; Антон Бевзюк (Intel)</title>
	<atom:link href="http://software.intel.com/ru-ru/blogs/author/416696/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/ru-ru/blogs</link>
	<description></description>
	<lastBuildDate>Thu, 24 May 2012 12:16:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Intel Agile 2010</title>
		<link>http://software.intel.com/ru-ru/blogs/2010/01/03/intel-agile-2010/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2010/01/03/intel-agile-2010/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 13:36:17 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Конкурсы и мероприятия]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2010/01/03/intel-agile-2010/</guid>
		<description><![CDATA[Собираюсь выступить на конференции Intel Agile 2010 в этом году. Есть несколько идей, с которыми можно выступить. * Совместное использование разных agile практик: XP, Scrum, Kanban &#38; Lean * TDD подробно * Гибкий подход к разработке БД В первой я бы рассказал о том, какие практики из разных гибких методологий мы применяли и почему, как [...]]]></description>
			<content:encoded><![CDATA[<p>Собираюсь выступить на конференции Intel Agile 2010 в этом году. Есть несколько идей, с которыми можно выступить.</p>
<p>    * Совместное использование разных agile практик: XP, Scrum, Kanban &amp; Lean<br />
    * TDD подробно<br />
    * Гибкий подход к разработке БД</p>
<p>В первой я бы рассказал о том, какие практики из разных гибких методологий мы применяли и почему, как они друг с другом работают, про эволюцию практик - как мы отказывались от одних и приходили к другим, какие результаты мы получили, с какими проблемами столкнулись и какие практики помогли с ними справиться.</p>
<p>Во второй - про то, что такое TDD и чем оно не является, про общий подход к тестированию, принятый в нашей команде, про разные уровни и паттерны тестирования, практические примеры тестирования начиная от классических тестов бизнес логики до хитрых методов тестирования GUI и DB</p>
<p>В третьей - о различиях в гибком и традиционном подходе к разработке БД, обзор существуюших инструментов, расскажу о практиках, которые помогают нам гибко разрабатывать дизайн БД, способах автоматизации рутинных задач.</p>
<p>Вот раздумываю, стоит ли выбрать одну или отправлять все три?</p>
<p>Друзья, у меня к вам вопрос - какая тема вам была бы наиболее интересна? </p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2010/01/03/intel-agile-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lean</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/12/28/lean/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/12/28/lean/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 14:06:00 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Сертификация и обучение]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/12/28/lean/</guid>
		<description><![CDATA[В пятницу Асхат Уразбаев и Никита Филлипов из компинии ScrumTrek читали целый день тренинг по Lean. Давно я не был на таких полезных тренингах! До этого про Lean я знал совсем немного, можно сказать почти ничего не знал. А тут целый день нам про него рассказывали, показывали... Очень интересная история появления Lean. Корни его лежат [...]]]></description>
			<content:encoded><![CDATA[<p>В пятницу Асхат Уразбаев и Никита Филлипов из компинии ScrumTrek читали целый день тренинг по Lean. Давно я не был на таких полезных тренингах! До этого про Lean я знал совсем немного, можно сказать почти ничего не знал. А тут целый день нам про него рассказывали, показывали...</p>
<p>Очень интересная история появления Lean. Корни его лежат в Toyota Production System (TPS), системе управления производством Toyota, автором которой является Таичи Оно.<br />
Тойота поставила перед собой амбициозную цель - стать производителем автомобилей номер один в мире, обогнав американцев. Американское производство в те времена было построено на модели Генри Форда. Фордовский конвеер был идеален для выпуска машин в одинаковой комплектации. Производство же на Тойоте было организовано по другому - выпускать машин ровно столько, сколько они смогут продать и в такой комплектации, как захочет заказчик. Значит производство должно стать максимально гибким. Качеству уделялась особая роль.</p>
<p>Таичи Оно придумал и внедрил принципы TPS сначала в своем цеху, а затем в течение следующих 20 лет они распространились на все производство. Принципы эти часто противоречат общепринятым. Ну допустим, у нас есть производство машин. Машина состоит из деталей (дверей, двигателя, колес), которые в свою очередь состоят из множества других деталей. Колесо, к примеру, состоит из протектора и диска. Допустим, у нас есть станок, который штампует диски. Станок этот дорогущий, стоит 1 000 000$. Согласно классической экономической теории, раз станок такой дорогой, он ни в коем случае не должен простаивать. То есть он должен постоянно штамповать диски и наполнять ими склад. Когда надо будет делать другие диски, станок перенастраивается (это занимает несколько дней) и опять запускается в работу. Таичи Оно переворачивает этот принцип с ног на голову. Лишние диски, которые лежат на складе - это потери (waste), а потерь надо избегать. Поэтому станок должен штамповать ровно столько дисков, сколько требуется и не больше. это в частности приводит к тому, что у сборщика нет лишних деталей, которыми он бы мог заменить бракованные. Если возникает брак - это сигнал к тому, что нужно устранить причину возникновения этого брака, а не просто заменить делать на исправную.</p>
<p>Как я говорил, качество стоит на первом месте. Интересный принцип Stop the line. Если обнаруживается неисправность, например, приводящая к браку, конвейер останавливается до полного устранения причины брака. Все рсурсы мобилизуются на то, чтобы найти и устранить причину, которая мешает работать.</p>
<p>Много внимания уделяется персоналу. Персонал в модели Lean надо растить, холить и лелеять. Тренировать, учить, воспитывать, в общем инвестировать. Что тоже довольно сильно отличается от фордовской модели, где сотрудник выполняет однообразные операции и при случае легко может быть заменен другим.</p>
<p>Принцип Kaizen (Кайдзен) говорит о том, что процесс должен постоянно улучшаться.</p>
<p>Тренинг был построен как workshop, то есть очень большую часть времени мы выполняли упражнения. Мы руководили воображаемой строительной фирмой, лозунг которой звучал "Мы сделаем вам ремонт в два раза дешевле и в два раза быстрее, чем конкуренты". Самое интересное, что когда мы начали думать над тем, как мы можем построить работу таким образом, чтобы удовлетворить это требование, мы сами вывели для себя большую часть принципов Lean. Что по моему мнению только доказывает, что они соответствуют принципам здравого смысла.</p>
<p>В общем мне понравилось. Тренинг реально полезный. Он заставляет думать по другому, приподнимать голову из своей коробки и оглядываться по сторонам, находить потери и понимать, как можно с ними справляться. Почувствовал себя в начале новой тропинки, по которой предстоит увлекательное путешествие.</p>
<p>PS. Вчера приехал на заправку. Было еще не поздно, часов 7 вечера. Заправка закрыта - сливают бензин из автоцистерны. Перед заправкой стоит очередь машин 10, первые стоят уже минут 50. Пошел узнавать - будет закрыта еще полчаса как минимум. Ждать не стал, уехал, но по дороге, пользуясь принципами Lean, придумал несколько способов, как можно было эту ситуацию избежать. А заодно и как можно увеличить пропускную способность заправки примерно вдвое <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/12/28/lean/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Рецепты XP. Каска-чекинка.</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/08/03/xp-2/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/08/03/xp-2/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 09:55:20 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Разработка софта]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[XP]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/08/03/xp-2/</guid>
		<description><![CDATA[Есть у нас в команде забавный артефакт: каска-чакинка. ]]></description>
			<content:encoded><![CDATA[<p>Есть у нас в команде забавный артефакт: каска-чакинка.<br />
<a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d0bad0b0d181d0bad0b0-d187d0b5d0bad0b8d0bdd0bad0b0.jpg"><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d0bad0b0d181d0bad0b0-d187d0b5d0bad0b8d0bdd0bad0b0-300x225.jpg" alt="" width="300" height="225" class="alignnone size-medium wp-image-2001852" /></a></p>
<p>Она играет очень важную роль. Нет, не то, что может показаться - она не защищает наши головы от ударов. Она помогает нам избегать конфликтов при интеграции кода. </p>
<p>Над проектом работает одновременно несколько пар разработчиков. Часто бывают ситуации, когда несколько пар работают над одним и тем же участком кода. При интеграции кода, то есть при check-in'е изменений в общий репозиторий, могут возникать конфликты. Например, над одним участком кода работают 2 пары. Первая пара решает зачекинить свои изменения. Перед этим им нужно взять последнюю версию, разреши конфликты (если они есть), прогнать тесты. В  это время, пока первая пара готовится к чекину, вторая пара чекинит свои изменения, которые пересекаются с первой парой. Когда первая пара начнет чекинить свой код, система хранения кода будет ругаться на то, что есть более свежие версии файлов на сервере. Первая пара будет вынуждена по-новой брать последнюю версию, разрешать конфликты, чинить тесты. Если изменений было сделано много, это может отнять довольно много времени, в это время вторая пара опять может зачекиниться, и так далее.</p>
<p>А теперь представьте, что одновременно работают не 2 пары, а 5. Вероятность таких конфликтов будет значительно выше. Это ведет к непродуктивной работе, так как люди вынуждены делать одно и тоже без видимого прогресса, а так же может привести к возникновению обид внутри команды. </p>
<p>- Я же просил не чекинить, пока мы не закончим!<br />
- А мы забыли <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /><br />
- }8-Е</p>
<p>Избежать таких конфликтов нам помогает каска-чекинка.<br />
<a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/ManInHat.jpg"><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/d187d0b5d0bbd0bed0b2d0b5d0ba-d0b2-d0bad0b0d181d0bad0b5-d187d0b5d0bad0b8d0bdd0bad0b5-300x289.jpg" alt="" width="300" height="289" class="alignnone size-medium wp-image-2001855" /></a><br />
Чекинить код может только та пара, которая владеет каской. После того, как чекин закончен, другим парам рекомендуется взять последнюю версию. Всем хорошо, все довольны, конфликтов при чекине не возникает, хотя иногда приходится постоять в очереди за каской <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/08/03/xp-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Рецепты SCRUM. Stand-up митинг.</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/07/29/scrum-stand-up/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/07/29/scrum-stand-up/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 08:24:21 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Разработка софта]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Agile development]]></category>
		<category><![CDATA[SCRUM]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/07/29/scrum-stand-up/</guid>
		<description><![CDATA[Давно собирался рассказать о том, какие практики из XP и SCRUM применяются в нашей команде, зачем и что они нам дают. Начну с простого и понятного - ежедневного Stand-up митинга.
]]></description>
			<content:encoded><![CDATA[<p>Давно собирался рассказать о том, какие практики из XP и SCRUM применяются в нашей команде, зачем и что они нам дают. Начну с простого и понятного - ежедневного Stand-up митинга.</p>
<p>Почему название такое странное?<br />
В переводе с английского - "стоячая планерка". Означает, что все участники митинга стоят.<br />
<a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/standup.jpg"><img class="size-full wp-image-2001806" src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/standup.jpg" alt="stand-up митинг" width="500" height="374" /></a><br />
А зачем они стоят?<br />
А для того, чтобы митинг не затягивался. Хороший stand-up длится не больше 15 минут.</p>
<p>А зачем он вообще нужен?<br />
Все участники отвечают на 3 вопроса:<br />
Что я сделал вчера?<br />
Что я буду делать сегодня?<br />
Какие у меня проблемы или затыки, которые мешают мне выполнить мою работу?</p>
<p>Надо сказать, что это не допрос с пристрастием. Я тут слышал про команды, которые тоже использовали SCRUM. У них тоже был stand-up, но он длился по часу-полтора, что было очень утомительно. Я честно говоря не представляю как можно простоять час. На этом митинге каждый разработчик докладывал что он сделал, а потом оправдывался, почему он не успел сделать то, что запланировал. Митинг превращался в публичную порку. Удручает также то, что им приходилось писать ежедневные отчеты о сделанной работе, а потом еще раз озвучавать это на stand-upе.</p>
<p>Так вот, это был неправильный митинг. Так делать ни в коем случае нельзя. Митинг должен проходить весело и быстро. Все быстро рассказали, что вчера сделали хорошего и что собираются сделать сегодня. Разбились по парам. Граждане довольные расходятся по <del>домам</del> парным станциям.</p>
<p>Ну и что это дает?<br />
А дает это то, что все члены команды понимают, кто чем занимается. Мы планируем работу на день. Мы разбиваемся по парам. Мы выбираем себе интересные задачи. Ну или не интересные - кому как повезет. А еще это сигнал к началу работы. Во время митинга все настраиваются на рабочий лад, вспоминают на чем вчера остановились. Если возникает какая-то проблема, находится другой человек, готовый помочь. После stand-upа все рассаживаются по парным станциям и начинают весело колбасить код.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/07/29/scrum-stand-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Как разработчикам ПО процветать во время кризиса</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/04/20/2001072/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/04/20/2001072/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 06:09:06 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Разработка софта]]></category>
		<category><![CDATA[Agile]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/04/20/2001072/</guid>
		<description><![CDATA[Вчера прочитал мини-книжку про то, как софтверным компаниям процветать во время кризиса Rocks Into Gold - Helping Programmers THRIVE through the Credit Crunch - by Clarke Ching Очень порадовал формат. Сделано в виде презентации, но по сути это мини-книжка с несколькими персонажами, характерами, построенная на диалогах. Полезная идея подана не в виде кучи слайдов, а [...]]]></description>
			<content:encoded><![CDATA[<p>Вчера прочитал мини-книжку про то, как софтверным компаниям процветать во время кризиса <a href="http://www.slideshare.net/cching/rocks-into-gold-by-clarke-ching-presentation">Rocks Into Gold - Helping Programmers THRIVE through the Credit Crunch - by Clarke Ching</a></p>
<p>Очень порадовал формат. Сделано в виде презентации, но по сути это мини-книжка с несколькими персонажами, характерами, построенная на диалогах. Полезная идея подана не в виде кучи слайдов, а в форме интересного рассказа.</p>
<p>Суть вкратце в следующем.</p>
<p>Программист Боб работает в компании KillerWattSoftware. Он хороший программист со стажем. В настоящий момент он работает над проектом под названием Flitzerboing-Ultra для компании MegaCorp. Проект очень крупный, заключен контракт на год стоимостью $12M. В настоящий момент Боб работает вместе с Питером, архитектором MegaCorp, над архитектурой будущего приложения.</p>
<p>На утреннем совещании Сэм, менеджер Боба, сообщает всем, что MegaCorp объявила о том, что они отказываются от проекта. Кризис, всем тяжело, и компания решила затянуть пояса. Это чревато неприятными последствиями, вплоть до сокращений в обоих компаниях.</p>
<p>Боб задумался и стал выспрашивать Сэм и других людей, что побуждает MegaCorp отказаться от контракта. Расчеты были несложные. Контракт на год стоимостью $12M стоит компании $1M в месяц. Это означает, что им нужен бюджет $12M в условиях кризиса, когда каждая копейка на счету. Разумеется, Flitzerboing-Ultra нужен им не просто так, а для того, чтобы с его помощью получать прибыль. Ожидаемая прибыль составляет $2M в месяц, что означает, что проект окупится только спустя 18 месяцев после его начала. Может быть меньше, может быть больше, но приблизительный порядок примерно такой.</p>
<p><img src="http://farm4.static.flickr.com/3542/3454295667_9cd0124239.jpg" alt="Затраты MegaCorp" /></p>
<p>Становится понятно, почему MegaCorp отказывается от контракта, не так ли? В условиях кризиса найти лишние $12M непросто, да и неизвестно, что будет через 18 месяцев.<br />
Несмотря на это, никто не спорит с тем, что в долгосрочной перспективе проект Flitzerboing-Ultra выгоден, так как он в конце концов мог бы принести прибыль.</p>
<p>Боб старый волк, он знает, что если проект планируется на год, скорее всего он продлится полтора. Для KillerWattSoftware это выгодно, так как приносит допольнительные деньги. Лишние полгода потребуются для того, чтобы реализовать те требования, которые были не видны до начала планирования, которые появились в процессе разработки программы, или которые изменились. Что произошло бы, если бы проект растянулся на 2 года вместо запланированных 12 месяцев? Такое случается с проектами, знаете ли. MegaCorp потеряла бы ожидаемую прибыль за год использования продукта, то есть $24M. Компании KillerWattSoftware это тоже не сулило бы ничего хорошего, так как контракт предполагает серьезные штрафные санкции в случае срыва сроков. MegaCopr была очень заинтересована в проекте. Когда контракт только обсуждался, MegaCorp была готова заплатить даже больше $12M за проект, если бы он закончился за 6 месяцев. Техническая экспертиза оценивала проект в 8-10 месяцев, но менеджеры решили подстраховаться и заключили контракт на год.</p>
<p>Расстроенный Боб Боб вернулся к своему компьютеру, где его ожидало письмо от электронного магазина, в котором он заказывал 3 книжки. Первая - по программированию, вторая - художественная, а третья - по пчеловодству. Не то чтобы он пчеловод, просто заказал для развития общего кругозора. В письме говорилось, что третьей книжки нет на складе, поэтому ему вышлют только первые две, а третью потом, причем затраты по доставке магазин возьмет на себя.</p>
<p>Он думал, думал, думал, думал, думал, думал, думал, думал, думал, думал, думал, думал ... пока его не осенила блестящая идея.</p>
<p>Что если разбить Flitzerboing-Ultra на 4 маленьких релиза, каждый по 3 месяца? В этом случае MegaCorp получит первую версию спустя всего лишь 3 месяца, затратив на разработку $3M. Если предположить, что прибыль от первой версии будет не такая большая, как от всего продукта, но все-же будет, допустим, $1M в месяц, от второй - $1.2M, от третьей - $1.5M и от четвертой - $2M, это означало бы, что проект переставал быть затратным уже спустя 3 месяца после его начала. Начиная с 6 месяца он начинает самоокупаться, а полностью окупался через 14 месяцев. При этом затраты на проект сокращались с $12M до всего лишь $3M. MegaCorp тратит намного меньше, но получает тот же продукт через те же 12 месяцев, и при этом получает прибыль на 6 месяцев раньше! Разве это не стоит попробовать?</p>
<p><img src="http://farm4.static.flickr.com/3664/3455154974_acb345f0af.jpg" alt="Выгода MegaCorp" /></p>
<p>Кроме этого, все требования к проекту понадобилось разделить по приоритетам - нужные, очень нужные, очень-очень-очень нужные и не очень нужные. В первый релиз должны будут войти самые нужные функции, чтобы продукт мог приносить максимальную прибыль как можно раньше. Как известно, 80% пользователей пользуются только 20% продукта, так что если удастся реализовать эти 20% в первую очередь, это принесет максимальный эффект. Оставшиеся  требования могут измениться или вообще оказаться ненужными. Первый iPod имел вполовину меньше функций по сравнению в конкурентными продуктами, но он был хорош, очень хорош. То что он делал - он делал хорошо, он понравился пользователям и он сразу начал приносить прибыль компании. Затем новые функции добавлялись и добавлялись, и все больше и больше людей их покупали. Вспомним, как Google представил бету версию GMail. Продукт был еще не готов, но пользователи уже вовсю могли им пользоваться и могли давать свою оценку. Программисты еще долгое время доволили продукт до ума, добавляли новые фичи, вылизывали, но основная часть - получение и отправка почты, была доступна пользователям очень рано, и прибыль за счет рекламы продукт стал приносить очень рано. </p>
<p>Разумеется, предложение Боба понравилось. MegaCorp решила делать не 4, а 3 релиза за год, но сути дела это не меняло. Разумеется, это потребовало некоторых изменений в дизайне, некоторых усилий на то, чтобы облегчить переход пользователей с одной версии на другую, но это того стоило. Кроме того, поскольку в начале каждого релиза предполагалось пересматривать требования и выбирать наиболее критичные для каждого релиза, скорее всего, необходимость в последующей доработке продукта не потребовалось бы.</p>
<p>Как же к этом отнеслось руководство KillerWattSoftware? Ведь такое изменение лишило бы их заметной доли прибыли за доработку продукта? Оказывается, они отнеслись к этому с не меньшим воодушевлением, чем MegaCorp. Ведь при таком раскладе они произведут более качественный, более отвечающий требованиям заказчика продукт и избавят себя от самого большого источника противоречий с заказчиком.</p>
<p>Что было дальше?</p>
<p>Руководство MegaCorp настолько понравилась эта идея, что они захотели применить ее ко всем следующим проектам, в которых это возможно. Кроме этого, они хотели сохранить это ноу-хау в тайне от конкурентов. Бобу эта идея не понравилась. Что если врач изобретет супер лекарство, которое будет спасать жизни тысячам людей, и сохранит свое изобретение в тайне. Что если программист придумает блестящий алгоритм и сохранит его для себя. Разве это правильно? Боб думал, думал, думал, думал, как сделать это публичным. И придумал. Он начал писать, писать и писать... и написал эту книжку, и выложил ее в интернете <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/04/20/2001072/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Про софт</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/04/06/2000935/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/04/06/2000935/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 05:26:32 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Разработка софта]]></category>
		<category><![CDATA[Добавить метку]]></category>
		<category><![CDATA[софт]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/04/06/2000935/</guid>
		<description><![CDATA[Сегодня софт продается по одной и той же схеме. Ну ладно, по двум. Или ты приходишь и покупаешь красивую коробку (предоплата), или месяц пользуешься демо версией и потом покупаешь (тест-драйв). Обе эти схемы в первую очередь выгодны продавцам софта, но не слишком - пользователям, хотя вторая вроде бы для пользователя получше. Есть еще парочка возможных [...]]]></description>
			<content:encoded><![CDATA[<p>Сегодня софт продается по одной и той же схеме. Ну ладно, по двум. Или ты приходишь и покупаешь красивую коробку (предоплата), или месяц пользуешься демо версией и потом покупаешь (тест-драйв). Обе эти схемы в первую очередь выгодны продавцам софта, но не слишком - пользователям, хотя вторая вроде бы для пользователя получше.</p>
<p>Есть еще парочка возможных схем, которые по той или иной причине совершенно не используются.</p>
<p>1. Секонд хенд. Почему нет рынка б/у софта? Купил я допустим какой нибудь ну не знаю, к примеру, Автокад ну или там Corel Draw. Но он мне не для работы нужен, я не художник и не дизайнер. Я ремонт дома делаю, а плитку мне удобно в Corel-е планировать. Считать удобно, размеры точные, пораскрашивать можно - в общем удобнее чем в Paint-е гораздо. Зачем мне покупать полноценную коробочную версию, если она мне нужна от силы пару дней в год? Я бы лучше купил б/у за полцены, попользовался, а потом таки продал. Чем плохо? Производитель свои деньги уже получил от первого покупателя, а пользователей у программы становится больше. А, ну да, интересы производителя ущемляются - он же свои кровные теряет, которые в противном случае с каждого бы поимел. Но давайте не только о производителе думать, но и о нас, обычных пользователях.</p>
<p>2. Аренда. Я плачу не за коробку, а за время, потраченное на пользование тем или иным софтом. Да, тут возникает куча проблем - как считать время, как посылать его на сервер производителя, как быть если нет связи, но давайте пофантазируем. Предположим, что у нас повсеместно есть дешевый доступный интернет. Учитывая возможности современных беспроводных технологий, это вовсе не нереальное допущение. Насчет дешевости придется потерпеть, но надеюсь через пару (десятков?) лет провайдеры утолят врожденную жадность и интернет будет не дороже воды из-под крана. Допустим также что все пользователи честные благородные люди и если стоимость софта лежит в разумных пределах, они готовы за него платить. Ну давайте пофантазируем, чего вы? <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Ведь тогда нет принципиальных проблем посчитать чем я реально пользовался? В конце месяца получаем квитанцию<br />
- за Office 40 часов = 80 рублей<br />
- за Corel Draw 3 часа = 15 рублей<br />
Деньги снимаются с электронного счета, или с кредитки, да пофиг как лишь бы в сберкассу не бегать.</p>
<p>Почему такого до сих пор нет? Пора бежать за патентом? <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/04/06/2000935/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Паттерн &quot;Спецификация&quot; - отделяем условия</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/03/24/2000799/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/03/24/2000799/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 16:52:35 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Разработка софта]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[MyCommissions]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[Specification]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/03/24/2000799/</guid>
		<description><![CDATA[Большинство паттернов проектирования довольно изощренные. Иногда схема, объясняющая, как работает паттерн и для чего он нужен, может занять несколько страниц. Что отличает паттерн "Спецификация", придуманный Мартином Фаулером и Эриком Эвансом, так это его простота. Его и паттерном-то назвать трудно, так, паттерныш какой-то, однако польза от него несомненная. Применить его можно практически в любом приложении. Для [...]]]></description>
			<content:encoded><![CDATA[<p>Большинство паттернов проектирования довольно изощренные. Иногда схема, объясняющая, как работает паттерн и для чего он нужен, может занять несколько страниц. Что отличает паттерн "Спецификация", придуманный Мартином Фаулером и Эриком Эвансом, так это его простота. Его и паттерном-то назвать трудно, так, паттерныш какой-то, однако польза от него несомненная. Применить его можно практически в любом приложении. </p>
<p>Для примера возьмем излюбленный пример системы учета заказов. В системе имеются объекты заказчик (Customer) и заказ (Order). </p>
<p>Некоторые заказы требуют особого внимания, так как они являются критическими - пусть это будут заказы на сумму, большую миллиона долларов. Это условие выражается в коде</p>
<blockquote><p><code>order.Amount &gt;= 1000000M</code></p></blockquote>
<p>Скорее всего, подобное условие будет дублироваться в коде в нескольких местах. Чтобы избежать дублирования, введем спецификацию CriticalOrder.</p>
<p>Начнем, как всегда, с написания теста:</p>
<blockquote><p><code>[TestClass]<br />
public class SpecificationTests {<br />
[TestMethod]<br />
public void CriticalOrderTest() {<br />
&nbsp;&nbsp;var specification = new CriticalOrder();</p>
<p>&nbsp;&nbsp;Assert.IsFalse(specification.IsSatisfiedBy(new Order() {Amount = 0}));<br />
&nbsp;&nbsp;Assert.IsFalse(specification.IsSatisfiedBy(new Order() {Amount = 999999}));<br />
&nbsp;&nbsp;Assert.IsTrue(specification.IsSatisfiedBy (new Order() {Amount = 1000000}));<br />
&nbsp;&nbsp;Assert.IsTrue(specification.IsSatisfiedBy (new Order() {Amount = 2000000}));<br />
&nbsp;}<br />
}</code></p></blockquote>
<p>И собственно имплементация<br />
<blockquote><code>public class CriticalOrder {<br />
&nbsp;public bool IsSatisfiedBy(Order order) {<br />
&nbsp;&nbsp;return order.Amount &gt;= 1000000;<br />
&nbsp;}<br />
}</code></p></blockquote>
<p>Какой прикуп мы получили от введения спецификации? Имеет ли смысл ли вводить новый класс из-за какого-то одного условия? Возможно, не всегда, но в этом случае имеет. Ценность спецификации в том, что она</p>
<ul>
<li>Отделяет логику условия от объекта, хранящего данные</li>
<li>Легко тестируется в изоляции</li>
<li>Помогает избежать дублирования одинаковых условий</li>
<li>Дает условиям понятные мнемонические имена, отражающие их бизнес смысл</li>
</ul>
<p>Преймущества инкапсуляции, я думаю, объяснять не надо. Бизнес-правила могут измениться, а лучше сказать, что они точно изменятся. Например, в следующей итерации нужно будет выделить крупных заказчиков в особую категорию "KeyCustomers" и считать критическими все заказы этой категории, независимо от суммы. Или по прежнему зависимо, но от другой величины, например $200 000 (сказываются последствия кризиса). Можно сделать спецификацию параметризуемой пределом суммы:</p>
<blockquote><p><code>[TestClass]<br />
&nbsp;public class SpecificationTests {<br />
&nbsp;[TestMethod]<br />
&nbsp;public void CriticalOrderTest() {<br />
&nbsp;&nbsp;var specification = new CriticalOrder(200000);</p>
<p>&nbsp;&nbsp;var keyCustomer = new Customer {Type = CustomerType.KeyCustomer};<br />
&nbsp;&nbsp;var otherCustomer = new Customer {Type = CustomerType.Other};</p>
<p>&nbsp;&nbsp;Assert.IsFalse(specification.IsSatisfiedBy(new Order(keyCustomer) {Amount = 0}));<br />
&nbsp;&nbsp;Assert.IsFalse(specification.IsSatisfiedBy(new Order(keyCustomer) {Amount = 199999}));<br />
&nbsp;&nbsp;Assert.IsTrue(specification.IsSatisfiedBy(new Order(keyCustomer) {Amount = 200000}));<br />
&nbsp;&nbsp;Assert.IsFalse(specification.IsSatisfiedBy(new Order(otherCustomer) {Amount = 200000}));<br />
&nbsp;}<br />
}</code></p></blockquote>
<blockquote><p><code>public class CriticalOrder {<br />
&nbsp;private readonly int minimalAmount;</p>
<p>&nbsp;public CriticalOrder(int minimalAmount) {<br />
&nbsp;&nbsp;this.minimalAmount = minimalAmount;<br />
&nbsp;}</p>
<p>&nbsp;public bool IsSatisfiedBy(Order order) {<br />
&nbsp;&nbsp;return order.Customer.Type == CustomerType.KeyCustomer &amp;&amp; order.Amount &gt;= minimalAmount;<br />
&nbsp;}<br />
}</code></p></blockquote>
<p><strong>Композитные спецификации</strong><br />
Часто возникает задача выборки элементов, отвечающим каким-то условиям. К примеру, может понадобиться выбрать все заказы определенного заказчика или все заказы за год или все заказы в Россию и так далее. Можно было бы сделать несколько методов в фасаде слоя доступа к данным (Data Access Layer = DAL) типа GetOrdersByCustomer(Customer), GetOrdersByYear(int), GetOrdersByCountry(string) и т.д. А что делать, если условия нужно комбинировать, например получить все заказы в Россию за год? Если разных вариантов запросов много, интерфейс DAL будет неоправданно разрастаться. Можно эту проблему решить с помощью паттерна Query, а можно использовать спецификации. </p>
<p>Спецификация легко комбинируется с паттерном Composite, что позволяет объединять спецификации в сложные условия. В этом случае все спецификации будут наследоваться от базового класса Specification&lt;T&gt; </p>
<blockquote><p><code><br />
public abstract class Specification&lt;T&gt; {<br />
&nbsp;public abstract bool IsSatisfiedBy(T item);</p>
<p>&nbsp;public static Specification&lt;T&gt; operator !(Specification&lt;T&gt; specification) {<br />
&nbsp;&nbsp;return new NotSpecification&lt;T&gt;(specification);<br />
&nbsp;}</p>
<p>&nbsp;public static Specification&lt;T&gt; operator |(Specification&lt;T&gt; left, Specification&lt;T&gt; right) {<br />
&nbsp;&nbsp;return new OrSpecification&lt;T&gt;(left, right);<br />
&nbsp;}</p>
<p>&nbsp;public static Specification&lt;T&gt; operator &amp;(Specification&lt;T&gt; left, Specification&lt;T&gt; right) {<br />
&nbsp;&nbsp;return new AndSpecification&lt;T&gt;(left, right);<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<blockquote><p><code><br />
public abstract class CompositeSpecification&lt;T&gt; : Specification&lt;T&gt; {<br />
&nbsp;protected readonly List&lt;Specification&lt;T&gt;&gt; specifications;</p>
<p>&nbsp;protected CompositeSpecification(params Specification&lt;T&gt;[] specifications) {<br />
&nbsp;&nbsp;this.specifications = new List&lt;Specification&lt;T&gt;&gt;(specifications);<br />
&nbsp;}</p>
<p>&nbsp;public ReadOnlyCollection&lt;Specification&lt;T&gt;&gt; Specifications {<br />
&nbsp;&nbsp;get { return specifications.AsReadOnly(); }<br />
&nbsp;}</p>
<p>&nbsp;public void Add(Specification&lt;T&gt; specification) {<br />
&nbsp;&nbsp;specifications.Add(specification);<br />
&nbsp;}</p>
<p>&nbsp;public void Remove(Specification&lt;T&gt; specification) {<br />
&nbsp;&nbsp;specifications.Remove(specification);<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<blockquote><p><code><br />
public class AndSpecification&lt;T&gt; : CompositeSpecification&lt;T&gt; {<br />
&nbsp;public AndSpecification() {}<br />
&nbsp;public AndSpecification(params Specification&lt;T&gt;[] specifications) : base(specifications) {}</p>
<p>&nbsp;public override bool IsSatisfiedBy(T item) {<br />
&nbsp;&nbsp;foreach (var specification in specifications) {<br />
&nbsp;&nbsp;&nbsp;if (!specification.IsSatisfiedBy(item)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;return false;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return true;<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<blockquote><p><code><br />
public class OrSpecification&lt;T&gt; : CompositeSpecification&lt;T&gt; {<br />
&nbsp;public OrSpecification() {}<br />
&nbsp;public OrSpecification(params Specification&lt;T&gt;[] specifications) : base(specifications) {}</p>
<p>&nbsp;public override bool IsSatisfiedBy(T item) {<br />
&nbsp;&nbsp;foreach (var specification in specifications) {<br />
&nbsp;&nbsp;&nbsp;if (specification.IsSatisfiedBy(item)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return false;<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<blockquote><p><code><br />
public class NotSpecification&lt;T&gt; : Specification&lt;T&gt; {<br />
&nbsp;private readonly Specification&lt;T&gt; specification;</p>
<p>&nbsp;public Specification&lt;T&gt; Specification {<br />
&nbsp;&nbsp;get { return specification; }<br />
&nbsp;}</p>
<p>&nbsp;public NotSpecification(Specification&lt;T&gt; specification) {<br />
&nbsp;&nbsp;this.specification = specification;<br />
&nbsp;}</p>
<p>&nbsp;public override bool IsSatisfiedBy(T item) {<br />
&nbsp;&nbsp;return !specification.IsSatisfiedBy(item);<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<p>Это позволят создавать сложные спецификации. Вот эта, к примеру, выберет все критические заказы в Россию в 2009 году:</p>
<blockquote><p><code><br />
var specification =<br />
&nbsp;new CriticalOrder(CustomerType.KeyCustomer, 200000) &amp;<br />
&nbsp;new SoldTo(new Country("Russia")) &amp;<br />
&nbsp;new AsOf(2009);<br />
</code></p></blockquote>
<p>Фасад DAL в этом случае может иметь всего лишь один метод, принимающий спецификацию и возвращающий список объектов соответствующего типа</p>
<blockquote><p>public List&lt;T&gt; Get&lt;T&gt;(Specification&lt;T&gt; specification);</p></blockquote>
<p>Чтобы получить заказы, удовлетворяющие нашей спецификации, достаточно вызвать</p>
<blockquote><p>infrastructureFacade.Get(specification);</p></blockquote>
<p><strong>Спецификации валидации</strong><br />
Спецификации удобно использовать для проверки валидности объекта. К примеру, заказ должен удовлетворять требованиям:</p>
<ul>
<li>Сумма от $0 до $10 000 000</li>
<li>Дата заказа &gt;= 1 Января 2008</li>
<li>Дата отгрузки &gt;= Даты заказа</li>
<li>Дата оплаты &gt;= Даты заказа</li>
</ul>
<p>Хотелось бы, помимо собственно проверки, валиден объект или нет, иметь возможность показать пользователю внятное сообщение, что именно не в порядке. Естественно, сообщение будет зависеть от того, какое именно условие нарушено. Если такое требование возникает в нескольких местах (а как правило, так оно и есть), имеет смысл выделить базовый класс для спецификаций, отвечающих за валидацию.</p>
<blockquote><p><code><br />
public abstract class ValidationSpecification&lt;T&gt; : Specification&lt;T&gt; {<br />
&nbsp;public string Validate(T item) {<br />
&nbsp;&nbsp;return IsSatisfiedBy(item) ? string.Empty : BuildErrorMessage(item);<br />
&nbsp;}</p>
<p>&nbsp;protected abstract string BuildErrorMessage(T item);<br />
}<br />
</code></p></blockquote>
<p>Теперь мы можем создавать валидационные спецификации для каждого случая:</p>
<blockquote><p><code><br />
public class ValidAmount : ValidationSpecification  {<br />
&nbsp;public override bool IsSatisfiedBy(Order order) {<br />
&nbsp;&nbsp;return order.Amount &gt;= 0 &amp;&amp; order.Amount &lt; 10000000;<br />
&nbsp;}<br />
&nbsp;public override string BuildErrorMessage(Order order) {<br />
&nbsp;&nbsp;return "Сумма заказа должна лежать в пределах от 0 до 10000000.";<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<blockquote><p><code><br />
public class ValidDate : ValidationSpecification  {<br />
&nbsp;public override bool IsSatisfiedBy(Order order) {<br />
&nbsp;&nbsp;return order.Date &gt;= new DateTime(2008, 1, 1);<br />
&nbsp;}<br />
&nbsp;public override string BuildErrorMessage(Order order) {<br />
&nbsp;&nbsp;return "Дата заказа должна быть позже 1 Января 2008.";<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<blockquote><p><code><br />
public class ValidShipDate : ValidationSpecification  {<br />
&nbsp;public override bool IsSatisfiedBy(Order order) {<br />
&nbsp;&nbsp;return order.ShipDate &gt;= order.Date;<br />
&nbsp;}<br />
&nbsp;public override string BuildErrorMessage(Order order) {<br />
&nbsp;&nbsp;return string.Format("Дата отгрузки {0} не может быть меньше даты заказа {1}", order.ShipDate, order.Date);<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<blockquote><p><code><br />
public class ValidPayDate : ValidationSpecification  {<br />
&nbsp;public override bool IsSatisfiedBy(Order order) {<br />
&nbsp;&nbsp;return order.PayDate &gt;= order.Date;<br />
&nbsp;}<br />
&nbsp;public override string BuildErrorMessage(Order order) {<br />
&nbsp;&nbsp;return string.Format("Дата оплаты {0} не может быть меньше даты заказа {1}", order.PayDate, order.Date);<br />
&nbsp;}<br />
}<br />
</code></p></blockquote>
<p>Теперь можно построить композитную спецификацию ValidOrder</p>
<blockquote><p><code><br />
public class ValidOrder : AndSpecification {<br />
&nbsp;public ValidOrder() : base(<br />
&nbsp;&nbsp;new ValidAmount(),<br />
&nbsp;&nbsp;new ValidDate(),<br />
&nbsp;&nbsp;new ValidShipDate(),<br />
&nbsp;&nbsp;new ValidPayDate()<br />
&nbsp;) {}<br />
}<br />
</code></p></blockquote>
<p>которую можно использовать в нескольких местах:</p>
<ul>
<li>На экране при создании/редактировании заказа</li>
<li>При массовом импорте из внешней системы</li>
<li>При реконструировании из базы данных</li>
</ul>
<p><strong>Интеграция с расширенными методами .Net</strong><br />
Добавление к базовому классу Specification явного преобразования к Predicate </p>
<blockquote><p><code>public static implicit operator Predicate(Specification specification) {<br />
&nbsp;return specification.IsSatisfiedBy;<br />
}</code></p></blockquote>
<p>волшебным образом позволяет легко и просто использовать спецификации в расширенных методах:</p>
<blockquote><p><code><br />
orders.FindAll(new CriticalOrder());<br />
</code></p></blockquote>
<p><strong>Что мы узнали?</strong><br />
Спецификация - это абстракция условия, накладываемое на объект. Типичные области применения</p>
<ul>
<li>Фильтрация, например при получении списка объектов, удовлетворяющих некоторому условию</li>
<li>Валидация, например перед сохранением нужно проверить, что объект находится в корректном состоянии</li>
</ul>
<p>Спецификация часто может использоваться совместно с паттерном Composite, что позволяет создавать сложные вложенные спецификации. Спецификации легко использовать в расширенных методах языков .Net</p>
<p>Огромное спасибо тем, кто помогал при создании этого материала:<br />
Стас Неверов<br />
Женя Сорокин<br />
Дима Новоселов</p>
<p><strong>Ссылки</strong><br />
<a href="http://martinfowler.com/apsupp/spec.pdf">http://martinfowler.com/apsupp/spec.pdf</a></p>
<p>Уфф <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/03/24/2000799/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Насколько техническим должен быть технический пост?</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/03/22/2000841/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/03/22/2000841/#comments</comments>
		<pubDate>Sun, 22 Mar 2009 10:38:45 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Social Media]]></category>
		<category><![CDATA[Разработка софта]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/03/22/2000841/</guid>
		<description><![CDATA[Пишу пост про паттерн Спецификация и терзают меня смутные сомнения. В каком формате писать? На кого ориентироваться? Вижу три варианта: 1. Общеобразовательный. Рассчитанный на широкую публику. Рассказать для чего нужен, как паттерн помогает решать бизнес-задачи. Минимум кода. 2. Описательный. Рассчитанный на широкий круг разработчиков, с небольшим количеством технических деталей. Показать как работает на простых примерах, [...]]]></description>
			<content:encoded><![CDATA[<p>Пишу пост про паттерн Спецификация и терзают меня смутные сомнения.<br />
В каком формате писать? На кого ориентироваться? Вижу три варианта:</p>
<p>1. Общеобразовательный. Рассчитанный на широкую публику. Рассказать для чего нужен, как паттерн помогает решать бизнес-задачи. Минимум кода.<br />
2. Описательный. Рассчитанный на широкий круг разработчиков, с небольшим количеством технических деталей. Показать как работает на простых примерах, не вдаваясь в подробности.<br />
3. Технический. Ориентированный на опытных практикующих разработчиков. Максимально подробно рассказать детали реализации, примеры реального кода, рассмотреть разные варианты использования.</p>
<p>Есть идеи?</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/03/22/2000841/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Путешествия во времени</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/03/09/2000727/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/03/09/2000727/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 17:59:12 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Разработка софта]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[MyCommissions]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[Time Travel]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/03/09/2000727/</guid>
		<description><![CDATA[Еще Брукс писал, чем привлекательна профессия программиста. Мы можем с легкостью создавать и изменять целые миры и даже делать то, что невозможно в реальности. Как я уже говорил, наша команда разрабатывает финансовое приложение для расчета комиссионных. Приложение разрабатывается чуть больше года, и его дизайн и доменная модель постоянно эволюционирует в процессе разработки. Я хочу рассказать [...]]]></description>
			<content:encoded><![CDATA[<p>Еще Брукс писал, чем привлекательна профессия программиста. Мы можем с легкостью создавать и изменять целые миры и даже делать то, что невозможно в реальности. </p>
<p>Как я уже говорил, наша команда разрабатывает финансовое приложение для расчета комиссионных. </p>
<p>Приложение разрабатывается чуть больше года, и его дизайн и доменная модель постоянно эволюционирует в процессе разработки. Я хочу рассказать про одно из самых серьезных изменений - про версионность.</p>
<p>Доменная модель приложения содержит множество объектов. Центральным агрегатом является CommissionableEmployee, который содержит в себе информацию о сотруднике. Для упрощения допустим, что у сотрудника есть свойство - процент аванса. Кроме CommissionableEmployee есть еще большая куча связанных объектов, описывающих настройки расчета комиссий, я не буду сейчас вдаваться в подробности. Изначально CommissionableEmployee был обыкновенным плоским объектом с несколькими свойствами. Позже было добавлено требование, что некоторые свойства объекта должны быть зависимыми от времени, например процент аванса у сотрудника может изменяться в течение года. Это была первая волна версионности. </p>
<p>Для всех объектов, изменяемых во времени, была выделена постоянная (Continuity) и переменная (Version) часть. Управление версиями, такое как создание новой версии, разбиение существующей версии на две новых, слияние версий - было вынесено в базовый абстрактный класс, а все объекты, которым требовалась версионность, наследовались от него. Изменение в классе CommissionableEmployee было самым тяжелым, поскольку это центральный объект, от которого зависят практически все остальные, так что добавление версионности отняло практически месяц. Другие дались легче - меньше было зависимостей и использовался другой подход к изменениям. Если на CommissionableEmployee набросились сразу, разделили на две части и сломали весь код, который от него зависел, а затем мучительно собирали проект, мержили изменения других разработчиков, собирали снова, поднимали тесты, и так без конца, то с другими объектами делали проще - создавали версионный объект рядом с предыдущим, например Account2 и AccountVersion вместо Account и постепенно, один за другим, маленькими шагами, заменяли использование Account на Account2. В конце, когда никто не пользовался классом Account, его удалили, а Account2 переименовали в Account.</p>
<p>Спустя некоторое время после завершения перехода на версионные объекты, возникло требование о ведении аудита. Необходимо было отслеживать изменения во всех версионных объектах - кто, когда, что именно поменял, как объект выглядел до изменения и как - после. Задача не такая простая, учитывая, что структура объектов может быть совершенно произвольная, сколь угодно сложная. Существующая модель этого не позволяла. Можно было сделать изменения, затрагивающие прошлые периоды, например, изменить сотруднику процент аванса в уже заплаченном месяце, а потом пойди докажи, почему на тот момент ему была рассчитана зарплата именно так, как она была рассчитана. </p>
<p>Для решения этой задачи был использован паттерн Time Travel. Этот паттерн позволяет восстановить состояние объекта на любой момент в прошлом. Как побочный эффект сохраняется история всех изменений, выполняющая роль аудитных записей. </p>
<p><a href="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/versioning.gif"><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/versioning-256x300.gif" alt="" width="256" height="300" class="alignnone size-medium wp-image-2000742" /></a></p>
<p>К примеру, в начале администратор решает, что некий сотрудник может иметь три версии, каждая из которых хранит разные значения процента его аванса: </p>
<ul>
<li>40% с Января по Март</li>
<li>30% с Мая по Июнь</li>
<li>50% с Июля до конца времен</li>
</ul>
<p>Вся изменяемая информация о сотруднике хранится в транзакциях. Каждая транзакция содержит весь набор характеристик, зависящих от времени (такие, как процент аванса) и две временных характеристики: эффективный период и дату транзакции - дату, когда она была создана. Каждая транзакция <a href="http://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D1%8F%D0%B5%D0%BC%D1%8B%D0%B9_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82">не мутабельна</a>, то есть не может изменять свои значения после создания. Транзакции могут перекрывать друг друга, в этом случае берутся значения из более поздней (то есть той, которая была создана позже).</p>
<p>В нашем случае будет последовательно создано три транзакции: </p>
<ul>
<li>1. 40% с эффективным периодом Январь - конец времен</li>
<li>2. 30% с эффективным периодом Май - конец времен</li>
<li>3. 50% с эффективным периодом Июль - конец времен</li>
</ul>
<p>Затем, по прошествии какого-то времени, скажем, 10 Июня в 14:45, администратор обнаруживает ошибку. Оказывается, сотрудник должен иметь аванс 50% начиная с Апреля.<br />
Он создает новую транзакцию </p>
<ul>
<li>4. 50% с эффективным периодом Апрель - конец времен</li>
</ul>
<p>которая частично перекрывает 1-ю транзакцию и полностью отменяет 2-ю и 3-ю. С этого момента, то есть начиная с 10 Июня 14:45, программа будет показывать для сотрудника только 2 версии - с 40% и 50% соответственно. Если мы пересчитаем его зарплату на Май, задним числом, то она посчитается с авансом 50%. Но если возникнет вопрос, почему ранее сотруднику посчиталась зарплата на Май с авансом 30%, мы всегда сможем откатиться на момент времени, предшествующий 4-й транзакции, скажем на 9 Июня, и показать настройки сотрудника на тот момент.</p>
<p>Если сотрудник увольняется с Сентября, администратор создает транзакцию на увольнение (5), эффективную с Сентября по конец времен.</p>
<p>Переход с версионных объектов на транзакции был сравнительно простым, поскольку основная часть внутренних объектов, обеспечивающих версионность, уже была создана.</p>
<p>Паттерн Time Travel оказался очень полезным в применении к нашей задаче. Если статья вызовет интерес, я могу подробнее рассказать о деталях имплементации этого паттерна. </p>
<p>Ссылки:<br />
<em><br />
Time Travel: A Pattern Language for Values That Change<br />
Massimo Arnoldi, LifeWare<br />
Kent Beck, Daedalos Consulting<br />
Markus Bieri, LifeWare<br />
Manfred Lange, Hewlett-Packard</em></p>
<p><a href="http://www.manfred-lange.com/publications/TimeTravel.pdf">http://www.manfred-lange.com/publications/TimeTravel.pdf</a></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/03/09/2000727/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Привет</title>
		<link>http://software.intel.com/ru-ru/blogs/2009/03/05/2000724/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2009/03/05/2000724/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 07:15:52 +0000</pubDate>
		<dc:creator>Антон Бевзюк (Intel)</dc:creator>
				<category><![CDATA[Разработка софта]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2009/03/05/2000724/</guid>
		<description><![CDATA[Привет всем. В начале положено представляться, так что для тех, кто меня не знает - меня зовут Антон Бевзюк, я работаю в Интеле чуть более 3.5 лет, в настоящее время занимаю должность Senior Application Developer в отделе со сложным названием, но простой сутью. Наша группа занимается поддержкой SMG (Sales &#38; Marketing Group), то есть мы [...]]]></description>
			<content:encoded><![CDATA[<p>Привет всем. </p>
<p>В начале положено представляться, так что для тех, кто меня не знает - меня зовут Антон Бевзюк, я работаю в Интеле чуть более 3.5 лет, в настоящее время занимаю должность Senior Application Developer в отделе со сложным названием, но простой сутью. Наша группа занимается поддержкой SMG (Sales &amp; Marketing Group), то есть мы пишем внутренний софт, помогающий продавцам и маркетологам Интела делать свою работу. </p>
<p>Для наших приложений мы используем .Net платформу, пишем приложения на С# 2.0 - 3.5, в качестве БД используем в основном MS SQL, иногда приходится работать с Oracle, Terradata и прочими. </p>
<p>Визитной карточкой нашей команды является использование гибких методологий (XP, Scrum) в своей работе. Мы имеем более чем 6 летний опыт разработки бизнес приложений с применением гибких методологий и нам есть чем поделиться с теми, кто в этом заинтересован.</p>
<p>Я решил начать блогодеятельность на интеловском блоге по нескольким причинам. Во первых, хочется рассказать о том, как нам удается применять XP, с какими трудностями мы сталкиваемся и как успешно или не очень с ними правляемся. Во вторых, последний год я занят в разработке очень крупного проекта, который рассчитывает коммиссии для продавцов. Проект очень сложный и одновременно интересный как с бизнес, так и с технической точки зрения. Как и во всех прочих финансовых приложениях, особое внимание уделяется качеству данных, точности расчетов и возможности отследить изменения. Для решения этих и многих других проблем были найдены десятки интересных технических и дизайнерских решений, которыми грех не поделиться. Дизайнерских не в смысле дизайна интерьеров или сайтов, а в смысле дизайна приложений.</p>
<p>В следующий раз я расскажу о путешествиях во времени.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2009/03/05/2000724/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

