<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_hans.hu</title><subtitle type="text">夫天地者，万物之逆旅也；光阴者，百代之过客也。而浮生若梦，为欢几何？古人秉烛夜游，良有以也。况阳春召我以烟景，大块假我以文章。</subtitle><id>http://feed.cnblogs.com/blog/u/54224/rss</id><updated>2011-06-16T14:22:28Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/54224/rss"/><entry><id>http://www.cnblogs.com/huyh/archive/2011/06/16/2083112.html</id><title type="text">Event Broker: 通过发布事件源和订阅事件源来完成对象之间的协作</title><summary type="text">在实际应用中，我们可以使用EventBroker来进行发布和订阅事件通知以实现对象间的通信。</summary><published>2011-06-16T13:52:00Z</published><updated>2011-06-16T13:52:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2011/06/16/2083112.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2011/06/16/2083112.html"/><content type="html">&lt;p&gt;在实际应用中，我们可以使用EventBroker来进行发布和订阅事件通知以实现对象间的通信。通常做法都会把EventBroker实现为单例模式，我们在项目里是通过MEF的使用实现了EventBroker的单例模式： &lt;/p&gt;  &lt;pre &gt;&lt;span style="color: #400080"&gt;public class &lt;/span&gt;&lt;span style="color: #305fb6"&gt;EventSubscriptionToken&#xD;
&lt;/span&gt;{&#xD;
    &lt;span style="color: #400080"&gt;private &lt;/span&gt;&lt;span style="color: #010001"&gt;EventSubscriptionToken&lt;/span&gt;(){}&#xD;
&#xD;
    &lt;span style="color: #400080"&gt;public static &lt;/span&gt;&lt;span style="color: #010001"&gt;EventSubscriptionToken GetNewToken&lt;/span&gt;()&#xD;
    {&#xD;
        &lt;span style="color: #400080"&gt;var &lt;/span&gt;&lt;span style="color: #010001"&gt;guid &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;= &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Guid&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;NewGuid&lt;/span&gt;()&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;ToString&lt;/span&gt;();&#xD;
        &lt;span style="color: #400080"&gt;var &lt;/span&gt;&lt;span style="color: #010001"&gt;token &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;= &lt;/span&gt;&lt;span style="color: #400080"&gt;new &lt;/span&gt;&lt;span style="color: #010001"&gt;EventSubscriptionToken &lt;/span&gt;{&lt;span style="color: #010001"&gt;Value &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;= &lt;/span&gt;&lt;span style="color: #010001"&gt;guid&lt;/span&gt;};&#xD;
        &lt;span style="color: #400080"&gt;return &lt;/span&gt;&lt;span style="color: #010001"&gt;token&lt;/span&gt;;&#xD;
    }&#xD;
    &lt;span style="color: #400080"&gt;public string &lt;/span&gt;&lt;span style="color: #010001"&gt;Value &lt;/span&gt;{ &lt;span style="color: #400080"&gt;get&lt;/span&gt;; &lt;span style="color: #400080"&gt;private set&lt;/span&gt;; }&#xD;
}&#xD;
&#xD;
&lt;span style="color: #400080"&gt;public interface &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IEventBroker&#xD;
&lt;/span&gt;{&#xD;
    &lt;span style="color: #400080"&gt;void &lt;/span&gt;&lt;span style="color: #010001"&gt;Publish&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color: #010001"&gt;T eventArgs&lt;/span&gt;);&#xD;
    &lt;span style="color: #010001"&gt;EventSubscriptionToken Subscribe&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #010001"&gt;callback&lt;/span&gt;);&#xD;
    &lt;span style="color: #400080"&gt;bool &lt;/span&gt;&lt;span style="color: #010001"&gt;Unsubscribe&lt;/span&gt;(&lt;span style="color: #010001"&gt;EventSubscriptionToken subscriptionToken&lt;/span&gt;);&#xD;
}&#xD;
&#xD;
[&lt;span style="color: #010001"&gt;Export&lt;/span&gt;(&lt;span style="color: #400080"&gt;typeof&lt;/span&gt;(&lt;span style="color: #010001"&gt;IEventBroker&lt;/span&gt;))]&#xD;
&lt;span style="color: #400080"&gt;public class &lt;/span&gt;&lt;span style="color: #305fb6"&gt;EventBroker &lt;/span&gt;: &lt;span style="color: #010001"&gt;IEventBroker&#xD;
&lt;/span&gt;{&#xD;
    &lt;span style="color: #400080"&gt;private readonly &lt;/span&gt;&lt;span style="color: #010001"&gt;IDictionary&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #400080"&gt;string&lt;/span&gt;, &lt;span style="color: #400080"&gt;object&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #010001"&gt;_callbacksDictionary&lt;/span&gt;;&#xD;
&#xD;
    [&lt;span style="color: #010001"&gt;ImportingConstructor&lt;/span&gt;]&#xD;
    &lt;span style="color: #400080"&gt;public &lt;/span&gt;&lt;span style="color: #010001"&gt;EventBroker&lt;/span&gt;()&#xD;
    {&#xD;
        &lt;span style="color: #010001"&gt;_callbacksDictionary &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;= &lt;/span&gt;&lt;span style="color: #400080"&gt;new &lt;/span&gt;&lt;span style="color: #010001"&gt;Dictionary&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #400080"&gt;string&lt;/span&gt;, &lt;span style="color: #400080"&gt;object&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;();&#xD;
    }&#xD;
&#xD;
    &lt;span style="color: #400080"&gt;public void &lt;/span&gt;&lt;span style="color: #010001"&gt;Publish&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color: #010001"&gt;T eventArgs&lt;/span&gt;)&#xD;
    {&#xD;
        &lt;span style="color: #400080"&gt;var &lt;/span&gt;&lt;span style="color: #010001"&gt;callbacksToBeInvoked &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;= &lt;/span&gt;&lt;span style="color: #010001"&gt;_callbacksDictionary&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Where&lt;/span&gt;(&lt;span style="color: #010001"&gt;x &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;=&amp;gt; &lt;/span&gt;&lt;span style="color: #010001"&gt;x&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Value &lt;/span&gt;&lt;span style="color: #400080"&gt;is &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;);&#xD;
        &lt;span style="color: #400080"&gt;foreach &lt;/span&gt;(&lt;span style="color: #400080"&gt;var &lt;/span&gt;&lt;span style="color: #010001"&gt;callback &lt;/span&gt;&lt;span style="color: #400080"&gt;in &lt;/span&gt;&lt;span style="color: #010001"&gt;callbacksToBeInvoked&lt;/span&gt;)&#xD;
        {&#xD;
            &lt;span style="color: #400080"&gt;var &lt;/span&gt;&lt;span style="color: #010001"&gt;actionCallback &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;= &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;)&lt;span style="color: #010001"&gt;callback&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Value&lt;/span&gt;;&#xD;
            &lt;span style="color: #400080"&gt;try&#xD;
            &lt;/span&gt;{&#xD;
                &lt;span style="color: #010001"&gt;actionCallback&lt;/span&gt;(&lt;span style="color: #010001"&gt;eventArgs&lt;/span&gt;);&#xD;
            }&#xD;
            &lt;span style="color: #400080"&gt;catch &lt;/span&gt;(&lt;span style="color: #305fb6"&gt;Exception&lt;/span&gt;)&#xD;
            { }&#xD;
        }&#xD;
    }&#xD;
&#xD;
    &lt;span style="color: #400080"&gt;public &lt;/span&gt;&lt;span style="color: #010001"&gt;EventSubscriptionToken Subscribe&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Action&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;T&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color: #010001"&gt;callback&lt;/span&gt;)&#xD;
    {&#xD;
        &lt;span style="color: #400080"&gt;var &lt;/span&gt;&lt;span style="color: #010001"&gt;token &lt;/span&gt;&lt;span style="color: #2e53d1"&gt;= &lt;/span&gt;&lt;span style="color: #010001"&gt;EventSubscriptionToken&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;GetNewToken&lt;/span&gt;();&#xD;
        &lt;span style="color: #010001"&gt;_callbacksDictionary&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Add&lt;/span&gt;(&lt;span style="color: #010001"&gt;token&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Value&lt;/span&gt;, &lt;span style="color: #010001"&gt;callback&lt;/span&gt;);&#xD;
        &lt;span style="color: #400080"&gt;return &lt;/span&gt;&lt;span style="color: #010001"&gt;token&lt;/span&gt;;&#xD;
    }&#xD;
