设计的核心任务之二:信息隐藏
假使說我們認(rèn)同軟件的構(gòu)造是一個(gè)復(fù)雜的過程,那么管理這種復(fù)雜度必然需要一些技巧。而為了找出這些技巧,則需要先瞄一眼這種復(fù)雜度的基本構(gòu)成。
?
?
軟件的構(gòu)造過程牽涉了兩個(gè)最為基本的要素:一是軟件,一是構(gòu)造軟件的人。
假設(shè)說存在著一個(gè)標(biāo)準(zhǔn)的人,這個(gè)人智力水平恒定,創(chuàng)新能力恒定,技能水平恒定。那么軟件的復(fù)雜度只決定于其自身,比如軟件所需要面對的業(yè)務(wù)規(guī)則,所需要的計(jì)算水平等。應(yīng)對這類復(fù)雜度的有效手段是優(yōu)化方法,好比說快速排序的效率大多時(shí)候就是比冒泡排序好。
?
當(dāng)我們開始考慮人的可變因素時(shí),復(fù)雜度的來源則發(fā)生了變化。人是有著許多與生俱來的特質(zhì)的,比如說:人是會犯錯(cuò)的,人同一時(shí)間可以處理的事情是有限度的。因?yàn)檫@些特性,人在應(yīng)對軟件自身所擁有的復(fù)雜度的同時(shí),又帶來了偶然的,與個(gè)人特質(zhì)相關(guān)的復(fù)雜度。比如說:局部變量的名稱可能碰巧和一個(gè)全局變量相同,而我們又誤把這個(gè)局部變量作為全局變量使用了。
?
信息隱藏則是減少這類偶然性復(fù)雜度的一個(gè)有效手段。
對于方法或函數(shù)而言,輸入?yún)?shù),輸出參數(shù)描述了它的邊界。
對于類而言,公有屬性和公有方法描述了它的邊界。
邊界以內(nèi)的即是被隱藏掉的信息。
?
?
假設(shè)說我們用一個(gè)名為CustomerManager的類來管理客戶的基本信息,但在開放出AddCustomer(),?EditCustomer(),DeleteCustomer()這樣接口的同時(shí),也開放了內(nèi)部存放客戶信息的集合類。那么使用CustomerManager類的人,很可能直接通過操作集合類來獲取客戶信息。這個(gè)做法雖然可以被編譯器所接受,但實(shí)際上是對CustomerManager類的誤用。為了避免這類誤用,存放客戶信息的集合類應(yīng)該被隱藏起來,讓用的人只看到接口。
?
信息隱藏是抽象數(shù)據(jù)類型,類等之所以存在的一個(gè)比較主要的理由。但信息隱藏并不只在使用抽象數(shù)據(jù)類型和類的時(shí)候才有意義。定義接口的時(shí)候,甚至實(shí)現(xiàn)的時(shí)候信息隱藏這一原則同樣可以發(fā)揮作用。
比如說:實(shí)現(xiàn)方法A的時(shí)候,實(shí)際上只需要類的兩個(gè)屬性,但卻把整個(gè)類定義成了這個(gè)方法的參數(shù),這也是違背信息隱藏原則的。
?
?
還有一種比較有意思的情況是,目的是信息隱藏,但實(shí)際上卻違背了信息隱藏原則。
比如說:類的方法中常常會使用到成員變量。有時(shí)候和類自身關(guān)聯(lián)不是很緊密的屬性也會被添加為成員變量。像表征數(shù)據(jù)庫的類,比如DataBase,大多時(shí)候并不需要和獲取數(shù)據(jù)的類,比如傳感器的類Sensor直接關(guān)聯(lián),但有時(shí)候Sensor的實(shí)例卻會被添加為DataBase的私有成員變量。
?
與此同時(shí),大多時(shí)候類中的方法并不會把成員變量作為自身的參數(shù),而是會直接使用,比如說:由于Sensor的實(shí)例是DataBase的私有成員變量,那么DataBase::GatherData()在用到Sensor實(shí)例的時(shí)候會直接使用,而不會把接口定義為.DataBase::GatherData(Sensor&?sensor?)。這種用法與成員變量過度膨脹的趨勢撞在一起后,有意思的事情發(fā)生了。
?
從外部看,傳感器這樣的成員變量是私有的,達(dá)到了信息隱藏的目的。
但對于方法而言,結(jié)果卻完全相反。
每多使用一個(gè)成員變量,其自身的信息隱藏就被破壞一點(diǎn)?。
?
如果在同一方法中,用到五六個(gè)成員變量,那么這個(gè)方法會變得非常難懂。因?yàn)閷τ陬愔械姆椒ǘ?#xff0c;這些成員變量自身的變化是完全不被隱藏的,每個(gè)都有有自己獨(dú)立的脈絡(luò),比如說:DataBase::SetInterval()方法中可能會調(diào)整Sensro實(shí)例的狀態(tài),進(jìn)而對Sensor::GatherData()產(chǎn)生影響。這會導(dǎo)致方法的邊界不清晰。不清晰,也就不可能緊湊。不緊湊意味著閱讀的時(shí)候,一個(gè)方法所需要的信息不能立刻獲取。最終會導(dǎo)致程序難讀,難改,難維護(hù)。
?
這類實(shí)例提醒我們,并非把很多操作和數(shù)據(jù)成員都放到類里面就達(dá)成了信息隱藏的目的。
事實(shí)上這對每個(gè)類的可能規(guī)模提出了限制。極端的情況下,如果一個(gè)類很大,有2000SLOC,那么所有這2000SLOC代碼就等于通過成員變量粘結(jié)在一起,這和過度使用全局變量在一定程度上等價(jià)。
?
從信息隱藏的程度上來看,對方法而言,局部變量最佳,類的成員或?qū)傩陨圆?#xff0c;全局變量最差。
局部變量把信息隱藏在方法之內(nèi),成員或?qū)傩园研畔㈦[藏在類之內(nèi),而全局變量等于不做信息隱藏。
?
?
?
信息隱藏和前面提到的層次問題并不能分割開來。從基本趨勢來看,信息隱藏做的越徹底,層次也必然就會越多。而前面曾經(jīng)提及過層級自身是有副作用的。
?
從最小化層次的副作用的角度來看,使用函數(shù)或方法來隱藏?cái)?shù)據(jù),使用類似抽象數(shù)據(jù)類型的方法來把數(shù)據(jù)封裝到類之中,代價(jià)非常微小,幾乎總是對的。但在類A中包含B,類B中包含C,類C中包含D這類的方式則福禍難料。誠然B,C,D被隱藏了,但絕不是毫無代價(jià)。
?
?
--------------------------------------------------------------
?
理想流 + 軟件 =?《完美軟件開發(fā):方法與邏輯》
理想流 + 人生 = ??
理想流 + 管理 = ??
理想流 = 以概念和邏輯推演本質(zhì),追求真理。
?
總結(jié)
以上是生活随笔為你收集整理的设计的核心任务之二:信息隐藏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: erlang/thrift快速安装
- 下一篇: 返璞归真的Open×××的p2p模式