十分细微的收获
No way to no bug?
規(guī)格化設(shè)計(jì)的大致發(fā)展歷史
從一位大師的演講談起:
The major cause of the software crisis is that the machines have become several orders of magnitude more powerful! To put it quite bluntly: as long as there were no machines, programming was no problem at all; when we had a few weak computers, programming became a mild problem, and now we have gigantic computers, programming has become an equally gigantic problem. —?Edsger Dijkstra, The Humble Programmer (EWD340), Communications of the ACM在我看來(lái),他的意思是“編程”的復(fù)雜度隨著計(jì)算機(jī)性能的提升和需求的提升而增加了。復(fù)雜度提高意味著“單人作戰(zhàn)”和“閃電戰(zhàn)”不再適應(yīng)當(dāng)時(shí)的需求,勢(shì)必需要一種體系來(lái)支持“團(tuán)隊(duì)協(xié)作”和“持久戰(zhàn)”。這在過(guò)去科技發(fā)展的進(jìn)程中并非沒(méi)有類似經(jīng)驗(yàn):產(chǎn)品的生產(chǎn)如何從手工作坊制造到工場(chǎng)集中生產(chǎn)再到工業(yè)化生產(chǎn)的?規(guī)格化,標(biāo)準(zhǔn)化是其中重要的推動(dòng)力。編程領(lǐng)域的發(fā)展也是這樣,需要規(guī)格化設(shè)計(jì)來(lái)支撐起“工業(yè)級(jí)別”的編碼工程。
支持這一說(shuō)法的證據(jù)之一是:有“一攬子”軟件工程失敗了,這些工程復(fù)雜度高投入人力物力大,但卻依然以失敗告終。
| 1980s | 1993 | TAURUS | £75m |
| 1984 | 1990 | RISP | £63m |
| 1997 | 2000 | Bolit | $35m |
雖然導(dǎo)致軟件項(xiàng)目失敗的因素較為復(fù)雜,但從工程角度而言,沒(méi)有進(jìn)行規(guī)格化設(shè)計(jì)是關(guān)鍵因素之一。這說(shuō)明有需要“革新”的需求。
于是軟件工程開(kāi)始成為人們研究的重點(diǎn),人們期望研究出如何用系統(tǒng)化、規(guī)范化、數(shù)量化等工程原則和方法去進(jìn)行軟件的開(kāi)發(fā)和維護(hù),以降低軟件工程的失敗率。
期間出現(xiàn)和很多理論和優(yōu)秀的工程語(yǔ)言,而發(fā)展到現(xiàn)在,出現(xiàn)了JSF這樣的規(guī)格設(shè)計(jì)要求。 但,很不幸,現(xiàn)在依然有不少以失敗告終的軟件工程項(xiàng)目。wiki: List of failed and overbudget custom software projects
作業(yè)規(guī)格分析
規(guī)格BUG
- THREAD_EFFECTS
容易遺漏synchronized方法的lock()規(guī)格。
沒(méi)有其它規(guī)格問(wèn)題被發(fā)現(xiàn)。
規(guī)格 bug 產(chǎn)生的原因
完成工程的順序錯(cuò)了。應(yīng)當(dāng)先設(shè)計(jì)架構(gòu),細(xì)化為規(guī)格,在實(shí)現(xiàn)具體的代碼。否則在代碼實(shí)現(xiàn)后人工撰寫規(guī)格似乎意義不大——這項(xiàng)工作可以用自動(dòng)化的方式完成。
在構(gòu)建完代碼后再研究規(guī)格,容易產(chǎn)生:先入為主,想當(dāng)然等思維定勢(shì)。似乎這樣的方法在“利用”人的思維缺陷,而非幫助人避開(kāi)這些問(wèn)題。
之后的代碼構(gòu)建過(guò)程中應(yīng)當(dāng)注意設(shè)計(jì)和代碼構(gòu)建的順序。
前置條件
```* @REQUIRES: graphMatrix!=null; taxiGUI!=null; 0<=ID<100; time>0; _lights!=null; taxiCAL!=null;* graphMatrix.length==80;* (\all int i;0<i<=79; graphMatrix[i].length==80);* _lights.repOK() == true;* _taxiGUI.repOK() == true;* taxiCAL.repOK() == true; ``` 1. 先寫基本需求。 2. 分行列詳細(xì)需求。 3. 利用repOK()。 4. 限定嚴(yán)格的邊界條件。 5. 使用邏輯表達(dá)式后置條件
``` * (\this.type == rq.type && rq.startPosition == \this.startPosition && rq.endPosition == this.endPosition && rq.startWindowTime == this.startWindowTime)==>\result == true;* (!(\this.type == rq.type && rq.startPosition == \this.startPosition && rq.endPosition == this.endPosition && rq.startWindowTime == this.startWindowTime))==>\result == false;``` 1. 構(gòu)建代碼運(yùn)行分支。 2. 按分支構(gòu)建前件與后件。 3. 考慮異常情況。 4. 使用`==`。 5. 不過(guò)于糾結(jié)如何用邏輯表達(dá)式表示函數(shù)調(diào)用。基本思路和體會(huì)
JSF寫得越接近純bool表達(dá)式越好,在沒(méi)有自動(dòng)化邏輯檢測(cè)工具的情況下,這樣的方式在互測(cè)中比較占優(yōu)勢(shì)。
寫在后面
LSP設(shè)計(jì)原則
本系統(tǒng)中涉及到繼承的主要有兩類:Request和Taxi。
注意到這兩個(gè)類的主要的public方法在重載時(shí)都不改變?cè)蟹椒ǖ腅FFECTS,而是在原有方法的基礎(chǔ)上進(jìn)行擴(kuò)展,這使得外部調(diào)用者在調(diào)用子類public方法時(shí)得到的效果包含了調(diào)用父類相同方法的效果,這就使得外部調(diào)用任何父類出現(xiàn)的地方都可以使用子類來(lái)代替,并不會(huì)導(dǎo)致使用相應(yīng)類的程序出現(xiàn)錯(cuò)誤。
在實(shí)際實(shí)現(xiàn)的過(guò)程中也是以父類來(lái)統(tǒng)一管理不同的子類對(duì)象的,如TaxiHandler中的taxiList為Taxi數(shù)組,但卻管理了Sutaxi和Taxi。
舉例 Sutaxi -> Taxi
- public synchronized boolean setRequest (Request rq, TaxiStatusPackage p)
可見(jiàn),其返回值相關(guān)的約束條件與父類相同,但是增添了一些SuTaxi本身所需的功能。不影響Taxi約束。
接口
如何保證類的封裝行駛一個(gè)很復(fù)雜的問(wèn)題,這里討論一種特殊情況的解決方式:在某個(gè)類執(zhí)行完某些請(qǐng)求后其他類要執(zhí)行后續(xù)步驟,但其他類又不應(yīng)屬于執(zhí)行某請(qǐng)求的類。
例如:
出租車在更新位置之后要讓請(qǐng)求知道其是否進(jìn)入了請(qǐng)求搶單范圍,而在我的設(shè)計(jì)中,出租車不應(yīng)該負(fù)責(zé)與請(qǐng)求的這類交互操作。如何解決?——接口。
代碼樣例如下:
- TaxiHandler
Taxi中預(yù)留了空接口:
/*** @REQUIRES: NONE* @MODIFIES: NONE* @EFFECTS: NONE*/ public void afterMove(TaxiStatusPackage e, long curTime) {}轉(zhuǎn)載于:https://www.cnblogs.com/neolinsu/p/9112989.html
總結(jié)
- 上一篇: Redis数据库如何实现读写分离
- 下一篇: Zookeeper是什么?