Inversion of Control

本想看看 .Net 實做 Spring 的專案的.找著找著,又看到了 Castle. 後來發現他們都用了所謂的 Inversion of Control 的概念.
這我就好奇了,甚麼是 Inversion of Control ??
在這裡看到一段很好的解說:

“That’s the basic concept of Inversion of Control; you don’t create your objects, you describe how they should be created. You don’t directly connect your components and services together in code, you describe which services are needed by which components, and the container is responsible for hooking it all together. The container creates all the objects, wires them together by setting the necessary properties, and determines when methods are invoked.”

然後提到大致上有三種實做的方式:

type-3 Services dependencies are provided as constructor parameters (and are not exposed as JavaBeans properties). This is the exclusive approach used by PicoContainer, and is also used in HiveMind and Spring.

接著又提到 Inversion of Control Container 應該被稱為 Dependency Injection pattern 會比較恰當…看這篇:Inversion of Control Containers and the Dependency Injection pattern
PicoContainer 與 Castle 很接近,應該都屬於 type-3 – constructor injection, 此外也有很重的 Interface Injection 味道.
上面那篇文章寫的很好,可以算是經典文了.
其他參考性的東西,不再贅述…
*Castle 官網上對 IoC 的說明就直接貼出兩篇經典文的網址.
*c# 對 IoC 的實做,目前有三個實做: StructureMap, Castle, Spring.net
*Open Source Inversion of Control Containers in C#
*Design Better Software with the Inversion of Control Pattern
*Inversion of Control
*PicoContainer – Inversion of Control
*Apache Excalibur – guide-patterns-ioc

[新酷音]ChewingServer無法啟動

公司的電腦老是無法使用新酷音輸入法.
狀況是這樣子的,切換到新酷音輸入法之後,打任何字都會造成短暫的延遲,無法輸入.
大致的猜測,是因為 ChewingServer 無法載入.
利用 svn 下載 source code(包含 library) 之後

svn co https://svn.csie.net/chewing/win32-chewing/
svn co https://svn.csie.net/chewing/libchewing/
svn co https://svn.csie.net/chewing/libchewingpp/

進行 Trace, 花了不到十五分鐘,就找出原因.
答案是因為在載入家目錄下的 hash.dat ( 在 \Document and settings\xxx\application data\chewing\hash.dat)時,發生了異常,導致整個 ChewingServer crash.
這也是為甚麼會有短暫延遲的原因,每輸入一個字,新酷音輸入法就會試著去啟動 ChewingServer,每次啟動,每次都 crash, 因此就會有延遲.
刪除掉 hash.dat, 讓ChewingServer重新產生以後就行了.
這個問題也回報到這裡了…(很遺憾,第一次填寫,搞不清楚甚麼欄位要填啥,不小心把主旨填成自己的名字了,而且回報的內容也不夠好…下次改進)

Architecture

翻閱A UML Pattern Language的時候看到的,覺得很有道理.摘錄如下:

Architecture is what remains when you cannot take away any more things and still understand the system.
Architecture actually cover 3 similar but different ideas: architecture itself, framework, and toplogy.

ArchitectureTriple

FoxPro over TCP/IP

VFP 雖然可以使用 ODBC/OLEDB 存取自己的 Database, 但是, 基本上,那還是 File base 的方式,所以如果你想使用 TCP/IP 方式來存取資料庫,那麼你就得被迫使用其他的 Database,如 Microsoft SQL server, Firebird, Oracle… 之類的.
我的 idea 大致就像這樣子…
FoxProOverTCPIP
裡面的 Custom ODBC Driver 與 Daemon/Service 就是要寫的部份.
本想找找看,要怎麼寫 ODBC driver 的.
結果不小心發現,已經有人寫了類似的東西了.
一個是 ODBC Socket Server,另外一個則是Open Database Transport Protocol),都跟我的 idea 相當類似.
ODBC Socket Server, 主要是 client 提供 connect string 與 query string, 讓 server 去做 query 的動作並傳回 xml.
這裡有一些可以參考的文章:
*ODBC Socket Server, PHPBuilder.com
Open Database Transport Protocol)的話,跟 PHP 比較相近,所以提供的範例都是 PHP.
嗯嗯,看來是不用多此一舉再寫一次了… 🙂

About Web Crawler

什麼是 Web Crawler?? 其實就是一般慣稱的 bot.
定期在網路上漫遊,將網頁的部分(全部)資料以及特徵值放到自身的資料庫裡面,做為 Search engine 的資料來源.
所以你大概會這麼想,使用一部或多部 server, 以 multiple thread 甚或 multiple process 的方式,去網路上漫遊.
當遇到網頁中有連結的時候,先排程到 Queue 裡面,讓其他有空的 thread/process 能從 Queue 裡面循序取出來,進行漫遊.
設計這樣的一個程式,所需要考慮的一些事情:
1. Multiple database server的考量:一個 database server 可能會承受不住這種情況,所以需要考慮 replication 或是更適合用來取資料的 database engine.
2. Multiple host + Multiple thread 的考量:網路上現今的資料量絕對超過你的想像,所以你不可能使用一台機器甚或一個 thread 去做漫遊,這樣會花費太多時間.另外也要考慮 lock, resource …等等的問題.
3. Queue 實作的方式: 有些立即性的連結,可能需要放在 thread/process 自身的 queue 裡面,比較不具立即性的連結,就可能放在 database server 上. (Priority Queues)
我想我考慮的可能還太淺.
其他一些可以參考的或可能用上的技術:
* Lucene
* Google Desktop search API
* MySQL replication
* Thread pool
* DDJ 2001 April: Web site searching & Indexing in Perl

