How to Use Design Patterns
[URL=http://www.artima.com/lejava/articles/gammadp.html]
http://www.artima.com/lejava/articles/gammadp.html[/URL]
如何使用設(shè)計(jì)模式
與Erich Gamma的一次談話,第一部分
Bill Venners
May 23, 2005
翻譯:
http://blog.csdn.net/lxwde摘要
在開發(fā)者中間,設(shè)計(jì)模式是思考設(shè)計(jì)問題的很受歡迎的一種方法,但是怎樣才是思考設(shè)計(jì)模式的正確方法呢?在這次采訪中,Erich Gamma(里程碑式的書籍《設(shè)計(jì)模式》的作者之一)和Bill Venners談?wù)摿岁P(guān)于如何思考和使用設(shè)計(jì)模式的正確方法。
Erich Gamma是在1995年作為暢銷書籍《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》(Addison-Wesley, 1995) [see Resources]的合著者而躍上軟件業(yè)界舞臺(tái)的。這項(xiàng)具有里程碑意義的工作,經(jīng)常被援引為四人幫(GoF)的書,該書針對(duì)通常的設(shè)計(jì)問題分類整理出了23種特定的解決方案。1998年,他和Kent Beck組成團(tuán)隊(duì)開發(fā)JUnit[see Resources],這成為Java社區(qū)事實(shí)上的單元測(cè)試工具。Gamma現(xiàn)在是IBM的一名杰出工程師,他在位于瑞士蘇黎世的IBM Object Technology International(OTI)實(shí)驗(yàn)室工作。他擔(dān)任Eclipse社區(qū)的領(lǐng)導(dǎo)工作,負(fù)責(zé)Eclipse平臺(tái)[see Resources]上與Java開發(fā)相關(guān)的事務(wù)。
2004年10月27號(hào),Bill Venners 在加拿大溫哥華舉行的OOPSLA會(huì)議上遇到了Erich Gamma。在這次采訪中(這次采訪的內(nèi)容將分多次在Artima Developer的Leading-Edge Java頻道刊登出來),Gamma講述了軟件設(shè)計(jì)中深層次的東西。在這個(gè)系列的第一篇文章中,Gamma給出了他對(duì)于如何正確思考和使用設(shè)計(jì)模式的看法,并且描述了不同模式庫之間的差異,比如GoF和Alexandrian的模式語言。
設(shè)計(jì)模式的真正價(jià)值Bill Venners: Bruce Eckel 和我在教授設(shè)計(jì)模式課程,我們發(fā)現(xiàn)大家非常想了解四人幫(GoF)總結(jié)的那些模式。模式讓講座買的更火。圍繞設(shè)計(jì)模式有很多關(guān)于市場(chǎng)的噱頭可做。
Erich Gamma: 現(xiàn)在仍然這樣么,已經(jīng)過了10年了?
Bill Venners: 是的。大家想了解設(shè)計(jì)模式,而且我懷疑這很大程度上是因?yàn)椤澳J健比匀皇且粋€(gè)時(shí)髦的詞匯。我想繞過那些噱頭問問你人們到底該如何對(duì)待設(shè)計(jì)模式。他們對(duì)于設(shè)計(jì)模式的態(tài)度應(yīng)該是個(gè)什么樣子?人們?nèi)绾尾拍苁褂媚J桨压ぷ髯龅母錾克嬲膬r(jià)值到底是什么?
Erich Gamma: 我想模式作為一個(gè)整體可以幫助人們學(xué)習(xí)面向?qū)ο蟮乃枷耄耗闳绾尾拍苡煤枚鄳B(tài)(polymorphism),設(shè)計(jì)好組合(composition)和委托(delegation),平衡職責(zé),并且提供可插拔的行為(pluggable behavior)。相對(duì)于把對(duì)象應(yīng)用到繪畫圖形(graphical shape)的例子(有一個(gè)關(guān)于圖形的類層次和一些多態(tài)的draw方法),模式要更深入一些。當(dāng)你理解了模式以后,你就真正學(xué)會(huì)了多態(tài)。所以通常來說模式對(duì)于學(xué)習(xí)OO和設(shè)計(jì)是有好處的。
在此基礎(chǔ)上,每個(gè)單獨(dú)的模式都有不同的特性可以在某些地方為你提供幫助,比如你需要更大的靈活性或者需要封裝一個(gè)抽象或者需要讓你的代碼耦合的更松散的時(shí)候。這在大系統(tǒng)里確實(shí)是個(gè)大問題。如何保持你的分層?如何避免對(duì)向上的調(diào)用(up calls)或者循環(huán)依賴?GoF模式幾乎沒有提供什么工具幫助你解決這些問題。他們提供的幫助不是給你一個(gè)完美的解決方案而是通過解釋如何權(quán)衡利弊。盡管模式是從具體應(yīng)用中抽象出來的,他們?nèi)匀惶峁┙o你關(guān)于實(shí)現(xiàn)的有價(jià)值的線索。以我的觀點(diǎn)來看,正是因?yàn)槟J蕉际强蓪?shí)現(xiàn)的才使它們?nèi)绱擞袃r(jià)值。
模式都是從牛人的經(jīng)驗(yàn)里提取出來的。它們使你可以重復(fù)別人做過的成功的設(shè)計(jì)。這樣一來你就可以站在牛人的肩膀上,用不著重新發(fā)明輪子了。但是,因?yàn)槟J娇梢杂性S多實(shí)現(xiàn)上的變體,所以你仍然需要保持清醒的頭腦。最后,由于模式提供給你用于設(shè)計(jì)的積木塊的名稱,所以它們也提供給你用于描述和討論特定設(shè)計(jì)的一個(gè)詞匯表。
另一個(gè)問題是我們?cè)撊绾谓淌谀J?。我并不確切知道你該如何做,但是我想你不該做的一件事是用一個(gè)類來列舉23種模式。這么做并不能帶來任何好處。你必須得體會(huì)到一個(gè)有問題的設(shè)計(jì)所帶來的痛苦。我猜想只有感受到這種設(shè)計(jì)上的痛苦你才會(huì)認(rèn)識(shí)到某個(gè)模式的重要性。
Bill Venners: 什么痛苦?
Erich Gamma: 比如說意識(shí)到你的設(shè)計(jì)不夠靈活,一個(gè)小小的改動(dòng)會(huì)波及到整個(gè)系統(tǒng),你必須復(fù)制代碼,或者代碼變的越來越復(fù)雜。如果你在這樣一個(gè)棘手的情況下應(yīng)用某個(gè)模式,有可能會(huì)使這種痛苦消失并且后來還很舒服。當(dāng)你意識(shí)到,哦,實(shí)際上這個(gè)模式,工廠模式(factory)或者策略模式(strategy),是解決我的問題的方法,你會(huì)有一種恍然大悟的感覺。我想這才是教授設(shè)計(jì)模式真正有趣的方法。
我一開始教授設(shè)計(jì)模式的時(shí)候是非常單調(diào)乏味的,因?yàn)槲抑皇橇信e那些模式。我發(fā)現(xiàn)試著通過實(shí)際例子激發(fā)如何應(yīng)用模式會(huì)有趣的多。換句話說,你確實(shí)需要在現(xiàn)實(shí)背景中展示一個(gè)實(shí)際的例子——炮制出來的例子不管用。在OOPSLA的會(huì)議上我收到一本《Heads First Design Patterns》[see Resources]。這是一本很棒的書,不僅僅是因?yàn)樗x起來很有趣,而且還因?yàn)樗鼈兡軌蛲ㄟ^一種小說似的高度可視化的方法來傳達(dá)設(shè)計(jì)模式的本質(zhì)。
Bill Venners: 那么,是不是說模式的價(jià)值就是,當(dāng)我在現(xiàn)實(shí)世界中感受到某種特定的痛苦,我可以求助于某個(gè)已知的解決方案?
Erich Gamma: 毫無疑問,這是我推薦大家使用模式的方法。不要一開始就馬上把模式套進(jìn)某個(gè)設(shè)計(jì),而是當(dāng)你一邊深入并且對(duì)問題理解更多的時(shí)候才使用它們。因?yàn)檫@個(gè)原因,我更愿意在犯錯(cuò)誤之后使用模式,朝著模式的方向重構(gòu)(refactoring to patterns)。在模式剛剛開始變的更加流行的時(shí)候,我在一個(gè)新聞組里看到一條評(píng)論說,有人聲稱他們要在一個(gè)特定的程序里嘗試使用所有23種GoF模式。他們說他們失敗了,因?yàn)橹荒苡玫?0種。他們希望客戶會(huì)再叫他們回去,這樣他們可能就可以把剩下3種也加進(jìn)去。
試圖使用所有的模式是不好的做法,因?yàn)槟阕罱K得到的是人工臆想出來的設(shè)計(jì)——過于深思熟慮的設(shè)計(jì),有靈活性但卻沒有人需要用到?,F(xiàn)今的軟件都太復(fù)雜了。我們沒功夫推測(cè)它額外要做的事情。我們需要真正聚焦在它必需做的事情上。這就是為什么我喜歡朝著模式的方向重構(gòu)。人們應(yīng)該學(xué)會(huì)在碰到某個(gè)特定類型的問題或者代碼味道(現(xiàn)在大家都這么說)的時(shí)候,去他們的模式工具箱尋找一個(gè)解決方案。
Bill Venners: 真滑稽,因?yàn)槲业牡诙€(gè)問題是,我發(fā)現(xiàn)人們經(jīng)常覺得使用模式最多的設(shè)計(jì)是最好的設(shè)計(jì)。在我們講授設(shè)計(jì)的講座上,我讓參與者做一個(gè)設(shè)計(jì)項(xiàng)目,在講座結(jié)束的時(shí)候大家要把自己的設(shè)計(jì)講給別人聽。幾乎毫無例外,那些講述的人總是想炫耀他們?cè)谧约旱脑O(shè)計(jì)里使用了多少模式,盡管我試圖告訴他們目標(biāo)是要一個(gè)干凈,易于理解的API,而不是要他們贏得一個(gè)“看誰模式用的多”的比賽。我剛剛聽你說了同樣的事情,也就是說,這不是思考模式的正確方法。如果這種方法不對(duì),那么在設(shè)計(jì)里使用模式的正當(dāng)理由是什么呢?
Erich Gamma: 很多模式是關(guān)于擴(kuò)展性和重用性的。當(dāng)你確實(shí)需要擴(kuò)展性的時(shí)候,模式提供給你某種方法讓你實(shí)現(xiàn)它,而且這很酷。但是當(dāng)不需要它的時(shí)候,你應(yīng)該讓你的設(shè)計(jì)保持簡單并且不要添加不需要的抽象層。我們Eclipse的一條原則就是,我們只在要緊的地方需要擴(kuò)展性。實(shí)際上,如果你對(duì)我們?cè)贓clipse中是如何使用模式感興趣的話,我曾經(jīng)嘗試把模式的應(yīng)用提取出來放到《the Contributing to Eclipse》[see Resources]一書中的一個(gè)章節(jié)里。在這一章里,我使用設(shè)計(jì)模式解釋了Eclipse架構(gòu)的一些片斷。
Bill Venners: 說到擴(kuò)展性,您這是什么意思?
Erich Gamma: 就是說你可以定制行為,而不用觸及已經(jīng)存在的代碼——這是OO里面很經(jīng)典的一個(gè)主題。你可以重用針對(duì)特定問題調(diào)整過的某些東西。
被設(shè)計(jì)模式所包圍的核心抽象Bill Venners: 在您與Kent Beck合寫的一篇叫做“JUnit: A Cook's Tour” [see Resources]的文章中,你引領(lǐng)讀者沿著JUnit的設(shè)計(jì)路線,如您自己所寫的,“從零開始一個(gè)接一個(gè)的應(yīng)用模式,直到得到系統(tǒng)的架構(gòu)”。我想這種方法可能是受了Christopher Alexander的啟發(fā),他在建筑學(xué)上有關(guān)模式的工作激發(fā)了軟件模式的運(yùn)動(dòng)。您覺得把某個(gè)模式放置在另外一個(gè)模式的層次之上,直到最后完成設(shè)計(jì),這是一種有效的設(shè)計(jì)方法么?
Erich Gamma: “The Cook's tour”那篇文章多少有點(diǎn)人為炮制的痕跡。我們修整了JUnit原先的設(shè)計(jì)。然而,我們并不是以這么一種模式驅(qū)動(dòng)的方法開發(fā)JUnit的,事實(shí)上,我們是嚴(yán)格按照測(cè)試驅(qū)動(dòng)的方法來開發(fā)的。對(duì)于JUnit來說,它確實(shí)有一個(gè)針對(duì)測(cè)試的核心抽象,圍繞著這個(gè)核心抽象你會(huì)看到其它幾個(gè)設(shè)計(jì)要點(diǎn)顯現(xiàn)出來,這幾個(gè)設(shè)計(jì)要點(diǎn)又依次被模式實(shí)例具體化。這些東西是你在成熟設(shè)計(jì)里經(jīng)常能看到的。有一些關(guān)鍵抽象,你會(huì)經(jīng)常把他們看作一個(gè)設(shè)計(jì)的中心,圍繞這些關(guān)鍵抽象你希望完成各種各樣的事情。于是你就會(huì)看到模式從這樣一個(gè)中心不斷長出來。但是我不會(huì)把這個(gè)作為評(píng)判(軟件)質(zhì)量的標(biāo)準(zhǔn)。
Bill Venners: 這就是當(dāng)您說“模式密度(pattern density)”的時(shí)候所指的東西么?
Erich Gamma: 是的,確實(shí)如此,模式圍繞著某些中心抽象浮現(xiàn)出來的。
Bill Venners: 您說過測(cè)試用例(TestCase)是JUnit的核心抽象。
Erich Gamma: 準(zhǔn)確的說是由測(cè)試用例實(shí)現(xiàn)的測(cè)試接口,但是我們確實(shí)是從測(cè)試用例開始并且以它為基礎(chǔ)擴(kuò)展的。
Bill Venners: 那么,您能給密度(density)下個(gè)定義么?是指圍繞它的模式的個(gè)數(shù)么?您說過“JUnit Cook's Tour”那篇文章多少有點(diǎn)人為炮制的意思。
Erich Gamma: 炮制在某種意義上是說“the cooks tour”那篇文章是當(dāng)你去掉在我們的測(cè)試驅(qū)動(dòng)開發(fā)過程中所產(chǎn)生的所有測(cè)試活動(dòng)所剩下的東西。所以它是一個(gè)高度壓縮的陳述。密度從圍繞Test固定下來了的那些模式中顯現(xiàn)出來。
設(shè)計(jì)JUnit的時(shí)候,我們不是僅僅把模式捆綁在一起。我們用模式驅(qū)動(dòng)來做,從一個(gè)我們想要成功完成的測(cè)試開始,一旦它通過,我們會(huì)仔細(xì)看看如何能夠改善那些代碼。用測(cè)試驅(qū)動(dòng)的方法開發(fā)一個(gè)測(cè)試框架并不是說沒有沒有它的挑戰(zhàn)性,但是一旦基本的東西跑起來以后,會(huì)變得出奇的順利。你知道,Kent和我在開發(fā)JUnit的時(shí)候?qū)δJ椒浅J炀?。所以很自然,我們?huì)說諸如,“嘿,那是一個(gè)嵌套模式(composite)。” Composite是JUnit用到的一個(gè)模式。我們還使用了模板方法(template method)。這是很基本的一個(gè)模式。我們用過Command模式。這當(dāng)然是主要的一個(gè)。我們從測(cè)試開始并且說,“哦,這是一個(gè)command。哦,這是一個(gè)template。” 因?yàn)槲覀儗?duì)模式都很熟練,我們的交談進(jìn)行的非常的快,這使我們可以以高速度完成一個(gè)設(shè)計(jì)。
這實(shí)際上很好的說明了模式是如何為我們提供設(shè)計(jì)語匯的。當(dāng)你看一個(gè)UML圖的時(shí)候,情況也是類似的,你會(huì)看到方形和箭頭,但他們沒有真正告訴你在這些關(guān)系后面的含義。但是一旦你了解到那個(gè)模式,它就為你解釋了這些關(guān)系是到底是干嗎的。如果它是個(gè)觀察者模式(observer),那在兩個(gè)類之間為什么會(huì)有一個(gè)連線就很清楚了。那是因?yàn)橐粋€(gè)家伙要觀察另外一個(gè)家伙。你確切知道所發(fā)生的是什么。我猜這就是關(guān)鍵點(diǎn)。模式給了我們一種用于討論設(shè)計(jì)的語言。實(shí)際上,JUnit之旅并沒有結(jié)束,Kent和我現(xiàn)在還在忙于JUnit 4。我們?nèi)匀煌ㄟ^測(cè)試驅(qū)動(dòng)的方法不斷完善JUnit。我們有個(gè)想法就是要降低上手的門檻。為了達(dá)到這個(gè)目的,我們正在采用J2SE 5的中的某些功能,比如annotations,把JUnit弄得更加易于使用。
模式語言Bill Venners: 就Alexandrian的本意來說,什么是模式語言?
Erich Gamma: Alexander有一個(gè)非常遠(yuǎn)大的目標(biāo), 他想創(chuàng)造出可以提升生活質(zhì)量的建筑。為了完成這個(gè)目標(biāo),Alexander發(fā)展出了模式語言。這是一系列互相構(gòu)建于彼此之上的模式。模式語言指導(dǎo)設(shè)計(jì)者把單個(gè)的模式應(yīng)用到整個(gè)設(shè)計(jì)。我們開始弄設(shè)計(jì)模式的時(shí)候并沒有那么遠(yuǎn)大的理想。我們使用一種以微觀架構(gòu)(micro-architectures)為基礎(chǔ)的,更傾向于自底向上的方法。
Bill Venners: 您說的自底向上是什么意思?
Erich Gamma: 讓我往回一點(diǎn)說說我是如何進(jìn)入模式領(lǐng)域的。我想這可以回答你的問題。我曾經(jīng)和Andre Weinand一道開發(fā)ET++,這是一個(gè)龐大的C++類庫和框架。當(dāng)我深入思考ET++的時(shí)候,一個(gè)成熟的框架顯現(xiàn)了出來,它包括一些反復(fù)出現(xiàn)的設(shè)計(jì)結(jié)構(gòu)的,這些設(shè)計(jì)結(jié)構(gòu)能夠給你很多特性,諸如擴(kuò)展性,解藕,還有很重要的是——優(yōu)雅。這些結(jié)構(gòu)可以被認(rèn)為是為整個(gè)系統(tǒng)架構(gòu)做出貢獻(xiàn)的微觀架構(gòu)。最后我在自己的論文里以書面形式整理了十幾個(gè)這種微觀架構(gòu)。這種針對(duì)模式的方法有別于模式語言:它并不是以自頂向下的方法弄出一系列相互交織的模式,微觀架構(gòu)更傾向于是相互獨(dú)立而最終又以自底向上的方式相互關(guān)聯(lián)的模式。模式語言為你提供的知道貫穿整個(gè)設(shè)計(jì),而我們有的只是這些碎片式的,零星的工程學(xué)知識(shí)。我承認(rèn),這種做法目標(biāo)不夠遠(yuǎn)大,但是它仍然很重要并且很有用。
Bill Venners: 模式語言是不是就像持有一個(gè)上下文無關(guān)的語法,你可以用它來產(chǎn)生一大堆程序?
Erich Gamma:從抽象的層次上來說,它們之間有某些相似性。用一個(gè)語法可以定義一大堆程序,同樣的,模式語言可以產(chǎn)生一堆解決方案。Christopher Alexander是這么描述的,他說他的模式描述了某種解決方案,所以它就可以被多次應(yīng)用而沒必要每次都保持不變。但是我認(rèn)為到這個(gè)層次共同性就消失了。
Bill Venners: 說到產(chǎn)生,他是什么意思?如果我有一個(gè)上下文無關(guān)的語法,它并不能產(chǎn)生程序。我仍然的把它們寫出來。
Erich Gamma: 你仍然需要做決定,但是模式語言提供給你更多的指導(dǎo)而且它有一定的流程。比方說你想設(shè)計(jì)一個(gè)自己住著舒服的房間。他說,先在兩邊都放上燈。好,現(xiàn)在你在兩邊都放上了燈,下一步做什么?你如何安放窗戶?針對(duì)這個(gè)問題會(huì)有其它的模式描述一個(gè)解決方案。他基本上指導(dǎo)你布置整個(gè)空間。這種聯(lián)系正是一個(gè)模式庫(比如我們?cè)贕oF那本書里描述的那些)和模式語言的區(qū)別所在。我們發(fā)現(xiàn),這些微觀架構(gòu)實(shí)際上也不是孤島。它們之間也發(fā)生關(guān)系。我們?cè)谀潜緯姆饷娴膬?nèi)頁畫出了它們之間的關(guān)系,而且這是Alexander的擁護(hù)者認(rèn)為我們這本書唯一有價(jià)值的地方。
Bill Venners: 聽起來幾乎像是一個(gè)設(shè)計(jì)的方法論。你沿著這條路,一步步做下去,最后得到可以坐在里面的,漂亮而又舒服的房間。
Erich Gamma: 是的,當(dāng)你遵循Alexander的模式方法的時(shí)候,你就是在按照一定順序使用這些模式。我們并沒有限制一個(gè)特定的順序。如果你有問題,我們有相應(yīng)的解決方案,但是我們沒有下個(gè)步驟。我們不會(huì)給你暗示說下一步該干什么。就這種意義來說,Alexander的方法是更徹底的。JUnit采用了一點(diǎn)這種模式語言的方法,因?yàn)樗梢詭湍銓懸粋€(gè)測(cè)試用例。在JUnit的文檔里,Kent和我寫了一個(gè)關(guān)于如何實(shí)現(xiàn)一個(gè)測(cè)試的迷你型的模式語言。以一個(gè)測(cè)試作為開始,接下來你希望提取出公共的初始化代碼,然后你會(huì)希望給測(cè)試分組,等等。
下周 5月30號(hào),星期一,請(qǐng)您回來看與Erich Gamma這次談話的下一部分。如果你想收到Artima.com上新文章每周簡報(bào)的電子郵件,請(qǐng)訂閱 Artima Newsletter。
反饋 對(duì)本文中討論的設(shè)計(jì)模式話題有自己的觀點(diǎn)么?那么請(qǐng)到文章論壇里討論這個(gè)話題, The True Utility of Design Patterns.
資源Erich Gamma是《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》的合著者之一,可以在Amazon.com上找到這本書 :
http://www.amazon.com/exec/obidos/ASIN/0201633612/ Erich Gamma 是JUnit的作者之一,JUnit是事實(shí)上的Java單元測(cè)試標(biāo)準(zhǔn)工具:
http://www.junit.org/index.htm Erich Gamma 領(lǐng)導(dǎo)Eclipse平臺(tái)上與Java開發(fā)相關(guān)的事務(wù):
http://www.eclipse.org/ 《Head First Design Patterns》, 作者是 Elisabeth Freeman, Eric Freeman, Bert Bates, 和 Kathy Sierra, 這本書可以在Amazon.com上找到:
http://www.amazon.com/exec/obidos/ASIN/0596007124/ 你可以從Arima的樣章書庫(chapters library)下載《Head First Design Patterns》的一個(gè)免費(fèi)章節(jié) :
http://www.artima.com/chapters/book.jsp?num=90281 《Contributing to Eclipse: Principles, Patterns, and Plug-Ins》, 作者是 Erich Gamma 和 Kent Beck, 這本書可以在Amazon.com上找到:
http://www.amazon.com/exec/obidos/ASIN/0321205758/ JUnit: A Cook's Tour, 這是Erich Gamma 和Kent Beck寫的一篇文章, 這篇文章引領(lǐng)你沿著JUnit的設(shè)計(jì)路線,“從零開始一個(gè)接一個(gè)的應(yīng)用模式,直到得到系統(tǒng)的架構(gòu)”
http://junit.sourceforge.net/doc/cookstour/cookstour.htm 關(guān)于作者 Bill Venners 是Artima軟件公司的主席兼Artima Developer的主編。他是《Inside the Java Virtual Machine》一書的作者,該書從面向程序員的角度講述了Java平臺(tái)的架構(gòu)和內(nèi)幕。他在JavaWorld雜志上廣受歡迎的專欄覆蓋了Java內(nèi)幕,面向?qū)ο笤O(shè)計(jì),以及Jini。從Jini啟動(dòng)以來,Bill就活躍在這個(gè)社區(qū)。他領(lǐng)導(dǎo)Jini社區(qū)的ServiceUI項(xiàng)目,這個(gè)ServiceUI API成為連接用戶接口和Jini服務(wù)之間既成事實(shí)的標(biāo)準(zhǔn)方法。Bill還被選為Jini社區(qū)最初的技術(shù)監(jiān)管委員會(huì)(TOC)的一員,他擔(dān)任這個(gè)職務(wù)期間幫助定義了社區(qū)的管理流程。
posted on 2005-06-08 17:22
eamoi 閱讀(2796)
評(píng)論(0) 編輯 收藏 所屬分類:
Java