2006 年 08 月 的封存

Delphi.NET多層應用系統開發技術研討會

從上個星期就開始有朋友問我為什麼很久沒有更新Blog了,其實我想我寫Blog已經很勤快了,這次10多天沒有更新Blog想當然是我又開始出差了。上星期台灣進行了『Delphi.NET多層應用系統開發技術研討會』,在DevCo重新在台灣舉辦活動1,2個月之後,的確發現慢慢的一些客戶開始回流來參加研討會了,這是個好現象,也讓我有機會和一些朋友談談他們的工作近況以及他們希望能夠聽到什麼主題的研討會。而之所以DevCo會在上星期舉行『Delphi.NET多層應用系統開發技術研討會』就是因為許多朋友都在詢問如何把應用程式移植到.NET以及如何讓他們能夠使用ASP.NET開發新的Web應用程式但是又能夠同時使用現有的Midas/DataSnap應用系統。

其實要讓新的.NET應用系統和現有的Midas/DataSnap應用系統整佑在一起不困難,要解決的問題就只是讓.NET用戶端呼叫到Midas/DataSnap應用系統以及如何在兩個執行環境中進行資料型態的轉換。

 

 使用.NETInterOp2技術就可以讓.NET用戶端呼叫到Midas/DataSnap應用系統,至於資料型態轉換就有點困難。最簡單的想法就是讓兩邊都使用XML來交換資料,但是唯一的麻煩就是Midas/DataSnap在許多方法中都是以OleVariant的型態來封裝資料,因此.NET的用戶端必須知道如何處理Midas/DataSnap傳遞來的OleVariant資料封包,並且從其中擷取出以XML封裝性的真正資料。

 

還好我們可以在Delphi『隱誨』的文件中找到一絲曙光:

 

原來OleVariant/Variant可以對映成.NETSystem.Object或是Delphi.NET重新定義的TObject

有了這兩個知識之後我們就可以讓.NET用戶端和Midas/DataSnap應用系統整合了,在『Delphi.NET多層應用系統開發技術研討會』中,我從 BDE的專案開始討論如何移植到.NET,接著討論dbExpress專案,最後討論移植Midas/DataSnap應用系統整合並且開發.NETWindows FromASP.NET應用程式來呼叫並且使用Midas/DataSnap應用系統提供的服務和資料, 例如下圖是Win32 VCL Form以及.NET Windows Form同時呼叫COM+的Midas/DataSnap伺服器的執行畫面:

 

而下面是最後在研討會中的範例,我使用Delphi 2006開發一個ASP.NET的應用程式來呼叫Midas/DataSnap應用系統提供的服務和資料並且顯示在瀏覽器中,您可以看到使用Delphi 7開發的VCL Form應用程式也在執行,而且Midas/DataSnapCOM+伺服器也在運轉中同時提供Win32.NET的用戶端服務。

 

Delphi.NET多層應用系統開發技術研討會』是有關Delphi/Delphi.NET多層應用系統開發的第一個研討會,在下次DevCo將會舉辦第2次的『Delphi.NET多層應用系統開發技術研討會』,內容是討論如何在桌面型,主從架構,以及多層架構中都可以重覆使用由ECO開發出來的企業邏輯模型。

 

 我知道我大陸的同事這星期也要開始在4個城市進行Delphi2006技術研討會,這是3,4年以來我第一次無法去大陸進行研討會,在此先祝福他們順利,成功了。

廣告

14 則迴響

您也是打痛苦混戰的高手嗎?

我喜歡下圍棋,雖然我沒有太多的時間精進我的棋藝。在以前看棋譜或是看一些圍棋的故事時經常會看到一些敘述文字說某些圍棋高手是打混戰的高手,這是說圍棋局面愈亂擁有這種特質的圍棋高手就愈容易勝出。NBA也是一樣,每年我都和一些好友玩Fantasy NBA,也喜歡看NBA球賽,一些NBA好手也是打混戰的高手,這也是局勢愈混亂,比數愈接近的時候這些NBA球員就表現的愈好。