&#xD;
    &lt;span style="color: #400080"&gt;public bool &lt;/span&gt;&lt;span style="color: #010001"&gt;Unsubscribe&lt;/span&gt;(&lt;span style="color: #010001"&gt;EventSubscriptionToken subscriptionToken&lt;/span&gt;)&#xD;
    {&#xD;
        &lt;span style="color: #400080"&gt;return &lt;/span&gt;&lt;span style="color: #010001"&gt;_callbacksDictionary&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Remove&lt;/span&gt;(&lt;span style="color: #010001"&gt;subscriptionToken&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Value&lt;/span&gt;);&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;事件的订阅实例：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span style="color: #010001"&gt;_eventBroker&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Subscribe&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #010001"&gt;ModelNameChangedEvent&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;&amp;gt;&lt;/span&gt;(&lt;span style="color: #010001"&gt;EntityChangedEventHandler&lt;/span&gt;);&#xD;
&lt;span style="color: #400080"&gt;private void &lt;/span&gt;&lt;span style="color: #010001"&gt;EntityChangedEventHandler&lt;/span&gt;(&lt;span style="color: #010001"&gt;ModelNameChangedEvent obj&lt;/span&gt;)&#xD;
{&#xD;
    &lt;span style="color: #2e53d1"&gt;...&#xD;
&lt;/span&gt;}&lt;/pre&gt;&#xD;
&lt;p&gt;事件的订阅者不需要知道事件是由哪个对象发布的，双方是通过参数进行交互，订阅者根据传入的参数对象进行相应的操作以完成对象间的协作。&lt;/p&gt;&#xD;
&lt;p&gt;事件的发布实例：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span style="color: #010001"&gt;_eventBroker&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Publish&lt;/span&gt;(&lt;span style="color: #400080"&gt;new &lt;/span&gt;&lt;span style="color: #010001"&gt;ModelNameChangedEvent&lt;/span&gt;(&lt;span style="color: #010001"&gt;entity&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;ID&lt;/span&gt;, &lt;span style="color: #010001"&gt;entity&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;SpaceType&lt;/span&gt;, &lt;span style="color: #010001"&gt;entity&lt;/span&gt;&lt;span style="color: #2e53d1"&gt;.&lt;/span&gt;&lt;span style="color: #010001"&gt;Name&lt;/span&gt;));   &lt;/pre&gt;&#xD;
&lt;p&gt;在需要交互时通过参数对象发布出事件。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/2083112.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2011/06/16/2083112.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/10/29/1864781.html</id><title type="text">趣味编程（一）</title><summary type="text">最近遇到的几个编程小实例。</summary><published>2010-10-29T13:51:00Z</published><updated>2010-10-29T13:51:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/10/29/1864781.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/10/29/1864781.html"/><content type="html">&lt;p&gt;1、需求：找出一个给定字符串中每个字符及其重复次数，同时获取出重复次数最多的字符。&lt;/p&gt;&lt;pre &gt;&lt;span style="color: #0a3d4c"&gt;public static &lt;/span&gt;&lt;span style="color: #360202"&gt;T MaxElement&amp;lt;T, TCompare&amp;gt;(&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;this &lt;/span&gt;&lt;span style="color: navy"&gt;IEnumerable&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;lt;T&amp;gt; collection, &lt;/span&gt;Func&lt;span style="color: #360202"&gt;&amp;lt;T, TCompare&amp;gt; func) &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;where &lt;/span&gt;&lt;span style="color: #360202"&gt;TCompare : &lt;/span&gt;&lt;span style="color: navy"&gt;IComparable&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;lt;TCompare&amp;gt;&#xD;
{&#xD;
    T maxItem = &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;default&lt;/span&gt;&lt;span style="color: #360202"&gt;(T);&#xD;
    TCompare maxValue = &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;default&lt;/span&gt;&lt;span style="color: #360202"&gt;(TCompare);&#xD;
    &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;foreach &lt;/span&gt;&lt;span style="color: #360202"&gt;(&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;var &lt;/span&gt;&lt;span style="color: #360202"&gt;item &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;in &lt;/span&gt;&lt;span style="color: #360202"&gt;collection) {&#xD;
        TCompare temp = func(item);&#xD;
        &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;if &lt;/span&gt;&lt;span style="color: #360202"&gt;(maxItem == &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;null &lt;/span&gt;&lt;span style="color: #360202"&gt;|| temp.CompareTo(maxValue) &amp;gt; &lt;/span&gt;&lt;span style="color: #1a4c0a"&gt;0&lt;/span&gt;&lt;span style="color: #360202"&gt;) {&#xD;
            maxValue = temp;&#xD;
            maxItem = item;&#xD;
        }&#xD;
    }&#xD;
    &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;return &lt;/span&gt;&lt;span style="color: #360202"&gt;maxItem;&#xD;
}&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre &gt;&lt;span style="color: #0a3d4c"&gt;string &lt;/span&gt;&lt;span style="color: #360202"&gt;findStr = &lt;/span&gt;&lt;span style="color: #0a4c0b"&gt;"Beijing"&lt;/span&gt;&lt;span style="color: #360202"&gt;;&#xD;
&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;var &lt;/span&gt;&lt;span style="color: #360202"&gt;rm = findStr.ToCharArray().GroupBy(c =&amp;gt; c).Select(g =&amp;gt; &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;new &lt;/span&gt;&lt;span style="color: #360202"&gt;{ g.Key, Count = g.Count() }).MaxElement(r =&amp;gt; r.Count);&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;2、需求：生成不重复的随机数并排序。&lt;/p&gt;&lt;pre &gt;&lt;span style="color: #0a3d4c"&gt;public static &lt;/span&gt;&lt;span style="color: navy"&gt;IList&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;gt; GetRandoms(&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int &lt;/span&gt;&lt;span style="color: #360202"&gt;min, &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int &lt;/span&gt;&lt;span style="color: #360202"&gt;max, &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int &lt;/span&gt;&lt;span style="color: #360202"&gt;length)&#xD;
{&#xD;
    &lt;/span&gt;&lt;span style="color: navy"&gt;IList&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;gt; rlist = &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;new &lt;/span&gt;&lt;span style="color: #560051"&gt;List&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;gt;();&#xD;
    &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int &lt;/span&gt;&lt;span style="color: #360202"&gt;index = &lt;/span&gt;&lt;span style="color: #1a4c0a"&gt;1&lt;/span&gt;&lt;span style="color: #360202"&gt;;&#xD;
    &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int &lt;/span&gt;&lt;span style="color: #360202"&gt;seed = &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;new &lt;/span&gt;&lt;span style="color: #560051"&gt;Random&lt;/span&gt;&lt;span style="color: #360202"&gt;().Next();&#xD;
    &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;while &lt;/span&gt;&lt;span style="color: #360202"&gt;(index &amp;lt; length) {&#xD;
        &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;var &lt;/span&gt;&lt;span style="color: #360202"&gt;random = &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;new &lt;/span&gt;&lt;span style="color: #560051"&gt;Random&lt;/span&gt;&lt;span style="color: #360202"&gt;(seed++).Next(min, max);&#xD;
        &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;if &lt;/span&gt;&lt;span style="color: #360202"&gt;(!rlist.Contains(random))&#xD;
            rlist.Add(random);&#xD;
        index = rlist.Count();&#xD;
        &lt;/span&gt;&lt;span style="color: #560051"&gt;Console&lt;/span&gt;&lt;span style="color: #360202"&gt;.WriteLine(index);&#xD;
    }&#xD;
&#xD;
    &lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;return &lt;/span&gt;&lt;span style="color: #360202"&gt;rlist;&#xD;
}&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre &gt;&lt;span style="color: #560051"&gt;List&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #0a3d4c"&gt;int&lt;/span&gt;&lt;span style="color: #360202"&gt;&amp;gt; rlist = GetRandoms(&lt;/span&gt;&lt;span style="color: #1a4c0a"&gt;10&lt;/span&gt;&lt;span style="color: #360202"&gt;, &lt;/span&gt;&lt;span style="color: #1a4c0a"&gt;99&lt;/span&gt;&lt;span style="color: #360202"&gt;, &lt;/span&gt;&lt;span style="color: #1a4c0a"&gt;20&lt;/span&gt;&lt;span style="color: #360202"&gt;).ToList();&#xD;
rlist.Sort((x, y) =&amp;gt; &lt;/span&gt;&lt;span style="color: #560051"&gt;Math&lt;/span&gt;&lt;span style="color: #360202"&gt;.Sign(x - y));&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1864781.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/10/29/1864781.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/10/14/1850970.html</id><title type="text">折半查找的递归算法</title><summary type="text">递归算法就是把问题转化为规模较小的同类问题，然后递归调用函数来解决问题。</summary><published>2010-10-14T01:38:00Z</published><updated>2010-10-14T01:38:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/10/14/1850970.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/10/14/1850970.html"/><content type="html">&lt;p&gt;递归算法就是把问题转化为规模较小的同类问题，然后递归调用函数来解决问题。递归算法的关键在于：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;递归就是在过程中不断调用自身；  &lt;li&gt;需要提供一个明确的结束条件； &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;为了方便起见，我用javascript实现折半查找的递归算法，其他编程语言类似： &lt;/p&gt;&lt;pre &gt;&lt;span style="color: blue"&gt;function &lt;/span&gt;&lt;span style="color: #360202"&gt;binarySearch(list,find)&#xD;
    {&#xD;
        &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #360202"&gt;search(0,list.length-1,list,find);&#xD;
    }&#xD;
    &#xD;
    &lt;/span&gt;&lt;span style="color: blue"&gt;function &lt;/span&gt;&lt;span style="color: #360202"&gt;search(start,end,list,find)&#xD;
    {&#xD;
        &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt;&lt;span style="color: #360202"&gt;(start&amp;lt;=end)&#xD;
        {&#xD;
            &lt;/span&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;&lt;span style="color: #360202"&gt;index = Math.floor((start+end)/2);&#xD;
            &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt;&lt;span style="color: #360202"&gt;(list[index] == find)&#xD;
                &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #360202"&gt;index;&#xD;
            &lt;/span&gt;&lt;span style="color: blue"&gt;else if&lt;/span&gt;&lt;span style="color: #360202"&gt;(find&amp;gt;list[index])&#xD;
                &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #360202"&gt;search(index+1,end,list,find);&#xD;
            &lt;/span&gt;&lt;span style="color: blue"&gt;else if&lt;/span&gt;&lt;span style="color: #360202"&gt;(find&amp;lt;=list[index])&#xD;
                &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #360202"&gt;search(start,index-1,list,find);&#xD;
            &lt;/span&gt;&lt;span style="color: blue"&gt;else&#xD;
            &lt;/span&gt;&lt;span style="color: #360202"&gt;{&#xD;
                &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #360202"&gt;-1;&#xD;
            }                &#xD;
        }&#xD;
        &lt;/span&gt;&lt;span style="color: blue"&gt;else&#xD;
            return &lt;/span&gt;&lt;span style="color: #360202"&gt;-1;&#xD;
    }&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1850970.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/10/14/1850970.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/10/03/1841717.html</id><title type="text">BlackBerry 9520上结合139邮箱实现Gmail邮件的短信通知</title><summary type="text">在BlackBerry 9520上结合139邮箱实现Gmail邮件到达的短信通知。</summary><published>2010-10-03T12:37:00Z</published><updated>2010-10-03T12:37:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/10/03/1841717.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/10/03/1841717.html"/><content type="html">&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="BlackBerry" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/BlackBerry9520139_10F36/image_thumb_2.png" width="518" height="440"&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1841717.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/10/03/1841717.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/09/24/1834147.html</id><title type="text">一个项目的初步想法</title><summary type="text">近日计划开发一个人事管理系统，针对需求提出一些初步想法。</summary><published>2010-09-24T13:59:00Z</published><updated>2010-09-24T13:59:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/09/24/1834147.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/09/24/1834147.html"/><content type="html">&lt;p&gt;近日计划开发一个人事管理系统，该系统目的简言之就是对机关、企事业单位人员调动情况进行管理。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;一、需求概述&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;从项目需求书中可以得知本系统需要包含六大模块，概述如下：&lt;/p&gt; &lt;table style="border-bottom: gray 2px dashed; border-left: gray 2px dashed; border-collapse: collapse; border-top: gray 2px dashed; border-right: gray 2px dashed" border="1" width="886"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="456"&gt; &lt;ol&gt; &lt;li&gt;系统设置 - 包含四部分：用户管理、单位区域设置、单位性质设置、选项维护  &lt;li&gt;单位管理 - 负责单位信息的维护  &lt;li&gt;调动录入 - 第一步：分为调入和调出；第二步：分为单人调动和整体划转。在人员调动录入完成之后，应该能打印出《调动审批卡片》  &lt;li&gt;调动审批 - 经领导签字后的调动材料，需要在系统录入其审批时间  &lt;li&gt;查询导出 - 根据查询条件导出为Excel表格  &lt;li&gt;系统备份 - 对系统数据进行备份和恢复 &lt;/li&gt;&lt;/ol&gt;&lt;/td&gt; &lt;td valign="top" width="427"&gt; &lt;ul&gt; &lt;li&gt;以下采取用例图的方式展示出来:&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/a8d07be75956_116B9/image_thumb.png" width="235" height="260"&gt; &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;strong&gt;二、整体架构&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;考虑到该系统的使用情况，我计划采用C/S架构来实现该人事管理系统：&lt;/p&gt; &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/a8d07be75956_116B9/image_thumb_2.png" width="375" height="339"&gt;&lt;/p&gt; &lt;p&gt;下面是我的一些原始想法：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;对于ORM操作方面，可以使用ADO.NET Entity Framework，EF的设计在很多地方保留了高度扩展性。在此基础之上，开发期间我计划采用SQL Server Compact Edition进行开发测试；  &lt;li&gt;采用仓储模式，根据单一职责原则SRP，利用分散的类对数据访问进行封装；  &lt;li&gt;用户权限方面 - 考虑到本系统的用户使用情况，客户目前并没有复杂的权限设置需求，所以我认为下面的设计就可以满足现阶段需求：  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/a8d07be75956_116B9/image_thumb_1.png" width="244" height="60"&gt; &lt;/p&gt; &lt;li&gt;对其中一些关键操作、异常情况进行日志记录，以备查询使用；  &lt;li&gt;使用xUnit/Moq进行单元测试；  &lt;li&gt;采用Common Service Locator对IoC容器进行抽象； &lt;/li&gt;&lt;/ol&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1834147.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/09/24/1834147.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/09/19/1830952.html</id><title type="text">[转载]痛而不言是一种智慧，笑而不语是一种豁达</title><summary type="text">在抓虾上看到这篇文章《痛而不言是一种智慧，笑而不语是一种豁达》，写得很有智慧。</summary><published>2010-09-19T05:19:00Z</published><updated>2010-09-19T05:19:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/09/19/1830952.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/09/19/1830952.html"/><content type="html">&lt;p&gt;痛而不言是一种智慧。人生在世，往往会因这样或那样的伤害而心痛不已。罗素曾说过，累累伤痕是生命给你的最好礼物。 &lt;/p&gt; &lt;p&gt;与其喋喋抱怨，不如静下深思，流年似水，灼痛终将沉淀为一种经历，成为躲藏在灵魂深处的暗夜精灵。与其怒形于色，不如痛过之后，轻轻拭去眼角的残泪，用灿烂的笑脸遮藏明媚的忧伤，将暗涌深藏，再一脸阳光重新投入忙碌的生活。正是这些刻骨铭心的痛让我们懂得了珍惜生活，珍惜身边的人。  &lt;p&gt;笑而不语是一种豁达。朋友之间的戏虐，遭人误解后的无奈，这时，过多的言辞申辩反让人觉得华而不实，莫不如留下一抹微笑，任他人作评。所谓君子坦荡荡，小人常戚戚。  &lt;p&gt;有时一个微笑可以让两个宿怨之人冰释前嫌，可以让身居他乡之人倍感温暖。世界上最简单的动作完美的诠释了人世间最复杂的道理。  &lt;p&gt;笑而不言留给人们更多遐想的空间，犹如蒙娜丽莎嘴角那抹淡淡的微笑，散发出来的魅力，让世人为之作出无数猜想，一个平凡的女人因为不平凡的微笑而感动了无数人，而世界也因此多了一份神秘美。  &lt;p&gt;痛而不言是一种智慧，笑而不语是一种豁达。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;转自&amp;lt;&lt;a href="http://www.mrleochen.com/?p=1290"&gt;痛而不言是一种智慧，笑而不语是一种豁达&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1830952.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/09/19/1830952.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/09/14/1825543.html</id><title type="text">《UML和模式应用》读书笔记（二）</title><summary type="text">《UML和模式应用》最后几部分章节侧重于通过示例展现相关UML和模式的具体应用。</summary><published>2010-09-14T00:18:00Z</published><updated>2010-09-14T00:18:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/09/14/1825543.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/09/14/1825543.html"/><content type="html">&lt;p&gt;&lt;strong&gt;第四部分 细化迭代2 更多模式&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1、在熟练使用UP的项目中，为早期迭代所选择的需求,是根据风险和高业务价值组织的,这样就能够尽早识别并解决高风险问题。&lt;/p&gt; &lt;p&gt;2、最后四个GRASP模式：&lt;/p&gt; &lt;p&gt;&lt;strong&gt;多态（Polymorphism）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;当相关选择或行为随类型（类）有所不同时，使用多态操作为变化的行为类型分配职责。不要测试对象的类型，也不要使用条件逻辑来执行基于类型的不同选择。&lt;/p&gt; &lt;p&gt;除非在超类中具有默认的行为，否则将超类中的多态方法声明为{abstract}。&lt;/p&gt; &lt;p&gt;多态意味着在大部分OO语言中要使用抽象超类或接口。何时应该考虑使用接口呢？普遍的答案是，当你想要支持多态但是又不想约束于特定的类层次结构时，可以使用接口。如果使用了抽象超类AC而不是接口，那么任何新的多态方案都必须是AC的子类，这对于诸如Java和C#的单根继承语言来说将十分局限。经验的做法是：如果有一个具有抽象超类C1的类层次结构，可以考虑对应于C1中的公共方法特征标记来定义接口I1，然后声明C1来实现接口I1。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;间接性（Indirection）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;将职责分配给中介对象，使其作为其他构件或服务之间的媒介，以避免它们之间的直接耦合。中介实现了其他构件之间的间接性（indirection）。&lt;/p&gt; &lt;p&gt;“计算机科学中的大多数问题都可以通过增加一层间接性来解决”，这一格言特别适用于面向对象设计。 &lt;/p&gt; &lt;p&gt;&lt;strong&gt;纯虚构（Pure Fabrication）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;对人为制造的类分配一组高内聚的职责，该类并不代表问题领域的概念-虚构的事物，用以支持高内聚、低耦合和复用。&lt;font color="#ff0000"&gt;注：通常作为辅助类/帮助类使用。&lt;/font&gt;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;防止变异（Protected Variation）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;识别预计变化或不稳定之处，分配职责用以在这些变化之外创建稳定接口。 &lt;/p&gt; &lt;p&gt;&lt;em&gt;幸运将会出现在规划之后。 -布兰奇.瑞基(Branch Rickey)&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;第五部分 细化迭代3 中级主题&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1、一个UML活动图表示一个过程中的多个顺序活动和并行活动。这些活动图有助于对业务过程、工作流、数据流和复杂算法进行建模。&lt;/p&gt; &lt;p&gt;基本的UML活动图表示法包括：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;动作（action）- 它完成某些事物。在其完成时存在一个自动转换。  &lt;li&gt;分区（partition）- 表示参加过程的不同参与者。  &lt;li&gt;分叉点（fork）- 一个输入转换，以及多个输出的并行转换或对象流。  &lt;li&gt;连接点（join）- 多个输入转换或对象流，一个输出变换，其输出直到所有输入都到达时才发生。  &lt;li&gt;对象节点（object node）- 由动作产生或使用的对象，这允许我们对数据流或对象流进行建模。&lt;/li&gt;&#xD;
&lt;li&gt;决策（decision）- 互斥发生的任何分支。&lt;/li&gt;&lt;li&gt;合并（merge）- 任何输入的延续。&lt;/li&gt;&#xD;
&lt;/ul&gt; &lt;p&gt;2、在活动图建模方面，有下面一些准则：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;活动图通常对于涉及众多参与者的非常复杂的业务过程建模具有价值。对于简单的业务过程，用例文本就够用了。  &lt;li&gt;在进行业务过程建模时，可以利用耙子（rake）符号和子活动图。  &lt;li&gt;与上一条相关的是，尽量保持同一张图中所有动作节点的抽象水平一致。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;3、同活动图一样，UML状态图是动态视图。UML包含了可用来描述事物（事务、用例和人等）的事件和状态的表示法。UML状态机图（state machine diagram）描述了某个对象的状态和感兴趣的事件以及对象响应该事件的行为。转换（transition）用标记有事件的箭头表示。状态（state）用圆角的矩形表示。通常的做法是会包含一个初始伪状态，当实例创建时，自动从初始伪状态转换到另外一个状态。 &lt;/p&gt; &lt;p&gt;4、状态图显示了对象的生命周期：对象经历的事件、对象的转换和对象在这些事件之间的状态。状态图不必描述所有可能的事件；如果所发生的事件未在图中表示，则说明其不影响该状态机图所关注的内容。&lt;/p&gt; &lt;p&gt;5、用例彼此之间可能具有联系：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;包含关系 - 多个用例中存在部分相同的行为，与其重复文本描述，不如将这部分交互行为分离为单独的子功能用例，并适用包含关系加以指示。Fowler给出了何时使用包含关系的简单且实用的准则：当在两个或多个独立用例中存在重复，而你想避免这种冗余时，可以使用包含关系。  &lt;li&gt;扩展关系 - 创建扩展或附加用例，并且在其中描述：在何处和何种条件下该用例扩展某基础用例的行为。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;6、架构分析的本质是要识别影响架构的因素，理解这些因素的可变性和优先级，并且解决这些问题。其难点是要知道应该问什么样的问题，权衡利弊和了解处理一个重要架构因素的各种办法。&lt;/p&gt; &lt;p&gt;7、架构分析（architectural analysis）是在功能性需求的语境中，识别和处理系统非功能性需求的活动。&lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;注：详细阅读第36、37章中的示例，肯定会有很大收获。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;书中示例：NextGen POS &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1、需求之一是，当远程服务访问失败时（例如当产品数据库（暂时）无法访问时），得到某种程度的恢复。&lt;/p&gt; &lt;p&gt;使用适配器和工厂模式能够间接地实现这一特性：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;ServiceFactory总是返回本地产品信息服务的适配器。  &lt;li&gt;本地产品“适配器”并不会真正地适配其他构件，它将自己负责实现本地服务。  &lt;li&gt;使用实际的远程产品服务适配器的引用来初始化本地服务。  &lt;li&gt;如果本地服务在缓存中找到数据，就将数据返回；否则，将请求转发给外部服务。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/c009683b65c8_12FF0/lt_2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="lt" border="0" alt="lt" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/c009683b65c8_12FF0/lt_thumb.png" width="635" height="279"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;对于产品信息服务的初始化：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/c009683b65c8_12FF0/ct_4.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="ct" border="0" alt="ct" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/c009683b65c8_12FF0/ct_thumb_1.png" width="550" height="269"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;2、通过代理（GoF）使用本地服务进行容错&lt;/p&gt; &lt;p&gt;通过在外部服务的前端添加本地服务，实现了产品信息的本地服务容错；使用中总是优先尝试本地服务。但是，此设计方案并不是对所有的服务都适用。有时需要先尝试外部服务，然后才是本地服务。例如，在帐务服务中记录销售。在业务上希望这一过程越快越好，以便能够实时地追踪商店和终端的活动。&lt;/p&gt; &lt;p&gt;在此情形下，GoF的代理（Proxy）模式可以解决这个问题。NextGen案例中使用的代理是重定向代理（Redirection Proxy）变体，该代理也称为冗错代理（Failover Proxy）。&lt;/p&gt; &lt;p&gt;代理只不过是与被代理对象实现相同接口的对象，它保存指向被代理对象的引用，并且用于控制对被代理对象的访问。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/c009683b65c8_12FF0/proxy_2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="proxy" border="0" alt="proxy" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/c009683b65c8_12FF0/proxy_thumb.png" width="803" height="430"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;第六部分 其他主题&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1、有很多种方法可以计划一次迭代，下面是较典型的方法：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一步应确定迭代的时间长度；常见的时间长度为2~6周。一般来说，短一些较好。延长迭代周期的因素包括在早期工作中有较多发现和变化、较大的开发团队以及分布式开发。迭代的结束时间一旦确定，就不应改变-这是时间定量的实践。但是，可以通过减少本次迭代的工作范围来满足该结束时间。  &lt;li&gt;第二步是召集迭代计划会议。这通常在上一次迭代完成（例如星期五）而下一次迭代（例如星期一）尚未开始时进行。在理想情况下，主要涉众都应该参加：顾客（营销人员、最终用户）、开发者、首席架构师和项目经理等。  &lt;li&gt;列出本次迭代的潜在目标（新特性或者用例、缺陷等），并标记优先级。目标列表通常由客户（业务目标）和首席架构师（技术目标）共同确定。  &lt;li&gt;团队的每个成员应为本次迭代编制个人自愿预算（以消失或天为单位），所有的资源预算应当被汇总起来。  &lt;li&gt;对于某一目标（例如一个用例），在计划中对其进行较为详细的描述，并分解其对应的问题。接着，参加会议的人（特别是开发人员）对与目标相关的一组更详细的任务进行头脑风暴式的讨论，并形成粗略估计。  &lt;li&gt;反复进行第五步直到确定了足够多的工作：迭代阶段的总任务应该与总的资源预算相匹配。在指定的资源预算和时间定量最终期限的限制之下，如果工作量基本匹配，则可以结束会议。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;2、迭代开发的重要思想之一就是根据反馈不断改进，而不是试图详细预测和计划整个项目。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1825543.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/09/14/1825543.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/09/12/1824611.html</id><title type="text">《UML和模式应用》读书笔记（一）</title><summary type="text">08年看了收获不多，近日看完该书最后几章节颇有收益，故记录下来。</summary><published>2010-09-12T14:50:00Z</published><updated>2010-09-12T14:50:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/09/12/1824611.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/09/12/1824611.html"/><content type="html">&lt;p&gt;&lt;strong&gt;第一部分 绪论&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1、在OO开发中，至关重要的能力是熟练地为软件对象分配职责；&lt;font color="#ff0000"&gt;个人认为将对象进行抽象的能力也相当重要。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;2、分析(analysis)强调的是对问题和需求的调查研究，而不是解决方案；设计(design)强调的是满足需求的概念上的解决方案(在软件方面和硬件方面)，而不是其实现。&lt;/p&gt; &lt;p&gt;有益的分析和设计可以概括为：做正确的事（分析）和正确地做事（设计）。&lt;/p&gt; &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="xl" border="0" alt="xl" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/UML_C77F/xl_thumb_1.png" width="459" height="44"&gt;&lt;/p&gt; &lt;p&gt;3、需求分析可能包括人们如何使用应用的情节或场景，这些情节或场景可以被编写成用例（use case）。&lt;/p&gt; &lt;p&gt;4、面向对象分析关注从对象的角度创建领域描述，面向对象分析需要鉴别重要的概念、属性和关联。面向对象分析的结果可以表示为领域模型，在领域模型中展示重要的领域概念或对象。&lt;/p&gt; &lt;p&gt;5、面向对象设计关注软件对象的定义-它们的职责和协作。&lt;/p&gt; &lt;p&gt;6、与领域模型表示的是真实世界的类，设计类图表示的是软件类。&lt;/p&gt; &lt;p&gt;7、敏捷建模（agile modeling）强调了UML作为草图的方式，这也是适用UML的普通方式，而且通常对时间投入具有高回报（一般费时较短）。&lt;/p&gt; &lt;p&gt;8、迭代开发（iterative development）是UP和大多数其他现代方法中的关键实践。在这种生命周期方法中，开发被组织成一系列固定的短期（如三个星期）小项目，称为迭代（iteration），每次迭代都产生经过测试、集成并可执行的局部系统。每次迭代都具有各自的需求分析、设计、实现和测试活动。&lt;/p&gt; &lt;p&gt;9、迭代开发的优点包括：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;减少项目失败可能性，提高生产率，降低缺陷率。  &lt;li&gt;在早期缓解高风险（技术、需求、目标、可用性等等）。  &lt;li&gt;早期可见的进展。  &lt;li&gt;早期反馈、用户参与和调整，会产生更接近涉众真实需求的精化系统。  &lt;li&gt;可控复杂性；团队不会被“分析瘫痪”或长期且复杂的步骤所淹没。  &lt;li&gt;一次迭代中的经验可以被系统地用于改进开发过程本身，并如此反复进行下去。 &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;10、在复杂、变更系统中（如大多数软件项目），反馈和调整是成功的关键要素。&lt;/p&gt; &lt;p&gt;11、如何进行迭代和进化式分析和设计：&lt;/p&gt; &lt;p&gt;1）在第1次迭代之前，召开第一个时间定量的需求工作会议，例如确切地定义为两天时间，业务和开发人员（包括首席架构师）需要出席。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;在第一天上午，进行高阶需求分析，例如仅仅确定用例和特性的名称，以及关键的非功能性需求。这种分析不可能是完美的。  &lt;li&gt;通过咨询首席架构师和业务人员，从高阶列表中选择10%列表项，这些项目具备以下三种性质：1，具有重要的架构意义；2，具有高业务价值；3，具有高风险。  &lt;li&gt;在剩下的一天半内，对这三个用例的功能和非功能性需求进行详细的分析。完成这一过程后，对10%进行了深入分析，90%进行了高阶分析。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;2）在第1次迭代之前，召开迭代计划会议，选择上述三种用例的子集，在特定时间内（例如，四周的时间定量迭代）进行设计、构造和测试。&lt;/p&gt; &lt;p&gt;3）在三到四周内完成第1次迭代（选择时间定量，并严格遵守时间）：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;在开始的两天内，开发者和其他成员分组进行建模和设计工作，在首席架构师的带领和指导下，于“公共作战室”的众多白板上，画出UML的草图（及其他的模型）。  &lt;li&gt;然后，开发者摘掉其“建模帽子”并戴上“编程帽子”，开始编程、测试和集成工作并且剩余的时间均用于完成这项工作。  &lt;li&gt;进行大量的测试，包括单元测试、验收测试、负载测试和可用性测试等。  &lt;li&gt;在结束前的一周，检查是否能够完成初始的迭代目标；如果不能，则缩小迭代的范围，将次要目标置回任务列表中。  &lt;li&gt;在最后一周的星期二，冻结代码。必须检入、集成和测试所有代码，以建立迭代的基线。  &lt;li&gt;在星期三的上午，向外部涉众演示此局部系统，展示早期可视进展，同时要求反馈。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;4）在第1次迭代即将结束时（如最后一周的星期三和星期四），召开第二次需求工作会，对上一次会议的所有材料进行复查和精化，然后选择具有重要架构意义和高业务价值的另外10%到15%的用例，用一到两天对其进行详细分析。&lt;/p&gt; &lt;p&gt;5）于周五上午，举行下一迭代的迭代计划会议。&lt;/p&gt; &lt;p&gt;6）以相同步骤进行第2次迭代。&lt;/p&gt; &lt;p&gt;7）反复进行四次迭代和五次需求工作会，这样在第4次迭代结束时，可能已经详细记录了大约80%-90%的需求。&lt;/p&gt; &lt;p&gt;8）我们大概推进了整个项目过程的20%。此时，可以估计这些精化的、高质量的需求所需工作量和时间。因为具有依据现实得出的调查、反馈结论并进行了早期编程和测试，因此估计能够做什么和需要多长时间的结果会更为可靠。&lt;/p&gt; &lt;p&gt;9）此后，一般不需要再召开需求工作会；需求已经稳定了（尽管需求永远不会被冻结）。接下来是一系列为期三周的迭代，在最后一个周五召开的迭代计划会上选择适宜的下一步工作，每次迭代都要反复询问：“就我们现在所知，下一个三周应该完成的、最关键的技术和业务特性是什么？”&lt;/p&gt; &lt;p&gt;利用这种方式，经过早期探索式开发的几次迭代之后，团队将能够更准确地回答“什么、多少、何时”。&lt;/p&gt; &lt;p&gt;12、建模（构建UML草图……）的目的主要是为理解，而非文档。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;第二部分 初始阶段&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1、用一句话来概括初始阶段：预见项目的范围、设想和业务案例。用一句话来概括初始阶段要解决的主要问题：涉众是否就项目设想基本达成一致，项目是否值得继续进行认真研究。&lt;/p&gt; &lt;p&gt;2、需求分析的最大挑战是寻找、沟通和记住（通常是指记录）什么是真正需要的，并能够清楚地讲解给客户和开发团队的成员。&lt;/p&gt; &lt;p&gt;3、在统一过程中，需求按照“FURPS+”模型进行分类，这是一种有效的记忆方法，其含义如下：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;功能性（Funcational）：特性、功能、安全性。  &lt;li&gt;可用性（Usability）：人性化因素、帮助、文档。  &lt;li&gt;可靠性（Reliability）：故障频率、可恢复性、可预测性。  &lt;li&gt;性能（Performance）：响应时间、吞吐量、准确性、有效性、资源利用率。  &lt;li&gt;可支持性（Supportability）：适用性、可维护性、国际化、可配制性。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;”FURPS+“中的”+“是指一些辅助性的和次要的因素，比如：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;实现（Implementation）：资源闲置、语言和工具、硬件等。  &lt;li&gt;接口（Interface）：强加于外部系统接口之上的约束。  &lt;li&gt;操作（Operation）：对其操作设置的系统管理。  &lt;li&gt;包装（Packaging）：例如无力的包装盒。  &lt;li&gt;授权（Legal）：许可证或其他方式。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;em&gt;若想从生活中得到什么，必不可少的第一步就是：决定想要什么。 -本。斯坦(Ben Stein)&lt;/em&gt;&lt;/p&gt; &lt;p&gt;4、用例是文本形式的情节描述，广泛应用于需求的发现和记录工作中。&lt;/p&gt; &lt;p&gt;5、用例是一种优秀的方法，使领域专家或需求提供者自己编写（或参与编写）用例成为可能，并使这项工作难度降低。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;第三部分 细化迭代1 基础&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;1、细化（elaboration）是一般项目中最初的一系列迭代，其中包括：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;对核心、有风险的软件架构进行编程和测试。  &lt;li&gt;发现并稳定需求的主体部分。  &lt;li&gt;规避主要风险。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;font color="#000000" face="Georgia"&gt;细化阶段是最初的一系列迭代，在这一阶段，小组进行细致的调查、实现（编程和测试）核心架构、澄清大多数需求和应对高风险问题。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;2、在细化阶段可能出现的一些关键思想和最佳实践包括：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;实行短时间定量、风险驱动的迭代。  &lt;li&gt;及早开始编程。  &lt;li&gt;对架构的核心和风险部分进行适应性的设计、实现和测试。  &lt;li&gt;尽早、频繁、实际地测试。  &lt;li&gt;基于来自测试、用户、开发者的反馈进行调整。  &lt;li&gt;通过一系列讨论会，详细编写大部分用例和其他需求，每个细化迭代举行一次。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;3、通过关联而不是属性来表示概念类之间的关系。&lt;/p&gt; &lt;p&gt;4、没有所谓唯一正确的领域模型。所有模型都是对我们试图要理解的领域的近似。领域模型主要是在特定群体中用于理解和沟通的工具。&lt;/p&gt; &lt;p&gt;5、在同一层内的对象在职责上应该具有紧密关联，不同层中对象的职责则不应该混淆。&lt;/p&gt; &lt;p&gt;6、需要哪些对象，它们如何通过消息和方法进行协作，通过动态对象建模（例如绘制顺序图）才能真正落实这些准确和详细的结论。&lt;/p&gt; &lt;p&gt;7、应该把时间花费在交互图（顺序图或通信图），而不仅是类图上。&lt;/p&gt; &lt;p&gt;8、任何顺序图都可以使用sd图框围绕起来，并对其命名。当你想要引用相应名字的sd图框时，可以使用ref图框。&lt;/p&gt; &lt;p&gt;9、在类图中，使用依赖线描述对象之间的全局变量、参数变量、局部变量和静态方法（对其他类的静态方法加以调用）的依赖。&lt;/p&gt; &lt;p&gt;10、GRASP是通用职责分配软件模式（General Responsibility Assignment Software Patterns）的缩写。GRASP的9个模式如下所示：&lt;/p&gt; &lt;p&gt;&lt;strong&gt;创建者（Creator）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;如果以下的条件之一（越多越好）为真时，将创建类A实例的职责分配给类B：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;B“包含”或组成聚集A。  &lt;li&gt;B记录A。  &lt;li&gt;B直接使用A。  &lt;li&gt;B具有A的初始化数据，并且在创建A时会将这些数据传递给A。因此对于A的创建而言，B是专家。  &lt;li&gt;B是对象A的创建者。 &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;注意：对象的创建常常具有相当的复杂性，这时最好的方法是把创建职责委派给称为具体工厂（Concrete Factory）或抽象工厂（Abstract Factory）的辅助类，而不是使用创建者模式所建议的类。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;信息专家（Information Expert）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;把职责分配给信息专家，它具有实现这个职责所必需的信息。分配职责应当从清晰地描述职责开始。&lt;/p&gt; &lt;p&gt;注意：由于耦合与内聚问题导致某些情况下，专家模式建议的方案并不合适。 &lt;/p&gt; &lt;p&gt;&lt;strong&gt;低耦合（Low Coupling）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;分配职责，使耦合性尽可能低。利用这一原则来评估可选方案。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;控制器（Controller）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;控制器是UI层之上的第一个对象，它负责接收和处理系统操作消息。&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;高内聚（High Cohesion）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;内聚（或更为专业地说，是功能内聚）是对元素职责的相关性和集中度的度量。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;多态性（Polymorphism）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;纯虚构（Pure Fabrication）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;间接性（Indirection）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;防止变异（Protected Variations）&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1824611.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/09/12/1824611.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/06/18/1760399.html</id><title type="text">行为驱动开发之道</title><summary type="text">介绍了行为驱动开发(Behavior Driven Development)常用的两个框架:SpecUnit与MSpec。</summary><published>2010-06-18T08:22:00Z</published><updated>2010-06-18T08:22:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/06/18/1760399.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/06/18/1760399.html"/><content type="html">&lt;p&gt;用Context/Specification风格编写单元测试，可以使用一种更加自然的方式反映出用户故事、客户需求。BDD更为注重从需求的角度将测试用例分为若干关注点Concerns，在类的层次上把Context, Action和Observations抽象到不同的方法中，从而可以很好的应用Arrange, Act, Assert模式进行单元测试的编写。&lt;/p&gt; &lt;p&gt;&lt;em&gt;The core principles of BDD are: &lt;/em&gt; &lt;ul&gt; &lt;li&gt;&lt;em&gt;Expressing behaviour in terms that show the value to the system actors &lt;/em&gt; &lt;li&gt;&lt;em&gt;Expressing behaviours / scenarios in a format that clearly separates the context, the action and the observations &lt;/em&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;为了阐述方便，先看下面这个TDD风格的测试用例(&lt;a href="http://www.cnblogs.com/huyh/archive/2010/06/14/1758143.html" target="_blank"&gt;上篇文章&lt;/a&gt;中的测试用例)：&lt;pre &gt;[&lt;span style="color: #2b91af"&gt;Test&lt;/span&gt;]&#xD;
&lt;span style="color: blue"&gt;public void &lt;/span&gt;TestRetrieveOrders() {&#xD;
    &lt;span style="color: green"&gt;// arrange&#xD;
    &lt;/span&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;mockView = &lt;span style="color: #2b91af"&gt;MockRepository&lt;/span&gt;.GenerateMock&amp;lt;&lt;span style="color: #2b91af"&gt;IOrdersView&lt;/span&gt;&amp;gt;();&#xD;
    &lt;span style="color: blue"&gt;var &lt;/span&gt;mockRepository = &lt;span style="color: #2b91af"&gt;MockRepository&lt;/span&gt;.GenerateStub&amp;lt;&lt;span style="color: #2b91af"&gt;IRepository&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt;&amp;gt;();&#xD;
&#xD;
    &lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; defaultOrders = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; { &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"moq"&lt;/span&gt;), &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"RhinoMock"&lt;/span&gt;) };&#xD;
