架構(gòu)設(shè)計最佳實踐之DRY
在軟件過程中的自我重復(fù),總的來說有五種類型:
(1) 一件事物,有多種的不同語言和方式來表達,不同的角色采用不同的語言去描述同一事物。在這些角色之間需要協(xié)同工作時造成的重復(fù)。
比如,架構(gòu)設(shè)計師用一種語言和方式描述其架構(gòu)設(shè)計,可為PPT、Word文檔、Visio、建模工具等。開發(fā)人員的工作語言則是程序代碼。兩種角色描述的是同一事物,只是描述語言不同而已,這樣造成架構(gòu)設(shè)計師的架構(gòu)輸出,不能作為開發(fā)人員的開發(fā)輸入,而不能被開發(fā)人員重用,導(dǎo)致一定的自我重復(fù)。這就像一個人用英文寫書,一個人用中文寫書,內(nèi)容類似,那么中文作者要么重新整理內(nèi)容并書寫書籍,要么就翻譯英文書籍,不管哪種,造成重復(fù)工作勞動是在所難免。
對于此類的自我重復(fù),隨著模型驅(qū)動的成熟和廣泛應(yīng)用將逐漸減少。模型驅(qū)動架構(gòu)中業(yè)務(wù)建模、架構(gòu)建模和程序編碼等之間,通過Unified Modeling Language(UML)、the Meta-Object Facility (MOF)、XML Metadata Interchange (XMI)和自動化代碼生成等語言、標(biāo)準(zhǔn)和技術(shù)進行互相轉(zhuǎn)換,達到Don't Repeat Yourself。如下圖所示:

傳統(tǒng)的開發(fā)過程中,需求、分析、設(shè)計、開發(fā)等各個階段,可能采用不同的描述語言和方式,互相之間也較難轉(zhuǎn)換,所以他們之間不能無縫的相互轉(zhuǎn)換,造成了重復(fù)溝通、理解和建模。
模型驅(qū)動開發(fā),在開發(fā)過程的每個階段基于標(biāo)準(zhǔn)和轉(zhuǎn)換工具,所以每一個階段的成果,都可以被下一個階段復(fù)用,消除重復(fù)。這也是標(biāo)準(zhǔn)的魅力之一吧。
(2) 同一件事物,不同的人各描述了該事物的不同方面,造成他們之間所描述的事物既類似又不同,有重復(fù)的地方,又不完全一樣,導(dǎo)致自我重復(fù)。
比如,銀行中的用戶信息模塊,在"網(wǎng)上銀行"、"公積金貸款",和"信用卡系統(tǒng)"中各自都可能有一個模塊,從數(shù)據(jù)庫、到邏輯、到界面都各自重復(fù)一套,他們之間既類似又有一些區(qū)別,如需要的信息不一樣。導(dǎo)致這些模塊之間的自我重復(fù)。
對于此類的自我重復(fù),是由架構(gòu)設(shè)計導(dǎo)致,在架構(gòu)設(shè)計階段沒有按照"組件化"、"服務(wù)化"和"層次化"的架構(gòu)設(shè)計,造成在一個事物不能符合不同模塊和系統(tǒng)的需求,并且無法擴展。
這種自我重復(fù),在企業(yè)的遺留系統(tǒng)和新系統(tǒng)之間尤為明顯。因為大多企業(yè)的老系統(tǒng)在構(gòu)建時由于技術(shù)、組織結(jié)構(gòu)等原因,都是采用垂直的渠道架構(gòu),即存儲層、邏輯層、展現(xiàn)層完全重新實現(xiàn),甚至連技術(shù)框架都和其他渠道相異。如某銀行業(yè)的多渠道應(yīng)用中,不同渠道(如網(wǎng)上銀行和手機銀行)的邏輯類似,但在兩個系統(tǒng)中重用性不高,存在著大量的自我重復(fù)。如下圖左所示:

隨著SOA(Service Oriented Architecture)的廣泛使用,再輔助以層次化架構(gòu),能有效解決此類問題。
重復(fù)的組件要被重用,就需要是組件化的,并且能夠被訪問到。EJB、Web Service以及相應(yīng)的組件化、基于服務(wù)的設(shè)計思想,一定程度解決了這些問題,緩和了在企業(yè)架構(gòu)中的重用性問題。
而層次化的架構(gòu)設(shè)計則既是解決架構(gòu)重復(fù)的途徑,也是結(jié)果。層次化的架構(gòu)演變過程,可以在人類社會發(fā)展過程中找到似曾相似的影子。在人類社會中,任何事情重復(fù)到一定程度,就會產(chǎn)生一個新的職業(yè)或階層,比如,找房子的人多了,就自然會產(chǎn)生中介。在架構(gòu)設(shè)計中也是一樣。任何設(shè)計重復(fù)到一定程度,就應(yīng)該抽象出新的層次。這個層次也許可以作為一個新的組件,也可能做出一個新的產(chǎn)品。
上圖2右邊的架構(gòu),是銀行多渠道整合的架構(gòu)設(shè)計,是基于SOA架構(gòu)的、多層次高度重用的架構(gòu)設(shè)計,銀行在新增一個渠道(如增加ATM渠道)時,能夠重用大量的其他渠道的組件。
(3) 沒有自我重復(fù),但重復(fù)別人。指一個功能有很好的免費開源框架或者標(biāo)準(zhǔn)可以依據(jù),但設(shè)計開發(fā)時沒有采用,而重新發(fā)明輪子,導(dǎo)致不能重用已有的標(biāo)準(zhǔn)或開源框架的優(yōu)勢。
記得幾年前參加的一個企業(yè)信息管理系統(tǒng)的產(chǎn)品開發(fā),該產(chǎn)品從底層MVC框架開始開發(fā),還開發(fā)了界面UI控件、自己的XML流程引擎實現(xiàn)等,然后才是在這個基礎(chǔ)上開發(fā)該企業(yè)的信息管理系統(tǒng)。最后結(jié)果如何可想而知:投入產(chǎn)出比失衡,以失敗告終。這是一個典型的"沒有重復(fù)自己,但重復(fù)標(biāo)準(zhǔn)或免費成熟框架"的例子。
在商業(yè)中的專業(yè)分工、競爭優(yōu)勢理論和軟件架構(gòu)思想有很多相通之處。一個開飯店的,不應(yīng)該去種大米、白菜或養(yǎng)豬,而應(yīng)該抓住自己的核心競爭優(yōu)勢,開好飯店。相同的,種菜的、養(yǎng)豬的,也不應(yīng)該無緣無故跑去開飯店。除非他們各自都想轉(zhuǎn)行,進入另外的專業(yè)化分工領(lǐng)域,同另外領(lǐng)域內(nèi)公司競爭。
在軟件業(yè)中也是一樣的道理,每個產(chǎn)品都有其核心競爭力,每個產(chǎn)品都應(yīng)該把握住本產(chǎn)品的核心競爭力,并投入最大的人力物力去經(jīng)營。而對于其它的標(biāo)準(zhǔn)、輔助工具、框架或產(chǎn)品等,應(yīng)該持開放的態(tài)度,復(fù)用已有的標(biāo)準(zhǔn)、成熟框架或產(chǎn)品。當(dāng)然,除非你想重新定位你的產(chǎn)品。
這種類型的錯誤技術(shù)人員經(jīng)常會犯,但作為產(chǎn)品的架構(gòu)設(shè)計師,應(yīng)該盡量杜絕這種錯誤的發(fā)生。
(4) 開發(fā)過程中信息重復(fù),如軟件過程中用到的工具(項目管理系統(tǒng)、開發(fā)工具、測試計劃及用例、Build工具、版本管理工具等)之間的信息重復(fù);還有軟件過程中各種角色的溝通重復(fù),如開發(fā)人員報告進度給開發(fā)組長、開發(fā)組長又重新報告進度給項目經(jīng)理等。如下圖所示:

對這一類型的自我重復(fù),一個集成的協(xié)作平臺能解決問題?;谶@個協(xié)作平臺,軟件過程中所有角色、工具和流程都能無縫的協(xié)作,消除了信息重復(fù)和溝通重復(fù),加快開發(fā)效率。如下圖所示:所有的工具無縫集成,消除了信息重復(fù);所有的角色都基于一個協(xié)作平臺,能夠?qū)嵤┓从钞a(chǎn)品的狀態(tài)、信息、各種歷史記錄等,極大降低了溝通重復(fù)。
(5) 缺乏重構(gòu)導(dǎo)致自我重復(fù)。這一種自我重復(fù)是最幼稚且低級的重復(fù),但在很多產(chǎn)品的代碼和文檔也大量存在。一個功能在不同模塊中重復(fù)拷貝使用、對象繼承和組合關(guān)系混亂、文檔關(guān)系混亂等都屬于這一類的問題。
對于這一類型的自我重復(fù),對軟件進行持續(xù)重構(gòu)是唯一的好方法。代碼重構(gòu)具體請參考《重構(gòu)》這本書;至于文檔重復(fù),大家不妨把《重構(gòu)》的思想應(yīng)用于文檔,也必有所得。
總結(jié)
Don't Repeat Yourself,是軟件開發(fā)的最佳實踐,良好的軟件開發(fā)應(yīng)該是非自我重復(fù)的,同樣按照非自我重復(fù)思想設(shè)計開發(fā)的軟件,往往是好的軟件。
· DRY,消除軟件開發(fā)的各個階段之間的重復(fù),以客戶和需求為中心,加快開發(fā)速度。
· DRY,遵循"組件化"、"服務(wù)化"、"層次化"的架構(gòu)設(shè)計,使得架構(gòu)清晰,層次分明,并易于重用。
· DRY,不自我重復(fù),也不重復(fù)別人,特別是標(biāo)準(zhǔn)和成熟的開源框架,使得架構(gòu)開放,穩(wěn)定,并減少成本。
· DRY,不重復(fù)信息,不重復(fù)溝通,改進管理流程,加快開發(fā)速度,達到有效溝通。
· DRY,持續(xù)重構(gòu)代碼,文檔等,保持軟件簡介、清晰,便于維護。
【編輯推薦】