您也是打痛苦混战的高手吗?

您也是打痛苦混战的高手吗?

我喜欢下围棋,虽然我没有太多的时间精进我的棋艺。以前看棋谱或是看一些围棋的故事时经常会看到一些叙述文字说某些围棋高手是打混战的高手,这是说围棋局面愈乱拥有这种特质的围棋高手就愈容易胜出。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的价值之一是开始让我们思考新的选择以及新的选择可能带来的影响是什么!

 

 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1092703


你可能感兴趣的:(您也是打痛苦混战的高手吗?)