但是很不幸的,在撰寫軟體方面如果我們說某人是打混戰的高手,那麼我就不知道這是恭維或是暗諷。什麼是寫軟體的打混戰的高手? 想想您寫過多少似曾相識的程式碼? 許多寫軟體的打混戰的高手在寫程式碼時非常的快速,腦筋更是運轉的快得不得了,因此當他們需要一些程式碼時,往往不願意花時間想想或是找找是不是已經有了可供使用的程式碼,就很快的再寫了一次,因為他們覺得再寫一次更快。或是當他們在寫COM+.NETJava時,許多中介的程式碼都大同貝異,只是因為程式語言的不同或是使用的技術不同,就再寫一次。

另外的情形則不一定是寫軟體的打混戰的高手,而應該說是一個團隊中的成員所發生的事情。例如在一個軟體開發團隊中,AB在寫自自的應用程式時,AB都可能同時在撰寫類似的程式碼,例如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+dbExpressDelphi+ADODelphi+,,,VB? PHP? Python? 嗯這個問題太簡單了,許多人也許不根本不屑一顧。

但是仔細看看上面的模型,不管使用JavaC#Delphi或是其他的程式語言,上面的企業邏輯規則都是一樣的,不會因為選擇的程式語言不同而改變,最多是實作方法不同的,那麼您也許會問然後呢?

讓我們換個角度想想,如果我們在企業邏輯模型中就完成GetClosedQAs方法呢?

看看下面的圖形,我在GetClosedQAsBody特性值中直接使用了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呼叫了IObjectInstanceInvoke來執行‘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介面就可以使用Delphifor…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的價值之一是開始讓我們思考新的選擇以及新的選擇可能帶來的影響是什麼!

9 則迴響

我以前的痛苦,你也擁有一樣的痛苦嗎?

記得筆者在以前使用Delphi/C++/Java開發軟體時,經常需要撰寫許多的輸入驗證碼,例如當使用者輸入身分證字號,或是輸入數值時,都需要根據企業邏輯來檢查使用者輸入的資料是否正確,通常許多的驗證邏輯程式碼幾乎都是一樣的,但是對於不同的程式語言,不同的開發環境都可能需要不斷重寫。更麻煩的是,由於一個團隊擁有許多的開發人員,因此不同的開發人員可能會使用不同的程式碼,不同的驗證邏輯,並且分散在整個應用程式不同的地方進行資料驗證的工作。這造成了許多的困擾,例如當驗證邏輯需要修改或是更正時,可能忘記改某些地方,或是由於開發人員撰寫的方式不同,而讓一些臭蟲因此而出現。雖然後來許多的開發人員把這些驗證程式碼封裝成函式庫統一讓開發人員使用,或是封裝成元件讓開發人員使用,例如現在.NET/Java都提供了一些簡單,常用的Validation元件,但是驗證程式碼分散在整個應用程式不同的地方的問題仍然無法得到解決,而由這個現象延伸出的問題也一樣存在。那麼我們有什麼好方法可以解決嗎?

在回答之前也許我們應該想想這些驗證程式碼的目的到底是什麼?在這些驗證程式碼中除了一般檢查使用者輸入的字元,格式,長度或是語意之外,最重要的驗證工作應該是使用者的輸入應該符合應用程式的企業邏輯規則,不是嗎?

