第一部分 打好基礎(chǔ) Laying the Foundation
- 第一章 歡迎進(jìn)入軟件構(gòu)建的世界 Welcome to Software Construction
- 什么是軟件的構(gòu)建
- 定義問(wèn)題
- 需求分析
- 規(guī)劃構(gòu)建
- 軟件架構(gòu) 或者 高層設(shè)計(jì)
- 詳細(xì)設(shè)計(jì)
- 編碼與調(diào)試
- 單元測(cè)試
- 集成測(cè)試
- 集成
- 系統(tǒng)測(cè)試
- 保障維護(hù)
- 總結(jié)
- 軟件構(gòu)建是軟件開(kāi)發(fā)中唯一不可缺少的部分李丰,也就是必須完成的部分
- 軟件的構(gòu)建主要包括:詳細(xì)設(shè)計(jì)炭臭、編碼調(diào)試、集成和開(kāi)發(fā)者測(cè)試(單元測(cè)試和集成測(cè)試)
- 你對(duì)軟件構(gòu)建的理解程度決定 程序員的優(yōu)秀程度
- 第二章 用隱喻來(lái)更充分地理解軟件開(kāi)發(fā) Metaphors for a Richer Understanding of Software Development
- 第三章 三思而后行:前期準(zhǔn)備 Measure Twice, Cut Once: Upstream Prerequisites
- 第四章 關(guān)鍵的『構(gòu)建』決策 Key Construction Decisions
第二部分 創(chuàng)建高質(zhì)量的代碼 Creating-High Quality Code
- 第五章 軟件構(gòu)建中的設(shè)計(jì) Design in Construction
- 第六章 可以工作的類(lèi) Working Classes:抽象是以簡(jiǎn)化方式看待復(fù)雜操作的能力
- 6.1類(lèi)的基礎(chǔ):抽象數(shù)據(jù)類(lèi)型 ADTs
- ADT,abstract data type 抽象數(shù)據(jù)類(lèi)型职车。它指的是一些數(shù)據(jù)及對(duì)這些數(shù)據(jù)的操作的集合遮斥。這里的"數(shù)據(jù)",不僅僅是數(shù)學(xué)上或者軟件工程中的數(shù)據(jù)克婶,而是現(xiàn)實(shí)世界中可以操作的實(shí)體
- ADT 的好處:
- 隱藏實(shí)現(xiàn)細(xì)節(jié)(可能會(huì)有后續(xù)操作)
- 容易改動(dòng)(更改數(shù)據(jù)結(jié)構(gòu)筒严,優(yōu)化提高性能)
- 讓接口提供更多信息(通過(guò)名稱(chēng))
- 可讀性提高
- 不需要多次傳值(相關(guān)操作需要用到變量都放在ADT里面了)
- 把常見(jiàn)的底層數(shù)據(jù)類(lèi)型(棧 隊(duì)列)創(chuàng)建為ADT并使用
如出場(chǎng)演員名單(底層數(shù)據(jù)類(lèi)型是列表)
- 對(duì)于應(yīng)用層面上ADT,最好在原有ADT的基礎(chǔ)上創(chuàng)建一個(gè)針對(duì)現(xiàn)實(shí)世界問(wèn)題的抽象層次情萤。
- 簡(jiǎn)單的事情可以抽取成ADT(方便擴(kuò)展后續(xù)操作)
- 在支持面向?qū)ο蟮恼Z(yǔ)言鸭蛙,ADT可以用自己的class(類(lèi))實(shí)現(xiàn)。class=ADT+繼承+多態(tài)
- 6.2良好的類(lèi)接口:用接口去展示抽象筋岛,確保細(xì)節(jié)隱藏在抽象背后
- 接口中的每個(gè)子程序都朝著這個(gè)一致的目標(biāo)而工作
- 類(lèi)的接口要展示一致的抽象層次娶视,一個(gè)類(lèi)只能實(shí)現(xiàn)一個(gè)ADT,不然就要拆分
- 要理解類(lèi)要抽象出什么功能睁宰,避免把使用的類(lèi)庫(kù)或者容器類(lèi)暴露出來(lái)
- 盡可能讓接口可編程(programatic,編譯器強(qiáng)制要求)肪获,而不是表達(dá)語(yǔ)義(sematic,通過(guò)方法名和注釋)寝凌。
比如多個(gè)類(lèi)的初始化有先后順序;一個(gè)類(lèi)沒(méi)有初始化調(diào)用會(huì)報(bào)錯(cuò)
- 擴(kuò)展的時(shí)候要注意新增公用方法的 抽象的一致性
- 不要對(duì)類(lèi)的使用者做任何假設(shè)孝赫,接口已經(jīng)隱含了契約(接口已經(jīng)提供了調(diào)用的條件說(shuō)明)
- 語(yǔ)義上的封裝比語(yǔ)法上的封裝要困難(公用接口不要暴露內(nèi)部實(shí)現(xiàn)和數(shù)據(jù))
P142 很多例子
- 封裝和抽象要么兩者皆有硫兰,要么全部沒(méi)有
- 6.3有關(guān)設(shè)計(jì)和實(shí)現(xiàn)的問(wèn)題:包含/繼承/成員函數(shù)/數(shù)據(jù)成員/類(lèi)之間的耦合性
- 包含(has a "有一個(gè)的關(guān)系"):數(shù)據(jù)成員的限制:7-+2
數(shù)據(jù)成員都是基本數(shù)據(jù)類(lèi)型,數(shù)據(jù)成員不超過(guò)9寒锚;數(shù)據(jù)成員都是復(fù)雜對(duì)象劫映,數(shù)據(jù)成員不超過(guò)5
- 繼承(is a “是一個(gè)的關(guān)系”)(使用時(shí)會(huì)增加復(fù)雜度,有違軟件的技術(shù)使命-管理復(fù)雜度的)
- 要考慮方法和屬性對(duì)派生類(lèi)是否可見(jiàn)刹前,方法是否要有默認(rèn)的實(shí)現(xiàn)泳赋,是否可以覆蓋?
- 繼承要符合里氏替換原則:對(duì)于基類(lèi)定義的接口喇喉,在派生類(lèi)的語(yǔ)義應(yīng)該是相同的
- 不要覆蓋不可覆蓋的方法(不要新建一個(gè)與基類(lèi)的private相同的方法)
- 只有一個(gè)派生類(lèi)祖今,可能犯了提前設(shè)計(jì)的毛病
- 繼承不要超過(guò)2-3層,派生類(lèi)總數(shù)不超過(guò)該7+-2個(gè)拣技;
- 盡可能讓數(shù)據(jù)讓數(shù)據(jù)時(shí)private千诬,因?yàn)?strong>繼承會(huì)破壞封裝
- 如果多個(gè)類(lèi)共享數(shù)據(jù)而非行為,創(chuàng)建這些類(lèi)包含共用對(duì)象
- 如果多個(gè)類(lèi)共享行為而非數(shù)據(jù)膏斤,在基類(lèi)定義接口徐绑,繼承基類(lèi)
- 如果多個(gè)類(lèi)共享行為和數(shù)據(jù),在基類(lèi)定義接口和數(shù)據(jù)成員莫辨,繼承基類(lèi)
- 當(dāng)你想由基類(lèi)控制接口時(shí)傲茄,用繼承,由自己控制接口沮榜,用包含
- 成員函數(shù)和數(shù)據(jù)成員:
-
減少以下數(shù)字的數(shù)量
- 所實(shí)例化對(duì)象的種類(lèi)
- 調(diào)用實(shí)例化對(duì)象的子程序的數(shù)量
- 調(diào)用由其他對(duì)象返回對(duì)象的子程序數(shù)量
- 子程序的數(shù)量
- 構(gòu)造函數(shù)
- 盡可能在構(gòu)造函數(shù)中初始化全部數(shù)據(jù)成員
-
減少以下數(shù)字的數(shù)量
- 6.4創(chuàng)建類(lèi)的原因
- 對(duì)現(xiàn)實(shí)對(duì)象的建模
- 對(duì)抽象對(duì)象的建模(如shape就是抽象對(duì)象盘榨,得出恰當(dāng)?shù)某橄髮?duì)象很重要)
- 降低復(fù)雜度(調(diào)用類(lèi)的接口不用關(guān)心實(shí)現(xiàn)細(xì)節(jié))
- 隔離復(fù)雜度
- 隱藏實(shí)現(xiàn)細(xì)節(jié)
- 限制變化的影響范圍
- 隱藏全局?jǐn)?shù)據(jù)
- 讓參數(shù)傳遞更流暢
- 創(chuàng)建中心控制點(diǎn)
- 讓代碼重用
- 為程序族做規(guī)劃
- 把相關(guān)操作放在一起(子程序的組合)
- 實(shí)現(xiàn)特定的重構(gòu)
- 6.5與具體編程語(yǔ)言有關(guān)的問(wèn)題
- 6.6超越類(lèi):包
- 類(lèi)的質(zhì)量核對(duì)表P157-P158
- 第七章 高質(zhì)量的子程序 High-Quality Routines
- 7.1 創(chuàng)建子程序(routines)的正當(dāng)理由:提高程序管理能力,包括提高可讀性蟆融、可靠性和可修改性草巡,節(jié)省代碼空間是次要,或者是副作用(side effect)型酥。
- 降低復(fù)雜度
- 引入中間山憨,易懂的抽象
- 避免重復(fù)
- 支持子類(lèi)化(subclassing)
- 隱藏順序
- 隱藏指針操作
- 提高可移植性
- 簡(jiǎn)化布爾判斷
- 改善性能
- 確保所有程序都很小
- 7.2 在子程序?qū)由显O(shè)計(jì)(Design at the Routine Level):抽象和封裝理念適合類(lèi)層次的設(shè)計(jì),內(nèi)聚性適合子程序設(shè)計(jì)
- 內(nèi)聚性(cohesion):指子程序中各種操作之間聯(lián)系的緊密程度冕末。(一個(gè)子程序就干一個(gè)活)
- 功能內(nèi)聚性:一個(gè)子程序只干一件事情
- 以下是不夠理想的內(nèi)聚性萍歉,但是有作用的侣颂。
- 順序上的內(nèi)聚性:子程序包含按特定順序執(zhí)行的操作档桃,這些操作共享數(shù)據(jù),而且只有在操作全部執(zhí)行完畢的時(shí)候才達(dá)到一項(xiàng)完整的功能
- 通信上的內(nèi)聚性:指一個(gè)子程序內(nèi)的不同操作用同樣的數(shù)據(jù)憔晒,但不存在任何的聯(lián)系
- 臨時(shí)的內(nèi)聚性:一些因?yàn)樾枰瑫r(shí)操作而放在一起的操作
startUp()
- 以下是不可取的內(nèi)聚性
- 過(guò)程內(nèi)聚性:把一組操作放在子程序中并按照特定順序執(zhí)行藻肄,除此之外沒(méi)有其他彼此的聯(lián)系
- 邏輯上內(nèi)聚性(其實(shí)是缺乏邏輯的內(nèi)聚性):把若干操作放入同一子程序蔑舞,通過(guò)傳入的控制符執(zhí)行不同的操作
- 如果子程序僅有由一系列if else語(yǔ)句以及其他子程序語(yǔ)句組成,這樣的邏輯上內(nèi)聚性的子程序是可以的嘹屯,就是這個(gè)子程序只發(fā)出各種指令攻询,不進(jìn)行任何的處理,那么他就是一個(gè)事件處理器(event handler)
- 巧合的內(nèi)聚性:子程序的操作之間沒(méi)有任何的 聯(lián)系
- 7.3 好的子程序的名字 Good Routine Names
- 描述子程序所做的所有的事
- 避免使用無(wú)意義州弟、模糊或者表達(dá)不清的動(dòng)詞
event handling
事件處理除外
handleCalculation()
PerformServices()
OutputUser()
ProcessInput()
DealwithOutPut
- 不僅僅通過(guò)數(shù)字形成不同子程序名
outPut1()
;outPut2()
- 根據(jù)需求確定子程序的名稱(chēng)長(zhǎng)度
- 函數(shù)命名時(shí)要對(duì)函數(shù)的返回值有所描述
printer.isReady()
customerId.next()
- 給子程序命名時(shí)要使用語(yǔ)氣強(qiáng)烈的動(dòng)詞加賓語(yǔ)的形式钧栖,在面向?qū)ο笳Z(yǔ)言中,不用再過(guò)程(Procedure)名中不用加入對(duì)象名(賓語(yǔ))
document.print()
orderInfo.check()
- 準(zhǔn)確使用對(duì)仗詞
add/remove
insert/delete
start/stop
up/down
begin/end
increment/decrement
open/close
get/set
first/last
old/new
min/max
show/hide
create/destory
lock/unlock
source/target
get/put
- 為常用操作確立命名規(guī)則
- 7.4 子程序可以寫(xiě)多長(zhǎng) How long can a Routine be
- 雖然有很多研究但是仍然沒(méi)有一個(gè)公認(rèn)的說(shuō)法婆翔,一般是50-200行左右拯杠,可以從子程序的內(nèi)聚性、嵌套層次啃奴、變量數(shù)量潭陪、決策點(diǎn)(desicions points)和注釋來(lái)決定子程序的長(zhǎng)度,當(dāng)超過(guò)200行最蕾,就要考慮在可讀性上問(wèn)題了依溯。
- 7.5 如何使用子程序參數(shù) How to Use Routine Parameters
- 按照輸入-修改-輸出的順序排列參數(shù):暗含了操作數(shù)據(jù)的順序
- 如果子程序用了類(lèi)似的參數(shù),參數(shù)的排列順序應(yīng)該一致
- 使用所有的參數(shù)瘟则,沒(méi)有用的要撇除
- 把狀態(tài)或者出錯(cuò)變量放在最后黎炉,因?yàn)樗鼈冎皇浅绦虻母綄?/li>
- 不要把子程序參數(shù)當(dāng)做工作變量
對(duì)輸入?yún)?shù)進(jìn)行操作,并將其作為返回值返回結(jié)果醋拧。
* 在接口中對(duì)參數(shù)的假定加以說(shuō)明拜隧,在接口文檔說(shuō)明
* 參數(shù)是僅用于輸入,要被修改趁仙,還是僅用于輸出
* 表示數(shù)量的參數(shù)單位(秒/分)
* 沒(méi)有用枚舉類(lèi)型的話(huà)洪添,應(yīng)該說(shuō)明狀態(tài)碼和錯(cuò)誤碼的含義
* 所能接受的數(shù)據(jù)范圍
* 不能接受的特定數(shù)值
* 把子程序的參數(shù)個(gè)數(shù)限制在7個(gè)以?xún)?nèi)
* 如何一直需要傳遞很多參數(shù),說(shuō)明子程序之間的耦合太過(guò)緊密雀费。如果需要向很多不同的子程序傳入相同的數(shù)據(jù)干奢,就把這些子程序組成一個(gè)類(lèi),并把那些經(jīng)常使用的數(shù)據(jù)作為類(lèi)的內(nèi)部數(shù)據(jù)
* 考慮對(duì)參數(shù)使用某種輸入盏袄、修改忿峻、輸出的命名規(guī)則
>i_xxx
,m_xxx
,o_xxx
或者Input_xxx
,Modify_xxx
,Output_xxx
* 為子程序傳遞用以維持其接口抽象的變量和對(duì)象
* 假如經(jīng)常需要修改子程序的參數(shù)表,且都是來(lái)自同一個(gè)對(duì)象辕羽,那就傳遞整個(gè)對(duì)象
* 如果只是為傳遞幾個(gè)特定的數(shù)據(jù)逛尚,把數(shù)據(jù)填入對(duì)象,再到子程序讀取這些數(shù)據(jù)刁愿,那就只傳遞數(shù)據(jù)的值 - 使用具名參數(shù)绰寞?
- 確保實(shí)際參數(shù)與形式參數(shù)相匹配?
- 7.6 使用函數(shù)時(shí)要特別考慮的問(wèn)題
- 函數(shù)是有返回值的子程序,過(guò)程是指沒(méi)有返回值的子程序
- 設(shè)置函數(shù)的返回值
- 檢查所有可能的返回路徑
- 假如需要返回有關(guān)的數(shù)據(jù)滤钱,那就應(yīng)該作為類(lèi)的成員保存起來(lái)觉壶,而不是作為局部數(shù)據(jù)的引用或者指針?lè)祷亍?/li>
- 7.7 宏子程序和內(nèi)聯(lián)子程序 Macro Routine And Inline Routines?
- 把宏表達(dá)式整個(gè)都包含在括號(hào)內(nèi)
- 把包含多條語(yǔ)句的宏用大括號(hào)括起來(lái)
- 用給子程序命名的方法給展開(kāi)后代碼形同子程序的宏命名件缸,以便需要可以用子程序來(lái)替換宏铜靶。
- 高質(zhì)量的子程序核對(duì)表P185
- 7.1 創(chuàng)建子程序(routines)的正當(dāng)理由:提高程序管理能力,包括提高可讀性蟆融、可靠性和可修改性草巡,節(jié)省代碼空間是次要,或者是副作用(side effect)型酥。
- 第八章 防御式編程 Defensive Programming:子程序應(yīng)該不因傳入錯(cuò)誤的數(shù)據(jù)而被破壞,哪怕是由其他子程序產(chǎn)生的錯(cuò)誤的數(shù)據(jù)他炊。即核心思想是程序都是有問(wèn)題争剿,都是要被修改。
- 8.1 保護(hù)程序免遭非法輸入數(shù)據(jù)破壞 Protecting your program from invalid inputs
- 檢查所有來(lái)源于外部數(shù)據(jù)的值:從文件痊末、網(wǎng)絡(luò)秒梅、用戶(hù)或者其他外部接口獲得的數(shù)據(jù)應(yīng)該檢查其有效性
- 檢查子程序所有輸入?yún)?shù)的值
- 決定如何處理錯(cuò)誤的輸入數(shù)據(jù)
- 8.2 斷言 Assertions
- 在開(kāi)發(fā)期間使用的,讓程序運(yùn)行時(shí)進(jìn)行自檢的代碼舌胶,一個(gè)斷言一般包含兩個(gè)參數(shù)捆蜀,一個(gè)布爾表達(dá)式,一個(gè)斷言為假時(shí)顯示的消息幔嫂。斷言程序執(zhí)行的前條件和后條件
- 用斷言檢查一下假定:
- 輸入?yún)?shù)或者輸出參數(shù)在預(yù)定范圍內(nèi)
- 子程序開(kāi)始(結(jié)束)文件或者流處于開(kāi)啟或者關(guān)閉的狀態(tài)
- 子程序開(kāi)始(結(jié)束)文件或者流讀寫(xiě)的位置位于開(kāi)頭或者結(jié)尾
- 指針不為空
- 傳入子程序的數(shù)組或者其他容器至少能存儲(chǔ)X個(gè)數(shù)據(jù)元素
- 表已經(jīng)初始化辆它,存儲(chǔ)著真實(shí)的數(shù)據(jù)
- 僅用于輸入的變量的值沒(méi)有被子程序改變
- 子程序開(kāi)始或者結(jié)束的時(shí)候,某個(gè)容器為滿(mǎn)或者為空
- 高度優(yōu)化的子程序與運(yùn)行緩慢但邏輯清晰的子程序運(yùn)行結(jié)果一致
- 對(duì)于高健壯性的代碼履恩,應(yīng)該先斷言再處理錯(cuò)誤
- 8.3 錯(cuò)誤處理技術(shù) Erro-Handling Technique:斷言處理不應(yīng)該發(fā)生的錯(cuò)誤锰茉,錯(cuò)誤處理技術(shù)處理預(yù)料中可能發(fā)生的錯(cuò)誤。
- 返回中立值
- 數(shù)值計(jì)算返回0
- 字符串操作返回空字符串
- 指針操作返回空指針等
- 換用下一個(gè)正確的數(shù)據(jù)
溫度計(jì)讀取數(shù)值失敗切心,可以等下一次如1/100秒讀取
* 返回前次相同的數(shù)據(jù)
> 上面溫度計(jì)的例子同樣適用
* 換用最接近的合法值
>得到字符串長(zhǎng)度小于0飒筑,那返回0
* 把警告信息寫(xiě)到日志
* 返回一個(gè)錯(cuò)誤碼
* 調(diào)用處理錯(cuò)誤的對(duì)象或者子程序
* 健壯性 vs 正確性 robustness vs correctness
* 高層次設(shè)計(jì)對(duì)錯(cuò)誤處理方式的影響 - 返回中立值
- 8.4 異常Exceptions:是把錯(cuò)誤或者異常事件傳遞給調(diào)用方代碼的特殊手段
- 用異常通知其他的程序,發(fā)生了不可忽略的錯(cuò)誤
- 與斷言相似绽昏,都是用來(lái)處理罕見(jiàn)甚至不可能出現(xiàn)的情況???
- 是處理意外的有效途徑协屡,但是增加復(fù)雜度
- 不能用異常來(lái)推卸責(zé)任,明確是由自身處理異常還是由調(diào)用方處理異常
- 避免在解構(gòu)函數(shù)和構(gòu)造函數(shù)拋出異常全谤,除非在同一地方進(jìn)行捕獲
- 在恰當(dāng)?shù)某橄髮哟螔伋霎惓?/em>肤晓,就異常應(yīng)于當(dāng)前接口的抽象層次一致,避免暴露實(shí)現(xiàn)細(xì)節(jié)和內(nèi)部信息
- 避免使用空的catch語(yǔ)句认然,除非將catch的異常文檔化
- 了解函數(shù)庫(kù)可能拋出的異常补憾、
- 考慮創(chuàng)造一個(gè)集中的異常報(bào)告機(jī)制,就是對(duì)于異常進(jìn)行統(tǒng)一的格式化并記錄和存儲(chǔ)
- 把項(xiàng)目中對(duì)異常的使用標(biāo)準(zhǔn)化
- 可以定義項(xiàng)目特定的異常類(lèi)卷员,記錄日志盈匾、報(bào)告錯(cuò)誤的集中起來(lái)和標(biāo)準(zhǔn)化
- 規(guī)定何種場(chǎng)合異常時(shí)需要局部處理
- 規(guī)定何種場(chǎng)合異常只能拋出,不能局部處理
- 考慮異常的替換方案
- 8.5 隔離程序毕骡,使之包容由程序錯(cuò)誤造成的傷害Barricade Your Program to Contain the Damage Caused by Errors
- 隔欄是一種容錯(cuò)的策略 damage containment strategy
- 可以在類(lèi)的層面上采用這種方法削饵,在類(lèi)的公有方法假定輸入的數(shù)據(jù)時(shí)不安全的岩瘦,對(duì)數(shù)據(jù)進(jìn)行檢查并清理,之后再將數(shù)據(jù)傳給私有方法葵孤,類(lèi)的私有方法假定數(shù)據(jù)都是安全的
- 隔欄外部的程序使用錯(cuò)誤處理技術(shù),在那里對(duì)數(shù)據(jù)的假定是不安全的橱赠。內(nèi)部的程序使用斷言技術(shù)尤仍,這樣如果隔欄內(nèi)的出現(xiàn)錯(cuò)誤的數(shù)據(jù),就是程序上的錯(cuò)誤而非數(shù)據(jù)上的錯(cuò)誤
- 8.6 輔助調(diào)試的代碼 Debugging aids
- 不要把自動(dòng)地把產(chǎn)品版的限制強(qiáng)加于開(kāi)發(fā)版上:開(kāi)發(fā)版可以花費(fèi)更多的資源狭姨,允許運(yùn)行緩慢宰啦,允許暴露不安全的操作
- 盡早引入輔助代碼
- 采用攻擊式編程 offensive programming
- 確保斷言使程序中止,及時(shí)修復(fù)錯(cuò)誤
- case語(yǔ)句的default分支或者else分支產(chǎn)生嚴(yán)重的錯(cuò)誤以致不被忽視
- 計(jì)劃移除調(diào)試輔助的代碼
- 8.7 確定在產(chǎn)品中該保留多少防御式代碼 Determine How much Defensive Programming to Leave in Production code
- 保留那些檢查重要錯(cuò)誤的代碼
- 去掉檢查細(xì)微錯(cuò)誤的代碼
- 去掉可以導(dǎo)致程序硬性崩潰的代碼:雖然便于調(diào)試饼拍,但是用戶(hù)體驗(yàn)差
- 為你的技術(shù)支持員記錄錯(cuò)誤信息
- 確認(rèn)留在代碼中的錯(cuò)誤信息是友好的(friendly):就是要嚴(yán)謹(jǐn)赡模,正式
- 8.8 對(duì)防御式編程采取防御姿態(tài) Being Defensive about Defensive Programing
- 防御式編程增加復(fù)雜度
- 防御式編程因?yàn)橐獧z查參數(shù)使程序運(yùn)行緩慢
- 核對(duì)表 P211
- 8.1 保護(hù)程序免遭非法輸入數(shù)據(jù)破壞 Protecting your program from invalid inputs
- 第九章 偽代碼編程過(guò)程 The Pseudocode Programming Process
- 9.1 創(chuàng)建類(lèi)和子程序的步驟概述 Summary steps of Building Classes and Routines
-
圖9.1 at p216:
- 創(chuàng)建一個(gè)類(lèi)的步驟 Steps in Creating a class
- 創(chuàng)建類(lèi)的總體設(shè)計(jì) 具體參考第六章 可以工作類(lèi)
- 定義類(lèi)的職責(zé)
- 定義類(lèi)要隱藏的"秘密"
- 定義類(lèi)的接口所代表的抽象概念
- 決定這個(gè)類(lèi)是否要從其他類(lèi)派生出來(lái)
- 決定這個(gè)類(lèi)是否可以被派生,即是否能被繼承
- 指出類(lèi)的關(guān)鍵公用方法
- 標(biāo)識(shí)并設(shè)計(jì)出類(lèi)所需要的重要數(shù)據(jù)成員
- 創(chuàng)建類(lèi)的子程序 Steps in Building a routine
-
圖9.2 at p217
- 子程序的種類(lèi):成員訪(fǎng)問(wèn)子程序 (accessor routine ),轉(zhuǎn)發(fā)到其他對(duì)象(pass-throughs)的子程序
- 步驟:設(shè)計(jì)子程序->檢查設(shè)計(jì)->編寫(xiě)子程序的代碼->檢查代碼
-
圖9.2 at p217
- 復(fù)審并測(cè)試整個(gè)類(lèi) :在子程序創(chuàng)建的同時(shí)經(jīng)過(guò)測(cè)試师抄,在整個(gè)類(lèi)可以工作后漓柑,應(yīng)該再對(duì)整體進(jìn)行復(fù)查和測(cè)試,以便于發(fā)現(xiàn)在子程序獨(dú)立測(cè)試層次上無(wú)法發(fā)現(xiàn)的問(wèn)題
- 創(chuàng)建類(lèi)的總體設(shè)計(jì) 具體參考第六章 可以工作類(lèi)
-
圖9.1 at p216:
- 9.2 偽代碼 Pseudocode for Pros
- 偽代碼:描述 算法叨吮、子程序辆布、類(lèi)或者完整程序的工作邏輯、非正式的茶鉴、類(lèi)似英語(yǔ)的記法
- 偽代碼的注意事項(xiàng):
- 用類(lèi)似英語(yǔ)的語(yǔ)句來(lái)精確描述特定的操作
- 避免使用目標(biāo)編程語(yǔ)言的元素锋玲,偽代碼是比代碼本身略高的設(shè)計(jì)層次,使用目標(biāo)編程語(yǔ)言的元素會(huì)降低設(shè)計(jì)層次
- 在本意 intent 層面編寫(xiě)偽代碼
- 在足夠低的層次編寫(xiě)偽代碼涵叮,以便可以近乎轉(zhuǎn)化為代碼
- 好的偽代碼能轉(zhuǎn)換為注釋
- 偽代碼的好處:
- 偽代碼使得評(píng)審更容易
- 偽代碼支持反復(fù)迭代精化思想:自頂向下惭蹂,逐層拆解問(wèn)題,解決問(wèn)題
- 偽代碼使變更更加容易
- 偽代碼能使給代碼作注釋的工作量減少
- 偽代碼比其他設(shè)計(jì)形式的文檔更容易維護(hù)
- 9.3 通過(guò)偽代碼編碼過(guò)程創(chuàng)建子程序
- 設(shè)計(jì)子程序 Design the Routine
- 檢查先決條件:子程序工作是否定義好割粮,是不是與整體設(shè)計(jì)相匹配盾碗。是否項(xiàng)目必需的
- 定義子程序的解決的問(wèn)題:
- 子程序要隱藏的信息
- 子程序的輸入
- 子程序的輸出
- 調(diào)用子程序前確保有關(guān)的前條件成立(輸入數(shù)據(jù)在特定范圍內(nèi),流已經(jīng)初始化等)
- 在子程序?qū)⒖刂茩?quán)交回調(diào)用程序前舀瓢,確保后條件成立(輸出數(shù)據(jù)在特定范圍內(nèi)置尔,流已經(jīng)關(guān)閉)
- 為子程序命名
- 決定如何測(cè)試子程序
- 在標(biāo)準(zhǔn)庫(kù)搜索可用的功能:重用好的代碼,不重復(fù)造輪子
- 考慮錯(cuò)誤處理
- 考慮效率問(wèn)題:
第一種情況絕大數(shù)系統(tǒng)而言氢伟,效率并不是十分緊要榜轿。另一種情況是對(duì)少數(shù)系統(tǒng)而言性能非常重要。在除了上述兩種情況朵锣,在子程序效率的優(yōu)化是白費(fèi)功夫的谬盐,因?yàn)橹饕膬?yōu)化是在于完善高層的設(shè)計(jì)
* 研究算法和數(shù)據(jù)類(lèi)型
* 編寫(xiě)偽代碼:先寫(xiě)頭注釋 head comment,再寫(xiě)偽代碼
* 考慮數(shù)據(jù)
* 檢查偽代碼:確認(rèn)很容易诚些,很自然地理解子程序做些什么以及怎樣做
* 在偽代碼中試驗(yàn)一些想法飞傀,留下最好的想法(迭代):偽代碼試驗(yàn)想法成本比代碼低皇型。
> 用偽代碼反復(fù)描述這個(gè)子程序,直到偽代碼寫(xiě)出句子已經(jīng)足夠簡(jiǎn)單砸烦,你可以把偽代碼直接變成代碼文檔為止弃鸦。最初偽代碼層次太高,不斷的精化和分解偽代碼幢痘,直到再寫(xiě)偽代碼實(shí)在浪費(fèi)時(shí)間為止
* 編寫(xiě)子程序代碼 Code the Routine
* 圖9.3 at p225
* 寫(xiě)出子程序的聲明:把如果接口名稱(chēng)起得直接了當(dāng)唬格,就不需要接口假定(interface assumption)的事情
* 把偽代碼轉(zhuǎn)變?yōu)楦邔哟蔚淖⑨?br> * 在每條注釋下填充代碼: 偽代碼相當(dāng)于文章的提綱,每段偽代碼注釋描述類(lèi)一段或者一句代碼
* 檢查代碼是否需要進(jìn)一步分解
* 如果一行偽代碼下的代碼過(guò)多颜说,可以refactor重構(gòu)成一個(gè)子程序
* 遞歸recursively地應(yīng)用偽代碼編程過(guò)程购岗。如果一行偽代碼下的代碼過(guò)
多,可以把一行偽代碼拆分為多行偽代碼
- 檢查代碼 Check the Code
- 在腦海檢查程序的錯(cuò)誤:當(dāng)子程序足夠短小精悍门粪,檢查到程序所有可能的執(zhí)行路徑喊积、端點(diǎn)和異常情況,不但要自己查(這叫桌面檢查 desk checking)玄妈,可以同行審查peer review乾吻,詳查walk-through或者審查inspection
從superstition迷信到理解,調(diào)查顯示只有5%的錯(cuò)誤是由于編譯器或者硬件造成的,所以遇到的錯(cuò)誤大部分都是程序員自身造成的
* 編譯子程序:把編譯器的警告級(jí)別調(diào)到最高,使用像lint的檢查工具拟蜻,及時(shí)消除產(chǎn)生錯(cuò)誤信息和警告的所有根源
* 在調(diào)試器中逐行運(yùn)行代碼
* 測(cè)試代碼
* 消除程序中的錯(cuò)誤
- 在腦海檢查程序的錯(cuò)誤:當(dāng)子程序足夠短小精悍门粪,檢查到程序所有可能的執(zhí)行路徑喊积、端點(diǎn)和異常情況,不但要自己查(這叫桌面檢查 desk checking)玄妈,可以同行審查peer review乾吻,詳查walk-through或者審查inspection
- 收尾工作 Clean Up LeftOvers
- 檢查子程序的接口
- 檢查子整體的設(shè)計(jì)質(zhì)量:內(nèi)聚性溶弟;子程序間松散耦合;防御式編程C7
- 檢查子程序的變量C10-13
- 檢查子程序的語(yǔ)句和邏輯:有無(wú)泄漏資源瞭郑,錯(cuò)誤辜御,死循環(huán),錯(cuò)誤嵌套C14-19
- 檢查子程序的布局:格式化 C31
- 檢查子程序的文檔
- 除去冗余的注釋
- 9.4 偽代碼編程過(guò)程的替代方案 Alternative to the PPP
- 測(cè)試先行開(kāi)發(fā)(測(cè)試驅(qū)動(dòng)開(kāi)發(fā))Test-first Development:在任何代碼之前先要寫(xiě)出測(cè)試用例屈张,使得程序可測(cè)試
- 重構(gòu)refactoring C24
- 契約式設(shè)計(jì) design by contract 即每一段程序都具有前條件preconditions和后條件postconditions
- 東拼西湊hacking
- 核對(duì)表 P233
- 9.1 創(chuàng)建類(lèi)和子程序的步驟概述 Summary steps of Building Classes and Routines
第三部分 變量 Variable
- 第十章 使用變量的一般事項(xiàng) General Issue in Using Variables
- 10.1 數(shù)據(jù)認(rèn)知: 列舉的常見(jiàn)的數(shù)據(jù)類(lèi)型
- 10.2 輕松掌握變量定義:
- 隱式聲明:避免隱式聲明擒权,可能導(dǎo)致編譯器的初始值不符合編程的要求,應(yīng)該關(guān)閉隱式聲明阁谆,并聲明全部變量碳抄;
- 10.3 變量初始化原則:
- 初始化錯(cuò)誤:
- 從未對(duì)變量賦值
- 變量值已經(jīng)過(guò)期
- 變量的一部分被賦值
- 避免初始化方法:
- 在聲明時(shí)初始化變量
- 在靠近變量第一次使用的地方初始化它
- ****理想狀態(tài)下****,在第一次使用的地方聲明并初始化變量
- 在可能的情況下场绿,使用final或者const
- 在計(jì)數(shù)累加器i j剖效,再次使用時(shí)忘記重置是一個(gè)常見(jiàn)的錯(cuò)誤
- 在類(lèi)的構(gòu)造函數(shù)中初始化該類(lèi)數(shù)據(jù)成員
- 檢查變量是否需要重新初始化
- 一次性初始化具名常量,用可執(zhí)行代碼初始化變量焰盗。
- 初始化錯(cuò)誤:
- 10.4 作用域 Scope
- 使變量引用局部化:跨度span:變量引用點(diǎn)之間的距離璧尸;應(yīng)該把變量的引用點(diǎn)集中起來(lái)
、 * 盡可能縮短存活時(shí)間:就是變量最初引用點(diǎn)到最后引用點(diǎn)之間的距離- 減少作用域的一般原則:
- 在循環(huán)開(kāi)始前初始化該循環(huán)里使用的變量熬拒,而不是在該循環(huán)所屬的子程序開(kāi)始處初始化這些變量
- 直到變量即將被使用的時(shí)候再為其賦值
- 把相關(guān)的語(yǔ)句放在一起
- 把相關(guān)的語(yǔ)句提出成單獨(dú)的子程序
- 開(kāi)始時(shí)采用嚴(yán)格的作用域爷光,然后根據(jù)需要擴(kuò)展變量的作用域
> private -> protected -> default- >public
- 減少作用域的一般原則:
- 10.5 持續(xù)性:有可能數(shù)據(jù)發(fā)生了變化,引用了過(guò)期的變量導(dǎo)致錯(cuò)誤
- 在子程序加入調(diào)試代碼或者斷言檢查關(guān)鍵數(shù)據(jù)的合理性
- 準(zhǔn)備拋棄變量時(shí)給它設(shè)置不合理的值 個(gè)人認(rèn)為在at C++
- 編寫(xiě)程序假定是沒(méi)有持續(xù)性的澎粟,但不適合c++或者java中的static數(shù)據(jù)
- 養(yǎng)成使用所有數(shù)據(jù)前聲明和初始化的習(xí)慣
- 10.6 綁定時(shí)間:綁定時(shí)間越早靈活性越差蛀序,其實(shí)跟上面的初始化變量的指導(dǎo)是一樣的
- 10.7 數(shù)據(jù)類(lèi)型和控制結(jié)構(gòu)之間的關(guān)系:
- 序列型數(shù)據(jù)翻譯為程序中的順序語(yǔ)句
- 選擇型數(shù)據(jù)翻譯為程序中的if else語(yǔ)句
- 迭代型數(shù)據(jù)翻譯為for repeat while等循環(huán)語(yǔ)句
- 10.8 為變量指定單一用途
- 每個(gè)變量只用于單一的用途
- 第十一章 變量名的力量
- 11.1 選擇好變量名的注意事項(xiàng)
- 最終重要的命名事項(xiàng):
- 名字要完全欢瞪、準(zhǔn)確地表達(dá)該事物
- 容易閱讀、不包含晦澀的縮寫(xiě)徐裸、同時(shí)無(wú)歧義
- 以問(wèn)題為導(dǎo)向:好的名字是表達(dá)”什么“(what)而不是”如何“(how)遣鼓,即反映問(wèn)題而不是解決方案。變量應(yīng)直指問(wèn)題的領(lǐng)域而非計(jì)算機(jī)世界
inputRecord 比 employeeData
* 最適當(dāng)?shù)拿珠L(zhǎng)度 Optimum Name Length:
* 有研究是平均長(zhǎng)度在10到16個(gè)字符
* 有研究是平均長(zhǎng)度在8到20個(gè)字符
* 最重要是強(qiáng)調(diào)當(dāng)自己代碼中出現(xiàn)很多更短的名字重贺,認(rèn)真檢查確保名字含義足夠清晰
* 變量名對(duì)作用域的影響 The Effect of Scope on Variable Names骑祟、
* 對(duì)位于全局命名空間中的名字加入限定詞
* 如果編程語(yǔ)言不支持命名空間,就在對(duì)應(yīng)的子系統(tǒng)加入前綴
- 最終重要的命名事項(xiàng):
- 變量名中計(jì)算值限定空間 Computed-Value Qualifiers In Variable Names
- 把總額 sum total檬姥、平均數(shù) average 曾我、最大值Max粉怕、最小值Min健民、記錄Record、字符串String贫贝、Pointer指針加入名字的后面
revenueTotal revenueAverage更具對(duì)稱(chēng)性秉犹,更容易維護(hù)
Num放在開(kāi)始位置代表總數(shù),放在結(jié)束位置代表一個(gè)下標(biāo)
customerCount代表員工總數(shù) customerIndex代表某個(gè)特定的員工
- 把總額 sum total檬姥、平均數(shù) average 曾我、最大值Max粉怕、最小值Min健民、記錄Record、字符串String贫贝、Pointer指針加入名字的后面
- 變量名中的對(duì)仗詞 Common Opposites In Variable Names
- begin/end
* first/last
- locked/unlocked
- min/max
- next/previous
- old/new
- opened/closed
- visible/invisible
- source/target
- source/destination
- up/down
- begin/end
- 11.2 為特定類(lèi)型的數(shù)據(jù)命名 Naming Specific Types of Data
- 為循環(huán)下標(biāo)命名 Naming Loop Index:
- 一般情況下使用i稚晚、j崇堵、k
- 多層循環(huán)嵌套的情況或者循環(huán)長(zhǎng)度超過(guò)一兩行代碼,應(yīng)該給計(jì)數(shù)器賦予更長(zhǎng)的名字以表達(dá)其含義
- 為狀態(tài)變量命名 Naming Status Variables
- 為狀態(tài)變量取一個(gè)比f(wàn)lag更好的名字
- 標(biāo)記應(yīng)該用枚舉類(lèi)型客燕、具名常量或者作為具名常量的全局變量對(duì)其進(jìn)行賦值鸳劳,增加可讀性
- 為臨時(shí)變量命名 Naming Temporary Variables:在使用temp等命名前最好思考是否有能表達(dá)其含義的名字
- 為布爾變量命名 Naming Boolean Variables:
- 謹(jǐn)記典型的布爾變量命名:
- done 表示事情是否完成,未完成前是false也搓,完成后是true
- error 表示有錯(cuò)誤發(fā)生赏廓,錯(cuò)誤發(fā)生前是false,錯(cuò)誤發(fā)生后是true
- found 表示某個(gè)值已經(jīng)找到傍妒,在未找到該值前是false幔摸,找到該值后是true
- success或者ok 表示一項(xiàng)操作是否成功,失敗是false颤练,成功是true
- 為布爾變量賦予隱含“真/假”含義的名字
- status不是一個(gè)好的命名
- isXXX優(yōu)點(diǎn)是:不能用于哪些模糊的名字既忆。缺點(diǎn)是可讀性較差
isStatus無(wú)意義 isFound 比f(wàn)ound可讀性差
* 使用肯定布爾命名
- 謹(jǐn)記典型的布爾變量命名:
- 為枚舉變量命名 Naming Enumerated Types:
- 可以通過(guò)使用組前綴為明確表示該類(lèi)型的成員都同屬于一個(gè)組
Color_XXX
* 對(duì)于枚舉的命名有不同的觀(guān)點(diǎn):有大小寫(xiě)混合Color_Blue
;與常量類(lèi)似的大寫(xiě)Color.BULE
* 在處理枚舉像類(lèi)的編程語(yǔ)言里嗦玖,處理枚舉很像類(lèi)患雇,所以枚舉成員總是冠以枚舉名字前綴,就無(wú)需重復(fù)前綴了
- 可以通過(guò)使用組前綴為明確表示該類(lèi)型的成員都同屬于一個(gè)組
- 為常量命名 Naming Constans:應(yīng)命名該常量代表的抽象事物而非數(shù)值
- 11.3 命名規(guī)則的力量 The Power of Naming Covenstions
- 為什么要有規(guī)則
- 要求你更多按規(guī)矩辦事宇挫,集中精力投入關(guān)注代碼更重要的特征
- 有助于項(xiàng)目之間傳遞知識(shí)
- 有助于學(xué)習(xí)新項(xiàng)目
- 有助于減少名字增生 name Proliferation
- 彌補(bǔ)編程語(yǔ)言的不足
- 強(qiáng)調(diào)相關(guān)變量之間的關(guān)系:把相關(guān)變量設(shè)置相同前綴將它們關(guān)聯(lián)起來(lái)
- 何時(shí)采用命名規(guī)則
- 多人開(kāi)發(fā)
- 程序需要轉(zhuǎn)交別人
- 程序規(guī)模太大庆亡,無(wú)法同時(shí)了解全局,必需分而治之
- 程序開(kāi)發(fā)周期過(guò)長(zhǎng)
- 一個(gè)項(xiàng)目存在一些不常見(jiàn)的術(shù)語(yǔ)捞稿,在編寫(xiě)代碼中使用術(shù)語(yǔ)或者縮寫(xiě)的時(shí)候
- 為什么要有規(guī)則
- 11.4 非正式命名規(guī)則 Informal Naming Conventions
- 與語(yǔ)言無(wú)關(guān)的命名規(guī)則指導(dǎo)原則
- 與語(yǔ)言相關(guān)的命名規(guī)則指導(dǎo)原則:有C又谋,C++,只列舉Java
- i,j是整數(shù)下標(biāo)
- 常量全部大寫(xiě)并用下劃線(xiàn)分割
- 類(lèi)名和接口每個(gè)單詞首字母大寫(xiě)
- 變量名和方法名第一個(gè)單詞首字母小寫(xiě)拼缝,后續(xù)單詞首字母大寫(xiě)
- 除用于全部大寫(xiě)的名字外,不使用下劃線(xiàn)作為名字中的分隔符
- 訪(fǎng)問(wèn)器子程序使用get和set前綴
- 混合語(yǔ)言編程注意事項(xiàng)
- 命名規(guī)則示例
- 包含以下三類(lèi)信息:
- 變量的內(nèi)容(是什么)
- 數(shù)據(jù)的種類(lèi)(具名常量彰亥,簡(jiǎn)單變量咧七,用戶(hù)自定義類(lèi)型或者類(lèi))
- 變量的作用域(局部,私用的任斋,類(lèi)的继阻,包的或者全部的作用域)
- 類(lèi)成員數(shù)據(jù):mXXX,全局變量:gXXX
- 包含以下三類(lèi)信息:
- 11.5 標(biāo)準(zhǔn)前綴 Standardized Prefixes:分用戶(hù)自定義類(lèi)型(UDT)的縮寫(xiě)和語(yǔ)義前綴
- 用戶(hù)類(lèi)型縮寫(xiě) User-Defined Type Abbreviation:UDT縮寫(xiě)可以標(biāo)識(shí)被命名對(duì)象或者變量的數(shù)據(jù)類(lèi)型
- 語(yǔ)義前綴 Semantic Prefixes:描述變量或者對(duì)象是如何被使用的
- c:count 數(shù)量
- first:數(shù)組需要處理的第一個(gè)元素
- g:全局變量
- i:數(shù)組的下標(biāo)
- last:數(shù)組中需要處理的最后一個(gè)元素
- lim:數(shù)組中需要處理的元素上限废酷,是非法的瘟檩,不存在的上限,而last是合法的
- m:類(lèi)一級(jí)的變量
- min:數(shù)組或者其他種類(lèi)列表中絕對(duì)最前一個(gè)元素
- max:數(shù)組或者其他種類(lèi)列表中絕對(duì)最后一個(gè)元素
- p:pointer 指針
- 標(biāo)準(zhǔn)前綴的優(yōu)點(diǎn):使名字更緊湊澈蟆、增加可讀性
- 11.6 創(chuàng)建具備可讀性的短名字 Creating Short Names That Are Readable
- 縮寫(xiě)的一般指導(dǎo)原則:
- 使用標(biāo)準(zhǔn)縮寫(xiě)(參考詞典)
- 去掉所有非前置元音墨辛??趴俘?
computer->cmptr screen->scrn
* 去掉虛詞
> and睹簇、or、the等
* 使用每個(gè)單詞的第一個(gè)或者前幾個(gè)字母
* 統(tǒng)一地使用單詞的第一寥闪、第二或者第三(自行確定)字母后截?cái)?br> * 保留每個(gè)單詞的第一和最后一個(gè)字母
* 使用名字中每個(gè)重要單詞太惠,最多不超過(guò)3個(gè)
* 去除無(wú)用的后綴
> ed疲憋,ing
* 確保不要改變變量的含義
- 縮寫(xiě)的一般指導(dǎo)原則:
- 11.7 應(yīng)該避免的名字 Kind of Names To Avoid
- 避免使用令人誤解的名字或者縮寫(xiě)
- 避免使用具有相似含義的名字
- 避免使用具有不同含義但是相似名字的變量:
一般是縮寫(xiě)很相似的情況如 clientReq 和 clientRes
* 避免使用發(fā)音相似的名字
* 避免在名字中使用數(shù)字
* 避免拼錯(cuò)單詞
* 避免使用容易拼錯(cuò)的單詞
* 不要僅靠大小寫(xiě)來(lái)區(qū)分變量名
* 避免使用多種自然語(yǔ)言:只有英語(yǔ)凿渊,不使用漢語(yǔ)等
* 避免使用標(biāo)準(zhǔn)類(lèi)型、變量和子程序名字:編程語(yǔ)言的關(guān)鍵詞
* 不要使用與變量含義無(wú)關(guān)的名字
* 避免在名字中使用容易混淆的字符:數(shù)字1對(duì)于字母l或者字母i缚柳,數(shù)字2對(duì)應(yīng)字母z埃脏,數(shù)字5對(duì)應(yīng)字母s,數(shù)字6對(duì)應(yīng)字母g喂击,數(shù)字0對(duì)應(yīng)字母o
- 11.1 選擇好變量名的注意事項(xiàng)
- 第十二章 基本數(shù)據(jù)類(lèi)型
- 12.1 數(shù)值概論
- 避免神秘?cái)?shù)值
- 可以使用硬編碼的1或者0
- 預(yù)防除零錯(cuò)誤
- 使類(lèi)型轉(zhuǎn)換變得明顯:不同的數(shù)據(jù)類(lèi)型之間會(huì)發(fā)生轉(zhuǎn)換時(shí)剂癌,利用顯式轉(zhuǎn)換而非隱式轉(zhuǎn)換
- 避免混合類(lèi)型的比較:應(yīng)該轉(zhuǎn)換成相同類(lèi)型再進(jìn)行比較
- 注意編譯器警告
- 12.2 整數(shù) Integers
- 檢查整數(shù)除法
- 檢查整數(shù)溢出:在整數(shù)加法或者乘法的過(guò)程中,留心較大的整數(shù)翰绊。
- 12.3 浮點(diǎn)數(shù) Floating-Point Numbers
- 避免數(shù)量級(jí)相差巨大之間加減運(yùn)算:解決方案:對(duì)于一系列相差巨大的數(shù)進(jìn)行運(yùn)算佩谷,先進(jìn)行從小到大排序,從最小值開(kāi)始把它們加起來(lái)监嗜,并不能消除舍入問(wèn)題谐檀,但是能減少到最低限度。
1000 000.00+0.1可能等于1000 000.00
* 避免等量判斷:確定數(shù)值在可接受的精度范圍內(nèi)
> double類(lèi)型變量裁奇,for循環(huán)中 加0.1桐猬,十次后不一定等于1.0
* 處理舍入誤差問(wèn)題:
* 換用精度更高的變量類(lèi)型
* 把浮點(diǎn)變量變成整數(shù)變量
* 檢查語(yǔ)言和函數(shù)庫(kù)對(duì)特定數(shù)據(jù)類(lèi)型的支持
* 12.4 字符和字符串 Characters and Strings
* 避免神秘字符和神秘字符串
* 了解你的語(yǔ)言和開(kāi)發(fā)環(huán)境是如何支持Unicode
* 在程序生命周期中盡早決定國(guó)際化/本地化策略
* 只支持一種文字語(yǔ)言,考慮使用ISO-8859字符集
* 需要支持多語(yǔ)言刽肠,請(qǐng)使用unicode
* 使用某種一致的字符串轉(zhuǎn)換策略
* 12.5 布爾變量
* 用布爾變量對(duì)程序加以文檔說(shuō)明:對(duì)于表達(dá)式的結(jié)果賦予一個(gè)布爾變量溃肪,以提高可讀性
* 用布爾變量簡(jiǎn)化復(fù)雜判斷:這是在上一條意見(jiàn)演化出來(lái)的免胃,也是提高可讀性
* 如果需要的話(huà),創(chuàng)建你自己的布爾類(lèi)型
* 12.6 枚舉類(lèi)型 Enumerated Types
* 用枚舉提高代碼可讀性
* 用枚舉提高代碼可靠性
* 用枚舉是程序易于簡(jiǎn)化修改
* 使用枚舉作為布爾值的替代方案:有多種失敗的類(lèi)型
* 檢查非法數(shù)值
* 定義枚舉的第一項(xiàng)和最后一項(xiàng)以用于循環(huán)邊界
> Enum Country{
Country_First = 0;
Country_China = 0;
Country_USA = 1;
Country_Last = 1;
}
* 把枚舉的第一個(gè)元素留作非法值
> Enum Country{
Country_InvalidFirst = 0;
Country_First = 1;
Country_China = 1;
Country_USA = 2;
Country_Last = 2;
}
* 明確定義項(xiàng)目代碼編寫(xiě)標(biāo)準(zhǔn)中第一個(gè)和最后一個(gè)元素的使用規(guī)則
* 警惕給枚舉元素明確賦值而帶來(lái)錯(cuò)誤:
> Enum Country{
Country_InvalidFirst = 0;
Country_First = 2;
Country_China = 2;
Country_UK = 4;
Country_USA = 6;
Country_Last = 6;
}
遍歷的時(shí)候會(huì)遍歷到1惫撰,3羔沙,5這些非法值
* 如果你的語(yǔ)言沒(méi)有枚舉類(lèi)型:p307
* 12.7 具名常量 Named Constants
* 12.8 數(shù)組 Arrays
* 確保數(shù)組下標(biāo)沒(méi)有越界
* 考慮用容器取代數(shù)組,或者將數(shù)組作為順序化結(jié)構(gòu)來(lái)處理
* 檢查數(shù)組的邊界
* 數(shù)組是多維厨钻,保證下標(biāo)的使用順序正確扼雏,防止下標(biāo)串話(huà)
* 在C中結(jié)合ARRAY_LENGTH()宏來(lái)使用數(shù)組
* 12.9 創(chuàng)造自己的類(lèi)型(類(lèi)型別名)Creating Your Own Types(Type Aliasing)
- 避免數(shù)量級(jí)相差巨大之間加減運(yùn)算:解決方案:對(duì)于一系列相差巨大的數(shù)進(jìn)行運(yùn)算佩谷,先進(jìn)行從小到大排序,從最小值開(kāi)始把它們加起來(lái)监嗜,并不能消除舍入問(wèn)題谐檀,但是能減少到最低限度。
- 12.1 數(shù)值概論
- 第十三章 不常見(jiàn)的數(shù)據(jù)類(lèi)型
- 13.1 結(jié)構(gòu)體 Structure:指使用其他類(lèi)型創(chuàng)建的數(shù)據(jù),類(lèi)似java中沒(méi)有公用子程序夯膀,完全由公用數(shù)據(jù)成員組成的類(lèi)诗充,個(gè)人認(rèn)為就是封裝
- 用結(jié)構(gòu)體明確數(shù)據(jù)關(guān)系:歸為一類(lèi),關(guān)聯(lián)起來(lái)
- 用結(jié)構(gòu)體簡(jiǎn)化對(duì)數(shù)據(jù)塊的操作
- 用結(jié)構(gòu)體簡(jiǎn)化參數(shù)列表
- 用結(jié)構(gòu)體減少維護(hù)
- 13.2 指針 Pointers诱建?蝴蜓?策泣?未學(xué)芹助,略
- 用來(lái)理解指針的范例:指針:內(nèi)存中的某個(gè)位置+如何解釋該位置的內(nèi)容
- 內(nèi)存中的位置:就是一個(gè)地址,以16進(jìn)制數(shù)表示
- 如何解釋指針?biāo)傅膬?nèi)容:由指針的基類(lèi)型 base type決定
- 使用指針的一般技巧:略
- 用來(lái)理解指針的范例:指針:內(nèi)存中的某個(gè)位置+如何解釋該位置的內(nèi)容
- 13.3 全局?jǐn)?shù)據(jù) Global Data
- 與全局變量有關(guān)的常見(jiàn)問(wèn)題:
- 無(wú)意間修改了全局?jǐn)?shù)據(jù)
- 與全局?jǐn)?shù)據(jù)有關(guān)的奇異的和令人激動(dòng)的別名問(wèn)題:就是出現(xiàn)兩個(gè)或者以上的名字都是指同一個(gè)變量
- 與全局?jǐn)?shù)據(jù)有關(guān)的代碼重入(re-entrant)問(wèn)題:多線(xiàn)程情況下全局?jǐn)?shù)據(jù)不僅是不同子程序共享,同時(shí)同一程序的不同拷貝之間也共享
- 全局?jǐn)?shù)據(jù)阻礙代碼重用
- 與全局變量有關(guān)的常見(jiàn)問(wèn)題:
- 13.1 結(jié)構(gòu)體 Structure:指使用其他類(lèi)型創(chuàng)建的數(shù)據(jù),類(lèi)似java中沒(méi)有公用子程序夯膀,完全由公用數(shù)據(jù)成員組成的類(lèi)诗充,個(gè)人認(rèn)為就是封裝
子程序用到全局?jǐn)?shù)據(jù)辜荠,不能直接將子程序復(fù)制到其他地方(其他類(lèi))里面,解決方法:上策是修改舊類(lèi)將全局?jǐn)?shù)據(jù)局部化抓狭;下策是在新類(lèi)創(chuàng)建與舊類(lèi)相同的全局?jǐn)?shù)據(jù)伯病,導(dǎo)致像病毒一樣傳染
* 與全局?jǐn)?shù)據(jù)有關(guān)的非確定的初始化順序事宜
> 在初始化一個(gè)類(lèi)的變量時(shí)需要使用其他文件的初始化全局變量,所以需要采用明確手段保證兩個(gè)變量按照正確順序進(jìn)行否过,不然將導(dǎo)致錯(cuò)誤
* 全局?jǐn)?shù)據(jù)破壞了模塊化和智力上的可管理性
* 使用全局?jǐn)?shù)據(jù)的理由:
* 保存全局?jǐn)?shù)據(jù):比如程序是否debug等
* 模擬具名常量
* 模擬枚舉類(lèi)型
* 簡(jiǎn)化對(duì)極其常用數(shù)據(jù)的使用
* 消除流浪數(shù)據(jù)(tramp data):
有時(shí)候傳遞數(shù)據(jù)給一個(gè)子程序或者類(lèi)午笛,只是想傳遞給另一個(gè)子程序或者類(lèi),如果調(diào)用鏈中間的子程序并不適用這一對(duì)象的時(shí)候苗桂,就稱(chēng)這些數(shù)據(jù)為流浪數(shù)據(jù)
* 只有萬(wàn)不得已才使用全局?jǐn)?shù)據(jù)
* 按照"局部數(shù)據(jù)->private數(shù)據(jù)->protected數(shù)據(jù)->全局?jǐn)?shù)據(jù)"順序設(shè)置數(shù)據(jù)的作用域
* 區(qū)分全局變量和類(lèi)變量
* 使用訪(fǎng)問(wèn)器子程序
* 用訪(fǎng)問(wèn)器子程序來(lái)取代全局?jǐn)?shù)據(jù)
* 訪(fǎng)問(wèn)器子程序的優(yōu)勢(shì)
* 獲得對(duì)數(shù)據(jù)的集中控制:如果要修改結(jié)構(gòu)方法是需要修改子程序即可
* 確保變量的所有引用得到保護(hù)药磺,避免出現(xiàn)異常
* 訪(fǎng)問(wèn)器子程序可以容易轉(zhuǎn)變?yōu)槌橄髷?shù)據(jù)類(lèi)型:即通過(guò)子程序名稱(chēng)實(shí)現(xiàn)抽象,提高代碼可讀性
* 如何使用訪(fǎng)問(wèn)器子程序
* 要求所有數(shù)據(jù)通過(guò)子程序訪(fǎng)問(wèn)
* 不要把全局?jǐn)?shù)據(jù)放在一起煤伟,而是放在相應(yīng)抽象水平的類(lèi)里面
* 用鎖來(lái)控制對(duì)全局?jǐn)?shù)據(jù)的訪(fǎng)問(wèn):在多線(xiàn)程下癌佩,子程序訪(fǎng)問(wèn)器加鎖,保證數(shù)據(jù)正確性
* 使得對(duì)一項(xiàng)數(shù)據(jù)的所有訪(fǎng)問(wèn)都發(fā)生在同一抽象層上
> 如果有add(event),就會(huì)有remove(event)
* 如何降低使用全局?jǐn)?shù)據(jù)的風(fēng)險(xiǎn)
* 創(chuàng)建一種命名規(guī)則來(lái)突出全局變量
> gXXX
* 為全局變量創(chuàng)建一份注釋良好的清單
* 不要用全局變量存儲(chǔ)中間結(jié)果
* 不要把全局變量都放在一個(gè)大對(duì)象中并到處傳遞便锨,以說(shuō)明你沒(méi)有使用全局變量
> 全局變量應(yīng)根據(jù)其抽象層次防到相應(yīng)的類(lèi)中
第三部分 語(yǔ)句 statement
- 第十四章 組織直線(xiàn)型代碼 Organizing Straight-Line Code
- 14.1 必須有明確順序的語(yǔ)句 statements That Must be in Specific Order
設(shè)法組織代碼围辙,讓依賴(lài)關(guān)系變得非常明顯
使子程序名能突顯依賴(lài)關(guān)系
-
利用子程序參數(shù)明確顯示依賴(lài)關(guān)系
參數(shù)
init(expenseData);
dayExpensse(expenseData);
monthlyExpensse(expenseData);
anunalExpensse(expenseData);
帶返回值
expenseData = init(expenseData);
expenseData = dayExpensse(expenseData);
expenseData = monthlyExpensse(expenseData);
expenseData = anunalExpensse(expenseData);
用數(shù)據(jù)表明依賴(lài)關(guān)系不重要
init(expenseData);
dayExpenseData = dayExpensse(expenseData);
monthlyExpenseData = monthlyExpensse(expenseData);
anunalExpensseData = anunalExpensse(dayExpenseData ,monthlyExpenseData );
* 用注釋對(duì)不清晰的依賴(lài)關(guān)系進(jìn)行說(shuō)明
* 用斷言或者錯(cuò)誤處理代碼來(lái)檢查依賴(lài)關(guān)系:但是增加類(lèi)復(fù)雜度,采用的時(shí)候需要衡量利弊
- 14.2 順序無(wú)關(guān)的 語(yǔ)句 Statements Whose Order Don't Matter
- 使代碼易于自上而下地閱讀 Making Code Read From Top to Bottom:跟把相關(guān)代碼組織在一起時(shí)道理是一樣的
- 把相關(guān)代碼組織在一起 Grouping Related Statements
- 14.1 必須有明確順序的語(yǔ)句 statements That Must be in Specific Order
- 第十五章 使用條件語(yǔ)句 Using Conditionals
- 15.1 if語(yǔ)句
- 簡(jiǎn)單的if-then語(yǔ)句
- 首先寫(xiě)正確代碼路徑放案,再處理不常見(jiàn)情況
- 確保等量分支是正確的:不要漏掉特定情況
- 把正常情況的處理放在if后面而不要放在else后面
- if后面不要跟空語(yǔ)句:要不就改成 if(!XXX){};
- 考慮else語(yǔ)句:如果需要可以配個(gè)空的else語(yǔ)句并加以說(shuō)明
- 測(cè)試else語(yǔ)句的正確性
- 檢查if else語(yǔ)句是不是弄反
- if-then-else語(yǔ)句串 Chains of if-then-else statements:
- 使用布爾值調(diào)用簡(jiǎn)化復(fù)雜的檢測(cè)
- 把最正確的情況放在最前面
if(xxx){
}else if(xxx){
}
else if(xxx){
}
* 如果語(yǔ)言支持把if-then-else語(yǔ)句串替換成其他結(jié)構(gòu):case語(yǔ)句姚建,更清晰
- 簡(jiǎn)單的if-then語(yǔ)句
- 15.2 case語(yǔ)句 case Statements
- 為case語(yǔ)句選擇最有效的排序
- 按字母順序或者數(shù)字順序排列各種情況:所有情況的重要性相同
- 把正常的情況放在前面
- 按執(zhí)行頻率排列case語(yǔ)句
- 使用case語(yǔ)句的訣竅
- 簡(jiǎn)化每種情況對(duì)應(yīng)的操作:對(duì)于某種情況的操作過(guò)于復(fù)雜,應(yīng)該變成一個(gè)子程序
- 不要為了使用case語(yǔ)句而刻意制造一個(gè)變量
- 把default語(yǔ)句只用于檢查真正默認(rèn)的情況
還剩一個(gè)情況吱殉,用default去檢查是不對(duì)的
* 使用case穿越(穿透)需要注釋說(shuō)明情況
* 核對(duì)表at p635
- 為case語(yǔ)句選擇最有效的排序
- 15.1 if語(yǔ)句
- 第十六章 控制循環(huán)
- 16.1 選擇循環(huán)的種類(lèi) Selecting the Kind of Loop p367
- 種類(lèi):
- 計(jì)數(shù)循環(huán) counted loop
- 連續(xù)求值循環(huán) continuously evaluated loop
- 無(wú)限循環(huán) endless loop
- 迭代器循環(huán) iterator loop
對(duì)于C掸冤、C++厘托、Java:for、foreach 稿湿、while催烘、檢查位置都是開(kāi)始 do- while是結(jié)尾
靈活度除了foreach 是嚴(yán)格之外其他均是靈活
- 16.1 選擇循環(huán)的種類(lèi) Selecting the Kind of Loop p367
do-while至少執(zhí)行一次,其他可以不執(zhí)行
* 什么時(shí)候使用while循環(huán) When to Use a Loop-While-Exit Loop
* 什么時(shí)候用帶退出的循環(huán)
* 正常帶退出的循環(huán)
* 帶退出的循環(huán)更容易理解
* 帶退出的循環(huán)可能使退出的地方很多缎罢,可能導(dǎo)致在調(diào)試伊群、修改或者測(cè)試時(shí)被忽略,如果可能盡可能把退出的代碼寫(xiě)在一個(gè)地方
* 非正常帶退出的循環(huán)
* 什么時(shí)候使用for循環(huán) When to Use a for Loop:
你在循環(huán)頭處寫(xiě)好后即把它忘掉策精,無(wú)須再循環(huán)中做任何事情去控制它舰始,如果有一個(gè)必須使循環(huán)從循環(huán)退出的條件,就使用while循環(huán)
* 什么時(shí)候使用foreach循環(huán) When to Use a foreach Loop:消除循環(huán)內(nèi)務(wù)處理算數(shù)咽袜,防止off-by-one越界錯(cuò)誤
- 16.2 循環(huán)控制 Controlling the Loop p373
- 防止出現(xiàn)錯(cuò)誤的方法:
- 減少能影響該循環(huán)各種原因的因素:說(shuō)了跟沒(méi)有一樣——
- 把循環(huán)內(nèi)部當(dāng)做子程序丸卷,把控制盡可能放在循環(huán)體外
while(XXX && XXX && (XXX||XXX)){
XXXXXXXXXX }
- 進(jìn)入循環(huán) Entering Loop
- 只從一個(gè)位置進(jìn)入循環(huán)
- 把初始化代碼緊放在循環(huán)前面
- 用while(true)代表無(wú)限循環(huán)
- 在適當(dāng)情況下多使用for循環(huán)
因?yàn)閒or循環(huán)把循環(huán)控制代碼集中了,while需要在循環(huán)頂部初始化循環(huán)條件,然后在底部修改循環(huán)的相關(guān)代碼
* 在while循環(huán)更適用的時(shí)候询刹,不要使用for循環(huán)
> 不是for(xx;xx;xx)中間代碼不是簡(jiǎn)單對(duì)計(jì)數(shù)值進(jìn)行判斷谜嫉,而是其他表達(dá)式則應(yīng)當(dāng)該為while循環(huán)
* 處理好循環(huán)體 Processing The Middle of the Loop
* 用{}
將循環(huán)體重的語(yǔ)句包起來(lái):個(gè)人:即使是一條語(yǔ)句也需要,因?yàn)閿U(kuò)展凹联、修改程序可能會(huì)出現(xiàn)意料之外的錯(cuò)誤
* 避免空循環(huán):不要出現(xiàn)循環(huán)體為空的情況沐兰,應(yīng)改成do-while
* 把循環(huán)體的內(nèi)務(wù)操作要么放在循環(huán)開(kāi)始處,要么放在結(jié)尾處:內(nèi)務(wù)操作如i= i+1這樣的表達(dá)式
* 一個(gè)循環(huán)只做一件事
* 退出循環(huán) Exiting Loop
* 設(shè)法確認(rèn)循環(huán)能夠終止:考慮正常情況蔽挠、端點(diǎn)以及每一種異常情況
* 不要為了終止循環(huán)混亂修改for循環(huán)下標(biāo)
* 避免出現(xiàn)依賴(lài)于下標(biāo)最終取值的代碼:下標(biāo)值只在循環(huán)體內(nèi)有效住闯,可以說(shuō)是縮小作用域的一種做法
* 考慮使用安全計(jì)數(shù)器
* 提前退出循環(huán)
* 考慮在while循環(huán)中使用break而不是布爾標(biāo)記:
- 防止出現(xiàn)錯(cuò)誤的方法:
就是循環(huán)體中前后操作有條件限制關(guān)系,當(dāng)達(dá)到某個(gè)條件澳淑,不執(zhí)行后續(xù)操作時(shí)比原,應(yīng)當(dāng)使用break直接退出
* 小心那些有很多break散布在循環(huán)中
* 在循環(huán)開(kāi)始處使用continue:提高可讀性
* 如果語(yǔ)言支持,請(qǐng)使用帶標(biāo)記號(hào)break結(jié)構(gòu):是break退出的目標(biāo)一目標(biāo)然
* 使用break和continue要小心謹(jǐn)慎
* 檢查端點(diǎn) Checking EndPoints
> 簡(jiǎn)單的循環(huán):開(kāi)始情況+任意選擇的中間情況+最終情況杠巡,先腦海模擬量窘,如果有復(fù)雜計(jì)算,手動(dòng)檢查計(jì)算是否正確
* 使用循環(huán)變量 Using Loop Variables
* 用整數(shù)或者枚舉類(lèi)型表示數(shù)組和循環(huán)的邊界
* 嵌套循環(huán)中使用有意義的變量名提高其可讀性
* 用有意義的名字防止循環(huán)下標(biāo)串話(huà)
* 把循環(huán)下標(biāo)變量限制在本循環(huán)內(nèi)
* 循環(huán)應(yīng)該多長(zhǎng) How Long Should a Loop Be
* 把循環(huán)代碼的行數(shù)限制在50行以?xún)?nèi)
* 把嵌套限制在3層以?xún)?nèi)
* 把長(zhǎng)循環(huán)的內(nèi)容移到子程序內(nèi)
* 要讓長(zhǎng)循環(huán)格外清晰
- 16.3 輕松創(chuàng)建循環(huán)-由內(nèi)而外 Creating Loop Easily- From the inside Out p385
- 循環(huán)內(nèi)部邏輯->循環(huán)控制語(yǔ)句
*偽代碼->代碼
- 循環(huán)內(nèi)部邏輯->循環(huán)控制語(yǔ)句
- 16.4 循環(huán)和數(shù)組的關(guān)系 Corresponse Between Loop And Arrays p387
- 第十七章 不常見(jiàn)的控制結(jié)構(gòu) Unusual Control Structures
- 17.1 子程序中多處返回 Multiple Return From a Routine p391
- 如果能增加可讀性氢拥,就用return
- 用防衛(wèi)句子(guard clause)(早返回或早退出) 來(lái)簡(jiǎn)化復(fù)雜的錯(cuò)誤處理
- 17.2 遞歸 Recursion p393
- 使用遞歸的技巧
- 確認(rèn)遞歸能夠終止
- 使用安全計(jì)數(shù)器防止無(wú)限循環(huán)
- 把遞歸限制在一個(gè)子程序里面
- 留心棸鐾空間:防止棧溢出
- 不要用遞歸去計(jì)算階乘和斐波那契數(shù)列
- 17.3 goto p398
- 反對(duì)goto的觀(guān)點(diǎn) The Arguments Against gotos
- 支持goto的觀(guān)點(diǎn) The Arguments for gotos
- 關(guān)于goto的虛假辯論 The phony goto Debate
- 錯(cuò)誤處理和goto Erro Processing And goto
- goto和在else字句中的共享代碼 goto And The Sharing Code In an else Clause
- goto使用原則總結(jié) Summary of Guidlines For Using *gotos *
- 17.4 針對(duì)不常見(jiàn)控制結(jié)構(gòu)的觀(guān)點(diǎn) Perspective on Unusual Control Structures
- 第十八章 表驅(qū)動(dòng)法 Table-Driven Methods
- 18.1 表驅(qū)動(dòng)法使用總則 General Considerations in Using Table-Driven Methods p411
- 查詢(xún)表取代復(fù)雜的邏輯控制結(jié)構(gòu)
if(xxx|xxx){
xxxxx }else if(xxx ||xxx && xxx){ }else if(xxx ||xxx && xxx){ }
- 使用表驅(qū)動(dòng)法的兩個(gè)問(wèn)題 Two Issues in Using Table-Driven Methods
- 怎樣從表中查詢(xún)條目(查詢(xún))
- 直接訪(fǎng)問(wèn) Direct access
- 索引訪(fǎng)問(wèn) Index access
- 階梯訪(fǎng)問(wèn) Stair-step access
- 在表中存些什么(數(shù)據(jù))
- 怎樣從表中查詢(xún)條目(查詢(xún))
- 18.2 直接訪(fǎng)問(wèn)表 Direct Access Tables p413
- 示例 一個(gè)月中的天數(shù) 保險(xiǎn)費(fèi)率 靈活消息的格式
- 靈活的消息格式:20種消息類(lèi)型打印出來(lái)
- 基于邏輯:根據(jù)消息的類(lèi)型,一個(gè)類(lèi)型對(duì)應(yīng)一個(gè)子程序執(zhí)行打印消息
- 面向?qū)ο笤O(shè)計(jì):定義一個(gè)消息基類(lèi)兄一,在其中定義一個(gè)打印消息的共有方法厘线,派生出不同的消息子類(lèi),然后重載打印消息的方法出革,通過(guò)多態(tài)的方式打印消息
- 表驅(qū)動(dòng)法:根據(jù)不同的消息類(lèi)型查找其對(duì)應(yīng)字段信息和字段類(lèi)型造壮,并通過(guò)同一個(gè)子程序?qū)⒒緮?shù)據(jù)信息打印出來(lái)
- 構(gòu)造鍵值對(duì)值 Fudging Lookup Keys
- 復(fù)制信息從而能夠直接使用該值:缺點(diǎn)是導(dǎo)致數(shù)據(jù)冗余,浪費(fèi)空間
- 轉(zhuǎn)換鍵值對(duì)以使其能夠直接使用
- 把鍵值對(duì)轉(zhuǎn)換提出成獨(dú)立的子程序
- 18.3 索引訪(fǎng)問(wèn)表 Indexed Access Table p425
- 通過(guò)居間的索引進(jìn)行訪(fǎng)問(wèn)
- 優(yōu)點(diǎn):
- 減少存儲(chǔ)空間,主查詢(xún)表每條記錄都很大耳璧,索引表相對(duì)而言每條數(shù)據(jù)占用空間小很多
- 即使使用索引訪(fǎng)問(wèn)成箫,操作索引中記錄也比操作主表中的記錄來(lái)得簡(jiǎn)單
- 表查詢(xún)技術(shù)在可維護(hù)性上具有優(yōu)點(diǎn)
- 18.4 階梯訪(fǎng)問(wèn)表 Stair-Step Access Table p426
- 表中的數(shù)據(jù)對(duì)于不同數(shù)據(jù)范圍有效,而不是對(duì)不同的數(shù)據(jù)點(diǎn)有效
- 注意事項(xiàng):
- 留心端點(diǎn):端點(diǎn)的情況是否被考慮到
- 考慮用二分查找取代順序查找
- 考慮用索引訪(fǎng)問(wèn)來(lái)取代階梯技術(shù)
- 18.5 表查詢(xún)的其他示例 Other Example of Table Lookups p429
- 18.1 表驅(qū)動(dòng)法使用總則 General Considerations in Using Table-Driven Methods p411
- 第十九章 一般控制問(wèn)題 General Control Issue
- 19.1 布爾表達(dá)式 Boolean Expressions p431
- 用true或者false做布爾判斷 Using true of false For Boolean Tests
- 用true或者false做判斷旨枯,而不用0和1等數(shù)值做判斷
- 隱式地比較布爾值與true和false:
while(success){xx}
而不是while(success == true){xxx}
* 簡(jiǎn)化復(fù)雜的表達(dá)式 Making Complicated Expression Simple
* 拆分復(fù)雜判斷并引入新的布爾變量
* 把復(fù)雜的表達(dá)式做成布爾函數(shù)
* 用決策表替代復(fù)雜的條件
* 編寫(xiě)肯定形式的布爾表達(dá)式 Forming Boolean Expression Positively
* 先肯定再否定語(yǔ)句
>if(xx){xxx}else{xxx}
而不是if(!xx){xxx}else{xxx}
* 用狄摩根定理(逆反定理)簡(jiǎn)化否定的布爾判斷
*not A and not B = not(A or B)
not A or not B = not (A and B)
* 用括號(hào)使布爾表達(dá)式更清晰 Using Parentheses to Clarify Boolean Expressions
* 用簡(jiǎn)單的技術(shù)技巧來(lái)使括號(hào)對(duì)稱(chēng):開(kāi)始為0蹬昌,遇到一個(gè)左括號(hào)加1,遇到一個(gè)右括號(hào)減1
* 把布爾值括在括號(hào)里面
* 理解布爾表達(dá)式如何求值 Knowing How Boolean Expression Are Evaluated
* 按照數(shù)軸順序編寫(xiě)數(shù)值表達(dá)式 Writing Numeric Expressions in Number-Line Order
* 從左到右攀隔,從大到小
* 與0比較的知道原則 Guidelines for Comparisons to 0
* 隱式地比較邏輯變量
* 把數(shù)和()相比較
* 在C中顯式地比較字符和零終止符(‘\0’)
* 把指針與NULL相比較
* 布爾表達(dá)式的常見(jiàn)問(wèn)題
* java中 == 和equal的區(qū)別
- 用true或者false做布爾判斷 Using true of false For Boolean Tests
- 19.2 復(fù)合語(yǔ)句(語(yǔ)句塊)Compound Statements (Blocks) p443
*把括號(hào)對(duì)一起寫(xiě)出- 用括號(hào)把條件表達(dá)清楚
- 19.3 空語(yǔ)句 Null Statements p444
- 小心使用空語(yǔ)句
- 為空語(yǔ)句創(chuàng)建一個(gè)DoNothing()預(yù)處理函數(shù)或者內(nèi)聯(lián)函數(shù):強(qiáng)調(diào)空語(yǔ)句
- 考慮如果換用一個(gè)非空的循環(huán)體皂贩,是否會(huì)讓代碼更清晰
- 19.4 馴服危險(xiǎn)的深層嵌套 Taming Dangerously Deep Nesting p445
- 通過(guò)重復(fù)檢測(cè)條件中某一部分來(lái)簡(jiǎn)化嵌套的if語(yǔ)句
- 用break來(lái)簡(jiǎn)化嵌套if
- 把嵌套if轉(zhuǎn)換成一組if-then-else語(yǔ)句:即轉(zhuǎn)換成
if(xxx){xxx}elseif(xxx){xxx}elseif(xxx){xxxx}
- 把嵌套if轉(zhuǎn)換成case語(yǔ)句
- 把深層嵌套的代碼抽取出來(lái)放進(jìn)單獨(dú)的子程序
- 使用一種更面向?qū)ο蟮姆椒ǎ杭炊鄳B(tài)
- 重新設(shè)計(jì)深層嵌套代碼
- 爭(zhēng)議 用狀態(tài)變量重寫(xiě)代碼(增加復(fù)雜度)17.3
- 爭(zhēng)議 用防衛(wèi)字句退出子程序,從而使代碼的主要路徑更為清晰 17.1
- 使用異常 8.4
- 19.5 編程基礎(chǔ):結(jié)構(gòu)化編程 p454
- 核心思想:應(yīng)用程序只采用一些單入口昆汹,單出口的控制結(jié)構(gòu)明刷。單入單出的控制結(jié)構(gòu)就是一個(gè)代碼塊,只能從一個(gè)位置開(kāi)始執(zhí)行满粗,并且只能結(jié)束于某個(gè)位置辈末。(有且只有一個(gè)入口和出口)
- 結(jié)構(gòu)化編程的三個(gè)組成部分 The Three Components of Structured Programming
- 順序 Sequence:賦值和調(diào)用子程序
- 選擇 Selection:if和case語(yǔ)句
- 迭代 Iteration:
- 19.6 控制結(jié)構(gòu)與復(fù)雜度 Control Structure and Complexity p456
- 復(fù)雜度的重要性 How Import is Complexity
- 降低復(fù)雜度的一般性原則 General Guidelines For Reducing Complexity
- 怎樣去度量復(fù)雜度:
程序一開(kāi)始為1
一旦遇到關(guān)鍵詞或者其同類(lèi)加1:if repeat,while映皆,for挤聘,and,or
給case語(yǔ)句中每一種情況加1
* 如何處理復(fù)雜度的度量結(jié)果
> 0-5子程序可能不錯(cuò)|
6-10得想辦法 簡(jiǎn)化子程序類(lèi)
10+把子程序 的某一部分拆分成另一個(gè)子程序并調(diào)用它
- 19.1 布爾表達(dá)式 Boolean Expressions p431
第五部分 代碼改善 Code Improvement
- 第二十章 軟件質(zhì)量描述 p463
- 20.1 軟件質(zhì)量的特性
- 外在特性:
- 正確性 Correctness 指系統(tǒng)規(guī)范捅彻、設(shè)計(jì)和實(shí)現(xiàn)方面的錯(cuò)誤的稀少程度
- 可用性 Usability:指用戶(hù)學(xué)習(xí)和使用的成本
- 效率 Efficiency:指占用的內(nèi)存组去,儲(chǔ)存和執(zhí)行時(shí)間
- 可靠性 Reliability:在指定必需條件下,完成所需功能的能力:很長(zhǎng)的無(wú)故障時(shí)間
- 健壯性 Robustness:接受無(wú)效數(shù)據(jù)或者在壓力環(huán)境下運(yùn)行的能力
- 完整性 Integrity:阻止對(duì)程序或者數(shù)據(jù)進(jìn)行未經(jīng)驗(yàn)證或者不正確訪(fǎng)問(wèn)的能力
- 適應(yīng)性 Adaptability:為特定應(yīng)用或者環(huán)境參數(shù)設(shè)計(jì)的系統(tǒng)沟饥,能不修改的情況給其他應(yīng)用或者環(huán)境使用
- 精確性 :輸出結(jié)果的誤差程度
- 內(nèi)在特性:
- 靈活性 Flexibility: 適應(yīng)需求
- 可維護(hù)性 Maintainability
- 可移植性 Portability
- 可重用性 ReuSability
- 可讀性 Readability
- 可測(cè)試性 Testability
- 可理解性 Understandability
- 20.2 改善軟件質(zhì)量的技術(shù)
- 20.3 不同質(zhì)量保障技術(shù)的相對(duì)效能
- 20.4 什么時(shí)候進(jìn)行質(zhì)量保證工作
- 20.5 軟件質(zhì)量的普遍原理
- 20.1 軟件質(zhì)量的特性
- 第二十一章 協(xié)同構(gòu)建 p479
- 第二十二章 開(kāi)發(fā)者測(cè)試 p499
- 22.1 開(kāi)發(fā)者測(cè)試在軟件質(zhì)量中的角色 p500
- 測(cè)試的種類(lèi):
- 單元測(cè)試(Unit testing):測(cè)試的代碼:一個(gè)程序員或者一個(gè)團(tuán)隊(duì)編寫(xiě) 代碼規(guī)模:完整的類(lèi)添怔、子程序或者小程序
- 組件測(cè)試(Component testing)測(cè)試代碼:一個(gè)類(lèi)湾戳、包小程序或者其他程序元素 代碼規(guī)模:涉及到多個(gè)程序員或者多個(gè)團(tuán)隊(duì)
- 集成測(cè)試(Integration testing):是對(duì)兩個(gè)或更多的類(lèi)贤旷、包、組件或者子系統(tǒng)進(jìn)行聯(lián)合測(cè)試砾脑。這些組件由多個(gè)程序員或者開(kāi)發(fā)團(tuán)隊(duì)所創(chuàng)建幼驶。
- 測(cè)試的作用:
- 測(cè)試與其他開(kāi)發(fā)活動(dòng)背道而馳,測(cè)試的目標(biāo)識(shí)找出錯(cuò)誤韧衣,成功的測(cè)試是弄垮軟件盅藻,而其他開(kāi)發(fā)活動(dòng)是避免程序錯(cuò)誤和軟件崩潰
- 測(cè)試永遠(yuǎn)不可能徹底證明程序中沒(méi)有錯(cuò)誤
- 測(cè)試并不能解決錯(cuò)誤,改善軟件質(zhì)量
- 程序員傾向于做出”干凈“的測(cè)試
- 構(gòu)建中測(cè)試
- 構(gòu)建期間:先根據(jù)需求構(gòu)想子程序->編寫(xiě)子程序或者類(lèi)->先在腦海檢查->進(jìn)行復(fù)查或者測(cè)試
- 每寫(xiě)一個(gè)子程序畅铭,對(duì)其進(jìn)行獨(dú)立測(cè)試氏淑,確實(shí)不容易,但是單獨(dú)調(diào)試比繼承之后再測(cè)試容易多硕噩。
- 新加入的子程序發(fā)現(xiàn)新的錯(cuò)誤假残,就知道這是子程序或者其接口引發(fā)的問(wèn)題
- 測(cè)試的種類(lèi):
- 22.2 開(kāi)發(fā)者測(cè)試的推薦方法 Recommend Approad to Developer Testing p503
- 基礎(chǔ)方法:
- 對(duì)每一項(xiàng)相關(guān)的需求進(jìn)行測(cè)試
- 對(duì)每隔相關(guān)的設(shè)計(jì)關(guān)注點(diǎn)進(jìn)行測(cè)試
- 用基礎(chǔ)測(cè)試basic testing來(lái)擴(kuò)充針對(duì)需求和設(shè)計(jì)的詳細(xì)測(cè)試用例:增加數(shù)據(jù)流測(cè)試 data-flow test,然后補(bǔ)充其他所需的測(cè)試用例
- 使用一個(gè)檢查表,其中記錄著你在項(xiàng)目中所犯的錯(cuò)誤
- 測(cè)試先行還是測(cè)試后行:測(cè)試先行
- 先寫(xiě)測(cè)試用例只是工作順序問(wèn)題:所花代價(jià)一樣
- 先編寫(xiě)測(cè)試用例辉懒,可以更早發(fā)現(xiàn)缺陷
- 開(kāi)發(fā)者測(cè)試的局限性
- 開(kāi)發(fā)者測(cè)試傾向于”干凈“測(cè)試
- 開(kāi)發(fā)者測(cè)試對(duì)于代碼覆蓋率過(guò)于樂(lè)觀(guān)
- 開(kāi)發(fā)者測(cè)試往往忽略一些更復(fù)雜的測(cè)試覆蓋率類(lèi)型
- 22.3 測(cè)試技巧錦囊 p505
- 不完整的測(cè)試Incomplete Testing:進(jìn)行完整測(cè)試是不可能的事情
- 結(jié)構(gòu)化的基礎(chǔ)測(cè)試 Structured Basic Testing
- 測(cè)試程序中的每一條語(yǔ)句至少一次
- 結(jié)構(gòu)化基礎(chǔ)測(cè)試最少數(shù)量計(jì)算:
- 對(duì)于通過(guò)子程序的直路阳惹,開(kāi)始的時(shí)候加1
- 遇到每個(gè)關(guān)鍵詞或者等價(jià)物加1,如:if眶俩、while莹汤、repeat、for颠印、and以及or
- 遇到每個(gè)case語(yǔ)句就加1
- 數(shù)據(jù)流測(cè)試 Data-Flow Testing:數(shù)據(jù)流出錯(cuò)率不低于控制流
- 數(shù)據(jù)的狀態(tài)
- 已定義:數(shù)據(jù)已經(jīng)初始化了纲岭,但是沒(méi)有被使用
- 已使用:數(shù)據(jù)已經(jīng)用于計(jì)算或者作為某子程序的參數(shù)
- 已銷(xiāo)毀:變量出了作用域或者指針已經(jīng)被釋放
- 數(shù)據(jù)的狀態(tài)的組合:正確的是已定義-已使用
- 數(shù)據(jù)的狀態(tài)
- 等價(jià)類(lèi)劃分 Equipment Partitioning
- 猜測(cè)錯(cuò)誤 Error Guessing
- 邊界值分析 Boundary Analysis
- 常規(guī)邊界值:小于、等于和大于
- 復(fù)合邊界值
- 幾類(lèi)壞數(shù)據(jù) Classes of Bad Data
- 數(shù)據(jù)太少(沒(méi)有數(shù)據(jù))
- 太多的數(shù)據(jù)
- 錯(cuò)誤(無(wú)效)的數(shù)據(jù)
- 未初始化的數(shù)據(jù)
- 幾類(lèi)好數(shù)據(jù) Classes of Good Data
- 正常的情況-中間或者期望值
- 最小的正常局面
- 最大的正常局面
- 與舊數(shù)據(jù)的兼容性
- 22.4 典型錯(cuò)誤 p517
- 錯(cuò)誤不是均勻分布的
- 絕大數(shù)錯(cuò)誤與少數(shù)幾個(gè)具有嚴(yán)重缺陷的子程序有關(guān)
- 錯(cuò)誤有幾大類(lèi):結(jié)構(gòu)方面的錯(cuò)誤线罕?荒勇,數(shù)據(jù)方面的錯(cuò)誤,已實(shí)現(xiàn)的功能(可能是說(shuō)隨著迭代闻坚,新需求跟舊實(shí)現(xiàn)之間的錯(cuò)誤)
- 大多數(shù)錯(cuò)誤的影響范圍有限
- 大多數(shù)構(gòu)建錯(cuò)誤是編程人員的錯(cuò)誤造成的
- 拼寫(xiě)錯(cuò)誤是一個(gè)常見(jiàn)的問(wèn)題
- 22.5 測(cè)試支持工具 Test-Support Tools p523
- 為測(cè)試各個(gè)類(lèi)構(gòu)造腳手架 Building Scaffolding to Test Individual Classes
- 啞類(lèi)(模仿對(duì)象/樁對(duì)象) dummy class(mock object/stub object):根據(jù)所需的真實(shí)性決定他們與現(xiàn)實(shí)的近似程度
- 調(diào)用待測(cè)試的真實(shí)函數(shù)的偽造函數(shù)沽翔,稱(chēng)為“驅(qū)動(dòng)函數(shù)”或者“測(cè)試夾具”
- 測(cè)試數(shù)據(jù)生成器 Test-Data Generations
- 產(chǎn)生程序員意想不到的數(shù)據(jù)組合
- 比起手工構(gòu)造測(cè)試數(shù)據(jù),隨機(jī)數(shù)據(jù)生成器能夠更徹底地進(jìn)行測(cè)試
- 覆蓋率監(jiān)視器 Coverage Monitors
- 數(shù)據(jù)記錄器/日志記錄器
- 符號(hào)調(diào)試器
- 系統(tǒng)干擾器
- 錯(cuò)誤數(shù)據(jù)庫(kù)
- 為測(cè)試各個(gè)類(lèi)構(gòu)造腳手架 Building Scaffolding to Test Individual Classes
- 22.6 改善測(cè)試過(guò)程 Improving Your Testing p528
- 有計(jì)劃的測(cè)試
- 重新測(cè)試(回歸測(cè)試):在徹底檢查代碼的前提下窿凤,當(dāng)相關(guān)代碼發(fā)生改變之后仅偎,需要重新測(cè)試,可能產(chǎn)品迭代增加新的測(cè)試用例的同時(shí)應(yīng)保留舊的測(cè)試用例
- 自動(dòng)化測(cè)試
- 22.7 保留測(cè)試記錄 Keeping Test Records p529
- 22.1 開(kāi)發(fā)者測(cè)試在軟件質(zhì)量中的角色 p500
- 第二十三章 調(diào)試 p535
- 第二十四章 重構(gòu) p563
- 第二十五章 代碼調(diào)整策略 p587
- 第二十六章 代碼調(diào)整技術(shù) p609