MSN messenger+ foolbar2000

早先就知道可以讓 Windows Media Player 播放的曲目資訊顯示在 MSN messenger 上.
可是…我並不喜歡用 Windows Media Player 來播放歌曲啊.
之前也逛到讓 foolbar2000 播放的曲目資訊顯示在 MSN messenger 上的方法,可是我並沒有去試.
今天心血來潮了,上網搜尋了一下:
*PCDVD數位科技討論區 – [教學]如何不慣WMP9啟動MSN歌名同步
節錄步驟如下,照著作就對了.
1. 先到這裡 HKEY_CURRENT_USER\Software\Microsoft\MSNMessenger\PerPassportSettings000000000\
把 “ShowTransientPSM” 改成 dword:00000001.
2. 下載 MSN Messenger Now Playing Plugin (gen_msn), 解開以後,放到 foolbar2000 目錄下的 components.
3. 收工.

RFMaintainer 的 statechart (補)

昨天的RFMaintainer 的 statechart並沒有實作部份,今天補上…
你可以看到這些都是寫在 Form 裡面,並沒有跟 UI 切開….
這就是我疑問的地方…
不過對照圖之後,你會發現這樣的寫法很清楚…不會有補東牆挖西牆,東改一塊西改一塊的問題…

		#region State Chart Implementation.
private int _StateVariable = 0;
private int _StateVariable_A = 0;
private int _StateVariable_B = 0;
private int _StateVariable_C = 0;
/// 
/// State 1: Transient
/// 
private void go_state_1()
{
_StateVariable = 1;
if( txtConnectString.Text == "" )
go_state_2();
else
go_state_3();
}
/// 
/// State 2: Connection string null
/// 
private void go_state_2()
{
_StateVariable = 2;
// disable controls.
radioButton1.Enabled = false;
radioButton2.Enabled = false;
dtpFrom.Enabled = false;
dtpTo.Enabled = false;
cboType.Enabled = false;
txtPath.Enabled = false;
btnBrowse.Enabled = false;
btnExport.Enabled = false;
}
/// 
/// State 3: Connection string not null
/// 
private void go_state_3()
{
_StateVariable = 3;
// enable controls.
radioButton1.Enabled = true;
radioButton1.Checked = true;
radioButton2.Enabled = true;
cboType.Enabled = true;
txtPath.Enabled = true;
btnBrowse.Enabled = true;
go_state_4();
go_state_7();
go_state_10();
}
/// 
/// State 4: Region A: Transient
/// 
private void go_state_4()
{
_StateVariable_A = 4;
if( radioButton2.Checked )
go_state_5();
else if( radioButton1.Checked )
go_state_6();
}
/// 
/// State 5: Region A: "Period" checked
/// 
private void go_state_5()
{
_StateVariable_A = 5;
dtpFrom.Enabled = true;
dtpTo.Enabled = true;
}
/// 
/// State 6: Region A: "All" checked
/// 
private void go_state_6()
{
_StateVariable_A = 6;
dtpFrom.Enabled = false;
dtpTo.Enabled = false;
}
/// 
/// State 7: Region B: Transient
/// 
private void go_state_7()
{
_StateVariable_B = 7;
if( txtPath.Text == "" )
go_state_8();
else
go_state_9();
}
/// 
/// State 8: Region B: "output file" null
/// 
private void go_state_8()
{
btnExport.Enabled = false;
}
/// 
/// State 9: Region B: "output file" not null
/// 
private void go_state_9()
{
btnExport.Enabled = true;
}
/// 
/// State 10: Region C: "Export type" is XML
/// 
private void go_state_10()
{
_StateVariable_C = 10;
cboType.SelectedIndex = 0;
}
/// 
/// State 11: Export
/// 
/// 
private void go_state_11()
{
}
#endregion
#region UI independence routines
/// 
/// I don't consider this button in State chart.
/// And I am lazy to change....
/// 
/// 
private bool testConnection( string connectString )
{
}
private bool export( int type, DateTime dtFrom, DateTime dtTo, string outputFile )
{
}
#endregion
#region Event handler
private void btnExport_Click(object sender, System.EventArgs e)
{
int iType = 0;
if( radioButton1.Checked == true )
iType = 1;
else if( radioButton2.Checked == true )
iType = 2;
if( export( iType, dtpFrom.Value, dtpTo.Value, txtPath.Text ) )
MessageBox.Show( "Finished!" );
else
MessageBox.Show( "Fail!!" );
}
private void btnBrowse_Click(object sender, System.EventArgs e)
{
// Displays a SaveFileDialog so the user can save the Image
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "XML file|*.xml";
saveFileDialog1.Title = "Save to XML File";
saveFileDialog1.ShowDialog();
saveFileDialog1.OverwritePrompt = true;
// If the file name is not an empty string open it for saving.
if(saveFileDialog1.FileName != "")
{
txtPath.Text = saveFileDialog1.FileName;
}
}
private void btnTest_Click(object sender, System.EventArgs e)
{
testConnection( txtConnectString.Text );
}
private void radioButton1_CheckedChanged(object sender, System.EventArgs e)
{
go_state_6();
}
private void radioButton2_CheckedChanged(object sender, System.EventArgs e)
{
go_state_5();
}
private void txtPath_TextChanged(object sender, System.EventArgs e)
{
go_state_7();
}
private void txtConnectString_TextChanged(object sender, System.EventArgs e)
{
go_state_1();
}
#endregion
}