因此如果我們能夠把這些驗證程式碼進行的工作定義在企業邏輯模型之中,那麼不管日後開發人員使用什麼程式語言,或是在應用程式的什麼地方,開發人員只需要在需要進行驗證程式碼的工作時從企業邏輯模型中最出定義好的驗證邏輯,再根據這些驗證邏輯來驗證使用者輸入的資料。如此一來一旦驗證邏輯有改變或是更新,我們只需要更新定義在企業邏輯模型之中的驗證邏輯,那麼由於整個應用程式都是從企業邏輯模型中取得驗證邏輯,那麼我們不就解決了可能忘記更改一些分散在不同地方的問題了嗎? 更進一步的想想,如果我們能夠使用一段通用的程式碼來檢查企業邏輯規則,而不需要對每一個不同的使用者輸入撰寫不同的程式碼來檢查,那麼不是更棒嗎(如果讀者真的開發過這樣的應用程式驗證邏輯,就知道筆者說的痛苦,以及難以維護的程式碼了)?

問題是,能夠有方法解決這長久以來的痛苦嗎?

也許有可能,讓我們繼續往下看。

UML中,開發人員可以使用OCL來定義類別/屬性的驗證邏輯或是約束條件,之後開發人員便可以在程式碼中藉由EcoSpace取得這些約束條件(Constraints),並且使用來驗證異動的物件是否符合這些約束條件,一旦符合約束條件才能夠更新回資料來源之中。在ECO架框中支援了這樣的機制,ECO藉由提供開發人員使用OCLECO類別/ECO屬性定義約束條件,以及在ECO架框中提供服務讓開發人員能夠在程式碼中存取這些約束條件並且執行約束條件以便驗證物件。

在您瞭解了上面討論的觀念之後,接下來的內容中將深入的說明如何在企業邏輯模型中使用OCL來定義約束條件,並且使用來驗證物件。

在企業邏輯模型中定義約束條件

開發人員可以在ECO的類別設計家中藉由物件檢視器設定類別或是屬性的Constraints特性來定義約束條件。使用Constraints特性定義約束條件時開發人員必須瞭解下面的觀念:

n          Constraints特性可以定義任何數目的約束條件

n          約束條件是使用OCL來撰寫的

n          開發人員使用Constraints特性定義約束條件後,如果使用者違反了約束條件那麼仍然可以更新物件回資料來源。因此檢查物件是否違反約束條件是開發人員的責任,開發人員必須確定物件在更新回資料來源之前沒有違反約束條件。

現在讓我們以圖1的範例模型來說明如何定義約束條件以及如何在程式碼中檢查企業邏輯模型的約束條件。

 

1範例模型

 

如下圖所示,我們可以點選Joiner類別,並且在物件檢視器中定義Constraints特性:

2 ECO設計家中為類別/屬性定義約束條件

 

開發人員可以直接在Constraints特性中輸入OCL或是點選Constraints特性旁的按鈕啟動Constraints編輯器,點選Constraints編輯器下方的Add按鈕加入約束條件。下面的圖形加入了兩個約束條件,每一個約束條件必須輸入約束條件的名稱以及約束條件的OCL敘述,例如NameNotEmpty約束條件規定了Name屬性不可為空白,同樣的EMailNotEmpty也是類似的規定。

 

3 啟動約束條件編輯器為Joiner類別定義約束條件

 

最後,範例企業邏輯模型也為DevCoSeminarMaxCount屬性定義了最多參加人數的約束條件必須小於120:

 

4 啟動約束條件編輯器為DevCoSeminar類別定義約束條件

 

定義完Constraints的約束條件後,讓我們再解釋一下封裝約束條件的IConstraint介面。

IConstraint介面

ECO架框中企業邏輯模型中的約束條件是由IConstraint介面封裝,定義的,開發人員藉由ECO架框服務介面存取到IConstraint介面,再藉由執行IConstraint介面定義的約束條件來驗證物件是否符合企業邏輯。下面是IConstraint介面的定義:

    public interface IConstraint: IModelElement

    {

        IExpression Body { get; }

        IEcoConstraint EcoConstraint { get; }

    }

IConstraint介面有兩個唯讀屬性,其中的Body即代表封裝的約束條件,而EcoConstraint則是專屬於ECO的額外資訊。Body屬性型態是IExpression介面,而IExpression介面的定義如下:

    public interface IExpression

    {

        string Language { get; }

        string Body { get; }

    }