&#xD;
    mockRepository.Stub(ir =&amp;gt; ir.FindAll()).Return(defaultOrders);&#xD;
    &lt;span style="color: blue"&gt;var &lt;/span&gt;presenter = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;OrdersPresenter&lt;/span&gt;(mockView, mockRepository);&#xD;
    &lt;span style="color: green"&gt;// act&#xD;
    &lt;/span&gt;presenter.OnInit();&#xD;
    &lt;span style="color: green"&gt;// assert&#xD;
    &lt;/span&gt;mockView.AssertWasCalled(v =&amp;gt; v.Orders = defaultOrders);&#xD;
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;这是平时很常见的书写测试用例的传统方法，下面我将使用介绍的BDD框架进行重写，以实现Context/Specifications风格的单元测试。将上述测试代码以Context/Specifications方式表示出来，如下所示：&amp;nbsp; &lt;p&gt;&lt;em&gt;&lt;strong&gt;Concern&lt;/strong&gt;: Orders retrieve &lt;/em&gt;&#xD;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Context&lt;/strong&gt;: when initializing the presentation &lt;/em&gt;&#xD;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Observation&lt;/strong&gt;: should retrieve all the orders&lt;/em&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;SpecUnit.Net&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;基于.NET单元测试框架NUnit提供了BDD风格的语法。简单来说就是将初始化、执行代码部分抽象出来封装进ContextSpecification，然后在子类具体实现其中的Context, Because方法(&lt;a href="http://www.dofactory.com/Patterns/PatternTemplate.aspx" target="_blank"&gt;Template Method&lt;/a&gt;)，从而在一个测试类中很好的实现了Context, Action和Observation的分离：&lt;/p&gt;&lt;pre id="collapse_634124662683105000" &gt;&lt;a onclick="document.getElementById('expand_634124662683105000').style.display='block';document.getElementById('collapse_634124662683105000').style.display='none';" href="javascript:void(0);"&gt;展开&lt;/a&gt;&lt;/pre&gt;&lt;pre style="display: none" id="expand_634124662683105000" &gt;&lt;a onclick="document.getElementById('collapse_634124662683105000').style.display='block';document.getElementById('expand_634124662683105000').style.display='none';" href="javascript:void(0);"&gt;折叠&lt;/a&gt;&#xD;
&#xD;
&lt;span style="color: blue"&gt;public abstract class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ContextSpecification&#xD;
&lt;/span&gt;{&#xD;
    [&lt;span style="color: #2b91af"&gt;SetUp&lt;/span&gt;]&#xD;
    &lt;span style="color: blue"&gt;public void &lt;/span&gt;SetUp() {&#xD;
        Context();&#xD;
        Because();&#xD;
    }&#xD;
&#xD;
    &lt;span style="color: blue"&gt;protected virtual void &lt;/span&gt;Context() { }&#xD;
    &lt;span style="color: blue"&gt;protected virtual void &lt;/span&gt;Because() { }&#xD;
}&lt;/pre&gt;&#xD;
&lt;p&gt;现在我们用SpecUnit来实现BDD风格的单元测试：&lt;/p&gt;&lt;pre &gt;[&lt;span style="color: #2b91af"&gt;Concern&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Orders retrieve"&lt;/span&gt;)]&#xD;
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;when_initializing_the_presentation &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ContextSpecification&#xD;
&lt;/span&gt;{&#xD;
    &lt;span style="color: blue"&gt;protected &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IOrdersView &lt;/span&gt;_view;&#xD;
    &lt;span style="color: blue"&gt;protected &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IRepository&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; _repository;&#xD;
    &lt;span style="color: blue"&gt;protected &lt;/span&gt;&lt;span style="color: #2b91af"&gt;OrdersPresenter &lt;/span&gt;_presenter;&#xD;
    &lt;span style="color: green"&gt;// mocking orders&#xD;
    &lt;/span&gt;&lt;span style="color: blue"&gt;protected readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; DefaultOrders = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; { &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"moq"&lt;/span&gt;), &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"RhinoMock"&lt;/span&gt;) };&#xD;
    &lt;span style="color: green"&gt;// arrange&#xD;
    &lt;/span&gt;&lt;span style="color: blue"&gt;protected override void &lt;/span&gt;Context() {&#xD;
        _view = &lt;span style="color: #2b91af"&gt;MockRepository&lt;/span&gt;.GenerateMock&amp;lt;&lt;span style="color: #2b91af"&gt;IOrdersView&lt;/span&gt;&amp;gt;();&#xD;
        _repository = &lt;span style="color: #2b91af"&gt;MockRepository&lt;/span&gt;.GenerateStub&amp;lt;&lt;span style="color: #2b91af"&gt;IRepository&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt;&amp;gt;();&#xD;
        _repository.Stub(ir =&amp;gt; ir.FindAll()).Return(DefaultOrders);&#xD;
        _presenter = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;OrdersPresenter&lt;/span&gt;(_view, _repository);&#xD;
    }      &#xD;
    &lt;span style="color: green"&gt;// act&#xD;
    &lt;/span&gt;&lt;span style="color: blue"&gt;protected override void &lt;/span&gt;Because() {&#xD;
        _presenter.OnInit();&#xD;
    }&#xD;
    &lt;span style="color: green"&gt;// assert&#xD;
    &lt;/span&gt;[&lt;span style="color: #2b91af"&gt;Observation&lt;/span&gt;]&#xD;
    &lt;span style="color: blue"&gt;public void &lt;/span&gt;should_retrieve_all_the_orders() {&#xD;
        _view.AssertWasCalled(v =&amp;gt; v.Orders = DefaultOrders);&#xD;
    }&#xD;
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;其中Concern标示出本次测试的关注点，class标示出Context，表示了我们的一个测试用例；Because包含的是我们需要进行测试的行为，是具体的执行逻辑，而用Observation标记出来的方法代表了Specifications，表示我们期望得到的结果；另外，我们可以看到上述例子的类名、方法名都是自解释的，可以很容易明白所需要测试的内容。 &lt;/p&gt;&#xD;
&lt;p&gt;在实际开发过程中会经常碰到多个Context重用相同的行为测试，显然可以通过继承的方式以达到行为重用的目的。&amp;nbsp; &lt;p&gt;此外SpecUnit.Net自带一个工具可以使用它来生成测试报告页面，直观的看到最后的测试结果：SpecUnit.Report.exe &amp;lt;assembly name&amp;gt; &#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/MachineSpecifications_14541/specunit_4.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="specunit" border="0" alt="specunit" src="http://images.cnblogs.com/cnblogs_com/huyh/WindowsLiveWriter/MachineSpecifications_14541/specunit_thumb_1.png" width="244" height="55"&gt;&lt;/a&gt; &#xD;
&lt;p&gt;&lt;strong&gt;Machine.Specifications(MSpec)&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Aaron Jensen受到SpecUnit与RSpec的灵感启发而开发出来的。MSpec利用委托和匿名方法定义了以下几个委托：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Establish:&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;进行Context(Class)里的初始化工作 &#xD;
&lt;li&gt;一个Context(Class)里至多只有一个Establish &#xD;
&lt;li&gt;运行于Because之前&lt;/li&gt;&lt;/ul&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Because:&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;需要测试的行为 &#xD;
&lt;li&gt;一个Context(Class)里只能有一个Because&lt;/li&gt;&lt;/ul&gt;&#xD;
&lt;p&gt;&lt;strong&gt;It:&lt;/strong&gt; &lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;测试期望得到的结果 &#xD;
&lt;li&gt;一个Context(Class)里可以有多个It委托 &#xD;
&lt;li&gt;运行在Because之后&lt;/li&gt;&lt;/ul&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Behaves_like:&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;封装好的、可重用的行为&lt;/li&gt;&lt;/ul&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Cleanup:&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;Context(Class)里执行TearDown的工作 &#xD;
&lt;li&gt;运行于It委托之后&lt;/li&gt;&lt;/ul&gt;&#xD;
&lt;p&gt;这些委托是我们编写MSpec测试代码时经常需要用到的：&lt;/p&gt;&lt;pre &gt;&lt;span style="color: blue"&gt;namespace &lt;/span&gt;Machine.Specifications&#xD;
{&#xD;
  &lt;span style="color: blue"&gt;public delegate void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Establish&lt;/span&gt;();&#xD;
&#xD;
  &lt;span style="color: blue"&gt;public delegate void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Because&lt;/span&gt;();&#xD;
&#xD;
  &lt;span style="color: blue"&gt;public delegate void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;It&lt;/span&gt;();&#xD;
  &lt;span style="color: blue"&gt;public delegate void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Behaves_like&lt;/span&gt;&amp;lt;TBehavior&amp;gt;();&#xD;
&#xD;
  &lt;span style="color: blue"&gt;public delegate void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Cleanup&lt;/span&gt;();&#xD;
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;上述测试例子的相应MSpec写法如下：&lt;/p&gt;&lt;pre &gt;[&lt;span style="color: #2b91af"&gt;Subject&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Orders retrieve"&lt;/span&gt;)]&#xD;
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;when_initializing_the_presentation&#xD;
&lt;/span&gt;{&#xD;
    &lt;span style="color: blue"&gt;protected static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IOrdersView &lt;/span&gt;_view;&#xD;
    &lt;span style="color: blue"&gt;protected static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IRepository&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; _repository;&#xD;
    &lt;span style="color: blue"&gt;protected static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;OrdersPresenter &lt;/span&gt;_presenter;&#xD;
    &lt;span style="color: green"&gt;// mocking orders&#xD;
    &lt;/span&gt;&lt;span style="color: blue"&gt;protected static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; DefaultOrders = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt; { &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"moq"&lt;/span&gt;), &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"RhinoMock"&lt;/span&gt;) };&#xD;
    &lt;span style="color: green"&gt;// arrange&#xD;
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Establish &lt;/span&gt;context = () =&amp;gt; {&#xD;
        _view = &lt;span style="color: #2b91af"&gt;MockRepository&lt;/span&gt;.GenerateMock&amp;lt;&lt;span style="color: #2b91af"&gt;IOrdersView&lt;/span&gt;&amp;gt;();&#xD;
        _repository = &lt;span style="color: #2b91af"&gt;MockRepository&lt;/span&gt;.GenerateStub&amp;lt;&lt;span style="color: #2b91af"&gt;IRepository&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order&lt;/span&gt;&amp;gt;&amp;gt;();&#xD;
        _repository.Stub(ir =&amp;gt; ir.FindAll()).Return(DefaultOrders);&#xD;
        _presenter = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;OrdersPresenter&lt;/span&gt;(_view, _repository);  &#xD;
    };&#xD;
    &lt;span style="color: green"&gt;// act&#xD;
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Because &lt;/span&gt;of = ()=&amp;gt; _presenter.OnInit();&#xD;
    &lt;span style="color: green"&gt;// assert&#xD;
    &lt;/span&gt;&lt;span style="color: #2b91af"&gt;It &lt;/span&gt;should_retrieve_all_the_orders = () =&amp;gt; _view.AssertWasCalled(v =&amp;gt; v.Orders = DefaultOrders);&#xD;
}&#xD;
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;注意到这个例子，由于Context中的匿名方法需要访问_view, _repository等字段，所以其中的所有字段必须都是static。&lt;/p&gt;&#xD;
&lt;p&gt;为了可以将同样的行为应用到多个Context里，MSpec提供了[Behaviors]以达到重用的目的：&lt;/p&gt;&lt;pre &gt;[&lt;span style="color: #2b91af"&gt;Behaviors&lt;/span&gt;]&#xD;
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTimeParsingBehavior&#xD;
&lt;/span&gt;{&#xD;
  &lt;span style="color: blue"&gt;protected static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTime &lt;/span&gt;ParsedDate;&#xD;
&#xD;
  &lt;span style="color: #2b91af"&gt;It &lt;/span&gt;should_parse_the_expected_date = () =&amp;gt; ParsedDate.ShouldEqual(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;(2009, 1, 21));&#xD;
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;这样我们就可以在多个Context里使用该Behavior：&lt;/p&gt;&lt;pre id="collapse_634124702469430000" &gt;&lt;a onclick="document.getElementById('expand_634124702469430000').style.display='block';document.getElementById('collapse_634124702469430000').style.display='none';" href="javascript:void(0);"&gt;展开&lt;/a&gt;&lt;/pre&gt;&lt;pre style="display: none" id="expand_634124702469430000" &gt;&lt;a onclick="document.getElementById('collapse_634124702469430000').style.display='block';document.getElementById('expand_634124702469430000').style.display='none';" href="javascript:void(0);"&gt;折叠&lt;/a&gt;&#xD;
&#xD;
[&lt;span style="color: #2b91af"&gt;Subject&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Date time parsing"&lt;/span&gt;)]&#xD;
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;when_a_date_is_parsed_with_the_regular_expression_parser &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;DateTimeParsingSpecs&#xD;
&lt;/span&gt;{&#xD;
  &lt;span style="color: #2b91af"&gt;Establish &lt;/span&gt;context = () =&amp;gt; { Parser = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RegexParser&lt;/span&gt;(); };&#xD;
&#xD;
  &lt;span style="color: #2b91af"&gt;Because &lt;/span&gt;of = () =&amp;gt; { ParsedDate = Parser.Parse(&lt;span style="color: #a31515"&gt;"2009/01/21"&lt;/span&gt;); };&#xD;
&#xD;
  &lt;span style="color: #2b91af"&gt;Behaves_like&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;DateTimeParsingBehavior&lt;/span&gt;&amp;gt; a_date_time_parser;&#xD;
}&#xD;
&#xD;
[&lt;span style="color: #2b91af"&gt;Subject&lt;/span&gt;(&lt;span style="color: #a31515"&gt;"Date time parsing"&lt;/span&gt;)]&#xD;
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;when_a_date_is_parsed_by_the_infrastructure &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;DateTimeParsingSpecs&#xD;
&lt;/span&gt;{&#xD;
  &lt;span style="color: #2b91af"&gt;Establish &lt;/span&gt;context = () =&amp;gt; { Parser = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;InfrastructureParser&lt;/span&gt;(); };&#xD;
&#xD;
  &lt;span style="color: #2b91af"&gt;Because &lt;/span&gt;of = () =&amp;gt; { ParsedDate = Parser.Parse(&lt;span style="color: #a31515"&gt;"2009/01/21"&lt;/span&gt;); };&#xD;
&#xD;
  &lt;span style="color: #2b91af"&gt;Behaves_like&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;DateTimeParsingBehavior&lt;/span&gt;&amp;gt; a_date_time_parser;&#xD;
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;同样，Machine.Specifications.Console.exe可以生成最后的测试报告页面。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;xUnit BDD Extensions&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;随着使用xUnit测试框架的流行，有许多人希望可以基于xUnit构建自己的BDD单元测试用例，其中xUnit.Samples中就有很不错的例子，大家有兴趣可以下载看看，这里就不再详细解释。 &lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Conclusion：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在.NET世界里常见的BDD框架还有：NBehave, NSpec等，目的都是以贴近自然语言的方式描述软件系统的行为过程。与TDD相比，BDD更侧重于从客户的角度来表达需求，方便需求方与实现方的交流与沟通。而从开发人员角度看，BDD相比TDD在组织测试代码的结构上有很大不同。&lt;/p&gt;&#xD;
&lt;p&gt;下面列出SpecUnit与MSpec的主要特点：&lt;/p&gt;&#xD;
&lt;table style="border-bottom: gray 2px dashed; text-align: center; border-left: gray 2px dashed; border-collapse: collapse; border-top: gray 2px dashed; border-right: gray 2px dashed" border="1" width="500"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;th valign="top" width="110"&gt;&amp;nbsp;&lt;/th&gt;&#xD;
&lt;th valign="top" width="155"&gt;TDD&lt;/th&gt;&#xD;
&lt;th valign="top" width="115"&gt;MSpec&lt;/th&gt;&#xD;
&lt;th valign="top" width="119"&gt;SpecUnit&lt;/th&gt;&lt;/tr&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="110"&gt;[Category]&lt;/td&gt;&#xD;
&lt;td valign="top" width="155"&gt;[Category]&lt;/td&gt;&#xD;
&lt;td valign="top" width="115"&gt;[Subject]&lt;/td&gt;&#xD;
&lt;td valign="top" width="119"&gt;[Concern]&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="110"&gt;Arrange&lt;/td&gt;&#xD;
&lt;td valign="top" width="155"&gt;SetUp/TestFixtureSetUp&lt;/td&gt;&#xD;
&lt;td valign="top" width="115"&gt;Establish&lt;/td&gt;&#xD;
&lt;td valign="top" width="119"&gt;Context&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="110"&gt;Act&lt;/td&gt;&#xD;
&lt;td valign="top" width="155"&gt;Run code under test&lt;/td&gt;&#xD;
&lt;td valign="top" width="115"&gt;Because&lt;/td&gt;&#xD;
&lt;td valign="top" width="119"&gt;Because&lt;/td&gt;&lt;/tr&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="110"&gt;Assert&lt;/td&gt;&#xD;
&lt;td valign="top" width="155"&gt;[Test]&lt;/td&gt;&#xD;
&lt;td valign="top" width="115"&gt;It&lt;/td&gt;&#xD;
&lt;td valign="top" width="119"&gt;[Observation]&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
&lt;li&gt;&lt;a href="http://github.com/machine/machine.specifications" target="_blank"&gt;machine.specifications - GitHub&lt;/a&gt; &#xD;
&lt;li&gt;&lt;a href="http://code.google.com/p/specunit-net/" target="_blank"&gt;specunit-net - Google Code&lt;/a&gt; &#xD;
&lt;li&gt;&lt;a href="http://elegantcode.com/2010/03/01/an-evolution-of-test-specification-styles-my-journey-to-mspec/" target="_blank"&gt;An Evolution of Test-Specification Styles – My Journey to MSpec&lt;/a&gt;&#xD;
&lt;li&gt;&lt;a href="http://elegantcode.com/2010/02/26/behaviors-with-mspec/" target="_blank"&gt;Behaviors with MSpec&lt;/a&gt; &#xD;
&lt;li&gt;&lt;a href="http://www.lostechies.com/blogs/sean_chambers/archive/2008/12/07/starting-with-bdd-vs-starting-with-tdd.aspx" target="_blank"&gt;Starting with BDD vs. starting with TDD&lt;/a&gt; &#xD;
&lt;li&gt;&lt;a href="http://www.skimedic.com/blog/category/MSpec.aspx" target="_blank"&gt;Test Driven Requirements with MSpec&lt;/a&gt; &lt;/li&gt;&lt;/ol&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1760399.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/06/18/1760399.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/huyh/archive/2010/06/15/1758509.html</id><title type="text">Dependency Injection Frameworks</title><summary type="text">本人前一段时间整理好的、目前比较常用的IoC容器，在此做个记录以供日后参考使用。</summary><published>2010-06-15T01:01:00Z</published><updated>2010-06-15T01:01:00Z</updated><author><name>hans.hu</name><uri>http://www.cnblogs.com/huyh/</uri></author><link rel="alternate" href="http://www.cnblogs.com/huyh/archive/2010/06/15/1758509.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/huyh/archive/2010/06/15/1758509.html"/><content type="html">&lt;p&gt;Inversion of control, or IoC, is an abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to procedural programming. Dependency injection is the main method to implement Inversion of Control.&lt;/p&gt; &lt;p&gt;&lt;em&gt;Manually injected dependency&lt;br&gt;Framework-managed dependency&lt;br&gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;There are several frameworks available to further automate this process, allowing a complete delegation of instantiation and marshalling of such dependencies to a "meta-factory", often called a Container or Injector.&lt;/p&gt; &lt;p&gt;Dependency injection is a prime technique for building loosely coupled applications. It provides ways to handle the dependencies between objects.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;一、&lt;a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=unity" target="_blank"&gt;Unity&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The Unity Application Block (Unity) is a lightweight extensible dependency injection container with support for constructor, property, and method call injection. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;二、&lt;a href="http://code.google.com/p/autofac/" target="_blank"&gt;Autofac&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Autofac is a fresh approach to IoC in .NET that utilises modern C#.&lt;/p&gt; &lt;p&gt;Autofac was designed with modern .NET features and obsessive object-orientation in mind. It will change the way you approach dependency injection in .NET. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;三、&lt;a href="http://ninject.org/" target="_blank"&gt;Ninject&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;lightning-fast dependency injection for .net&lt;/p&gt; &lt;p&gt;Ninject helps you use the technique of &lt;em&gt;dependency injection&lt;/em&gt; to break your applications into &lt;em&gt;loosely-coupled, highly-cohesive&lt;/em&gt; components, and then glue them back together in a flexible manner. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;四、&lt;a href="http://mef.codeplex.com/" target="_blank"&gt;Managed Extensibility Framework&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The Managed Extensiblility Framework (MEF) is a new library in .NET that enables greater reuse of applications and components. Using MEF, .NET application can make the shift from being statically compiled to dynamically composed. If you are building extensible applications, extensible frameworks and application extensions, then MEF is for you.&lt;/p&gt; &lt;p&gt;The MEF simplifies the creation of extensible applications. MEF offers discovery and composition capabilities that you can leverage to load application extensions. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;五、&lt;a href="http://www.castleproject.org/" target="_blank"&gt;Castle MicroKernel/Windsor&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Castle Project offers two Inversion of Control Containers. The MicroKernel and the Windsor Container. Their documentation are kept together as the Windsor Container just augments the MicroKernel functionality. &lt;/p&gt; &lt;p&gt;The Castle MicroKernel is an inversion of control container that was designed towards extensibility.&lt;/p&gt; &lt;p&gt;Castle Windsor aggregates the MicroKernel and exposes a powerful configuration support. It is suitable for common enterprise application needs. It is able to register facilities and components based on the configuration and adds support for interceptors. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;六、&lt;a href="http://code.google.com/p/hiro/" target="_blank"&gt;Hiro&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Hiro is an IOC container compiler (currently in development) that will support the following features:&lt;/p&gt; &lt;p&gt;&lt;em&gt;Blazingly fast,Statically precompiled,Tiny,Supports Constructor and Property Injection&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;七、&lt;a href="http://code.google.com/p/linfu/" target="_blank"&gt;LinFu&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The LinFu Framework is a set of libraries that extend the CLR by adding the following language features:&lt;/p&gt; &lt;p&gt;&lt;em&gt;Aspect-Oriented Programming,Dynamic Proxies,Late Binding,Mixins,Universal Event Handling,Closures with Lambda Arguments,Duck Typing,Design by Contract&lt;/em&gt; &lt;/p&gt;&lt;font color="#333333" face="Verdana"&gt;&lt;/font&gt; &lt;p&gt;&lt;strong&gt;八、&lt;a href="http://funq.codeplex.com/" target="_blank"&gt;Funq&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This project provides a high performance DI framework by eliminating all runtime reflection through the use of lambdas and generic functions as factories.&lt;br&gt;Developed entirely in C# using TDD, it's a container you can crack open and actually understand to the core.  &lt;p&gt;&lt;strong&gt;九、&lt;a href="http://structuremap.github.com/structuremap/index.html" target="_blank"&gt;StructureMap&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;StructureMap is a Dependency Injection / Inversion of Control tool for .Net that can be used to improve the architectural qualities of an object oriented system by reducing the mechanical costs of good design techniques. StructureMap can enable looser coupling between classes and their dependencies, improve the testability of a class structure, and provide generic flexibility mechanisms. Used judiciously, StructureMap can greatly enhance the opportunities for code reuse by minimizing direct coupling between classes and configuration mechanisms.  &lt;p&gt;&lt;strong&gt;Comments&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;These information of the foregoing IoC frameworks are sorted out from the internet. In the following months, I plan to work on a serial posts about forementioned IoC containers to illustrate their usages.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;Dependency injection - Wikipedia, the free encyclopedia&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.picocontainer.org/"&gt;PicoContainer - What is PicoContainer? &lt;/li&gt;&lt;/ol&gt;&lt;img src="http://www.cnblogs.com/huyh/aggbug/1758509.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/huyh/archive/2010/06/15/1758509.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
