星期日, 12月 31, 2006

Agile Software Development相關教學

WebCasts

  • Test-Driven Development in Microsoft .NET (James Newkirk, Alexei Vorontsov)
  • Test-Driven Development, by Example (Kent Beck)
  • Test-Driven Development, A Pratical Guide (David Astels)
  • Unit Testing in Java (Johannes Link)

網站

Blogs

星期一, 12月 25, 2006

顯示容易看的MSBuild Log

若要在Dashboard上顯示容易看的MSBuild Log,只要在「C:\Program Files\CruiseControl.NET\webdashboard\dashboard.config」中加上以下設定即可

<xslreportbuildplugin description="MSBuild Details" actionname="MSBuildDetailsBuildReport" xslfilename="xsl\msbuild.xsl"/>

星期四, 12月 07, 2006

實作Equals method以及equality operator需遵守的規則

MSDN上提到:

The following rules outline the guidelines for implementing the Equals method and the equality operator (==):


  1. Implement the GetHashCode method whenever you implement the Equals method. This keeps Equals and GetHashCode synchronized.


  2. Override the Equals method whenever you implement the equality operator (==), and make them do the same thing. This allows infrastructure code such as Hashtable and ArrayList, which use the Equals method, to behave the same way as user code written using the equality operator.


  3. Override the Equals method any time you implement the IComparable Interface.


  4. Consider implementing operator overloading for the equality (==), not equal (!=), less than (<), and greater than (>) operators when you implement IComparable.


  5. Do not throw exceptions from the Equals or GetHashCode methods or the equality operator (==).

有空再來探討其背後的原因

Java與C#的string equal與==

根據陈叙远的世界


java:
String s1 = "abc";
String s2 = new String("abc");
String s3 = "a" + "bc";
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));

System.out.println(s1 == s2);
System.out.println(s1 == s3);

c#:
String s1 = "abc";
String s2 = new String(new char[] {'a', 'b', 'c'});
String s3 = "a" + "bc";

Console.WriteLine(s1.Equals(s2));
Console.WriteLine(s1.Equals(s3));

Console.WriteLine(s1 == s2);
Console.WriteLine(s1 == s3);

运行结果是:
java:
true
true
false
true

c#:
true
true
true
true


星期二, 12月 05, 2006

Excel如何做到類似SQL select功能?

  1. 先利用MATCH巨集確認符合條件的資料的順位, 如 =MATCH(F6,$A$1:$A$150,0)
  2. 利用=INDIRECT("B" & A6) 取用相關資料

轉換Pukiwiki到Trac wiki

暫時找不到好的解決方案, 先採用下列Ultraedit macro來轉換

InsertMode
ColumnModeOff
HexOff
UnixReOn
Top
Find RegExp "^\*\*\*\s*(.*)$"
Replace All "=== \1 ==="
Find RegExp "^\*\*\s*(.*)$"
Replace All "== \1 =="
Find RegExp "^\*\s*(.*)$"
Replace All "= \1 ="
Find RegExp "^---\s"
Replace All " * "
Find RegExp "^--\s"
Replace All " * "
Find RegExp "^-\s"
Replace All " * "
Find RegExp "\[#........\]"
Replace All ""
Find RegExp "\[\[(.+)\]\]"
Replace All "[wiki:\1]"
Find "|"
Replace All "||"
Find RegExp "~$"
Replace All "[[br]]"

星期四, 11月 30, 2006

修改subversion log訊息

TortoiseSVN有提供修改log訊息的功能:

若你很興奮地改了log訊息想存回,會得到以下回應:
解決方法為:
到subversion repository的hooks目錄中,新增或編輯一個名為pre-revprop-change的檔案,內容改為

#!/bin/sh
exit 0
即可,不過為了安全起見,改完後沒事還是把他還原成不能隨意更動log的狀態比較好

透過reflection取用array元素


for (int idx = 0; idx < myarray.Count; idx++)
{
object item = myarray[idx];
}

如何透過reflection做到上述功能?方法如下:

int count = (int)myarray.GetType().GetProperty("Count").GetValue(myarray, null);
for (int idx = 0; idx < count; idx++)
{
object item = myarray.GetType().GetProperty("Item").GetValue(myarray, new object[] { idx }
);

星期三, 11月 29, 2006

透過reflection機制初始化Field物件

一般來說,初始化Field必須要在定義時做,如:

class TestClass{
private static StringBuilder sb = new StringBuilder();
private static StringBuilder sb2 = new StringBuilder();
}

如果需要三不五時重設這些Field,可能會加上如下的Method:


class TestClass{
private static StringBuilder sb = new StringBuilder();
private static StringBuilder sb2 = new StringBuilder();
public static void ReInit(){
sb = new StringBuilder();
sb2 = new StringBuilder();
}
}

如果之後又有sb3, sb4, ....., sbn,那麼每加一個都得記得去修改ReInit()。不但不方便,還可能忘記。可能的解決方法是利用.NET Reflection機制,查出有哪些Field,然後再根據Field的型別去建立物件。以下範例示範初始化所有static fields (假設所有類別都有不含參數的constructor):


FieldInfo[] fs = typeof(TestClass).GetFields(BindingFlags.Static | BindingFlags.NonPublic);
foreach (FieldInfo f in fs)
{
if (f.IsStatic)
{
object obj = f.FieldType.Assembly.CreateInstance(f.FieldType.FullName);
f.SetValue(null, obj);
}
}

程式範例過大時自動產生捲軸

根據Ove Klykken的Post:
將程式碼用

<div class="scroll">  
void main(.....
</div>

包起來。然後搭配以下CSS:
div.scroll { 
/* height: 200px; 指定高度*/
width: 90%;
overflow: auto;
border: 1px solid #eee;
/* background-color: #ccc; 指定背景顏色*/
padding: 8px;
word-wrap: normal; /* 指定code不要自動換行 */
}

星期二, 11月 28, 2006

CruiseControl中設定程式環境變數

情境:同一個環境變數,但在不同的Project中需有不同的設定
解決方法:撰寫.bat檔案,在裡面設定環境變數

例如

<cruisecontrol>
<project name="MyProject">
<triggers>ooxxooxx</triggers>
<sourcecontrol>ooxxooxx</sourcecontrol>

<tasks>
<msbuild>ooxxooxx</msbuild>

<exec>
<executable>myexec.bat</executable>
</exec>

<nunit>
<path>nunit-console.bat</path>
<assemblies><assembly>ox.dll</assembly></assemblies>
</nunit>
</tasks>

</project>
</cruisecontrol>



其中myexec.bat的內容可能是:
set MyVar=ooxx
myProg.exe


nunit-console.bat的目的則是為了讓unittest時也能夠用對環境變數:
set MyVar=ooxx
C:\oo\pp\xx\nunit-console.exe %1 %2 %3 %4 %5 %6 %7 %8 %9

Visual C++如何決定候選candidate function list

Stan Lippman說明VC++中如何決定candidate function list:
  • Candidate Function List: 在某個呼叫點可視範圍內的所有function中,名稱相同的function所構成的集合
  • 以下例子中,對f(s)這個呼叫點來說,(1)(2)(3)(4)都是candidate function:
    void f(); // (1)
    void f( String^ ); // (2)
    void f( const string& ); // (3)
    void f( String^, array^ ); // (4)

    int main( array ^args )
    {
    if ( args == nullptr )
    handle_invalid_command_line();

    for each ( String^ s in args )
    f( s );
    }
  • 比較特殊的是以下例子,f雖然不在CLITypes namespace中,但因其argument cobj的type在CLITypes namespace中,使得CLITypes::takeC(C^)也列在Candidate Function中:
    namespace CLITypes
    {
    public ref class C {…};
    void takeC( C^ );
    }

    // …

    void f( CLITypes::C^ cobj )
    {
    // ok: calls CLITypes::takeC( C^ )
    takeC( cobj );
    }

星期一, 11月 27, 2006

CruiseControl.NET除錯技巧

CruiseControl Project Break的不明不白時怎麼辦?
打開Build Log,搜尋以下症狀:

  • 「Unhandled Exception:」:執行程式失敗時可能會有此訊息
  • 「success="False"」: Build或Test失敗都會有此訊息

  • 「不是內部或外部命令」:如當使用exec task時可能出現類似以下錯誤訊息
    'OOXX.exe' 不是內部或外部命令、
    可執行的程式或批次檔。


  • 「Assembly not found」: Nunit錯誤訊息

星期日, 11月 26, 2006

如何取得MSN Space內容

設定MSN Space

  1. 確認你的MSN帳號名稱, 假設你的Blog為http://OhOh.spaces.live.com, 則帳號名稱為"OhOh"
  2. 開啟電郵發佈功能
  3. 設定密語

使用MetaWeblog API

  1. 安裝XML-RPC.NET以便使用XML-RPC
  2. AddReference CookComputing.XmlRpcV2.dll
  3. 加入一個新的Class,將以下Code複製進去: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msnspaces/MetaWeblogAPI_CSharp_Code_Sample.asp
  4. using MetaWeblogApi;
  5. 完成:
    MsnSpacesMetaWeblog mw = new MsnSpacesMetaWeblog();
    Post[] ps = mw.getRecentPosts("MyBlog", "OhOh", "ooxxooxx",20);
上述方式最多只能夠在msn space抓到最新的20篇post,如果要抓更多,請參考國良先生在微軟技術社群討論區的文章:
我之前有用C#配合MetaWeblog API寫出一個備份程式,請參考「
Horn Village|牛角村: 【msnSpacesBackup 】利用 MetaWeblog API 來備份 msnSpaces 的網誌」。
要取得所有文章的重點在於postid,若上面那篇文章的URL是...cns!5759F9D78C26191!15004.entry 其中的5759F9D78C26191!15004就是postid,「5759F9D78C26191!」是固定的(但每個人的都不同)而「15004」都是整數而且是越新的文章數值越大,所以要抓全部文章的方法就是從GetRecentPosts取得最新文章的postid(簡單一點就用人工輸入)然後用迴圈遞減postid由GetPost()取得資料。
開站時間越久或文章越多,花費的時間就越多。