IExpression介面也有兩個唯讀屬性,其中的Language屬性會回傳約束條件使用的語言,通常都是”OCL”,代表是由OCL撰寫的約束條件。而Body屬性則是約束條件本身。例如前面的『NameNotEmpty』約束條件,它的IConstraint. Body. Body屬性便是self.Name.Length > 0

IEcoConstraint介面也定義了兩個唯讀屬性,IsAutoGenerated屬性回傳這個約束條件是否是自動產生的,而Description則是約束條件的敘述文字:

    public interface IEcoConstraint

    {

        bool IsAutoGenerated { get; }

        string Description { get; }

    }

因此在ECO程式碼中,要根據約束條件來驗證物件,它的執行步驟如下:

n          ECO企業邏輯物件中取得所有的約束條件的IConstraint介面物件

n          一一的使用IOclService執行這些約束條件並且判斷約束條件是否符合

n          如果ECO企業邏輯物件符合約束條件才能夠更新回資料來源

n          如果ECO企業邏輯物件不符合約束條件,那麼就通知使用者進行後續的處理

瞭解了IConstraint介面以及處理約束條件的步驟之後,接下來我們就可以使用範例和程式碼來展示如何使用約束條件了。

在程式碼中驗證物件的約束條件

要如何使用程式碼來檢查定義在企業邏輯模型中的約束條件呢? 其實非常的簡單的,本書在第4章已經介紹了ECO的企業邏輯模型的靜態通用機制,因此我們可以使用下面的步驟來完成檢查企業邏輯模型中的約束條件:

n          在更新異動物件回資料來源之前,藉由使用IDirtyListService服務介面取得使用者所有異動的物件

n          藉由ECO的企業邏輯模型的靜態通用機制取得定義在企業邏輯模型中的約束條件

n          藉由IOclService服務介面一一的執行約束條件並且檢查是否違反約束條件

n          如果沒有違反任何的約束條件就更新物件回資料來源中

n          如果違反約束條件的話,保留違反約束條件的物件,要求使用者進一步的處理

瞭解了進行約束條件檢查的步驟之後,讓我們看一些實際的程式碼來驗證上面的步驟。

在下面的片段程式碼中是準備呼叫EcoSpaceUpdateDatabase方法把使用者異動的物件更新回資料來源中,但是在這之前,它先呼叫了DoCheckObjectConstraints方法以便確定所有異動的物件是符合企業邏輯模型中的約束條件,否則DoCheckObjectConstraints會產生一個例外錯誤。

001    procedure TWinForm.Button2_Click1(sender: System.Object; e: System.EventArgs);

002    begin

003      try

004        DoCheckObjectConstraints;

005        EcoSpace.UpdateDatabase;

006      except on E: Exception do

007        MessageBox.Show (‘物件違反約束條件‘ + e.Message +’無法更新回資料庫‘,

008                          MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk);

009      end;

end;

DoCheckObjectConstraints方法中先在007行取得IDirtyListService介面,接著進入010行的for迴圈一一的取出每一個異動的物件並且呼叫DoHandleDirtyObject來檢查每一個異動物件的約束條件是否符合。

001    procedure TWinForm.DoCheckObjectConstraints;

002    var

003      dol : IDirtyListService;

004      Iobj : IObject;

005    begin

//藉由IdirtyListServices取得異動的物件

007      dol := EcoSpace.DirtyListService;

008      if (dol.HasDirtyObjects) then

009      begin

010        for Iobj in dol.AllDirtyObjects do

011        begin

012          DoHandleDirtyObject(Iobj);

013        end;

014      end;

015    end;

最後的DoHandleDirtyObject方法在008行取得IOclService介面,在009行進入for迴圈,藉由IObject 介面的UmlType.Constraints取得定義在這個物件類別中的所有約束條件,接著在012行呼叫IOclServiceEvaluate方法來執行/評量約束條件。如果有任何物件違反了任何的約束條件就產生一個例外錯誤。

