首先說明這裡的代碼複用指的是狹義的源代碼的複用,而不是廣義的黑盒複用和白合複用所指的代碼複用,是以文中所說的代碼複用都預設都是指前者所指的源代碼的複用。
我們知道在程式設計中複用代碼并不是一件容易的事情,其實每段代碼的編寫,都是通過一定的思考的,當然考慮的程度與其解決的問題的難度有關。我們很忌諱在一個工程中重複使用相同的源代碼,如果出現這樣的情況很多時候就是程式結構設計本身的不合理了。可是對于一個developer或一個product
team,源代碼的邏輯(主要是執行邏輯,而不是業務邏輯)在不同項目或同一項目不同版本中很可能需要複用,而這種複用很多時候又是很難抽象成廣義的代碼複用的。于是我們不得不ctrl+c
&
ctrl+v,這是一個好辦法,也确實能為我們節省很多的時間,可是這樣同時也會帶來很多的問題。如果被複用的代碼是近期所寫的,我們一般對其很熟悉,ctrl+v時心理也很有底。可是對于編寫了很久的代碼,我們在ctrl+v就不得不考慮一下代碼是不時完全合适被複用了。更多的時候我們還需要對複用代碼做一些小的修改,最簡單的修改莫過于把變量名改來适合目前代碼的上下文。
今天在用VS.NET 2005的時候,發現tools菜單裡有一個Code Snippets
Manager(或者用Ctrl+k,Ctrl+b呼出)。打開看了一下,第一感覺就是一個代碼模版管理嘛,看看了些預置的snippet,居然都是些很簡單的類似if語句結構、for語句結構、do語句結構、while語句結構等,覺得真是沒有意思,難道微軟要我們用滑鼠來程式設計嗎?繼續往後翻,發現了幾個比較複雜的snippets,有的有一屏那麼多的代碼。其實代碼多少不是snippet的重要的問題了,而是這些snippet在插入IDE後,可以根據其在檔案裡的指令定義,産生如下圖所示的自動添補提示功能:
在圖中黃底黑字區域内編輯完後按Tab,其下面的虛線框裡的内容會同步的更新。這樣的功能為我們收集并複用源代碼提供了很便利的支援,這個snippet是以xml格式儲存的,隻是whidbey
beta1裡面還沒沒有提供snippet檔案的可視化編輯器,不過xml本身在VS.NET裡也不難寫。上圖示例的代碼檔案如下:
#region CodeSnippet
<CodeSnippet Format="1.0.0">
<Header>
<Title>"named" iterator / indexer pair</Title>
<Shortcut>iterindex</Shortcut>
<Description>Implement a "named" iterator / indexer pair, using a nested class</Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<Default>ElementType</Default>
<ToolTip>Type to return from iterator / indexer</ToolTip>
</Literal>
<ID>name</ID>
<Default>MyView</Default>
<ToolTip>Name of the iterator/indexer pair</ToolTip>
<Literal Editable="false">
<ID>outer</ID>
<Default>MyOuterClass</Default>
<Function>ClassName()</Function>
<ID>SystemCollectionsGenericIEnumeratorG</ID>
<!-- Function>ShortName(System.IEnumerator)</Function -->
<Default>System.Collections.Generic.IEnumerator</Default>
<ID>SystemNotImplementedException</ID>
<!-- Function>ShortName(System.NotImplementedException)</Function -->
<Default>System.NotImplementedException</Default>
</Declarations>
<Code Language="csharp" Format="CData"><![CDATA[public $name$Impl $name$
{
get
{
return new $name$Impl(this);
}
}
public class $name$Impl
readonly $outer$ _outer;
internal $name$Impl($outer$ mc)
this._outer = mc;
// A Length property isn't required, but it's often useful.
public int Length { get { return 1; } }
public $type$ this[int index]
get
{
//
// TODO: implement indexer here
// you have full access to $outer$ privates.
$end$throw new System.NotImplementedException();
return default($type$);
}
public $SystemCollectionsGenericIEnumeratorG$<$type$> GetEnumerator()
// TODO: provide an appropriate implementation here
for (int i = 0; i < this.Length; i++)
{
yield return this[i];
}]]>
</Code>
</Snippet>
</CodeSnippet>
#endregion
有了這個snippet的管理支援和友善的使用方法後,基本就解決了我前面提到源代碼複用裡面版本控制和變量名修改的問題。
其實這個snippet的使用還有一個積極的意義,我們知道編寫相同的邏輯過程是枯燥的,我們都喜歡編寫新的邏輯過程,即使新的邏輯更難更複雜,反而更有挑戰。但是我們又不能避開很多程式邏輯的複用,在我們以一種類似"厭惡"的情緒重複着那些程式邏輯時,保證代碼的正确性真是一場噩夢
。
本文轉自部落格園鳥食軒的部落格,原文連結:http://www.cnblogs.com/birdshome/,如需轉載請自行聯系原部落客。