<?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; alik</title>
	<atom:link href="http://www.kurdyukov.com/author/alik/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kurdyukov.com</link>
	<description>Заметки о разработке и прочей жизни</description>
	<lastBuildDate>Sat, 04 Feb 2012 01:34:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Автоматическая реализация INotifyPropertyChanged на Spring.NET</title>
		<link>http://www.kurdyukov.com/2012/02/04/spring-inotifypropertychanged/</link>
		<comments>http://www.kurdyukov.com/2012/02/04/spring-inotifypropertychanged/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 01:34:55 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Spring.NET]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=188</guid>
		<description><![CDATA[В статье ранее я писал как сделать автоматическую реализацию INotifyPropertyChanged на основе расширений библиотеки NInject. К сожалению, моя жизнь с этой библиотекой не сложилась, NInject был заменен на Spring.NET. При этом схему автореализации надо было как-то перенести без особенных изменений прикладного кода. Объясню, что именно я сделал. Для начала нам нужен интерфейс, который будет реализовываться [...]]]></description>
			<content:encoded><![CDATA[<p>В статье <a href="http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/" title="Простая реализация INotifyPropertyChanged" target="_blank">ранее</a> я писал как сделать автоматическую реализацию INotifyPropertyChanged на основе расширений библиотеки NInject. К сожалению, моя жизнь с этой библиотекой не сложилась, NInject был заменен на Spring.NET. При этом схему автореализации надо было как-то перенести без особенных изменений прикладного кода. Объясню, что именно я сделал.</p>
<p><span id="more-188"></span><br />
Для начала нам нужен интерфейс, который будет реализовываться всеми потенциальными автонотифицируемыми классами:</p>
<pre class="brush: csharp; title: ; notranslate">
    public interface IAutoNotifyPropertyChanged : INotifyPropertyChanged
    {
        void OnPropertyChanged(string propertyName);
    }
</pre>
<p>Удобства ради можно использовать базовый класс для всех авто-реализаций:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class ViewModelBase : IAutoNotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
</pre>
<p>Кроме этого, нам понадобятся атрибуты, которыми мы будет включать/отключать авто-нотификацию:</p>
<pre class="brush: csharp; title: ; notranslate">
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class NotifyOfChangesAttribute : Attribute
    {
    }
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class DoNotNotifyOfChangesAttribute : Attribute
    {
    }
</pre>
<p>Теперь пришла очередь Pointcut, которые будет определять setter-ы целевых свойств:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class AutoNotifyPointcut : StaticMethodMatcherPointcut
    {
        public override bool Matches(MethodInfo method, Type targetType)
        {
            if (!typeof(IAutoNotifyPropertyChanged).IsAssignableFrom(targetType))
                return false;

            // non-setters ignored
            if (!method.Name.StartsWith(&quot;set_&quot;))
                return false;

            object[] attributes = targetType.GetCustomAttributes(typeof(NotifyOfChangesAttribute), true);
            if (attributes.Length &gt; 0)
            {
                object[] disables = method.GetCustomAttributes(typeof (DoNotNotifyOfChangesAttribute), true);
                if (disables.Length &gt; 0)
                    return false;

                return true;
            }

            attributes = method.GetCustomAttributes(typeof (NotifyOfChangesAttribute), true);
            return attributes.Length &gt; 0;
        }
    }
</pre>
<p>Затем нам нужен advice, в котором и будет происходить вся работа:</p>
<pre class="brush: csharp; title: ; notranslate">
    public class AfterPropertySetAdvice : IMethodInterceptor
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();

        public object Invoke(IMethodInvocation invocation)
        {
            object proxy = invocation.Proxy;
            string name = null;

            IAutoNotifyPropertyChanged model = proxy as IAutoNotifyPropertyChanged;
            if (model == null)
            {
                logger.Error(&quot;Advice is called on non-IAutoNotifyPropertyChanged class&quot;);
            }
            else
            {
                name = invocation.Method.Name;
                if (!name.StartsWith(&quot;set_&quot;))
                {
                    logger.Error(&quot;Cannot notify on non-setter&quot;);
                }
                name = name.Substring(4);
            }

            object rval = invocation.Proceed();

            if (name != null)
            {
                model.OnPropertyChanged(name);
            }

            return rval;
        }
    }
</pre>
<p>Тут для вящего удобсва отладки используется NLog. Его использование можно вовсе удалить.</p>
<p>Так, классы созданы, надо как-то их применить к объектам. Сразу скажу, что из-за особенностей Spring AOP для оборачивания класса в advice надо, чтобы экземпляр класса создавался Spring-ом. Код подключения выглядит примерно так:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;objects xmlns=&quot;http://www.springframework.net&quot;&gt;
  &lt;object id=&quot;notifyOnChangePointcut&quot; type=&quot;CommonControls.AutoNotify.AutoNotifyPointcut, CommonControls&quot;/&gt;
  &lt;object id=&quot;afterPropertySetAdvice&quot; type=&quot;CommonControls.AutoNotify.AfterPropertySetAdvice, CommonControls&quot;/&gt;

  &lt;object id=&quot;notifyInterceptor&quot; type=&quot;Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop&quot;&gt;
    &lt;property name=&quot;Pointcut&quot; ref=&quot;notifyOnChangePointcut&quot;/&gt;
    &lt;property name=&quot;Advice&quot; ref=&quot;afterPropertySetAdvice&quot;/&gt;
  &lt;/object&gt;

  &lt;object type=&quot;Spring.Aop.Framework.AutoProxy.InheritanceBasedAopConfigurer, Spring.Aop&quot;&gt;
    &lt;property name=&quot;ProxyDeclaredMembersOnly&quot; value=&quot;false&quot;/&gt;
    &lt;property name=&quot;ObjectNames&quot;&gt;
      &lt;list&gt;
        &lt;value&gt;*Model&lt;/value&gt;
      &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name=&quot;InterceptorNames&quot;&gt;
      &lt;list&gt;
        &lt;value&gt;notifyInterceptor&lt;/value&gt;
      &lt;/list&gt;
    &lt;/property&gt;
  &lt;/object&gt;
&lt;/objects&gt;
</pre>
<p>Можно заметить, что оборачиванию будут подвергнуты объекты, id которых заканчивается на &laquo;Model&raquo;. Анонимные объекты будет проигнорированы.</p>
<p>Кажется, что ограничение по имени какое-то странное. Также кажется, что использование InheritanceBasedAopConfigurer выглядит странно в контексте наличия тега aop:config в Spring.NET. Поясню, почему именно так.</p>
<p>В рамках Spring.NET существует 3 способо создания proxy объектов для вызова advice:</p>
<ol>
<li>Aggregation based &#8211; для объекта-обертки генерируется DynamicProxy со своим интерфейсом. Такой объект нельзя привести к оригинальному типу target объекта. Реальный объект в этом случае будет аггрегирован внутри proxy. Нам не подходит из-за несовместимого интерфейса.</li>
<li>Inheritance based &#8211; объект-прокси будет наследником класса target объекта, при этом обернуты будут только virtual методы и свойства оригинала. Оригинальный объект будет аггрегирован внутри proxy. В нашем случае это дает интересный спец-эффект: поскольку события тоже проксируются, то добавление обработчика события на объект-обертку не влияет на оригинальный объект. Значит, если внутри advice вызвать событие, то вызов будет превращен в вызов объекта-оригинала, а не обертки. А на внутреннем объекте обработчиков как небыло так и нет. Значит, тоже не подходит</li>
<li>InheritanceBasedAopConfigurer &#8211; новый способ генерации вызовов, добавленный в Spring 1.2. Идея состоит в изменении кода оригинального объекта. Вот это нам подходит, но дает указанные выше ограничения на создание объектов</li>
</ol>
<p>Пример создания объекта:</p>
<pre class="brush: xml; title: ; notranslate">
  &lt;object id=&quot;mainModel&quot; type=&quot;DataServer.ViewModel.RetranslatingDataServerManagerModel, DataServer&quot;/&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/02/04/spring-inotifypropertychanged/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Неопределенное будущее Titanium Desktop</title>
		<link>http://www.kurdyukov.com/2012/02/01/titanium-desktop-future/</link>
		<comments>http://www.kurdyukov.com/2012/02/01/titanium-desktop-future/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 01:42:39 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Titanium]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=180</guid>
		<description><![CDATA[Около полугода я следил на развитием проекта Titanium Desktop. Идея продукта состоит в том, что можно создавать полноценные desktop приложения на HTML+JS. Я подумывал использовать этот фреймворк в одном из своих проектов. Но сегодня, проверяя новости, обнаружил нерадостное &#8211; проект снимают с финансирования AppCelerator и передают сообществу разработчиков. Официальный пресс-релиз можно прочитать здесь. Все это [...]]]></description>
			<content:encoded><![CDATA[<p>Около полугода я следил на развитием проекта <a href="http://www.appcelerator.com/products/titanium-desktop-application-development/" title="http://www.appcelerator.com/products/titanium-desktop-application-development/" target="_blank">Titanium Desktop</a>. Идея продукта состоит в том, что можно создавать полноценные desktop приложения на HTML+JS. Я подумывал использовать этот фреймворк в одном из своих проектов. Но сегодня, проверяя новости, обнаружил нерадостное &#8211; проект снимают с финансирования AppCelerator и передают сообществу разработчиков. Официальный пресс-релиз можно прочитать <a href="http://developer.appcelerator.com/blog/2012/01/the-future-of-titanium-desktop.html" title="http://developer.appcelerator.com/blog/2012/01/the-future-of-titanium-desktop.html" target="_blank">здесь</a>.</p>
<p>Все это означает, что проект может приостановиться на неопределенный срок. А значит надо будет взвесить все &laquo;за&raquo; и &laquo;против&raquo; прежде чем использовать.</p>
<p>В качестве альтернативы предлагается <a href="http://code.google.com/p/chromiumembedded/" title="http://code.google.com/p/chromiumembedded/" target="_blank">chromiumembedded</a>, который тоже находится в непонятном состоянии. По этому проекту даже с документацией есть проблемы, вся поддержка &#8211; через полуживой форум.</p>
<p>Таким образом, многоплатформенных технологий для создания desktop приложений на HTML+JS в доступности не видно. Разве что Adobe AIR, но он пугает чем, что Adobe.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/02/01/titanium-desktop-future/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Простая реализация INotifyPropertyChanged</title>
		<link>http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/</link>
		<comments>http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 01:10:34 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[INotifyPropertyChanged]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=168</guid>
		<description><![CDATA[При разработке для платформы .NET часто приходится делать так раздражающие всех реализации интерфейса INotifyPropertyChanged на классах-моделях. Типичный пример выглядит так: На мой взгляд, с этим кодом есть 2 проблемы: Очень много повторений и кода вызванного необходимостью вызвать NotifyPropertyChanged. Увеличивается количество &#171;тупой&#187; работы. Использование строковой константы Name в качестве аргумента. Рефакторинг может привести к разрушению биндинга [...]]]></description>
			<content:encoded><![CDATA[<p>При разработке для платформы .NET часто приходится делать так раздражающие всех реализации интерфейса <code>INotifyPropertyChanged</code> на классах-моделях. Типичный пример выглядит так:</p>
<pre class="brush: csharp; title: ; notranslate">
class StatisticsRecord: INotifyPropertyChanged
{
    private string name;
    public string Name { get { return name; } set { name = value; NotifyPropertyChanged(&quot;Name&quot;); } }	

    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
</pre>
<p>На мой взгляд, с этим кодом есть 2 проблемы:</p>
<ol>
<li>Очень много повторений и кода вызванного необходимостью вызвать <code> NotifyPropertyChanged</code>. Увеличивается количество &laquo;тупой&raquo; работы.</li>
<li>Использование строковой константы Name в качестве аргумента. Рефакторинг может привести к разрушению биндинга к такому свойству.</li>
</ol>
<p><span id="more-168"></span><br />
По счастью разработчики симпатичного фреймворка <a href="http://http://ninject.org/" title="http://ninject.org/" target="_blank">NInject</a> сделали расширение <a href="https://github.com/ninject/ninject.extensions.interception" title="https://github.com/ninject/ninject.extensions.interception" target="_blank">Ninject.Extensions.Interception</a>, которое позволяет решить описанные выше проблемы за счет использования динамического AOP. Используется это так:</p>
<ol>
<li>Подключаем к проекту библиотеки NInject, Ninject.Extensions.Interception, Castle.Core, Ninject.Extensions.Interception.DynamicProxy</li>
<li>Создаем класс-реализацию интерфейса IAutoNotifyPropertyChanged, например так:
<pre class="brush: csharp; title: ; notranslate">
public class ViewModelBase : IAutoNotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;

     public void OnPropertyChanged(string propertyName)
     {
         PropertyChangedEventHandler handler = PropertyChanged;
         if (handler != null)
         {
             handler(this, new PropertyChangedEventArgs(propertyName));
         }
     }
}
</pre>
</li>
<li>Используем этот класс в нашем классе модели. Например:
<pre class="brush: csharp; title: ; notranslate">
[NotifyOfChanges]
class StatisticsRecord: INotifyPropertyChanged
{
    public virtual string Name { get; set; }

    [DoNotNotifyOfChanges]
    public virtual string NonNotifyableProperty { get; set; }
}
</pre>
<blockquote><p><strong>NB!</strong> Важно, чтобы getter-ы и setter-ы были виртуальными, поскольку мы используем DynamicProxy для добавления нотификаций
</p></blockquote>
</li>
<li>Подключаем &laquo;перехватчик&raquo; при конфигурации ядра NInject:
<pre class="brush: csharp; title: ; notranslate">
...
kernel.Components.Add&lt;IPlanningStrategy, AutoNotifyInterceptorRegistrationStrategy&gt;();
...
</pre>
</li>
<p>Код стал короче и понятнее напорядок.</p>
<p>PS. Детали того, как именно это все устроено смотрите тут: <a href="http://innovatian.com/2010/01/ninject-extensions-interception-and-iautonotifypropertychanged-ianpc/" title="http://innovatian.com/2010/01/ninject-extensions-interception-and-iautonotifypropertychanged-ianpc/" target="_blank"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/01/31/aop-inotifypropertychanged/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>System.BadImageFormatException при загрузке тестов в ReSharper</title>
		<link>http://www.kurdyukov.com/2012/01/24/system-badimageformatexception-tests-resharper/</link>
		<comments>http://www.kurdyukov.com/2012/01/24/system-badimageformatexception-tests-resharper/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 22:31:01 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[ReSharper]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=161</guid>
		<description><![CDATA[В начале создания авто-тестов в одном проекте на C# начал возникать System.BadImageFormatException при попытке запуска тестов из ReSharper. Выяснение показало, что проблема была в том, что сборка с тестами имела Any CPU. А тестируемые классы были в EXE, который был собран в x86. При этом Windows используется 64х битный, следовательно Any CPU = x64. Решение [...]]]></description>
			<content:encoded><![CDATA[<p>В начале создания авто-тестов в одном проекте на C# начал возникать System.BadImageFormatException при попытке запуска тестов из ReSharper. Выяснение показало, что проблема была в том, что сборка с тестами имела Any CPU. А тестируемые классы были в EXE, который был собран в x86. При этом Windows используется 64х битный, следовательно Any CPU = x64.</p>
<p>Решение просто &#8211; указать в тестовой сборке целевую платформу x86. Это делается в закладке Build свойств проекта тестовой сборки.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/01/24/system-badimageformatexception-tests-resharper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Названия обработчиков событий в VS2010</title>
		<link>http://www.kurdyukov.com/2012/01/09/vs2010-handy/</link>
		<comments>http://www.kurdyukov.com/2012/01/09/vs2010-handy/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 15:05:36 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[c#]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=152</guid>
		<description><![CDATA[После установки ReSharper на Visual Studio 2010 (всем разработчикам на C# рекоммендую, кста) наиболее активно разражает подсвечивание названий методов, который автоматически генерируются Visual Designer для обработки событий, поскольку название типа &#171;Form1_Load&#187; никак не соответствует идеям начинать название с глагола и не использовать &#171;_&#187;. Но это можно исправить. Есть 2 способа исправления проблемы. 1. Изменить способ [...]]]></description>
			<content:encoded><![CDATA[<p>После установки ReSharper на Visual Studio 2010 (всем разработчикам на C# рекоммендую, кста) наиболее активно разражает подсвечивание названий методов, который автоматически генерируются Visual Designer для обработки событий, поскольку название типа &laquo;Form1_Load&raquo; никак не соответствует идеям начинать название с глагола и не использовать &laquo;_&raquo;. Но это можно исправить.<br />
<span id="more-152"></span><br />
Есть 2 способа исправления проблемы.</p>
<p><strong>1. Изменить способ генерации названий методов</strong><br />
<em>Предпочтительный</em><br />
<a href="http://www.kurdyukov.com/wp-content/uploads/2012/01/screenshot.png"><img src="http://www.kurdyukov.com/wp-content/uploads/2012/01/screenshot.png" alt="" title="Настройки" width="250" height="249" class="alignright size-full wp-image-155" /></a><br />
Установить плагин <a href="http://visualstudiogallery.msdn.microsoft.com/14f62cb9-b559-4bad-9388-37da2150e238/?SRC=Home" target="_blank">EventHandler Naming</a>, который позволяет менять политику именования методов-обработчиков. Устанавливать можно прямо из Extension manager. Даже настройки не требует, по умолчанию настроен как <code>On${SiteName}${EventName}</code>, например, <code>OnForm1Load</code>. Если надо, настраивается.</p>
<p><strong>2. Настроить ReSharper, чтобы он не ругался</strong></p>
<ol>
<li>Идем в меню ReSharper | Options | Languages | C# | C# Naming Style</li>
<li>Переключаем на &laquo;Advanced settings&#8230;&raquo;</li>
<li>Меняем значение &laquo;Event subscriptions on fields&raquo; с умолчального <code>$object$_On$event$</code> на <code>$object$_$event$</code></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2012/01/09/vs2010-handy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Поучимся?</title>
		<link>http://www.kurdyukov.com/2011/09/26/learning/</link>
		<comments>http://www.kurdyukov.com/2011/09/26/learning/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 12:06:08 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[leaning]]></category>
		<category><![CDATA[stanford]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=142</guid>
		<description><![CDATA[Я считаю, без каких-то новых знаний жить не особо интересно. Поэтому стараюсь учиться. А тут Стэнфорд предлагает уникальную возможность бесплатно поучиться computer science. Предлагаемые курсы: Класс по машинному обучению Класс по искусственному интеллекту Класс введения в базы данных Все классы бесплатные, будут домашние задания. Стартуют примерно 10 октября. Язык преподавания &#8211; английский. Я сам записался [...]]]></description>
			<content:encoded><![CDATA[<p>Я считаю, без каких-то новых знаний жить не особо интересно. Поэтому стараюсь учиться. А тут Стэнфорд предлагает уникальную возможность бесплатно поучиться computer science.<br />
<span id="more-142"></span><br />
Предлагаемые курсы:</p>
<ul>
<li><a href="http://www.ml-class.org/course/auth/welcome">Класс по машинному обучению</a></li>
<li><a href="http://www.ai-class.com/">Класс по искусственному интеллекту</a></li>
<li><a href="http://www.db-class.org/course/auth/welcome">Класс введения в базы данных</a></li>
</ul>
<p>Все классы бесплатные, будут домашние задания. Стартуют примерно 10 октября. Язык преподавания &#8211; английский.</p>
<p>Я сам записался на машинное обучению и искусственному интеллекту.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2011/09/26/learning/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Software People 2011, день первый</title>
		<link>http://www.kurdyukov.com/2011/04/07/software-people-2011-day-one/</link>
		<comments>http://www.kurdyukov.com/2011/04/07/software-people-2011-day-one/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 18:46:34 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=134</guid>
		<description><![CDATA[Сегодня начала работу конференция Software People, на которой я, к счастью, присутствую. Изложу свои мысли на счет мероприятий, на которых был сам. Сильно вдаваться в подробности не буду, приведу личные впечатления. Нил Мейден &#8211; Инженерия требований как творческое решение проблем С самого начала стало ясно, что русское название не совсем верное, скорее это &#171;&#8230; творческое [...]]]></description>
			<content:encoded><![CDATA[<p>Сегодня начала работу конференция Software People, на которой я, к счастью, присутствую. Изложу свои мысли на счет мероприятий, на которых был сам. Сильно вдаваться в подробности не буду, приведу личные впечатления.<br />
<span id="more-134"></span></p>
<h1>Нил Мейден &#8211; Инженерия требований как творческое решение проблем</h1>
<p>С самого начала стало ясно, что русское название не совсем верное, скорее это &laquo;&#8230; творческое решение задач&raquo;.</p>
<p>Нил считает, что для множества проектов недостаточно просто расспросить пользователя, поскольку пользователь еще не знает, что именно ему надо. Часто есть только общая формулировка проблем. Но иногда и ее нет &#8211; скажем, когда разрабатывался iPad, примера такого устройства просто небыло. Была только смутная проблема, что &laquo;компы тяжелые и недолго работают от батареек&raquo; (ну или как-то так, я сам проблему придумал). Поэтому в процессе работы над требованиями надо привлекать подходы, характерные для творчества.</p>
<p>В качестве референтного творческого процесса он рассматривал CPS Method (Osborn 1953). И на нем построил собственный процесс. На входе процесса &#8211; люди и их знания, на выходе &#8211; скрипты и пользовательские сценарии для анализа и разработки.</p>
<p>Процесс был успешно применен в задаче проектирования новой системы управления аэропортами. В самом процессе проектирования принимала участие большая группа специалистов по транспорту, не только воздушному, но и наземному &#8211; автомобильные и железные дороги. В результате &#8211; свежие и эффективные решения.</p>
<p>Указал на важный пункт &#8211; техническим людям часто сложно участвовать в традиционном творческом процессе, поскольку человек больше сконцентрирован на декомпозиции, чем на синтезе. А именно синтез и аналогия считаются наиболее мощными инструментами творчества.</p>
<p>Еще полезный хинт &#8211; чтобы дискуссия и генерация идей не стагнировала, лучше спрашивать не &laquo;Что можно сделать?&raquo;, а &laquo;Что сделать сейчас сделать нельзя?&raquo;, а потом мысленно убрать ограничение из поставки задачи.</p>
<h1>Jutta Eckstein &#8211; Agile by Planning Continuously</h1>
<p>К сожалению, доклад был рассчитан на менее подготовленную аудиторию, из-за чего лично мне показалось, что я по сути не услышал ничего особенно нового.</p>
<p>Единственная моя заметка: очень важно, чтобы у user story присутствовали следующие пункты:</p>
<ul>
<li>явно обозначен business value</li>
<li>было четко определено кому именно сдавать результат</li>
<li>явно указывалось по какому критерию будет оцениваться результат</li>
</ul>
<p>Я сам иногда нарушаю эти правила, от чего возникают проблемы с некоторыми фичами.</p>
<h1>Lasse Koskela &#8211; Specification By Example</h1>
<p>Я не придавал какого-то специального значения примерам, тогда как на них можно рассчитывать как на существенный элемент в спецификации некоторых фич. Собственно, именно про это и был весь доклад. Докладчик приводил примеры различных способов спецификации на примерах, показал парочку диалогов с заказчиком по определению репрезентативных примеров.</p>
<p>Лично для меня было наиболее важным:</p>
<ul>
<li>В процессе формулировки примеров не надо уходить в делали &#8211; так всем станет скучно и процесс остановится</li>
<li>Всегда используйте реальные данные, а не абстрактных &laquo;Васей Пупкиных&raquo; &#8211; так вы избежите &laquo;шарообразных коней&raquo;</li>
</ul>
<p>Надо будет попробовать применять подход и начать спецификацию чего-нибудь заковыристого с примеров. Думаю, что и заказчикам так будет много понятнее. Это лучше, чем требовать &laquo;правильную спецификацию&raquo;.</p>
<h1>Юрий Шиляев &#8211; Программа обучения на 50 000 часов&#8230;</h1>
<p>Докладчик очень живо и интересно рассказал, как он построил образовательную программу в, пожалуй, крупнейшей в СНГ outsource компании EPAM. Они не только учат, но и меряют кто как учится. Тренера мотивированы, в т. ч. деньгами. У них в каждом офисе нашлось по человеку, которых был готов учить.</p>
<p>Обратил внимание, что в EPAM есть 2 иерархии &#8211; производственная (менеджер по производству) и кадровая (менеджер по кадрам). Очень напомнило параллельные иерархии на советских производствах &#8211; производственную и партийную.</p>
<h1>Ольга Павлова &#8211; Менеджеры и программисты: как перестать обижаться друг на друга?</h1>
<p>Интересный по сути, но не очень живой по подаче доклад про основы психологии программистов для менеджеров. Ольга считает, что менеджер &#8211; это человек, обеспечивающий комфортную работу команды. И немножко психолог &#8211; чтобы кого-то погладить, с чем-то поговорить в приватной обстановке. Полностью согласен.</p>
<p>После доклада рассказала о хорошем опыте организации контроля менеджерской работы на основе того, чтобы открыть все результаты всем сотрудникам. Результаты &#8211; это и код, и переписка. А потом &laquo;оком Саурона&raquo; смотреть на процесс и решать возникающие проблемы до того, как они начали существенно влиять на процесс и на заказчика. Очень разумное решение, на мой взгляд. Много лучше стандартных &laquo;корпоративных окопов&raquo;, которые можно встретить в множестве российских компаний.</p>
<p>PS. Считаю, что первый день прошел полезно, но несколько &laquo;жидковато&raquo; &#8211; к сожалению, именитые гест-спикеры часто надевали фуражку Капитана Очевидности. Завтра ожидается просто взрыв мозга.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2011/04/07/software-people-2011-day-one/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Наемная работа мечты</title>
		<link>http://www.kurdyukov.com/2011/03/08/dream-hired-work/</link>
		<comments>http://www.kurdyukov.com/2011/03/08/dream-hired-work/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 11:22:10 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[tailand]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=129</guid>
		<description><![CDATA[Кажется, я нашел идеальный вариант организации наемной работы. Вот текст объявления: Таиланд — море, солнце, счастливые лица вокруг. Теперь и у Вас есть возможность попасть туда, причем бесплатно и Вам еще за это доплатят Вакансия: разработчик Ruby on Rails Ну и так далее&#8230;. Ведь если задуматься, то представляется что огромное количество реальных проектов могут делаться [...]]]></description>
			<content:encoded><![CDATA[<p>Кажется, я нашел идеальный вариант организации наемной работы. Вот текст объявления:</p>
<blockquote><p>Таиланд — море, солнце, счастливые лица вокруг. Теперь и у Вас есть возможность попасть туда, причем бесплатно и Вам еще за это доплатят <img src='http://www.kurdyukov.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Вакансия: разработчик Ruby on Rails</p></blockquote>
<p><span id="more-129"></span><br />
Ну и так далее&#8230;.<br />
Ведь если задуматься, то представляется что огромное количество реальных проектов могут делаться именно в таком режиме. Но есть несколько скрытых ограничений:</p>
<ul>
<li>Разработчики должны быть достаточно мобильны &#8211; т.е. никаких &laquo;привязок&raquo; на родине</li>
<li>Разработчики должны быть достаточно &laquo;рисковыми&raquo; и неконфликтными людьми &#8211; ведь непонятно как внивь прибывший будет уживаться в уже сложившемся коллективе.</li>
</ul>
<p>И все таки, перспектива работать в практически идеальных экологических условиях &#8211; это прекрасно, по-моему.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2011/03/08/dream-hired-work/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Как я домен продлял</title>
		<link>http://www.kurdyukov.com/2011/02/23/domain-extending/</link>
		<comments>http://www.kurdyukov.com/2011/02/23/domain-extending/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 16:13:35 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[life]]></category>
		<category><![CDATA[2domains]]></category>
		<category><![CDATA[rbk]]></category>
		<category><![CDATA[webmoney]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=121</guid>
		<description><![CDATA[На меня зарегистрирован некоторый домен для будущих проектов. Его название не имеет значения, тут речь пойдет о регистраторе. Когда-то давно один мой друг посоветовал мне обратиться в сервис https://2domains.ru, поскольку цены несколько ниже чем по рынку. Что я и сделал год назад. Сейчас подошло время продлять регистрацию домена. И тут началось. Мне начали приходить письма [...]]]></description>
			<content:encoded><![CDATA[<p>На меня зарегистрирован некоторый домен для будущих проектов. Его название не имеет значения, тут речь пойдет о регистраторе. Когда-то давно один мой друг посоветовал мне обратиться в сервис <a href="https://2domains.ru">https://2domains.ru</a>, поскольку цены несколько ниже чем по рынку. Что я и сделал год назад. Сейчас подошло время продлять регистрацию домена. И тут началось.<br />
<span id="more-121"></span><br />
Мне начали приходить письма от reg.ru с информацией о необходимости продления домена и т.п. Когда же я попробовал зайти в личный кабинет на этом сайте меня не пустили. И пароль отказались восстанавливать на все email-ы которые я мог указать при регистрации. Потыкавшить с проблемой полчаса я просто позвонил в их службу поддержки. И тут выяснилось, что домен-то я регистрировал через партнера (2domains) о чем успешно забыл. И этот партнер никак меня не уведомил об истечении домена. Ладно, хотя бы личный кабинет найден. Но тут началось самое интересное…</p>
<p>Для того, чтобы продлить домен надо, естественно, его оплатить. А для этого &#8211; пополнить счет на 2domains. С этим меня ждала мегазасада. Вариантов пополнения &#8211; мильон, но большинство работает или через RoboKassa-у или через не менее неведомые z-payment.</p>
<p>Сначала я попытался оплатить с карточки через РобоКассу. Их сайт нещажно зависал, постоянно показывал 503 internal Server Error и прочие безобразия. Ну ладно, не получается через карточку, давайте через вебмани попробуем. У меня когда-то давно был кошелек с вебманями, только от него сертификат истек давно, да и денег там было немного. Значит надо восстановить доступ к кошельку.</p>
<p>Восстановление началось с нормальной формы типа &laquo;введите номер wmid, вам на email ушло письмо&raquo;. В емейле ссылка &#8211; мол, откройте. Дальше надо было зарегистрировать новый wmid. Потом заполнить форму восстановления. Плюс все это обвешано массой способов авторизации, любой чих авторизуется. Но это не помогает &#8211; иногда логин просто тупо глючит и не узнает свои же цифры капчи. После бесконечного заполнения всяких форм у меня закончились попытке e-num авторизации по sms, на чем я и остановился. Вывод один:</p>
<blockquote><p>
Дорогие разработчики WebMoney!<br />
Сделайте, пожалуйста, простую систему. Упростите формы и общий flow. Лично я порвал весь моск об ваш чудо-интерфейс. Было бы не так надо &#8211; бросил бы нафиг.
</p></blockquote>
<p>Ладно, раз WM не работает &#8211; давайте попробуем через недевомые RBK Money. Почему они &#8211; потому что я подумал, что эти вроде должны как-то в гранях реальности быть. Сказало &#8211; сделано. Зарегистрировался. Даже деньги перевел с карточки со жлобской коммиссией. И все бы хорошо, но при оплате моего домена через RBK Money увидел сакральную надпись &laquo;На Вашем кошельке отсутствуют денежные средства.&raquo;. Как это, блин, отсутвуют если я в соседней закладке виду свои кровные 110р на счету? Перезагружал страницу, пробовал выходит и опять входить. Ничего не помогает. Потом еще раз посмотрел на интерфейс RBK и увидел неприметную надпиcь:</p>
<blockquote><p>
RU000761000<br />
- для покупок:	 110 руб.<br />
- для перевода:	 0 руб.
</p></blockquote>
<p>Причем, чтобы увидеть это самое &laquo;для перевода&raquo; надо догадаться нажать на малюсенькую зеленую стрелочку вниз около суммы. Поистине, чудо-интерфейс. При этом как пополнить эту самую &laquo;для перевода&raquo; нифига не ясно. Ладно, наверное для этого надо подтвердить что я &#8211; это я, т.е. повысить уровень кошелька. Ладно, повышаем. Заполняет мильон форм с паспортными данными, номера счетов и т.п. А дальше &#8211; фокус &#8211; с моего счета пропадает 40р. Меня нигде об этом не предупреждали! Вот уроды, думаю. Ну да ладно, продолжение будет дальше &#8211; пока банконский перевод дойдет и т.п. Но отношение уже сформировалось. Вывод:</p>
<blockquote><p>
Господа из RBK Money!<br />
Наймите наконец юзабелиста. Денег вам, наверняка, хватит. Мой моск был порван вашим интерфейсом второй раз за день.
</p></blockquote>
<p>Перепробовав кучу вариантов я начал внимательно разглядывать мильон провайдеров на 2domains. И тут заметил кнопочку с простой надписью &laquo;Z-Payment&raquo;. Ну, думаю, была не была. И точно &#8211; там в списке есть &laquo;оплата банковской картой&raquo;. Причем нам было 3 таких варианта с разными комиссиями. Ура! Наконец то! Через этот вариант мне, наконец, удалось перевести свои 200р и оплатить домен.</p>
<p>В сухом остатке я потерял около 2х часов на <strong>тривиальную</strong> операцию. Интерфейсы большинства сайтов &laquo;электронных денег&raquo; находятся примерно на уровне доисторическом уровне, для их использования явно нужна уличная магия. И судя по всему, им это положение нравится. Пора что-то делать, господа!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2011/02/23/domain-extending/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Пропустил Google Developer Day</title>
		<link>http://www.kurdyukov.com/2009/11/11/google-developer-day-missed/</link>
		<comments>http://www.kurdyukov.com/2009/11/11/google-developer-day-missed/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 07:54:44 +0000</pubDate>
		<dc:creator>alik</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.kurdyukov.com/?p=116</guid>
		<description><![CDATA[Вчера в Москве проходил Google Developer Day. На который я не попал, поскольку не знал об этом мероприятии. Так и не нашел способа узнавать о таких событиях своевременно. А вы знаете такой способ?]]></description>
			<content:encoded><![CDATA[<p>Вчера в Москве проходил Google Developer Day. На который я не попал, поскольку не знал об этом мероприятии. Так и не нашел способа узнавать о таких событиях своевременно. А вы знаете такой способ?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurdyukov.com/2009/11/11/google-developer-day-missed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