001    procedure TWinForm.DoHandleDirtyObject(Iobj : IObject);

002    var

003      IOcl : IOclService;

004      ICnt : IConstraint;

005      iCount: Integer;

006      bResult : boolean;

007    begin

008      IOcl := EcoSpace.OclService;

009      for iCount := 0 to Iobj.UmlType.Constraints.Count – 1 do

010      begin

011        ICnt := Iobj.UmlType.Constraints.Item[iCount];

012        bResult := boolean(IOcl.Evaluate(Iobj as IElement,iCnt.Body.Body).AsObject);

013        if (not bResult) then

014          raise Exception.Create(ICnt.Name);

015      end;

016    end;

現在如果我們執行上面的範例程式碼並且搭配圖3和圖4定義的約束條件,那麼我們可以看到當執行下面的範例程式並且在DevCoSeminar物件的MaxCount屬性中輸入超過120的數值:

 

5 修改DevCoSeminar物件的MaxCount屬性值

 

那麼在更新物件回資料來源之前就會看到下面的例外錯誤,代表上面的程式碼果然檢查出了物件違反了約束條件。

6 程式碼檢查出使用者輸入的資料違反了約束條件

 

如果我們接著又如下圖對Joiner類別進行異動並且試著把EMail屬性清為空白:

 

7 程式碼檢查出使用者輸入的資料違反了約束條件

 

那麼在更新物件回資料來源之前我們又可以看到範例程式檢查出Joiner物件違反了EmailNotEmpty的約束條件。

 從上面的程式碼看到了什麼? 如果您有注意的話會發現只需要使用相同的一份程式碼,在一個程序/函式中就可以檢查任何物件的任何約束條件。這和以前許多開發人員需要使用不同的程式碼,在不同的地方檢查不同的使用者輸入資料是完全不一樣的,這可以讓程式碼更容易維護,也不容易產生臭蟲,或是因為疏失而造成的錯誤。

如果我們進一步的結合.NET/開發工具提供的Validation元件和約束條件,那麼我相信大多數的程式碼驗證工作都可以順利,有效率的完成。

您注意到,感覺到了使用模型和約束條件的好處了嗎?

7 則迴響

Turbo產品系列回來了!

對於像我這樣年紀的IT人來說,BorlandTurbo系列幾乎是從學生時代就一直陪伴著我成長的朋友,我還記得大學2年級時我的第一個Data Structure and Algorithm的作業就是使用Turbo Pascal完成的。稍後學習C/C++BorlandTurbo C/C++更是不能離手的工具,而我現在也仍然保留著BorlandTurbo Prolog 1.0,雖然磁片都已經發霉不能用了,不過Turbo Prolog當時帶給我的樂趣是現在我都忘不了的。

Borland決定賣出開發工具產品線之後,其實也代表Borland把它的核心精神賣掉了,但是DevCo卻以繼承Borland原始精神的並且以持續發揚『寫程式的樂趣』為目標。許多人都在等著看DevCo如何能夠重新把Delphi/C++Builder/JBuilder帶回往日的盛況,雖然我還不確定DevCo能不能夠做到這點,但是至少現在我已經看到DevCo在具體行動了。Turbo產品系列是DevCo第一個在開發工具界的行動,我想DevCoTurbo系列重新帶回來除了在市場,產品和收入的影響之外,更重要的意義是向全世界的開發人員宣示DevCo經營開發工具市場的決心。

在這次2006年的Turbo系列中,包含了Turbo Delphi for Win32, Turbo Delphi for .Net, Turbo C++ 以及 Turbo C#。每一個Turbo版本又分為ExplorerProfessional版本,其中的Explorer版本是免費的,主要是為了讓教育界的人員或是想要學習程式設計的人使用的,DevCo特別強調希望把寫程式的樂趣藉由Turbo Explorer系列讓想進入軟體開發的人所充分的體驗到。

