維's profileIT : 是工作還是嗜好?PhotosBlogListsMore ![]() | Help |
|
August 17 您也是打痛苦混戰的高手嗎?我喜歡下圍棋,雖然我沒有太多的時間精進我的棋藝。在以前看棋譜或是看一些圍棋的故事時經常會看到一些敘述文字說某些圍棋高手是打混戰的高手,這是說圍棋局面愈亂擁有這種特質的圍棋高手就愈容易勝出。NBA也是一樣,每年我都和一些好友玩Fantasy NBA,也喜歡看NBA球賽,一些NBA好手也是打混戰的高手,這也是局勢愈混亂,比數愈接近的時候這些NBA球員就表現的愈好。 但是很不幸的,在撰寫軟體方面如果我們說某人是打混戰的高手,那麼我就不知道這是恭維或是暗諷。什麼是寫軟體的打混戰的高手? 想想您寫過多少似曾相識的程式碼? 許多寫軟體的打混戰的高手在寫程式碼時非常的快速,腦筋更是運轉的快得不得了,因此當他們需要一些程式碼時,往往不願意花時間想想或是找找是不是已經有了可供使用的程式碼,就很快的再寫了一次,因為他們覺得再寫一次更快。或是當他們在寫COM+,.NET,Java時,許多中介的程式碼都大同貝異,只是因為程式語言的不同或是使用的技術不同,就再寫一次。 另外的情形則不一定是寫軟體的打混戰的高手,而應該說是一個團隊中的成員所發生的事情。例如在一個軟體開發團隊中,A和B在寫自自的應用程式時,A和B都可能同時在撰寫類似的程式碼,例如A可能寫了select * from employee,而B也正寫select e.ID, e.Name, … from employee e。或是A需要一個方法叫做GetSeminarQA以便得到研討會所有的QA問題,而B也在寫類似的方法,只是A使用Delphi程式語言,而B則使用Java。許多有對專案開發有經驗的人都知道,一旦當專案完成(或是完成不了)之後,如果使用Audit/Metric工具來檢查專案程式碼,就會發現許多,許多類似的程式碼不斷的出現在專案的不同的程式中。 也許重構正是因為那些聰明的人在檢視了以往的程式碼之後發現原來自己正是打混戰的高手因此而發展出來的技術。 混戰高手需要改變嗎? 我也不知道,各人愛好不同,讓我們看看下面的一個企業邏輯模型。DevCoSeminar類別定義了三個方法,其中的GetClosedQAs方法可以回傳一個研討會所有的QA問題,那麼我們應該如何實作GetClosedQAs呢? 如果這去問Java的朋友,他們會用Java + JDBC或是Java + Hibernate來實作,如果詢問C#的朋友,他們馬上會用C#+ADO.NET在數秒之內完成,Delphi? 那選擇更多了,Delphi+dbExpress,Delphi+ADO,Delphi+,,,。VB呢? PHP呢? Python呢? 嗯這個問題太簡單了,許多人也許不根本不屑一顧。 但是仔細看看上面的模型,不管使用Java,C#,Delphi或是其他的程式語言,上面的企業邏輯規則都是一樣的,不會因為選擇的程式語言不同而改變,最多是實作方法不同的,那麼您也許會問然後呢? 讓我們換個角度想想,如果我們在企業邏輯模型中就完成GetClosedQAs方法呢? 看看下面的圖形,我在GetClosedQAs的Body特性值中直接使用了OCL來撰寫GetClosedQAs方法。為什麼要使用OCL? 因為這個企業邏輯規則是一樣的,不會因為用戶端的程式語言,平台或是技術而改變。 有了上面的企業邏輯模型之後,對於開發人員人說仍然必須搞清楚如何在用戶端使用企業邏輯模型,這不困難,讓我們愛揮一下技術人員的天賦,追根究底的往下挖。 一旦在企業邏輯模型中定義了GetClosedQAs之後,ECO會自動產生如下的程式碼: [UmlTaggedValue('Eco.Body', 'self.hasQA->select(closed)->asSet()')] function getClosedQAs: System.&Object; 嗯ECO使用了.NET的屬性來定義DevCoSeminar類別的getClosedQAs方法。再往下看,getClosedQAs的實作如下: function DevCoSeminar.getClosedQAs: System.&Object; type TArrayOfobject = array of &object; begin Result := (System.&Object(Self.AsIObject.Invoke('getClosedQAs', New(TArrayOfobject, 0)))); end; 嗯,getClosedQAs呼叫了IObjectInstance的Invoke來執行'getClosedQAs',回傳的結果是一個包含執行結果物件的物件陣列,。而IObjectInstance有如下的定義: public interface IObjectInstance: IObject { IObjectStateMachine StateMachine { get; } object Invoke(IMethod method, object[] parameters); object Invoke(string methodName, object[] parameters); object Invoke(IMethod method, IElement[] parameters); } OK,很好,現在只要我們搞清楚如何擷取出getClosedQAs回傳的結果就可以取得依照企業邏輯模型定義的getClosedQAs方法的運算結果。下面的程式碼就是使用Delphi做為用戶端程式語言來存取執行的結果: procedure TWinForm.btnQAs_Click(sender: System.Object; e: System.EventArgs); var aSeminar : DevCoSeminar; anObject : System.&Object; begin aSeminar := Self.cmhSeminar.Element.AsObject as DevCoSeminar; anObject := aSeminar.getClosedQAs; HandleQAs(anObject); end; 現在唯一的難題就是如何從getClosedQAs方法回傳的型態為System.Object的結果值出運算結果。在這裡讓我給使用ECO的朋友一個暗示,對於像getClosedQAs方法執行OCL並且回傳結果物件串列的方法,這個回傳的結果都實作了ICollection介面,因此我們只需要把執行結果轉變型態為ICollection介面就可以使用Delphi的for…in迴圈或是C#的foreach迴圈取得結果,例如下面的程式碼就範例了從getClosedQAs的物件串列中取出所有符合條件的QA物件: procedure TWinForm.HandleQAs(anObject: System.&Object); var aQA : QA; begin for aQA in (anObject as ICollection) do begin Self.lbResult.Items.Add(aQA.Question); end; end; 執行一下上面的程式碼,我們就可以順利的得到正確的結果,下圖就是一個範例應用程式的執行結果畫面: 對於C#的朋友,程式碼和Delphi是一樣的,關鍵在企業邏輯模型,任何的用戶端程式語言都可以重覆使用企業邏輯模型中的設計: private void button1_Click(object sender, System.EventArgs e) { DevCoSeminar aSeminar = cmhSeminar.Element.AsObject as DevCoSeminar; System.Object anObject = aSeminar.getClosedQAs(); HandleQAs(anObject); }
我還是要問,您感覺到了什麼? 是繼續讓獨自的開發人員在不同的程式碼中仍然撰寫各自的程式碼? 為每一個類似的情形不斷的撰寫重覆的程式碼? 為不同的程式語言不斷的撰寫重覆的程式碼? 為不同的平台不斷的撰寫重覆的程式碼? 我想這沒有標準的答案,每個人的風格不同,有人永遠是打混戰的高手,有人卻能夠在知道了新的選擇之後開始思考這些新的選擇會或是可以帶來什麼改變。 也許學習MDA/DDA/ECO的價值之一是開始讓我們思考新的選擇以及新的選擇可能帶來的影響是什麼! Comments (9)
TrackbacksThe trackback URL for this entry is: http://gordonliwei.spaces.live.com/blog/cns!CCE1F10BD8108687!1115.trak Weblogs that reference this entry
|
|
|