Author: Anders小明
產品化和客戶化兩個詞語是一個對孿生兄弟,一個沒有強大客戶化能力的軟體是不能稱為產品化的軟體.產品化也就意味著軟體公司的開發至少分為兩個不同性質的角色:一個負責產品化,一個負責客戶化.除去傳統的參數化, 繼承以及plugin技術外,aspectJ為我們提供另一種能力.
如前所述, 公司有兩個不同角色的團隊在開發和維護—研發組和項目組,更進一步,本文所說適應如下的Team Dev結構:
一個研發組---多重專案組, 每個項目組需要定製化的東西各自不盡相同. 為了保證幾個團隊的工作的相對獨立性,公司希望項目組在做客戶化過程中不改研發團隊所開發的代碼,應用了已知的方法:參數化, 繼承以及plugin技術外.
然而這些技術並沒有覆蓋到所有的問題, 問題描述如下
經過分析發現需要客戶化的地方,是需要在Root類裡加一個propertyA, 這個時候基於已有的能力,我們可以做的選擇是要麼項目組A在修改Root類,要麼修改每個葉子類(LeafA....), 顯然修改root類是一個不錯的選擇. 然而槽糕的是,項目組B需要是添加另一個properyB,於是項目組B也這麼做了. 對於項目組A和B來說這樣做是沒有太多問題的.
但對於研發組來說問題卻是很嚴重的, 由於研發組需要從項目回收代碼,以便吸取優點改進軟體,研發組不得不小心的維護各個版本,並處理項目組所做的修改.而同時項目組擷取了修改研發組代碼的權力,處於時間的壓力,會產生不符合系統結構約束的代碼.
很明顯,這樣的工作方式不利我們的工作,我們需要一個新的思路.
在正式提出新方法前,我想先介紹一下微軟的DSL Tools以及C# 2.0,各位客官,還請耐心的看一下。
DSL Tools是微軟開發的Domain Specification Language,目的是用更接近於業務的語言模型來描述業務問題,並產生運行代碼。工具允許其使用者定義各自的Domain Language,目標是軟體工廠。DSL Tools面臨的一個問題(也是公司目前面臨),定義好的DSL以及產生代碼,不可避免的出現不同客戶存在細微的差異性,DSL Tools必須很好的解決它,事實上DSL Tools的確做到了——它基於是C#2.0 Partial Class技術。(有關於DSL Tools的更多資訊可以參見MSDN)。
簡單說的Partial Class的其實就是一個類的結構資訊可以被儲存在多個檔案中,以下是個例子:
file1.cs(微軟的一個檔案可以定義多個類,所有其檔案名稱不需要同類名):
public partial class CAgent {
private String name;
Property String Name{
get{
return name;
}
set{
this.name = name;
}
}
public void doSomethingA(){
....
}
}
file2.cs
public partial class CAgent {
private String code;
Property String Code{
get{
return code;
}
set{
this.code= code;
}
}
public void doSomethingB(){
....
}
}
雖然CAgent類被分解為兩個檔案,不過對於調用者類說,CAgent具體name以及code兩個property,以及doSomethingA和doSomethingB兩個方法。
現在你可以想象DSL Tools是如何解決客戶化這個問題的了!
DSL Tools產生的所有class都是partial class,當對於CAgent(或者其它類)有需要客戶化時,需要做的只是添加一個新的檔案,用同樣的類名加上一個partial的關鍵字,
public partial class CAgent 就可以添加新的屬性和方法(如同我展示的那樣,想象一下file1.cs是研發維護,而file2.cs是項目維護的)。也就說,DSL的研發團隊和客戶化團隊的工作時相對獨立的。
那麼你一定會說,這個微軟的C#,不幸的是公司用的是Java,java的語言規範不支援這樣的能力。
是的,你說的很對,Java語言本身是不支援,不過我們有這樣的手段——那就是AspectJ。
實際上AspectJ面世很久了,我接觸它至少有一年半了,不過支援一直沒有想到這樣的用法,直到我研究了DSL Tools(我相信很多道理是相通的,我們目前面臨的問題矽谷的那幫人也一樣面對過)
下面是一個簡單的例子:
OnType.java:
public class OnType {
public void doAction(){
System.out.println("OnType.doAction");
}
}
OnTypeAspect.aj
public aspect OnTypeAspect {
public String OnType.name = "OnTypeAspect";
public void OnType.doActionAspect(){
System.out.println("OnType.doActionAspect and name is "+ name);
}
}
Main2.aj
public class Main2 {
public static void main(String[] args){
OnType onType = new OnType();
onType.doActionAspect();
}
}
如你所見,程式是可以完整的運行。你的控制台打出了:OnType.doActionAspect and name is OnTypeAspect
不僅如此,AspectJ可以為已有的類添加新的介面,就像C#的partial class做的那樣。
我以為aspectj是實現我們的目標的一個捷徑,並且它是經過實踐的,我不相信aspectj和微軟的那幫人會閑著沒事來支援這樣的技術。BTW,我聽說weblogic的jrockit準備在虛擬機器一級上支援aspectj, 那麼或許剩下的工作就是如何管理使用AspectJ了.