令許多人懷念的Turbo系列如今捲土重來

 

如果您對DevCoTurbo系列有興趣,您可以在下面的URL找到更多的資訊:

www.turboexplorer.com

 

還記得您第一次寫程式所得到的樂趣嗎? 希望DevCo能夠把那些令人懷念又愉快的感覺再找回來。

32 則迴響

Windows Live Spacces出了什麼問題?

自從前幾天MS換了Windows Live Spaces之後還整個部落格變得非常的不穩定, 我經常無法存取我的部落格, 或是出現HTTP 500的錯誤, 造成了許多的問題, 這個情形已經持續了好幾天都沒有改善. 如果再這樣下去, 看來要開始考慮換一個部落格了.

3 則迴響

高效率C/C++Builder 2006程式設計研討會

終於忙完了上星期C/C++Builder的活動,在上星期5從高雄回台北的路上我利用在車上,飛機上的時間回想上一次在台灣進行C/C++技術研討會是什麼時候,但是我失敗了,我都記不得那是什麼時候了,連模糊的印象都沒有。我後來想這可能有2個原因,一是年齡慢慢大了,記憶力衰退了,二是台灣真的很久沒有舉辦C/C++Builder的技術研討會了。

說真的,當上星期2『高效率C/C++Builder 2006程式設計研討會』舉行時真的讓我出乎意料之外,因為我沒有想到會有那麼多的人來參加,而且參加的朋友許多都非常的年輕而且非常的眼生。這個現象非常的有趣,因為這代表仍然有許多新進的朋友使用C/C++Builder,另外代表的意思也許是DevCo真的需要多多舉辦技術研討會,因為很顯然的DevCo的客戶對於有意思的技術主題仍然願意參加參加。

回想C/C++Builder一路走來的發展史可以說並不是十分的順遂,C/C++Builder 2006好不容易又回到了繼續開發的路途,我真的希望DevCo能夠好好的把C/C++Builder發展下去,因為畢竟DevCo仍然有那麼多的C/C++Builder用戶,而且C/C++開發人員的數目雖然在Java/C#的猛烈攻勢下仍然擁有非常可觀的數量,並沒有像前幾年許多IT機構預測C/C++的人口會大幅度的下降。

C/C++Builder 2006C/C++Builder的產品線重啟了生機,也帶來了許多新的,有用的功能,但是就我個人意見而言C/C++Builder仍然需要急起直追,DevCo應該把C/C++Builder進化成和目前Java/C#一樣擁有最新的軟體技術並且支援最新的軟體工程。例如未來的C/C++Builder應該擁有更齊全的重構能力(最好和Java/C#一樣)C/C++Builder應該擁有自己的測試驅動架框(CPPUnit)C/C++Builder應該擁有TogetherScrum的功能,C/C++Builder的編譯器應該要更新了。如果再搭配DevCo宣告的64位元C/C++編譯器,Fully Unicode EnabledVCL/VCL64架框,BDS新的IDE功能,那麼C/C++ Builder未來仍然是大有看頭,希望DevCo不要再重蹈Borland的重蹈覆轍了。

上星期5從高雄回來之後,到我的Blog一看才發現我的Blog點閱率已經超過20萬次了,這樣的速度看來是蠻快的,不過到了DevCo之後工作更忙了,不但活動多,而且Evangelist還有許多其他的工作,因此寫Blog的時間也就被分散了,當然寫ECO的時間也就更少了。為了不讓等待ECO文章的朋友太久沒有東西可以玩一玩,我把寫到一半的ECO物件架構內容先Post出來,讓喜歡ECO的朋友可以找時間玩玩ECO的物件架構。

http://liwei.csdn.net/down/Chap04-1SC.pdf

http://liwei.csdn.net/down/Chap04-1TC.pdf

 Have fun, have a good ECO day!

17 則迴響