<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><!-- generator="wordpress/2.0.3" --><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">

<channel>
	<title>Outsourcing stories</title>
	<link>http://alexlebedev.com/blog</link>
	<description>Alex Lebedev writes about software development and outsourcing</description>
	<pubDate>Wed, 20 Aug 2008 10:07:47 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0.3</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/OutsourcingStories" type="application/rss+xml" /><item>
		<title>Почему консультанта найти проще, чем человека в штат</title>
		<link>http://alexlebedev.com/blog/why-contractors-are-easier-to-find/</link>
		<comments>http://alexlebedev.com/blog/why-contractors-are-easier-to-find/#comments</comments>
		<pubDate>Wed, 20 Aug 2008 10:07:47 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>бизнес</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/why-contractors-are-easier-to-find/</guid>
		<description><![CDATA[ Дополнение к посту &#8220;Мифология (Наемный рабочий vs Консультант)&#8221;, развенчивающему некоторые распространенные мифы о недостатках консультантов по сравнению со штатными сотрудниками.

Хорошего консультанта привлечь на порядок проще, чем нанять хорошего сотрудника. Хотя и дороже.

Почему так?


Для удержания хороших сотрудников нужно создавать соответствующие условия.  И не одному конкретному сотруднику, а всем, иначе суммарный эффект будет строго отрицательным.  [...] ]]></description>
			<content:encoded><![CDATA[<p>Дополнение к посту <a href="http://victorronin.com/2008/08/19/mifologiya-naemnyj-rabochij-vs-konsultant/">&#8220;Мифология (Наемный рабочий vs Консультант)&#8221;</a>, развенчивающему некоторые распространенные мифы о недостатках консультантов по сравнению со штатными сотрудниками.</p>

<p>Хорошего консультанта привлечь на порядок проще, чем нанять хорошего сотрудника. Хотя и дороже.</p>

<p>Почему так?</p>

<ol>
<li><p>Для удержания хороших сотрудников нужно создавать соответствующие условия.  И не одному конкретному сотруднику, а всем, иначе суммарный эффект будет строго отрицательным.  Дело это дорогое, и рассчитанное на долгую перспективу.  Условия для консультанта создает, по большей части, он сам, а от заказчика требуются только деньги и внятная коммуникация.</p></li>
<li><p>Чем выше квалификация специалиста, тем с большей вероятностью он будет заниматься консалтингом.  Это дополнительно снижает вероятность найти такого специалиста в штат.</p></li>
<li><p>У консультанта просто больше свободного времени.  Ему, как правило, не надо бросать предыдущий проект, чтобы начать новый (хотя и не в режиме полной загрузки).  Представьте, что всего в России 100 специалистов по какой-то редкой технологии.  Допустим, 60 из них работают в штате, а 40 занимаются консалтингом.  В произвольный момент времени готовы взяться за новый проект четверть штатных сотрудников и три четверти консультантов.  Получается, что потенциальному заказчику нужно будет выбирать из 15 сотрудников и 30 консультантов, несмотря на то, что общее число последних меньше в полтора раза.</p></li>
</ol>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/why-contractors-are-easier-to-find/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>200 cлов о стиле</title>
		<link>http://alexlebedev.com/blog/200-words-about-style/</link>
		<comments>http://alexlebedev.com/blog/200-words-about-style/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 07:14:11 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>программирование</category>
	<category>ruby</category>
	<category>рефакторинг</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/200-words-about-style/</guid>
		<description><![CDATA[ Небольшой пример рефакторинга ruby-кода.

... ]]></description>
			<content:encoded><![CDATA[<p>Небольшой пример рефакторинга ruby-кода.</p>

<p>Исходный вариант (взято из статьи <a href="http://railstips.org/2008/6/25/raking-etc-hosts-for-sweeter-subdomainage">Raking /etc/hosts For Sweeter Subdomainage</a>)</p>

<pre><code>hosts = []

# add all the site temporary domains
hosts &lt;&lt; Site.find(:all).inject([]) do |collection, site|
  collection &lt;&lt; site.harmony_url
end

# add all the account subdomains
hosts &lt;&lt; Account.find(:all).inject([]) do |collection, account|
  collection &lt;&lt; account.harmony_url
end
</code></pre>

<p>Как можно сделать лучше?</p>

<p>Программа-минимум:</p>

<pre><code># site and account subdomains
hosts = []
hosts &lt;&lt; Site.find(:all).collect(&amp;:harmony_url)
hosts &lt;&lt; Account.find(:all).collect(&amp;:harmony_url)
</code></pre>

<p>Улучшения здесь три:</p>

<ol>
<li><p>Заменяем низкоуровневый <code>inject</code> на <code>collect</code>.  Нет смысла пользоваться <code>inject</code> и выставлять наружу переменную-счетчик, если можно легко сделать то же самое с более высокого уровня абстракции.</p></li>
<li><p>Используем сокращенный способ вызова метода в блоке:  <code>(&amp;:harmony_url)</code> вместо <code>{|element| element.harmony_url}</code>.  Это улучшение является частью ActiveSupport, так что вне рельс само работать не будет.</p></li>
<li><p>Заменяем дословно повторяющие код комментарии на что-то хоть немного более высокоуровневое.</p></li>
</ol>

<p>Дополнительная программа:</p>

<ol>
<li><p>То же самое чуть компактнее</p>

<pre><code># site and account subdomains
hosts = Site.find(:all).collect(&amp;:harmony_url) + Account.find(:all).collect(&amp;:harmony_url)
</code></pre>

<p>Далее в коде нигде не используется факт, что массив хостов содержит два отдельных подмассива со значениями, поэтому можно просто запихать все в плоский массив.  Что, кстати, избавит нас не только от инициализации <code>hosts</code>, но и от вызова <code>flatten</code> при использовании значений.</p></li>
<li><p>Делаем код понятным без комментариев</p>

<pre><code>hosts =  Site.find(:all).collect(&amp;:subdomain) +  Account.find(:all).collect(&amp;:subdomain)
</code></pre>

<p>&#8230; а в классах моделей пишем:</p>

<pre><code>alias_method :harmony_url, :subdomain
</code></pre></li>
</ol>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/200-words-about-style/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>О будущем веб-разработки</title>
		<link>http://alexlebedev.com/blog/future-of-web-development/</link>
		<comments>http://alexlebedev.com/blog/future-of-web-development/#comments</comments>
		<pubDate>Wed, 19 Sep 2007 09:13:04 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>mustread</category>
	<category>ссылки</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/future-of-web-development/</guid>
		<description><![CDATA[ Время от времени стоит выныривать из текущей суеты и задумываться о будущем.

Сегодня появилась замечательная возможность для этого

Прочтите последнюю статью Джоэля Спольски, <a href="http://www.joelonsoftware.com/items/2007/09/18.html">Strategy Letter VI</a>.  Это лучше из всего, что я чидел за последние полгода о перспективах развития платформ разработки. ]]></description>
			<content:encoded><![CDATA[<p>Время от времени стоит выныривать из текущей суеты и задумываться о будущем.</p>

<p>Сегодня появилась замечательная возможность для этого</p>

<p>Прочтите последнюю статью Джоэля Спольски, <a href="http://www.joelonsoftware.com/items/2007/09/18.html">Strategy Letter VI</a>.  Это лучше из всего, что я чидел за последние полгода о перспективах развития платформ разработки.</p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/future-of-web-development/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Эффективное программирование: текстовое представление переменных в python</title>
		<link>http://alexlebedev.com/blog/effective-programming-python-variable-inspection/</link>
		<comments>http://alexlebedev.com/blog/effective-programming-python-variable-inspection/#comments</comments>
		<pubDate>Sun, 12 Aug 2007 11:25:54 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>программирование</category>
	<category>python</category>
	<category>эффективное программирование</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/effective-programming-python-variable-inspection/</guid>
		<description><![CDATA[ Предположим, что вы хотите повысить свою эффективность как программиста.  Или, что более интересно, повысить эффективность разработчиков в своей команде.  Какое занятие отнимает больше всего времени после непроизводительной активности в составе: кофе, перекуры, <a href="http://bash.org.ru">bash.org</a>?  Наверняка это отладка.  Отладка обычно занимает вдвое-втрое больше времени, чем написание первой (не работающей) версии кода.

Сегодня я напишу о способе, который позволит сделать отладку более приятной и эффективной.

[...] ]]></description>
			<content:encoded><![CDATA[<p>Я открываю новый цикл статей, &#8220;Эффективное программирование&#8221;.</p>

<p>Давно уже стало банальностью утверждение о том, что программисты могут отличаться в производительности в десять и более раз.  Среди важнейших причин, наряду с талантом и правильными условиями работы (сюда входит все от процессов разработки и тестирования до зарплаты, атмосферы в коллективе и удобства кресел), фигурирует и использование правильных практик программирования.  Кент Бек (Kent Beck), создатель методологии Extreme Programming, говорил о себе &#8220;Я не считаю себя замечательным программистом, я лишь неплохой программист с замечательными привычками&#8221;.  В этой и последующих статьях цикла будут рассмотрены некоторые практики, входящие в мой собственный  набор &#8220;замечательных привычек&#8221;, а также реально полезные инструменты и библиотеки.</p>

<p>В качестве основы взяты практические эпизоды наших текущих проектов.  Материал нового цикла будет в первую очередь полезен для разработчиков и, в особенности, для тех-лидов и руководителей, осуществляющих &#8220;тренерскую&#8221; работу.</p>

<hr />

<p>Предположим, что вы хотите повысить свою эффективность как программиста.  Или, что более интересно, повысить эффективность разработчиков в своей команде.  Какое занятие отнимает больше всего времени после непроизводительной активности в составе: кофе, перекуры, <a href="http://bash.org.ru">bash.org</a>?  Наверняка это отладка.  Отладка обычно занимает вдвое-втрое больше времени, чем написание первой (не работающей) версии кода.</p>

<p>Сегодня я напишу о способе, который позволит сделать отладку более приятной и эффективной.</p>

<p>Все, за исключением использования графических дебаггеров, способы отладки базируются на текстовом выводе значения переменных.  Логи, Exception&#8217;ы, консоль &#8212; все это требует представления данных программы в текстовом формате.  Каждый раз, когда это представление выбрано неудачно, вам придется менять его и проходить еще одну итерацию отладки.  Некоторые ошибки будет сложно или совсем невозможно воспроизвести.  Следовательно, очень желательно выбрать правильное представление с первого раза.</p>

<p>Сразу предупрежу, что стандартная реализация далеко не идеальна.</p>

<p>Что произойдет при попытке напечатать значение объекта в python?</p>

<pre><code>&gt;&gt;&gt; print 7
7
&gt;&gt;&gt; print range(5)
[0, 1, 2, 3, 4]
</code></pre>

<p>Пока все хорошо.  Попробуем отойти от базовых типов данных:</p>

<pre><code>class Run(object):
    pass

&gt;&gt;&gt; r = Run()
&gt;&gt;&gt; r.status = 'new'
&gt;&gt;&gt; print r
&lt;__main__.Run object at 0xd3f944c&gt;
&gt;&gt;&gt; print 'Shit happens...'
'Shit happens...'
</code></pre>

<p>Отвратительно.  Придется обращаться отдельно к каждому атрибуту, что не очень удобно.</p>

<p>Надо сказать, что в Ruby вывод подробного состояния объекта реализован очень правильно:</p>

<pre><code>&gt;&gt; Run.find :first
=&gt; #&lt;Run:0xb725f884 @attributes={"status"=&gt;"done",
"finished_at"=&gt;"1900-01-01 00:00:00", "id"=&gt;"1",
"started_at"=&gt;"1900-01-01 00:00:00"}&gt;
</code></pre>

<p>Python здесь явно проигрывает.  Впрочем, как я покажу дальше, не все так плохо.</p>

<p>Дело в том, что поведение объекта при вызове <code>print</code> можно настраивать.  Для этого служат два специальных метода:  <code>__str__</code> и <code>__repr__</code> &#8212; первый для описания объекта в свободной форме, второй &#8212; для максимально строго и полного описания соответственно (желательно, чтобы результат <code>__repr__</code> являлся валидным выражением на языке python, описывающем текущий объект).  Для отладки актуален, преимущественно, метод <code>__repr__</code>.</p>

<p>Классическое исполнение выглядит следующим образом:</p>

<pre><code>class Run(object):
    def __init__(self, status, started_at):
        self.status, self.started_at = status, started_at
    def get_name(self):
        return self.user_name
    def __repr__(self):
        return "Run: status=%s started_at=%s" % (
            self.status, self.started_at)

    &gt;&gt;&gt; from datetime import datetime
    &gt;&gt;&gt; r = Run('new', datetime.today())
    &gt;&gt;&gt; r
    Run: status=new started_at=2007-08-12 03:16:26.468553
</code></pre>

<p>В этом коде нарушается принцип DRY (don&#8217;t repeat yourself): при добавлении в класс нового атрибута вам придется менять код текстового представления объекта.</p>

<p>В один прекрасный день обнаруживаешь, что у тебя накопилось с десяток классов с 5-15 значимыми атрибутами каждый, а редактирование методов <code>__repr__</code> достало до печенок.  Как быстро выяснилось, есть способ реализовать <code>__repr__</code> раз и навсегда.  Для этого достаточно немного покопаться во внутренней механике объектов, а именно &#8212; использовать свойство <code>__dict__</code>, дающее доступ ко всем атрибутам данного объекта в виде dictionary формата &#8220;имя: значение&#8221;.  Такая реализация даже более компактна, чем явная печать каждого атрибута:</p>

<pre><code>class Run(object):    
    # ...
    def __repr__(self):
        return 'Run: %s' % dict([
            (k,v) for k,v in self.__dict__.items() if not k.startswith('_')])

&gt;&gt;&gt; session = create_session()
&gt;&gt;&gt; Run.get_latest(session)
Run: {'status': 'done', 'finished_at': datetime.datetime(2007, 8, 8, 20, 26, 48),
'resume_after': None, 'started_at': datetime.datetime(2007, 8, 8, 20, 26, 42),
'id': 4L, 'errors_in_a_row': 0}
</code></pre>

<p><strong>Примечание: здесь и далее в примерах работа с БД организована с помощью библиотеки <a href="http://sqlalchemy.org">SQLAlchemy</a>.  Это, пожалуй, лучшее что есть сейчас в python для работы с базами данных.</strong></p>

<p>Обратите внимание на выражение <code>dict([(k,v) for k,v in self.__dict__ if not k.startswith('_')])</code>.  В pyhton принято начинать имена private-атрибутов с одного подчеркивания (&#8221;_&#8221;), следовательно, мы отфильтровываем все private-атрибуты и не показываем их.  По опыту могу сказать, что это очень удобно при работе с <strong>SQLAlchemy</strong>, которая добавляет к вашим объектам кучу служебных свойств.</p>

<p>Уже гораздо лучше: написанный один раз код можно просто копировать в каждый новый класс.  Для тех, кто работает под девизом &#8220;зачем объектное программирование, когда есть блочное копирование&#8221; этого вполне достаточно.  Мы же пойдем чуть дальше и создадим действительно универсальную реализацию:</p>

<pre><code>class Inspectable(object):
    """Provide an ability to print class instance and its attributes"""
    def __repr__(self):
        return '&lt;%s: %s&gt;' % (
            self.__class__.__name__,
            dict([(x,y) for (x,y) in self.__dict__.items() if not x.startswith('_')])
            )

class Run(Inspectable, object):
    #...

&gt;&gt;&gt; session = create_session()
&gt;&gt;&gt; Run.get_latest(session)
&lt;Run: {'status': 'done', 'finished_at': datetime.datetime(2007, 8, 8, 20, 26, 48),
'resume_after': None, 'started_at': datetime.datetime(2007, 8, 8, 20, 26, 42),
'id': 4L, 'errors_in_a_row': 0}&gt;
</code></pre>

<p>Обратите внимание на порядок наследование в <code>Run</code>: <code>Inspectable, object</code>.  В python наследование от списка классов резолвится слева направо, поэтому первыми должны быть указаны классы, располагающиеся ниже в иерархии наследования.  В противном случае получите ошибку наследования:</p>

<pre><code>&gt;&gt;&gt; class Run(object, Inspectable):
...   pass
... 
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: Error when calling the metaclass bases
    Cannot create a consistent method resolution
order (MRO) for bases object, Inspectable
</code></pre>

<p>Кстати, явно наследовать от <code>object</code> совсем необязательно &#8212; ведь <code>Inspectable</code> тоже является потомком <code>object</code>.  Я, однако, предпочитаю указывать object если перед этим наследую только от абстрактных классов &#8212; по идеологии это близко концепции mixin&#8217;ов в Ruby.</p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/effective-programming-python-variable-inspection/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Переезд, переезд</title>
		<link>http://alexlebedev.com/blog/i-am-moving/</link>
		<comments>http://alexlebedev.com/blog/i-am-moving/#comments</comments>
		<pubDate>Mon, 16 Jul 2007 05:54:53 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>разное</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/i-am-moving/</guid>
		<description><![CDATA[ Пора что-то менять в этой жизни.  Подошел к этапу реализации один из самых значительных моих личных проектов за последний год. Я переезжаю в Санкт-Петербург.  [...] ]]></description>
			<content:encoded><![CDATA[<p>Пора что-то менять в этой жизни.  Подошел к этапу реализации один из самых значительных моих личных проектов за последний год. Я переезжаю в Санкт-Петербург.  Точнее, мы с моей спутницей жизни переезжаем: такие значительные изменения всегда скорее семейное дело, чем личное.  А еще точнее – уже переехали в начале прошлой недели.</p>

<h2>Зачем вообще куда-то ехать?</h2>

<ol>
<li><p>Просто потому что мы можем.  Работа у нас обоих требует только хорошего Интернет-соединения и никак не привязана к какому-либо физическому местоположению.  Я получил диплом в прошлом году, Вика - в этом, так что учеба нас тоже больше не держит.</p></li>
<li><p>Пора жить а) вместе, б) отдельно от родителей.  Съезжать в съемную квартиру в соседнем доме как-то мелочно, такую возможность лучше использовать более основательно, то есть, уехать куда-нибудь подальше и постараться побольше извлечь из этого переезда.</p></li>
</ol>

<h2>Почему Питер?</h2>

<p>На самом деле, это единственный сколько-нибудь разумный для нас вариант.</p>

<p>Логика следующая:</p>

<ol>
<li><p>«В деревню, в глушь, в Саратов» ехать рано – мы молоды и у нас совершенно другие жизненные приоритеты.</p></li>
<li><p>Уезжать из России пока не хочется.</p></li>
<li><p>Ехать из 700-тысячного Тольятти в какой-нибудь город-миллионник не имеет особого смысла – разница не настолько велика, чтобы стоило заморачиваться с переездом.</p></li>
<li><p>Москву мы активно не любим и как место, пригодное для жизни, не рассматриваем.</p></li>
<li><p>Как видите, остается только Питер.  Замечательный, красивый и интересный город, который  нам обоим очень нравится.  Мы давно хотели жить в Питере, а теперь еще и можем переехать.  Ну, о чем здесь еще говорить?</p></li>
</ol>

<h2>Цели и ожидания</h2>

<h3>Культура</h3>

<p>Даешь насыщенную культурную жизнь!  Выбор выставок, театров, концертов и всего остального просто феноменален.  Даже побывать во всех интересных местах &#8212; программа на годы.  Мы намерены по максимуму насладиться этим богатством и разнообразием.</p>

<h3>Профессиональное сообщество</h3>

<p>Основное ожидание от профессионального сообщества &#8212; то, что оно здесь есть.</p>

<p>В Тольятти я знаю многих умных людей, но никто из них не занимается тем, чем занимается наша команда.  В результате, профессиональное общение по поводу самых животрепещущих проблем ограничивается рамками команды, а с другими остается общаться на общие и философские темы, что, конечно, хорошо, но недостаточно.</p>

<p>Хочется надеяться, что ситуация в Питере отличается в лучшую сторону.</p>

<h3>Перспективы для бизнеса</h3>

<p>По моей оценке, они достаточно невнятные.  В Тольятти я работаю с замечательными и очень талантливыми ребятами, еще больше талантливых разработчиков я просто знаю, и, в то же время, компании, серьезно занимающиеся разработкой софта, можно пересчитать по пальцам.  В Питере же, похоже, серьезный дефицит профессионалов и избыток компаний.  Это хорошая ситуация для работника (см. <a href="http://stump-workshop.blogspot.com/2007/05/blog-post_06.html">«Золотой век русского программиста»</a>), но плохая для бизнесмена.  Если случится экономический спад, то ситуация сменится на противоположную, но это тема для отдельной статьи.</p>

<hr />

<p><img id="image96" src="http://alexlebedev.com/blog/wp-content/uploads/2007/07/strelka2.jpg" alt="Стрелка Васильевского острова" /></p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/i-am-moving/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Microsoft против TestDriven.NET</title>
		<link>http://alexlebedev.com/blog/ms-vs-testdriven-net/</link>
		<comments>http://alexlebedev.com/blog/ms-vs-testdriven-net/#comments</comments>
		<pubDate>Mon, 04 Jun 2007 09:15:24 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>инструменты</category>
	<category>разное</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/ms-vs-testdriven-net/</guid>
		<description><![CDATA[ <strong>Microsoft притесняет разработчика дополнений к Visual Studio.  По их утверждениям, <a href="http://www.testdriven.net/">TestDriven.NET</a> подрывает рынок коммерческих версий Visual Studio и нарушает условия лицензионного соглашения.</strong>

[...] ]]></description>
			<content:encoded><![CDATA[<p><strong>Microsoft притесняет разработчика дополнений к Visual Studio.  По их утверждениям, <a href="http://www.testdriven.net/">TestDriven.NET</a> подрывает рынок коммерческих версий Visual Studio и нарушает условия лицензионного соглашения.</strong></p>

<p>По-русски: <a href="http://sundest.blogspot.com/2007/06/microsoft.html">Microsoft снова против</a></p>

<p>Оригинал: <a href="http://weblogs.asp.net/nunitaddin/archive/2007/05/30/microsoft-vs-testdriven-net-express.aspx">Microsoft vs TestDriven.Net Express</a> &#8212; пишет автор дополнения, вызывающего разногласия.</p>

<h2>Кратко о сути проблемы</h2>

<p>TestDriven.NET &#8212; это Add-In для Microsoft Visual Studio, предоставляющий возможность интеграции юнит-тестов в проект.  Некоммерческое использование бесплатно, professional и enterprise версии платные, цены начинаются от $95 за лицензию.</p>

<p>Надо заметить, что роль TestDriven.NET в экосистеме инструментов .NET весьма значительна.  По опыту своего большого проекта на платформе Microsoft могу сказать, что без сторонних инструментов (как правило, open source) практически невозможно работать над чем-то серьезным.  NUnit, NAnt, CruiseControl.NET, fxCop, NCover, Selenium &#8212; без всего этого проект бы просто рассыпался как карточный домик.  Для тех, кто использует TestDriven.NET, его отсутствие было бы, думаю, столь же критично.</p>

<p>Microsoft недоволен тем, что TestDriven.NET работает со всеми версиями Visual Studio, включая бесплатную Visual Studio Express.  По их словам, это подрывает рынок для старших версий Visual Studio и нарушает условия лицензионного соглашения.</p>

<p>Развитие событий:</p>

<ul>
<li><p>1 декабря 2004 - Выпущен TestDriven.NET 1.0, пока бесплатный</p></li>
<li><p>27 февраля 2006 - Jamie получает статус MVP (Microsoft Most Valued Professional) за вклад в развитие профессионального сообщества.</p></li>
<li><p>10 июля 2006 - выпущены Professional и Enterprise версии TestDriven.NET</p></li>
<li><p>10 октября 2006 - Jamie лишается статуса MVP, вероятно в связи с разногласиями по TestDriven.NET</p></li>
<li><p>31 марта 2006 - 17 апреля 2007.  Идет переписка Jamie с Microsoft.  По итогам Jamie наконец-то узнает, какую лицензию по мнению  Microsoft нарушает (Visual studio Express EULA).  Какой пункт лицензии нарушен &#8212; неизвестно.  Быстро все-таки работают большие компании&#8230;</p></li>
</ul>

<p>Jamie утверждает что наконец-то получил от британских юристов Microsoft указание пункта EULA, который он нарушает.  Речь идет о запрете на использование Visual Studio Express для ряда коммерческих целей.  Впрочем, так и непонятно, является ли этот пункт соглашения законным и нарушает ли его TestDriven.NET.</p>

<h2>Что думает сообщество</h2>

<p>Реакция сообщества, думаю, очевидна.  Microsoft must die, глубокое сожаление о плохом инструментарии разработки на .NET, удивление бездарным принятием корпоративных решений.</p>

<h2>Аналитическое</h2>

<p>Прослеживается тенденция неуклюжего Microsoft обращения с экосистемой open source-инструментов разработки для .NET.  Могу предположить, что в дело вступает менеджмент Visual Studio, пытающийся за счет притеснения Microsoft поднять продажи инструментов разработки.  То, что .NET в качестве платформы разработки несет при этом потери, на много порядков превышающие продажи Visual Studio&#8230;  Да какое дело до этого менеджеру Visual Studio?  Перед нами типичный пример близорукого управления в больших корпорациях &#8212; задача отдельного менеджера конфликтует с целями корпорации в целом.</p>

<h2>В тему</h2>

<p>Мартин Фаулер <a href="http://martinfowler.com/bliki/RubyMicrosoft.html">пишет</a> о неясных перспективах Ruby на .NET, важности усилий сообщества по затыканию дыр в платформе (на примере Java) и о тенденции бегства лучших разработчиков с платформы .NET</p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/ms-vs-testdriven-net/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Нужны ли ИТ-бизнесу гражданские свободы?</title>
		<link>http://alexlebedev.com/blog/does-it-business-need-civil-rights/</link>
		<comments>http://alexlebedev.com/blog/does-it-business-need-civil-rights/#comments</comments>
		<pubDate>Fri, 04 May 2007 16:41:18 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>бизнес</category>
	<category>разное</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/does-it-business-need-civil-rights/</guid>
		<description><![CDATA[ <blockquote>
  Ну-ну! Я был как-то на конференции, кажется CRN проводил, так там IDC кажется или Gartner это говорил. И так они меня разозлили, что я вышел следующим выступать и спросил: "Есть ли в зале хоть один человек, которому "отсутствие" свободы слова нанесло ущерб хоть в один доллар? В зале сидело больше сотни реселлеров, большая часть нашего ИТ бизнеса, и ни один не поднял руки.
</blockquote>

Это человек -- я.  Я потерял много зеленых и хрустящих долларов. [...] ]]></description>
			<content:encoded><![CDATA[<p>Михаил Елашкин написал отличную провокационную <a href="http://itblogs.ru/blogs/elashkin/archive/2007/05/04/16265.aspx">статью</a>: о том, что свобода слова, европейская модель бизнеса и прочие «шашечки» не нужны для того, чтобы делать деньги &#8212; у бизнесов и так хорошо получается, были бы правила игры известны и предсказуемы.</p>

<p>Естественно, сразу же развернулось бурное обсуждение (17 комментариев за первые 10 часов).  Внесу и свою лепту в обсуждение:</p>

<blockquote>
  <p>Ну-ну! Я был как-то на конференции, кажется CRN проводил, так там IDC кажется или Gartner это говорил. И так они меня разозлили, что я вышел следующим выступать и спросил: &#8220;Есть ли в зале хоть один человек, которому &#8220;отсутствие&#8221; свободы слова нанесло ущерб хоть в один доллар? В зале сидело больше сотни реселлеров, большая часть нашего ИТ бизнеса, и ни один не поднял руки.</p>
</blockquote>

<p>Это человек &#8212; я.  Я потерял много зеленых и хрустящих долларов.  И продолжаю их терять.  Из-за того, что моя производительность труда ниже, чем могла бы быть, живи я в Калифорнии.  Мой калифорнийский коллега не должен тратить часы на стояние в ненужных очередях.  Он может продлить водительские права по почте.  У него есть основания не бояться, что «все отнимут и поделят», и не сушить сухари на этот случай.  У него нет необходимости жить с женой и детьми в панельной однушке или думать о том, где украсть денег на жилье, не унижающее человеческое достоинство.  Ну и так далее.  Представьте, сколько свободного времени и энергии остается на работу.</p>

<p>Так что связь самая прямая.  Процитирую свой комментарий:</p>

<blockquote>
  <p>Если вы что-то импортируете в страну (или что-то из нее экспортируете), то вас не будут волновать гражданские свободы &#8212; были бы правила игры понятны и стабильны.  Здесь ваши рассуждения полностью применимы.</p>
  
  <p>Но если вы что-то в этой стране производите, то качество госсервиса и степень гражданских свобод будут отражаться на вашем бизнесе очень заметно.  Дело в том, что эти показатели очень сильно коррелируют с производительностью труда, особенно интеллектуального.  Возможно, бизнес вполне устроят низкая производительность труда и дешевые трудовые ресурсы.  А если нет?</p>
</blockquote>

<p>Ответ Михаила:</p>

<blockquote>
  <p>Степень гражданских свобод отражается на производительности интеллектуального труда? Щаззззззз! Где российский космос? Наше авиастроение и оборонка пользуются наработками 30 летней давности. На моем химфаке МГУ остались конечно люди мирового класса, но им уже за 60 и это продукт другой эпохи. У нас хорошо только рекламу делать научились&#8230;</p>
  
  <p>Проблема науки и технологий в СССР была не в том, что не открывали или не разрабатывали, а в том что не внедряли. Но это другая история&#8230;</p>
</blockquote>

<p>На это у меня два возражения.</p>

<p>Первое: современную Россию никак нельзя считать примером «западной» рыночной экономики.  Не думаю, что по уровню коррупции мы далеко ушли от Казахстана и Республики Чад.  Так что мы &#8212; типичная «Византия», и по нашему текущему состоянию нельзя делать какие-либо выводы о западной модели экономики.</p>

<p>Второе: гражданские свободы, все-таки, нужны для высокой производительности интеллектуального труда, в том числе, и в сфере ИТ.  Проблемы с внедрением технологий в СССР, как раз, демонстрируют больное место несвободного общества.</p>

<p>Открывать новые цацки &#8212; интересно.  Ученые будут делать это из чистого интереса, лишь бы государство дало денег на оборудование.  А вот внедрение &#8212; тяжелый, нервный и совершенно неинтересный процесс.  Чтобы люди им занимались, им нужна возможность зарабатывать на этом деньги.  Толстые пачки пропахших потом денег.  То есть, для инноваций, как минимум, нужна свобода зарабатывать деньги – это должно быть доступно кому угодно, а не только людям с правильной родословной (им, кстати, можно и не работать, чтобы хорошо жить).  Ну а свобода зарабатывать деньги обязательно потянет за собой весь остальной комплекс гражданских свобод.</p>

<p>Иными словами, в &#8220;византийской&#8221; модели имеет место следующая логика:  отсутствие гражданских свобод => неравенство => привилегированным работать не нужно, остальным бесполезно => нет стимулов добровольно заниматься тяжелой и неинтересной работой => нет внедрений.  Разве это не логично?  Кстати, Пол Грэм писал в статье <a href="http://www.paulgraham.com/inequality.html">“Inequality and Risk”</a> о том, что невозможность заработать много денег тяжелым трудом останавливает инновации.</p>

<p>Принудительный труд может исправить ситуацию, но государство, в силу своей неэффективности, не может одновременно развивать все необходимые экономике отрасли.  Так и получается, что в космос летаем, а термос без дырок сделать не можем – без дырок только дуршлаг.</p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/does-it-business-need-civil-rights/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Estimate за 20 минут</title>
		<link>http://alexlebedev.com/blog/20-min-estimate/</link>
		<comments>http://alexlebedev.com/blog/20-min-estimate/#comments</comments>
		<pubDate>Tue, 01 May 2007 19:15:52 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>работа с заказчиком</category>
	<category>бизнес</category>
	<category>программирование</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/20-min-estimate/</guid>
		<description><![CDATA[ Небольшая зарисовка из трудовых будней

<h2>Вводная</h2>

Клиент: "Алекс, не мог бы ты посмотреть спецификацию проекта Х?  Можешь ли ты это сделать и сколько приблизительно времени это займет?" ]]></description>
			<content:encoded><![CDATA[<p>Небольшая зарисовка из трудовых будней</p>

<h2>Вводная</h2>

<blockquote>
  <p>Клиент: &#8220;Алекс, не мог бы ты посмотреть спецификацию проекта Х?  Можешь ли ты это сделать и сколько приблизительно времени это займет?&#8221;</p>
  
  <p>Я: &#8220;ОК, я так понимаю это высший приоритет на сейчас&#8221;</p>
  
  <p>Клиент: &#8220;Да&#8221;</p>
  
  <p>Я: &#8220;Что ж, тогда поехали&#8230;  Скоро вернусь&#8221;</p>
</blockquote>

<h2>Читаем спецификацию</h2>

<p>Открываю Basecamp, иду на страницу проекта.  Имеется:  один абзац общих требований и приаттаченый Word&#8217;овский файл.  Скачиваю.  Открываю.  5 страниц, на первой общие требования и предполагаемый план работ, на остальных четырех &#8212; описание функций в виде эскизов страниц с описанием.</p>

<p>Смотрю на расписание.  Три контрольных точки:</p>

<ul>
<li><p><strong>0-30% done</strong> &#8220;Complete design and markup of all presentation layers&#8221; плюс какой-то минорный функционал. Target Completion Date: через 3 дня</p></li>
<li><p><strong>30-70% done</strong> Весь функционал, включая биллинг и прием платежей.  Target Completion Date: через 10 дней</p></li>
<li><p><strong>all done</strong> Тестирование и доводка согласно пожеланиям заказчика.  Target Completion Date: через 25 дней</p></li>
</ul>

<p>Похоже, план можно полностью списать в утиль, на правах бреда сивой кобылы.  Возможно, он писался до осознания функциональности.  В любом случае, надо искать конструктив.  Посему, перехожу к описанию функционала.</p>

<p>Бегло просматриваю страницы с функционалом.  Похоже, это главные страницы основных секций проекта.  Относительно подробное описание функций есть в комментариях справа.  wiki, блоги, теги, комментарии, чаты, зоны видимости сообщений &#8212; черт, сколько умных слов-то&#8230;</p>

<h2>Делаем estimate</h2>

<p>Возвращаюсь к началу описания функционала.  Достаю планшет и чистый лист бумаги.  Начинаю медленно читать список функций и сразу же набрасываю модель данных &#8212; имена объектов (сущностей) и связи между ними.  Связи «многие ко многим» не детализирую. Кардинальность связей бросаю обозначать на пятой сущности &#8212; потом разберемся, если еще понадобится.  Заканчиваю первую страницу с функционалом &#8212; в активе 7 сущностей.  После следующей страницы – еще 6, да и связей прибавилось…</p>

<p>После последней страницы у меня уже 19 основных сущностей.  Можно предположить, что второстепенных сущностей будет, как минимум, столько же, если не вдвое больше.  Отдельно выписываю особо запомнившиеся фрагменты функционала: биллинг, прием платежей, live preview закачанных пользователями видеороликов и т.д.</p>

<p>По грубой прикидке, каждой сущности будет соответствовать класс модели.  На каждый класс придется несколько сотен строк кода (Ruby on Rails).  И еще на столько же потянут тесты.  В общем, уже понятно, о чем говорить клиенту:</p>

<blockquote>
  <p>Я: &#8220;Закончил читать спецификацию.  На реализацию уйдет заметно больше 6 месяцев при команде в 4 человека&#8221;.  Насколько больше &#8212; предсказать за полчаса невозможно, да и, учитывая указанные в документе контрольные точки, едва ли будет интересно заказчику.</p>
  
  <p>Клиент: &#8220;Ладно, забудь.  Можешь прекратить читать.  Я знаю парня, который сделает это за 4 недели&#8221;</p>
  
  <p>Я: &#8220;Что ж, удачи ему.  Я не верю, что это возможно&#8221;</p>
</blockquote>

<h2>В чем мораль?</h2>

<p>Во-первых, как мне кажется, я нашел простой способ экспресс-оценки трудоемкости.  В смысле, способ быстро раскрыть порядок реального размера проекта.</p>

<p>Во-вторых, почти всегда найдется клоун, который пообещает сдать пятилетку за три дня.  «Безумству храбрых поем мы песню».  А заказчик, вероятно, совсем скоро к нам вернется.</p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/20-min-estimate/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>9 баллов</title>
		<link>http://alexlebedev.com/blog/9-of-12/</link>
		<comments>http://alexlebedev.com/blog/9-of-12/#comments</comments>
		<pubDate>Thu, 26 Apr 2007 07:18:26 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>менеджмент</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/9-of-12/</guid>
		<description><![CDATA[ Недавно вспоминал очень хорошую книгу об управлении: «Сначала надо нарушить все правила: что лучшие в мире менеджеры делают по-другому?» (First, Break All the Rules: What the World&#8217;s Greatest Managers Do Differently):

В частности, там пишут о том, что качество рабочего места и потенциальные возможности занимающего его человека определяются возможностью положительно ответить на следующие 12 вопросов:


Знаю ли [...] ]]></description>
			<content:encoded><![CDATA[<p>Недавно вспоминал очень хорошую книгу об управлении: «Сначала надо нарушить все правила: что лучшие в мире менеджеры делают по-другому?» (First, Break All the Rules: What the World&#8217;s Greatest Managers Do Differently):</p>

<p>В частности, там пишут о том, что качество рабочего места и потенциальные возможности занимающего его человека определяются возможностью положительно ответить на следующие 12 вопросов:</p>

<ol>
<li><p>Знаю ли я, что от меня ожидается на работе?</p></li>
<li><p>Располагаю ли я материалами и оборудованием, необходимыми для правильного выполнения моей работы?</p></li>
<li><p>Есть ли у меня возможность ежедневно заниматься на работе тем, что я умею делать лучше всего?</p></li>
<li><p>Хвалили ли меня за хорошо сделанную работу в последние 7 дней?</p></li>
<li><p>Проявляет ли непосредственный руководитель или кто-либо другой на работе заботу обо мне как о личности?</p></li>
<li><p>Есть ли на работе человек, который поощряет мой личностный или профессиональный рост?</p></li>
<li><p>Считаются ли на работе с моим мнением?</p></li>
<li><p>Позволяет ли миссия компании чувствовать важность моей работы?</p></li>
<li><p>Считают ли мои коллеги своим долгом выполнять работу качественно?</p></li>
<li><p>Работает ли вместе со мной хотя бы один из моих лучших друзей?</p></li>
<li><p>Беседовал ли кто-нибудь со мной за последние 6 месяцев о моем прогрессе?</p></li>
<li><p>Были ли у меня за последний год возможности для учебы и развития?</p></li>
</ol>

<p>Моя работа, если ее так можно назвать, получает 9 баллов из 12.  Вот три вопроса, на которые я не могу ответить утвердительно:</p>

<ul>
<li><p><em>Хвалили ли меня за хорошо сделанную работу в последние 7 дней?</em>  Нет.  Типичная проблема аутсорсинга, обусловленная &#8220;утяжеленностью&#8221; процесса коммуникации.  Общение с коллегой за океаном требует значительно больших усилий, чем общение с соседом по офису.  В результате необязательная часть общения слетает как шелуха и остается только самое необходимое: планы, задания, вопросы, проблемы&#8230;</p></li>
<li><p><em>Есть ли на работе человек, который поощряет мой личностный или профессиональный рост?</em>  Нет (хотя мне это и не нужно &#8212; всегда хватало собственного стремления к совершенству).  Абсолютно типично для менеджерской должности, тем более что я работаю не в большой компании, а независимо.</p></li>
<li><p><em>Позволяет ли миссия компании чувствовать важность моей работы?</em>  Скорее нет.  Никто не отдает на аутсорсинг жизненно важные проекты.</p></li>
</ul>

<p>А на сколько баллов тянет ваша работа?</p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/9-of-12/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Вышел Windows 2003 Server SP2.  Видимо, зря</title>
		<link>http://alexlebedev.com/blog/beware-of-win2003sp2/</link>
		<comments>http://alexlebedev.com/blog/beware-of-win2003sp2/#comments</comments>
		<pubDate>Tue, 03 Apr 2007 09:45:16 +0000</pubDate>
		<dc:creator>Alex Lebedev</dc:creator>
		
	<category>разное</category>
		<guid isPermaLink="false">http://alexlebedev.com/blog/beware-of-win2003sp2/</guid>
		<description><![CDATA[ Как вы, наверное, все знаете, где-то с полмесяца назад вышел Service Pack 2 для Microsoft Windows 2003 Server.
Как вы, наверное, все знаете, где-то с полмесяца назад вышел Service Pack 2 для Microsoft Windows 2003 Server.

Общался сегодня с коллегами, трудящимися у моего предыдущего работодателя.  Они на свою голову обновили Windows 2003 Server до SP2 (к счастью, это был только тестовый сервер).  Вот к чему это привело: [...] ]]></description>
			<content:encoded><![CDATA[<p>Как вы, наверное, все знаете, где-то с полмесяца назад вышел Service Pack 2 для Microsoft Windows 2003 Server.</p>

<p>Общался сегодня с коллегами, трудящимися у моего предыдущего работодателя.  Они на свою голову обновили Windows 2003 Server до SP2 (к счастью, это был только тестовый сервер).  Вот к чему это привело:</p>

<h2>Настоящие герои не пользуются RDP</h2>

<p>Сразу же вылезло две проблемы с RDP (Remote Desktop)</p>

<ol>
<li><p>Часть разработчиков не смогла подключиться к серверу.  Неверный пароль и все тут.</p></li>
<li><p>Перестала работать функция Remote Control, позволяющая контролировать сессию другого человека и видеть его экран.  Когда работает, эта функция исключительно удобна для обучения территориально удаленного коллеги или для совместной диагностики проблем.</p></li>
</ol>

<h2>Сессии в ASP: &#8220;Эта музыка будет вечной&#8221;</h2>

<p>После обновления перестало срабатывать событие IIS, сигнализирующее об окончании сессий в классических ASP-приложениях.  Для приложений, использующих сессии, это, в большинстве случаев, Show Stopper.   Так что срочно сносите SP2 со всех своих серверов и серверов заказчиков.  Ну или расслабьтесь и получайте удовольствие до выхода фикса.</p>

<p>Если вы все еще используете ASP (что во многих случаях вполне оправдано), то рекомендую прочитать <a href="http://blogs.msdn.com/carloc/archive/2007/03/25/session-onend-not-firing-after-applying-windows-2003-service-pack-2.aspx">описание проблемы в Knowledge Base</a>.</p>

<p>Мораль:  выключите windows update на production серверах.  И всегда тестируйте все обновления на чем-нибудь не очень критичном.</p>

<p>Кажется, Microsoft только что выпустила hotfix.  Впрочем, он недоступен для скачивания, а распространяется только по специальному запросу в техподдержку, что наводит на тревожные мысли относительно степени его протестированности.</p>

<h2>Умри, Firefox!</h2>

<p>При обновлении Outlook и Internet Explorer становятся почтовым клиентом и браузером по умолчанию.  Вне зависимости от предыдущих настроек.  Сообщество писает по этому поводу кипятком <a href="http://blogs.msdn.com/ie/archive/2007/03/15/windows-server-2003-service-pack-2-released.aspx">вот здесь</a>  и <a href="http://reddit.com/info/1ap2h/comments">здесь</a>.</p>

<h2>Итог</h2>

<p>Microsoft облажалась по первому разряду.  Будем надеяться, такое непотребство будет происходить не очень часто&#8230;</p>
]]></content:encoded>
			<wfw:commentRSS>http://alexlebedev.com/blog/beware-of-win2003sp2/feed/</wfw:commentRSS>
		</item>
	<feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetFeedData?uri=OutsourcingStories</feedburner:awareness></channel>
</rss><!-- Dynamic Page Served (once) in 0.598 seconds -->
