版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第3章
面向?qū)ο蟮能浖?gòu)造第3章面向?qū)ο蟮能浖?gòu)造學(xué)習(xí)如何運(yùn)用面向?qū)ο蟮能浖?gòu)造技術(shù)管理和控制軟件的復(fù)雜性。繼續(xù)探討分解和模塊化,學(xué)習(xí)把抽象和封裝的原則表示成數(shù)學(xué)模型——抽象數(shù)據(jù)類型,用面向?qū)ο蠓椒▽?shí)現(xiàn)。通過面向?qū)ο蟮脑O(shè)計(jì),理解軟件設(shè)計(jì)及其原則和設(shè)計(jì)模式。學(xué)習(xí)調(diào)試技術(shù)和工具,并初步學(xué)習(xí)自動(dòng)化測試框架。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院2第3章面向?qū)ο蟮能浖?gòu)造故事4小強(qiáng)離校外出實(shí)習(xí),找好友小雨幫忙,并告訴了華經(jīng)理。小雨剛剛學(xué)完面向?qū)ο蠹夹g(shù),正想練習(xí)一下,就參考小強(qiáng)的描述和程序,重新編寫了程序。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院3第3章面向?qū)ο蟮能浖?gòu)造隨著要解決的問題及其程序變得越來越復(fù)雜,程序不斷增大,在編碼前考慮如何運(yùn)用良好的原則把程序功能(用戶需求)分解到模塊,考慮各個(gè)模塊之間的交互、每個(gè)模塊的數(shù)據(jù)結(jié)構(gòu)與算法等,稱之為設(shè)計(jì)(動(dòng)詞),結(jié)果稱為方案或設(shè)計(jì)(名詞),這個(gè)開發(fā)活動(dòng)的重要性凸現(xiàn)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院4第3章面向?qū)ο蟮能浖?gòu)造模塊化是在函數(shù)級(jí),通過函數(shù)間的交互表示程序結(jié)構(gòu)、分配程序功能,暫時(shí)忽略了函數(shù)的內(nèi)部實(shí)現(xiàn)。面向?qū)ο蠹夹g(shù)把數(shù)據(jù)及其操作封裝在一個(gè)對(duì)象中,并把具有相同屬性(數(shù)據(jù)名稱)和方法(函數(shù))的所有對(duì)象抽象成類,使得能在比函數(shù)更抽象、更大程序單元粒度的層次上進(jìn)行軟件開發(fā)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院5第3章面向?qū)ο蟮能浖?gòu)造傳統(tǒng)設(shè)計(jì)工程的目標(biāo)是創(chuàng)作出堅(jiān)固、適用和賞心悅目的模型或設(shè)計(jì)表示。堅(jiān)固或稱為可靠,是指程序不含任何妨礙其功能的缺陷。適用指滿足用戶需求,符合程序的開發(fā)目標(biāo)。賞心悅目則是指程序具有友好的界面,使用程序的快樂體驗(yàn)。為此,設(shè)計(jì)師必須首先獲得多種設(shè)計(jì)信息和方案,然后將其匯聚,從中精心挑選各種設(shè)計(jì)元素、得到某種特定的配置,最終形成滿足設(shè)計(jì)目標(biāo)的產(chǎn)品或系統(tǒng)的設(shè)計(jì)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院6第3章面向?qū)ο蟮能浖?gòu)造軟件設(shè)計(jì)的多樣化和聚合需要直覺和判斷力,其質(zhì)量取決于構(gòu)造類似實(shí)體的經(jīng)驗(yàn)、一系列指導(dǎo)面向演化的原則和啟發(fā)、一系列質(zhì)量評(píng)價(jià)標(biāo)準(zhǔn)及最終設(shè)計(jì)的表示的迭代過程。軟件設(shè)計(jì)在開發(fā)過程中處于技術(shù)核心,它使用的技術(shù)與軟件過程無關(guān)。軟件設(shè)計(jì)是軟件建模的最后一個(gè)活動(dòng),接著進(jìn)入構(gòu)造階段。軟件工程的一個(gè)獨(dú)特性是從分析到設(shè)計(jì)、從設(shè)計(jì)到程序的變遷。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院7第3章面向?qū)ο蟮能浖?gòu)造3.1抽象與封裝3.2認(rèn)識(shí)面向?qū)ο?.3面向?qū)ο蟮脑O(shè)計(jì)3.4調(diào)試的基本技術(shù)3.5軟件自動(dòng)化測試3.6案例分析與實(shí)踐3.7討論與提高3.8思考與練習(xí)題2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院83.1抽象與封裝3.1.1模塊產(chǎn)生與合成3.1.2抽象與封裝3.1.3抽象數(shù)據(jù)類型2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院93.1.1模塊產(chǎn)生與合成2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院103.1.1模塊產(chǎn)生與合成函數(shù)簇包含了對(duì)核心數(shù)據(jù)的產(chǎn)生、變更和使用的操作函數(shù)。函數(shù)簇與其之外的其他函數(shù)通常不能產(chǎn)生、變更函數(shù)簇內(nèi)的核心數(shù)據(jù),僅僅使用。從模塊化理解,一個(gè)函數(shù)簇實(shí)現(xiàn)了一組圍繞核心數(shù)據(jù)的功能,具備通信內(nèi)聚和功能內(nèi)聚,屬于強(qiáng)內(nèi)聚。函數(shù)簇其他函數(shù)、函數(shù)簇、模塊的連接方式主要是數(shù)據(jù)的傳遞及對(duì)理解函數(shù)簇?cái)?shù)據(jù)的函數(shù)的調(diào)用。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院113.1.1模塊產(chǎn)生與合成局部化,是實(shí)現(xiàn)模塊化的一種重要機(jī)制。如函數(shù)和復(fù)合語句的內(nèi)部變量函數(shù)調(diào)用可以視為模塊組合的一種機(jī)制。通過函數(shù)調(diào)用把函數(shù)聯(lián)系起來,構(gòu)成更大規(guī)模的程序。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院123.1.1模塊產(chǎn)生與合成數(shù)據(jù)結(jié)構(gòu),如數(shù)組或C的結(jié)構(gòu)體為組成更大、更復(fù)雜的數(shù)據(jù)提供了構(gòu)建具有層次結(jié)構(gòu)的組織方式。單純的數(shù)據(jù)結(jié)構(gòu)不含對(duì)數(shù)據(jù)的操作,也不能保護(hù)其中的數(shù)據(jù)元素??梢栽跀?shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)類型的基礎(chǔ)上實(shí)現(xiàn)模塊化機(jī)制,這就需要抽象與封裝。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院133.1.2抽象與封裝抽象是指對(duì)于一個(gè)過程或一件事物的某些細(xì)節(jié)有目的地隱藏,以便把其他方面、細(xì)節(jié)或結(jié)構(gòu)表達(dá)得更加清楚。抽象是從眾多的事物中抽取出共同的、本質(zhì)性的特征,而舍棄其非本質(zhì)的特征。抽象的目的是通過把相關(guān)的屬性和其他不相關(guān)的屬性分開,分離關(guān)注點(diǎn)。抽象是處理復(fù)雜問題的一個(gè)手段。抽象是分離對(duì)象特性、限制對(duì)它們?cè)诋?dāng)前環(huán)境關(guān)注的一個(gè)機(jī)制。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院143.1.2抽象與封裝如,教學(xué)管理系統(tǒng),把學(xué)生抽象成符號(hào)串(姓名、學(xué)號(hào)、學(xué)院、專業(yè)、課程)、數(shù)字(出生日期、課程成績)等用數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu)表示的屬性;查找一個(gè)學(xué)生的信息通過一個(gè)檢索函數(shù)實(shí)現(xiàn),使用者不必關(guān)心使用了什么檢索方法。又如,對(duì)口算題進(jìn)行了抽象,是有兩個(gè)運(yùn)算數(shù)、一個(gè)運(yùn)算符及一個(gè)運(yùn)算結(jié)果的符號(hào)串或數(shù)據(jù)結(jié)構(gòu),不考慮算式表示的涵義、物理屬性、表現(xiàn)形式等。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院153.1.2抽象與封裝程序設(shè)計(jì)有兩種抽象,分別是過程抽象(函數(shù)抽象)和數(shù)據(jù)抽象。過程抽象是在使用一個(gè)函數(shù)或方法時(shí)知道它干什么,而不知道它是如何完成的。數(shù)據(jù)抽象是將一個(gè)數(shù)據(jù)類型的特性(值及其運(yùn)算)與其實(shí)現(xiàn)分離。在軟件構(gòu)造中,我們需要一種機(jī)制來實(shí)現(xiàn)抽象,呈現(xiàn)關(guān)注點(diǎn),隱藏其他細(xì)節(jié)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院163.1.2抽象與封裝封裝有兩個(gè)含義:①把描述一個(gè)事物的性質(zhì)和行為結(jié)合在一起成為構(gòu)件,對(duì)外形成該事物的一個(gè)界限,封裝使構(gòu)件能夠集中而完整地對(duì)應(yīng)并描述具體的事物,體現(xiàn)了事物的相對(duì)獨(dú)立性;②信息隱蔽,即外界不能直接存取構(gòu)件的內(nèi)部信息(屬性)及隱藏起來的內(nèi)部操作,外界也不必知道操作的內(nèi)部實(shí)現(xiàn)細(xì)節(jié);信息隱藏強(qiáng)制封裝。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院173.1.2抽象與封裝封裝具有如下優(yōu)勢構(gòu)件外部只能通過外部可用的操作來訪問內(nèi)部數(shù)據(jù)和操作,降低了構(gòu)件間的耦合度。構(gòu)件內(nèi)部修改對(duì)外部的影響變小,減少了修改引起整個(gè)程序范圍的“波動(dòng)效應(yīng)”。更容易快速開發(fā)正確的程序,一旦程序員們確定了構(gòu)件間的交互,每個(gè)人都可以獨(dú)立地開發(fā)和測試分配的構(gòu)件。改善通用性和維護(hù)性。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院183.1.2抽象與封裝嚴(yán)格的封裝也會(huì)帶來諸如編程麻煩、執(zhí)行效率的問題。有些語言不強(qiáng)調(diào)嚴(yán)格的封裝和信息隱藏,而采取可見性控制來解決這些問題。例如,C++和Java語言通過定義對(duì)象的屬性和操作的可見性,規(guī)定了其他對(duì)象對(duì)其屬性和操作的可訪問性;另外,一個(gè)對(duì)象也可以通過把相應(yīng)的可見性指定為受保護(hù)的或私有的,而提供僅局限于特定對(duì)象的屬性和操作。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院193.1.2抽象與封裝【例3.1】一個(gè)商店中可能有一個(gè)人負(fù)責(zé)貨架(保管員),一個(gè)人負(fù)責(zé)進(jìn)貨(采購員)。對(duì)于保管員,貨架是存放商品位置的抽象,只需關(guān)注貨架的位置信息如行、列、層等,而不必關(guān)心貨架的材質(zhì)、色彩等。同樣,采購員對(duì)飲料進(jìn)行抽象,他只需知道飲料的名稱、編碼、價(jià)格、供應(yīng)商等有關(guān)信息,而不必關(guān)心飲料容器的大小、材料、色澤等。而保管員則必須知道這些信息,以便把商品放到正確的位置。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院203.1.2抽象與封裝封裝使得各行其責(zé)。當(dāng)保管員注意到庫存的飲料少了,只需通知采購員訂貨。保管員無須知道飲料的價(jià)格和來源。采購員也不關(guān)心飲料放在貨架的具體位置。封裝使得這些工作更加容易和安全。當(dāng)然,保管員和采購員相互獨(dú)立的職責(zé)有可能造成“采購員本周休假,飲料缺貨”的情形;或者保管員不在,倉庫有貨卻無法上架。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院213.1.3抽象數(shù)據(jù)類型數(shù)據(jù)類型是一個(gè)值的集合和定義在值集上的一組操作的總稱。明顯或隱含地規(guī)定了數(shù)據(jù)的取值范圍、存儲(chǔ)方式及其運(yùn)算。數(shù)據(jù)類型可分為:原子類型和結(jié)構(gòu)類型。程序設(shè)計(jì)語言都提供了基本數(shù)據(jù)類型。每個(gè)數(shù)據(jù)都屬于某種數(shù)據(jù)類型。對(duì)于復(fù)雜的信息,編程處理時(shí)僅僅使用基本數(shù)據(jù)類型是不夠的。比如,可以把“學(xué)生”的取值集合與規(guī)定的一組操作定義成一種數(shù)據(jù)類型。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院223.1.3抽象數(shù)據(jù)類型抽象數(shù)據(jù)類型(AbstractDataType,ADT)是一個(gè)數(shù)據(jù)模型及定義在該模型上的一組操作。定義一個(gè)ADT時(shí),必須給出它的名字及各操作的名稱,并且規(guī)定這些函數(shù)的參數(shù)性質(zhì)。一旦定義了一個(gè)ADT及具體實(shí)現(xiàn),程序設(shè)計(jì)中就可以像使用基本數(shù)據(jù)類型那樣,十分方便地使用ADT。學(xué)生ADT,包含各種屬性及取值范圍;還有一組操作,如按照不同屬性查詢學(xué)生的信息、更改一些信息。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院233.1.3抽象數(shù)據(jù)類型一個(gè)程序員定義的ADT要通過高級(jí)編程語言中已有的數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)。利用基本的數(shù)據(jù)結(jié)構(gòu)可以構(gòu)造一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu),如棧、隊(duì)列、樹、圖等,對(duì)數(shù)據(jù)集進(jìn)行抽象而不必讓使用者(程序員)關(guān)心實(shí)際數(shù)據(jù)的存儲(chǔ)細(xì)節(jié)(ADT的數(shù)據(jù)結(jié)構(gòu))。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院243.1.3抽象數(shù)據(jù)類型【例3.2】一個(gè)ADTStack提供如下操作。Stack():創(chuàng)建一個(gè)新的空棧;push(item):把參數(shù)item放在棧頂;pop():把棧頂元素從棧中移出并返回,若棧為空,則出錯(cuò);top():返回棧頂元素,但不移出,若棧為空,則出錯(cuò);isEmpty():若棧為空,返回真值,否則,返回假值;size():返回棧的元素的個(gè)數(shù)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院253.1.3抽象數(shù)據(jù)類型無論如何實(shí)現(xiàn)該棧,它只提供這6個(gè)操作,除此之外沒有其他操作。使用者不知道、也不必關(guān)心它是用數(shù)組、還是通用表等基本類型實(shí)現(xiàn)的。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院263.1.3抽象數(shù)據(jù)類型ADT的定義與其實(shí)現(xiàn)分離,使其用戶只需關(guān)注如何使用,而不是它的實(shí)現(xiàn)細(xì)節(jié)。這種分離要求與ADT的交互使用接口(定義的操作集)。通過封裝實(shí)現(xiàn)細(xì)節(jié),要求通過接口訪問ADT,使得我們能使用抽象進(jìn)行工作,專注ADT提供的功能,而不必理解這些功能的實(shí)現(xiàn)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院273.1.3抽象數(shù)據(jù)類型【例3.3】第2章把Equation當(dāng)成一個(gè)整體。如果Equation的定義包含運(yùn)算結(jié)果value,按照ADT的概念,value是Equation的一個(gè)成員,使用Equation的程序(函數(shù))是不允許訪問它的。但C可以通過equation.value訪問,包括更改它的值。這樣,就會(huì)導(dǎo)致equation的不一致:算式實(shí)際的運(yùn)算結(jié)果與存放結(jié)果value的值不一樣。所以在定義類型Equation時(shí)沒有包含它的運(yùn)算結(jié)果,而是用一個(gè)函數(shù)動(dòng)態(tài)地計(jì)算,才能使得一個(gè)算式保持一致。但是,這個(gè)計(jì)算顯然要占用資源。而且,在使用一個(gè)算式值時(shí)不能忘記這個(gè)計(jì)算函數(shù)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院283.1.3抽象數(shù)據(jù)類型面向?qū)ο鬄閷?shí)現(xiàn)ADT提供了良好的機(jī)制。類:ADT的一種實(shí)現(xiàn)方式。加上繼承、聚合、多態(tài)等特性,不僅提高了軟件開發(fā)效率,還能提高軟件產(chǎn)品的質(zhì)量,使得面向?qū)ο蟮某绦蛟O(shè)計(jì)獲得普遍應(yīng)用。面向?qū)ο笳Z言提供了良好的編程機(jī)制,但語言本身并不能保證開發(fā)出高質(zhì)量程序,因而還需要學(xué)習(xí)和運(yùn)用設(shè)計(jì)、編碼、測試等軟件構(gòu)造的基本原理,更好地運(yùn)用面向?qū)ο笳Z言的特性來構(gòu)造出高質(zhì)量的程序。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院293.2認(rèn)識(shí)面向?qū)ο竺嫦驅(qū)ο蠹夹g(shù)包括軟件開發(fā)方法和程序設(shè)計(jì)語言,在傳統(tǒng)面向過程程序設(shè)計(jì)語言、結(jié)構(gòu)化設(shè)計(jì)方法的基礎(chǔ)上做出了改進(jìn),并在軟件開發(fā)、編程語言方面提出了新的理論和實(shí)踐。3.2.1設(shè)計(jì)類3.2.2設(shè)計(jì)操作3.2.3分類2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院303.2.1設(shè)計(jì)類用面向?qū)ο箝_發(fā)軟件時(shí),我們把系統(tǒng)模塊化成類,它們封裝了屬性及其操作。決定一個(gè)類知道什么、做什么,就是抽象出一個(gè)類。在設(shè)計(jì)一個(gè)類如何做事情時(shí),就是把它們封裝起來。良好設(shè)計(jì)的類限制訪問它的屬性及其操作,實(shí)質(zhì)上就是隱藏了信息及其處理。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院313.2.1設(shè)計(jì)類抽象是設(shè)計(jì)類的基本方法。抽象是在某個(gè)東西周圍畫上一個(gè)白盒子的動(dòng)作:識(shí)別出它做什么、不做什么。抽象是對(duì)某個(gè)東西定義接口的動(dòng)作。抽象告訴我們存儲(chǔ)學(xué)生的姓名、學(xué)號(hào),也能讓學(xué)生選課。但是,抽象不告訴我們是如何做到這些的。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院323.2.1設(shè)計(jì)類封裝則處理如何將這些特性模塊化。封裝解決的是如何劃分一個(gè)系統(tǒng)的功能的設(shè)計(jì)問題。封裝是在某個(gè)東西周圍畫上一個(gè)黑盒子的動(dòng)作:它明確某事能完成,但是不告訴是怎樣做到的。換句話說,封裝對(duì)類的使用者隱藏了實(shí)現(xiàn)細(xì)節(jié)。為了使應(yīng)用程序容易維護(hù),要限制訪問類的數(shù)據(jù)和操作。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院333.2.1設(shè)計(jì)類模塊化原則——緊內(nèi)聚、松耦合仍然適用于評(píng)價(jià)面向?qū)ο蟪绦?。包括類的?nèi)聚、方法的內(nèi)聚;不同類之間的耦合、同一個(gè)類不同對(duì)象之間的耦合及同一個(gè)類內(nèi)函數(shù)之間的耦合。類的模塊化準(zhǔn)則要求一個(gè)類應(yīng)當(dāng)是完整的原始的充分的2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院343.2.2設(shè)計(jì)操作類的設(shè)計(jì)要盡量使其所有的操作都是原始的,每個(gè)操作僅提供簡單、良好定義的行為。根據(jù)松散耦合的原則,也傾向于分離操作、減少它們之間的溝通。矛盾:把復(fù)雜的行為集中在一個(gè)方法中,簡化了接口,但其實(shí)現(xiàn)復(fù)雜了;反之,方法行為和實(shí)現(xiàn)簡單了,但方法多了,接口復(fù)雜了。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院353.2.2設(shè)計(jì)操作通常在面向?qū)ο箝_發(fā)中,把類的方法作為整體來設(shè)計(jì),這是因?yàn)樗羞@些方法的合作構(gòu)成了抽象的全部協(xié)議。設(shè)計(jì)時(shí)考慮以下建議。復(fù)用:這個(gè)行為在更多的環(huán)境中更有意義嗎?復(fù)雜:實(shí)現(xiàn)這個(gè)行為有多難?適應(yīng):這個(gè)行為與其置身的類有多少關(guān)系?實(shí)現(xiàn)知識(shí):實(shí)現(xiàn)這個(gè)行為要依賴于類的內(nèi)部細(xì)節(jié)嗎?2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院363.2.2設(shè)計(jì)操作多態(tài)多態(tài)是類型理論的一個(gè)概念,一個(gè)名字可以表示多個(gè)不同類的實(shí)例,只要它們具有某個(gè)共同的超類而且相關(guān)。所以,被這個(gè)名字表示的任何對(duì)象都能以不同的方式對(duì)一組某些相同的操作做出響應(yīng)。由于多態(tài),一個(gè)操作就能在層次結(jié)構(gòu)中的所有類以不同方式實(shí)現(xiàn)。這樣,子類就能擴(kuò)展超類的能力或者覆蓋超類的操作。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院373.2.2設(shè)計(jì)操作很多類具有相同協(xié)議時(shí),多態(tài)最有用。如果沒有多態(tài),程序中會(huì)出現(xiàn)大量的if或switch語句?!纠?.4】一個(gè)幾何圖形類Geometry有子類Rectangel、Segment、Triangle和Circle,顯示圖形的抽象方法display,每個(gè)子類都有自己的實(shí)現(xiàn)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院383.2.2設(shè)計(jì)操作當(dāng)一個(gè)圖形編輯GraphicsEditor要顯示一個(gè)Geometry對(duì)象時(shí),不用多態(tài)的代碼結(jié)構(gòu)可能是:2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院393.2.2設(shè)計(jì)操作如果使用多態(tài),則代碼精簡:新增一個(gè)子類Polygon,要重新實(shí)現(xiàn)display,無須改變程序的其他部分,尤其不用改變使用Geometry的GraphicsEditor。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院403.2.3分類關(guān)鍵抽象是構(gòu)成問題域術(shù)語的一個(gè)類或?qū)ο?。其主要價(jià)值在于識(shí)別確定問題邊界的抽象,指出在系統(tǒng)中出現(xiàn)的問題相關(guān)的類(領(lǐng)域類)、因而與設(shè)計(jì)相關(guān)的事情。機(jī)制用于描述通過對(duì)象的協(xié)作提供滿足問題需求的某種行為的任何結(jié)構(gòu)。因?yàn)轭惖脑O(shè)計(jì)具體表達(dá)了單個(gè)對(duì)象行為的知識(shí),機(jī)制就是一個(gè)關(guān)于一組對(duì)象如何協(xié)作的設(shè)計(jì)決策。機(jī)制就是行為模式。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院413.2.3分類分類是對(duì)整理知識(shí)的一致手段。識(shí)別類和對(duì)象是面向?qū)ο箝_發(fā)的一個(gè)挑戰(zhàn)。識(shí)別包含發(fā)現(xiàn)和發(fā)明。通過發(fā)現(xiàn),我們認(rèn)識(shí)到構(gòu)成問題域詞語的關(guān)鍵抽象和機(jī)制。通過發(fā)明,設(shè)計(jì)出一般化的抽象和機(jī)制,說明對(duì)象是如何協(xié)作的。發(fā)現(xiàn)和發(fā)明都是分類問題,其核心就是發(fā)現(xiàn)問題的共性。分類就是試圖把具有共同結(jié)構(gòu)或表現(xiàn)出共同行為的事情分為一組。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院423.2.3分類1.類之間的關(guān)系在類之間建立關(guān)系的原因,首先是一種類關(guān)系會(huì)指出某種共享。其次,一種類關(guān)系會(huì)指出某種語義聯(lián)系。面向?qū)ο笾杏腥N類關(guān)系。普通與特殊(繼承),即“是一種”。例如,加法算式是一種二元算式。整體-部分(聚合),即“是成員”。例如,算式是習(xí)題的一部分。關(guān)聯(lián),表示沒有其他關(guān)系的類之間的某種語義依賴。如,“學(xué)生”和“教師”是兩個(gè)獨(dú)立的類,但是它們都和“課程”相關(guān)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院433.2.3分類面向?qū)ο筌浖€有一種常見的關(guān)系——依賴。依賴表示關(guān)系一端的成員以某種方式依賴于關(guān)系另一端的成員。它告訴開發(fā)者,如果這些元素發(fā)生變化,會(huì)影響其他成員。例如,以幾何圖形的顯示display為例,除了顯示圖形的形狀,還可以顯示圖形的顏色和線條,類Geometry則依賴類Color和Style(粗細(xì)、實(shí)線、虛線)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院443.2.3分類2.接口與實(shí)現(xiàn)Meyer認(rèn)為程序設(shè)計(jì)本質(zhì)上是契約:一個(gè)較大問題的功能通過把它們分包到不同元素的設(shè)計(jì),而分解成若干較小的問題。類的內(nèi)部和外部視角。類的接口提供了外部視角,重在抽象,同時(shí)隱藏了它的結(jié)構(gòu)和組成。接口主要包括聲明。類的實(shí)現(xiàn)是其內(nèi)部視角,包含其行為,主要由所有定義在類接口操作的實(shí)現(xiàn)組成。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院453.2.3分類類的接口可以進(jìn)一步分成4類。公共的:對(duì)所有用戶可訪問的聲明;保護(hù)的:僅允許類本身及其子類訪問的聲明;私有的:僅允許類本身訪問的聲明;包:僅允許和類在用一個(gè)包的聲明。接口是一些面向?qū)ο笳Z言的基本元素,如Java語言的接口Interface,必須有具體的類才能實(shí)現(xiàn)接口定義的操作。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院463.3面向?qū)ο蟮脑O(shè)計(jì)本節(jié)由淺入深地討論如何運(yùn)用面向?qū)ο蟮脑瓌t和原理設(shè)計(jì)并開發(fā)良好的程序。初步識(shí)別出兩個(gè)類,分別是加減法的二元運(yùn)算的算式及存放算式的練習(xí),分別命名為算式類BinaryOperation和習(xí)題類Exercise。3.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)3.3.2案例設(shè)計(jì)一3.3.3案例設(shè)計(jì)二2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院473.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)軟件設(shè)計(jì)語言或符號(hào),如可視化圖形設(shè)計(jì)符號(hào)。在面向?qū)ο笤O(shè)計(jì)中,普遍采用的包括描述程序靜態(tài)結(jié)構(gòu)的類圖、描述程序動(dòng)態(tài)行為的交互圖。它們掩藏了類中方法的實(shí)現(xiàn)細(xì)節(jié),突出了類的組成和類之間的關(guān)系,簡潔清晰地表達(dá)設(shè)計(jì)意圖和內(nèi)容。復(fù)雜的算法、數(shù)據(jù)結(jié)構(gòu)等操作的實(shí)現(xiàn),仍然使用代碼和偽代碼補(bǔ)充說明。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院483.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)統(tǒng)一建模語言UML類圖類用一個(gè)帶有類名、屬性和操作的矩形表示。分隔線用來分離類名、屬性和操作。類名在矩形的最上方,其次是屬性,然后是操作。類名:具體類的名稱正常書寫;抽象類名加abstract前綴,或用斜體書寫;接口名加前綴interface,屬性空著。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院493.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)屬性類似程序語言的聲明——可見性、變量名、類型、初始值;前綴表示可見性:“+”公用,“?”私有,“#”保護(hù)。靜態(tài)變量或常量用大寫字母的標(biāo)識(shí)符,成員變量允許具有初始值。操作用簽名表示——可見性、返回類型、操作名稱、參數(shù)及類型,可見性符號(hào)與屬性的相同。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院503.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院513.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)為了表示程序中類之間的關(guān)系,可以只用一個(gè)標(biāo)示類名的矩形表示類。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院523.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)類之間的關(guān)聯(lián)用一根線表示,包括每個(gè)關(guān)聯(lián)類的角色名、數(shù)目、方向和約束。泛化是一端帶空心三角形的連線,從子類到父類,空心三角形一端是父類。聚合用來描述一個(gè)元素(整體)包含另外的元素(部分),部分可以脫離整體作為一個(gè)獨(dú)立的個(gè)體存在。聚合的整體端用空心菱形表示。組合是一種語義更強(qiáng)的聚合,部分組成整體,不可分割,整體消失部分也跟著消失,部分不能脫離整體而單獨(dú)存在。組合的整體端用實(shí)心菱形表示。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院533.3.1面向?qū)ο蟮脑O(shè)計(jì)符號(hào)圖3.3表示設(shè)計(jì)的解釋:機(jī)械工程師、電氣工程師和軟件工程師都屬于員工,他們組成一個(gè)飛機(jī)建造團(tuán)隊(duì)。飛機(jī)由零件組成,零件還可以(遞歸)有零件。UML不僅能使軟件建??梢暬?,還有助于分析、評(píng)估和驗(yàn)證軟件設(shè)計(jì),支持從UML自動(dòng)產(chǎn)生部分代碼,指導(dǎo)產(chǎn)生測試用例。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院543.3.2案例設(shè)計(jì)一1.算式類BinaryOperation2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院553.3.2案例設(shè)計(jì)一2.習(xí)題類Exercise2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院563.3.3案例設(shè)計(jì)二1.算式類BinaryOperation軟件設(shè)計(jì)中的單一職責(zé)原則(SingleResponsibilityPrinciple,SRP)是最容易理解和運(yùn)用的。單一職能原則實(shí)際上是內(nèi)聚原則在面向?qū)ο蠓椒ㄖ械木唧w表現(xiàn),含義是就單個(gè)類而言,應(yīng)該只有一個(gè)引起它變化的原因。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院573.3.3案例設(shè)計(jì)二類BinaryOperation把其中的公共部分抽象出來,把差異部分細(xì)化成BinaryOperation的兩個(gè)子類:加法算式AdditionOperation減法算式SubstractOperation每個(gè)類只負(fù)責(zé)完成各自單一的功能,兩個(gè)子類相互獨(dú)立。這樣的程序結(jié)構(gòu)還便于程序擴(kuò)展,如增加乘法、除法子類,不影響已經(jīng)存在的類。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院583.3.3案例設(shè)計(jì)二里氏代換原則(LiskovSubstitutionPrinciple,LSP)是設(shè)計(jì)類層次結(jié)構(gòu)的基本原則,它要求子類型必須能夠替換其基類型。使用里氏代換原則的兩個(gè)要點(diǎn)如下。(1)子類的所有方法必須在父類中聲明,或子類必須實(shí)現(xiàn)父類中聲明的所有方法。(2)盡量把父類設(shè)計(jì)為抽象類或接口,讓子類繼承父類或?qū)崿F(xiàn)父接口,并實(shí)現(xiàn)在父類中聲明的所有方法。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院593.3.3案例設(shè)計(jì)二基類BinaryOperation設(shè)計(jì)成抽象類。子類AdditionOperation和SubstractOperation在基類中定義抽象方法intcalculate()返回運(yùn)算式的計(jì)算結(jié)果,抽象方法booleancheckingCalculation()檢查運(yùn)算結(jié)果。具體實(shí)現(xiàn)則分別在兩個(gè)子類中。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院603.3.3案例設(shè)計(jì)二2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院613.3.3案例設(shè)計(jì)二2.抽象類abstract類和接口interface的比較2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院623.3.3案例設(shè)計(jì)二3.依賴倒轉(zhuǎn)原則子類必須實(shí)現(xiàn)抽象父類定義的抽象方法才能生成對(duì)象,即低層的子類依賴高層的、抽象的父類。這種設(shè)計(jì)思想運(yùn)用了面向?qū)ο蠹夹g(shù)中的依賴倒轉(zhuǎn)原則(DependencyInversionPrinciple,DIP),它轉(zhuǎn)換了依賴關(guān)系:高層模塊不依賴于低層模塊,兩者都依賴于抽象。抽象不依賴于實(shí)現(xiàn),實(shí)現(xiàn)依賴于抽象。換言之,就是高層模塊定義接口,低層模塊負(fù)責(zé)實(shí)現(xiàn)。“上轉(zhuǎn)型對(duì)象”是面向?qū)ο蠓椒ㄖ袑?shí)現(xiàn)依賴倒轉(zhuǎn)原則的有效技術(shù)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院633.3.3案例設(shè)計(jì)二4.習(xí)題類Exercise按照單一職責(zé)原則,把類Exercise的產(chǎn)生職責(zé)和使用職責(zé)分離出來,使類Exercise僅僅作為一個(gè)存儲(chǔ)和管理一定數(shù)量的算式題的數(shù)據(jù)集容器,同時(shí)建立一個(gè)使用習(xí)題的新類ExerciseSheet。兩個(gè)類之間是依賴關(guān)系:ExerciseSheet按照Exercise提供的方法使用它,當(dāng)然受其影響。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院643.3.3案例設(shè)計(jì)二在面向?qū)ο笾?,依賴關(guān)系可以視為具有特殊語義的關(guān)聯(lián)。UML類圖用帶箭頭的虛線連接兩個(gè)有依賴關(guān)系的類:虛線起端表示使用、受影響的類,帶箭頭的末端表示產(chǎn)生影響、被使用的類。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院653.3.3案例設(shè)計(jì)二2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院663.3.3案例設(shè)計(jì)二5.?dāng)?shù)據(jù)集的數(shù)據(jù)結(jié)構(gòu)ExerciseSheet無法訪問類Exercise中存放算式的私有成員operationList。為了能讓其他對(duì)象使用Exercise中存儲(chǔ)在Array中的算式,它必須提供公共操作,如檢索、遍歷等。類Exercise可以選擇其他數(shù)據(jù)集的數(shù)據(jù)結(jié)構(gòu),存放算式。面向?qū)ο笳Z言的容器型數(shù)據(jù)結(jié)構(gòu),如List、Queue、Stack等。Java語言的Collection(C#的ICollection)類層次結(jié)構(gòu)提供了豐富的管理數(shù)據(jù)集的數(shù)據(jù)結(jié)構(gòu)、接口和(抽象)類。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院673.3.3案例設(shè)計(jì)二策略1:實(shí)現(xiàn)接口。隊(duì)列Queue的操作如contains、isEmpty、iterator等,完全滿足案例目前對(duì)Exercise的要求,可以讓Exercise實(shí)現(xiàn)接口Queue。在Java中使用隊(duì)列Queue,除了要實(shí)現(xiàn)這4個(gè)方法以外,還必須實(shí)現(xiàn)Queue及其繼承的所有其他所有方法,否則不能構(gòu)造對(duì)象實(shí)例。這違背了接口隔離原則(InterfaceSegregationPrinciple,ISP),根據(jù)該原則,不應(yīng)該強(qiáng)迫客戶程序依賴于它們不用的方法2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院683.3.3案例設(shè)計(jì)二策略2:運(yùn)用繼承。讓Exercise繼承容器數(shù)據(jù)結(jié)構(gòu)中的一個(gè),如具有動(dòng)態(tài)改變?nèi)萜鲾?shù)量的ArrayList。ArrayList可以視為動(dòng)態(tài)數(shù)組,即數(shù)組大小隨需增長。它提供了普通數(shù)組的操作,如按下標(biāo)添加、插入、查詢、刪除及迭代遍歷數(shù)據(jù)成員等方法,涵蓋了Exercise的設(shè)計(jì)要求。但這個(gè)設(shè)計(jì)策略暴露了存儲(chǔ)算式的內(nèi)部數(shù)據(jù)結(jié)構(gòu),因而違背了信息隱藏的基本原則。另外,同接口一樣,不能選擇性地繼承操作或?qū)傩?,子類Exercise繼承了一些不需要的操作。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院693.3.3案例設(shè)計(jì)二策略3:封裝結(jié)構(gòu)。Exercise定義容器類數(shù)據(jù)結(jié)構(gòu)(如Array、ArrayList、Queue、List)為私有成員變量封裝,Exercise提供訪問的next、hasNext等方法,以便ExerciseSheet能夠?qū)崿F(xiàn)遍歷等操作。不同的應(yīng)用需要Exercise提供的操作可能不完全一樣。例如,目前不需要從練習(xí)中刪除運(yùn)算題,就可以不實(shí)現(xiàn)刪除操作。而且,不同的容器類數(shù)據(jù)結(jié)構(gòu),如Array和ArrayList,對(duì)這些操作的實(shí)現(xiàn)也不同。ArrayList能提供包含上述要求的操作,甚至更多、更方便。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院703.4調(diào)試的基本技術(shù)在Eclipse中,Java視圖中選擇要調(diào)試的函數(shù)/類右擊,選擇debugas→JavaApplication,出現(xiàn)debug視圖。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院713.4調(diào)試的基本技術(shù)啟動(dòng)調(diào)試程序的兩種方式:(1)選擇菜單Run→DebugAs;(2)選擇debug的圖標(biāo)。使用調(diào)試器調(diào)試程序的基本模式如下:首先設(shè)置(若干)斷點(diǎn),啟動(dòng)運(yùn)行調(diào)試器;遇到一個(gè)斷點(diǎn)后停下,單步調(diào)試一段代碼,可以檢查、改變斷點(diǎn)的程序狀態(tài)和行為。然后恢復(fù),讓調(diào)試器繼續(xù)執(zhí)行程序,直到遇到下一個(gè)斷點(diǎn)或執(zhí)行到程序的結(jié)束。調(diào)試可在任何時(shí)刻終止。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院723.4調(diào)試的基本技術(shù)3.4.1單步調(diào)試源程序3.4.2檢查/更改變量的值3.4.3設(shè)置監(jiān)視點(diǎn)觀察變量3.4.4上下移動(dòng)調(diào)用棧2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院733.4.1單步調(diào)試源程序1.設(shè)置斷點(diǎn)在要檢查的語句上設(shè)置斷點(diǎn),程序執(zhí)行到斷點(diǎn)處會(huì)暫停。通過窗口觀察此刻變量的值、檢查程序運(yùn)行情況;可以輸入改變變量或表達(dá)式的值,然后讓程序繼續(xù)運(yùn)行。Eclipse中在代碼行左邊的頁邊空白處雙擊設(shè)置斷點(diǎn)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院743.4.1單步調(diào)試源程序2.單步調(diào)試?yán)脝尾矫?,從斷點(diǎn)處開始一次處理一條語句。變量值有助于程序員仔細(xì)觀察程序的執(zhí)行流程、了解程序變量值的變化、調(diào)查可疑代碼。在debug視圖中有三種方式執(zhí)行視圖中的圖標(biāo)右擊出現(xiàn)的選擇(含圖標(biāo))快捷鍵2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院753.4.1單步調(diào)試源程序單步調(diào)試的主要操作StepInto,F(xiàn)5,進(jìn)入方法內(nèi)部。StepOver,F(xiàn)6,執(zhí)行方法下一條語句。StepReturn,F(xiàn)7,從當(dāng)前方法跳出,跳轉(zhuǎn)到該方法的結(jié)尾代碼處。Resume,F(xiàn)8,恢復(fù)操作。跳出單步調(diào)試方式,讓程序繼續(xù)運(yùn)行到下一個(gè)斷點(diǎn)或執(zhí)行完。DropToFrame,使調(diào)試器重新跳到當(dāng)前方法的開始處重新執(zhí)行,所有上下文變量的值也恢復(fù)??梢栽陉P(guān)注的狀態(tài)下反復(fù)調(diào)試,而不用重新啟動(dòng)調(diào)試器。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院763.4.1單步調(diào)試源程序3.臨時(shí)斷點(diǎn)有時(shí)需要在顯示的代碼中臨時(shí)設(shè)置有期限的斷點(diǎn),以便細(xì)致觀察程序。在Eclipse中,突出顯示源碼窗口中要設(shè)置臨時(shí)斷點(diǎn)的代碼行,然后右擊并選擇RuntoLine。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院773.4.2檢查/更改變量的值當(dāng)調(diào)試器暫停了程序運(yùn)行后,可以執(zhí)行一些調(diào)試命令來顯示、改變程序變量的值。不使用調(diào)試器,在程序中增加打印語句顯示程序變量值的變化也可以。在圖(a)選中變量右擊選ChangePrimitiveValue,出現(xiàn)圖(b)所示的對(duì)話框。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院783.4.3設(shè)置監(jiān)視點(diǎn)觀察變量監(jiān)視點(diǎn)(watchpoint)結(jié)合了斷點(diǎn)和變量檢查的概念。每當(dāng)指定變量的值發(fā)生變化時(shí),都暫停程序的運(yùn)行。監(jiān)視點(diǎn)對(duì)局部變量的用途一般沒有對(duì)作用域更寬的變量的用途大,因?yàn)橐坏┳兞砍鲎饔糜颍ㄈ绾瘮?shù)結(jié)束),在局部變量上設(shè)置的監(jiān)視點(diǎn)就會(huì)被取消。main()中的局部變量例外,因?yàn)槠渲械淖兞恳鹊匠绦驁?zhí)行結(jié)束時(shí)才會(huì)被釋放。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院793.4.3設(shè)置監(jiān)視點(diǎn)觀察變量在Eclipse中設(shè)置監(jiān)視點(diǎn)的方法:在源碼窗口中右擊,選擇Watch,然后在對(duì)話框中填寫適當(dāng)?shù)谋磉_(dá)式,如圖3.11所示。代碼的執(zhí)行結(jié)果將顯示在表達(dá)式窗口中。選中一句或一段代碼右擊,選擇Inspect(檢查)項(xiàng),可以直接顯示表達(dá)式的值。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院803.4.4上下移動(dòng)調(diào)用棧與函數(shù)關(guān)聯(lián)的運(yùn)行時(shí)信息存儲(chǔ)在稱為幀的內(nèi)存區(qū)域中。幀中包含了函數(shù)局部變量的值、形參,以及調(diào)用該函數(shù)的位置。系統(tǒng)為每個(gè)調(diào)用函數(shù)創(chuàng)建一個(gè)幀,并將其放在一個(gè)運(yùn)行棧上;運(yùn)行棧最上面的幀表示當(dāng)前正在運(yùn)行的函數(shù),當(dāng)函數(shù)退出時(shí),這個(gè)幀就退出運(yùn)行棧并釋放所占的內(nèi)存。運(yùn)用調(diào)試器可以觀察運(yùn)行棧,追蹤函數(shù)之間的調(diào)用關(guān)系和變量值的來源、變化等信息。Eclipse中,運(yùn)行棧在debug透視圖本身連續(xù)可見。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院813.5軟件自動(dòng)化測試合適的測試工具和構(gòu)建工具,可以提高構(gòu)建效率,是現(xiàn)代軟件開發(fā)的基礎(chǔ)。JUnit已經(jīng)成為現(xiàn)代軟件開發(fā)方法和工具的核心組成。它是Java語言的測試框架,是包含測試用例、測試執(zhí)行、測試記錄等一組Java類和接口。JUnit由于簡單、實(shí)用、易用,特別適合自動(dòng)化的單元測試和回歸測試。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院823.5軟件自動(dòng)化測試3.5.1初識(shí)Junit3.5.2編寫Junit測試代碼2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院833.5.1初識(shí)Junit使用JUnit進(jìn)行測試的基本步驟如下。(1)建立測試類,命名規(guī)則:待測類名+Test,如BinaryOperationTest。在該類的前面用@RunWith指定測試運(yùn)行器,默認(rèn)JUnit4。(2)在用@Before注解的setUp()中為測試做必要準(zhǔn)備(測試裝置fixture)。(3)為待測類的成員方法/函數(shù)編寫測試方法,命名規(guī)則:test+待測方法,以@Test注解這個(gè)待測方法,其中務(wù)必包含測試斷言。(4)運(yùn)行測試,查看運(yùn)行結(jié)果,更改代碼。(5)增加方法或修改代碼時(shí),重復(fù)(3、4)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院843.5.2編寫Junit測試代碼1.基本測試2.追蹤失敗的測試2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院853.6案例分析與實(shí)踐3.6.1分析3.6.2構(gòu)造2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院863.6.1分析構(gòu)造任務(wù)3.1:實(shí)現(xiàn)BinaryOperation及其子類。構(gòu)造任務(wù)3.2:實(shí)現(xiàn)Exercise和ExerciseSheet。開發(fā)方式(1)順序,即完成子任務(wù)1的程序后開始2;(2)并行,同時(shí)開始子任務(wù)1和2的編程。在子任務(wù)2編程期間,可以使用簡單的算式類代替BinaryOperation,最后再用編寫好的BinaryOperation替換,完成整個(gè)任務(wù)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院873.6.1分析小強(qiáng)和小雨倆人的合作方式可以是:(1)兩人分別執(zhí)行一個(gè)子任務(wù);(2)兩人協(xié)作執(zhí)行一個(gè)子任務(wù)——一個(gè)人編寫程序,另一個(gè)人設(shè)計(jì)測試,等程序完成了就立刻執(zhí)行測試;整個(gè)開發(fā)期間兩人可以交換工作。合作方式(2)蘊(yùn)含了敏捷開發(fā)方法中兩種實(shí)踐的基本思想——測試驅(qū)動(dòng)開發(fā)與結(jié)對(duì)編程。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院883.6.2構(gòu)造2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院893.7討論與提高3.7.1對(duì)調(diào)試的進(jìn)一步認(rèn)識(shí)3.7.2設(shè)計(jì)原則與設(shè)計(jì)模式3.7.3面向?qū)ο蟮脑O(shè)計(jì)原則2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院903.7.1對(duì)調(diào)試的進(jìn)一步認(rèn)識(shí)1.調(diào)試與測試調(diào)試與測試都分析程序代碼、選擇性地運(yùn)行程序,并觀察程序的結(jié)果或運(yùn)行過程。測試與調(diào)試的目標(biāo)不同,采用了不同的技術(shù)、方法和工具。在軟件構(gòu)造過程中,開發(fā)者交替進(jìn)行測試與調(diào)試:測試發(fā)現(xiàn)程序可能存在錯(cuò)誤,然后通過調(diào)試來修改錯(cuò)誤,之后再通過測試確認(rèn)程序錯(cuò)誤得到了修改。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院913.7.1對(duì)調(diào)試的進(jìn)一步認(rèn)識(shí)2.不調(diào)試就是最好的調(diào)試精通程序調(diào)試不僅要掌握專門的調(diào)試器,還要充分利用其他編程輔助工具。最好的調(diào)試方法就是一開始就不要錯(cuò)誤地編程!首先,要熟練掌握編輯器的使用。充分利用支持編程語言的編輯器是最容易忽略的“預(yù)調(diào)試”方式。其次,充分利用編譯器。第三,使用靜態(tài)代碼檢查器。3.調(diào)試的智力活動(dòng)2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院923.7.2設(shè)計(jì)原則與設(shè)計(jì)模式面向?qū)ο蠹夹g(shù)在軟件開發(fā)過程中出現(xiàn)了一些可反復(fù)使用、解決實(shí)際問題的解決方案,稱為設(shè)計(jì)模式。一個(gè)設(shè)計(jì)模式針對(duì)一個(gè)具體問題,用抽象方式描述解決一類特殊問題的、通用的設(shè)計(jì)方案元素。設(shè)計(jì)模式的核心元素包括:標(biāo)示模式的名稱,適用環(huán)境的場景,描述設(shè)計(jì)的模板。在面向?qū)ο蠹夹g(shù)中,用類圖描述設(shè)計(jì)模式的結(jié)構(gòu),用交互圖描述設(shè)計(jì)模式的行為。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院933.7.2設(shè)計(jì)原則與設(shè)計(jì)模式1.策略模式(1)問題分析。算法多種多樣、經(jīng)常改變,其他類不使用的算法。如何在運(yùn)行時(shí)根據(jù)需要透明地更改對(duì)象的算法?將算法與對(duì)象本身解耦,從而避免上述問題?(2)解決思路。使用一個(gè)抽象的策略算法,用子類繼承這個(gè)公共的抽象類,定義一個(gè)個(gè)具體的策略算法,把它們封裝起來,通過實(shí)現(xiàn)抽象類的抽象算法使它們可互相替換。該模式使得算法可獨(dú)立于使用它的應(yīng)用客戶而變化和擴(kuò)展。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院943.7.2設(shè)計(jì)原則與設(shè)計(jì)模式1.策略模式(3)設(shè)計(jì)結(jié)構(gòu)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院953.7.2設(shè)計(jì)原則與設(shè)計(jì)模式1.策略模式(4)模式特點(diǎn)。策略類及其子類提供了一系列可重用的封裝算法,通過面向?qū)ο蟮亩鄳B(tài)、動(dòng)態(tài)綁定技術(shù),對(duì)象在運(yùn)行時(shí)根據(jù)需要在各個(gè)算法之間進(jìn)行切換。策略模式容易造成很多的策略類。(5)案例研究。策略類BinaryOperation包含兩抽象方法calculate和checkingCalculation,兩個(gè)實(shí)現(xiàn)具體策略的子類AdditionOperation和SubstractOperation分別實(shí)現(xiàn)了這兩個(gè)方法。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院963.7.2設(shè)計(jì)原則與設(shè)計(jì)模式2.迭代器模式(1)問題分析。在軟件構(gòu)建過程中要處理集合數(shù)據(jù),集合對(duì)象的內(nèi)部結(jié)構(gòu)變化各異。對(duì)于這些集合對(duì)象,希望在不暴露其內(nèi)部結(jié)構(gòu)的同時(shí),讓外部客戶代碼透明地順序訪問其中的每個(gè)成員對(duì)象;同時(shí)也為同一種算法在多種集合對(duì)象上進(jìn)行操作提供可能。(2)解決思路。提供一種方法有效地按順序訪問一個(gè)聚合對(duì)象中的各個(gè)成員對(duì)象,而又不暴露該聚合對(duì)象的內(nèi)部表示。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院973.7.2設(shè)計(jì)原則與設(shè)計(jì)模式2.迭代器模式(3)設(shè)計(jì)結(jié)構(gòu)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院983.7.2設(shè)計(jì)原則與設(shè)計(jì)模式2.迭代器模式(4)模式特點(diǎn)。迭代抽象——訪問一個(gè)聚合對(duì)象的內(nèi)容而無須暴露它的內(nèi)部表示。迭代多態(tài)——為遍歷不同的集合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口,從而支持同樣的算法在不同的集合結(jié)構(gòu)上進(jìn)行操作。健壯性考慮——遍歷的同時(shí)有可能更改迭代器所在的集合結(jié)構(gòu),導(dǎo)致問題。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院993.7.2設(shè)計(jì)原則與設(shè)計(jì)模式2.迭代器模式(5)案例研究。①Java的CollectionsFramework是迭代器模式的典型實(shí)現(xiàn)。它的接口Collection和Iterator分別對(duì)應(yīng)模式中的Aggregate和Iterator。②案例設(shè)計(jì)二中的策略3的封閉結(jié)構(gòu)可以視為迭代器模式的(變形的)應(yīng)用。Exercise封裝了ArrayList,BinaryOperation是ArrayList泛型的具體類型。客戶ExerciseSheet直接使用了Exercises提供的Iterator的接口next()和hasNext()。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1003.7.3面向?qū)ο蟮脑O(shè)計(jì)原則面向?qū)ο蟮?個(gè)基本原則(1)單一職責(zé)原則(SingleResponsibilityPrinciple,SRP)。一個(gè)類只有一種功能。面向?qū)ο蟪绦驅(qū)Φ婉詈?、高?nèi)聚原則的實(shí)踐。(2)開放封閉原則(OpenClosedPrinciple,OCP)。軟件實(shí)體(模塊、函數(shù)、類)應(yīng)該可以擴(kuò)展,但不可修改。對(duì)擴(kuò)展開放,對(duì)修改封閉。它是面向?qū)ο笏性瓌t的核心。(3)依賴倒轉(zhuǎn)原則(Dependency-InversionPrinciple,DIP)。抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。該原則與傳統(tǒng)的結(jié)構(gòu)化分析與設(shè)計(jì)方法對(duì)立。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1013.7.3面向?qū)ο蟮脑O(shè)計(jì)原則面向?qū)ο蟮?個(gè)基本原則(4)里氏代換原則(LiskovSubstitutionPrinciple,LSP)。子類型能夠替換基類型。這是保證繼承復(fù)用的基礎(chǔ)。違反了里氏代換原則必然導(dǎo)致違反開放封閉原則。(5)接口隔離原則(InterfaceSegregationPrinciple,ISP)。不應(yīng)該強(qiáng)迫客戶依賴于它們不用的方法。接口屬于客戶,不屬于它所在的類層次結(jié)構(gòu)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1023.7.3面向?qū)ο蟮脑O(shè)計(jì)原則1.開放封閉原則開放封閉原則是松散耦合的具體體現(xiàn):允許程序通過類的繼承、合成而擴(kuò)展,但是不允許或盡量減少改變已經(jīng)編譯好的類。解決程序修改問題的核心是模塊化。通過修改模塊(類)而實(shí)現(xiàn)程序的開放封閉原則。例如,目前的要求是100以內(nèi)的加減法運(yùn)算,如果想把數(shù)據(jù)擴(kuò)大到500,或者要求加法是200以內(nèi)、減法是100以內(nèi)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1033.7.3面向?qū)ο蟮脑O(shè)計(jì)原則遵循開閉原則,運(yùn)用策略模式改進(jìn)BinaryOperation結(jié)構(gòu),把算式產(chǎn)生與算式約束或規(guī)則分離,并且把運(yùn)算數(shù)的約束和運(yùn)算結(jié)果的約束也分離。讓BinaryOperation使用抽象約束類Constraints的操作checkRange和checkCalculation分別檢查運(yùn)算數(shù)和運(yùn)算結(jié)果是否滿足約束條件。不同運(yùn)算類型要求不同的約束,所以,增加兩個(gè)子類AdditionConstraint和SubstractConstraint,具體實(shí)現(xiàn)檢查兩個(gè)運(yùn)算數(shù)的約束checkRange、它們之和或差的約束checkCalculation。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1043.7.3面向?qū)ο蟮脑O(shè)計(jì)原則2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1053.7.3面向?qū)ο蟮脑O(shè)計(jì)原則實(shí)現(xiàn)開閉原則的核心是共性和個(gè)性分析,關(guān)鍵是抽象。需要分析要求,從不同狀態(tài)和行為中梳理出共性和個(gè)性,然后對(duì)應(yīng)用軟件進(jìn)行抽象化設(shè)計(jì):首先為整個(gè)軟件設(shè)計(jì)一個(gè)相對(duì)穩(wěn)定的抽象結(jié)構(gòu),提供充分的接口,保障可擴(kuò)展性;然后把不同的行為放在具體的實(shí)現(xiàn)層。最后,里氏代換原則是開閉原則的具體實(shí)現(xiàn)手段之一。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1063.7.3面向?qū)ο蟮脑O(shè)計(jì)原則2.合成復(fù)用原則合成復(fù)用原則(Composite/AggregateReusePrinciple,CARP)是指盡量使用組合/聚合關(guān)系,而不使用繼承。在一個(gè)新的對(duì)象里面通過組合/聚合關(guān)系使用一些已有的對(duì)象,使之成為新對(duì)象的一部分,新對(duì)象通過委派調(diào)用已有對(duì)象的方法達(dá)到復(fù)用其已有功能的目的,從而實(shí)現(xiàn)復(fù)用,同時(shí)滿足松散耦合的基本原則。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1073.7.3面向?qū)ο蟮脑O(shè)計(jì)原則根據(jù)合成復(fù)用原則,只有當(dāng)以下的條件全部被滿足時(shí),才應(yīng)當(dāng)使用繼承關(guān)系。(1)子類是基類的一個(gè)特殊種類,而不是超類的一個(gè)角色,即要區(qū)分“是……一部分”和“是……的一種”。(2)永遠(yuǎn)不會(huì)出現(xiàn)需要將子類換成另外一個(gè)類的子類的情況。(3)子類具有擴(kuò)展基類的責(zé)任,而沒有置換或注銷超類的責(zé)任。(4)只有在分類學(xué)角度有意義時(shí),才可以使用繼承。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院108第4章
數(shù)據(jù)處理的軟件構(gòu)造第4章數(shù)據(jù)處理的軟件構(gòu)造本章討論案例中數(shù)據(jù)處理的問題:按需選擇、使用數(shù)據(jù)及數(shù)據(jù)持久性。重點(diǎn)是如何把算式和習(xí)題從程序變量的值轉(zhuǎn)化為可共享的、持久性的文件數(shù)據(jù),學(xué)習(xí)文件的產(chǎn)生、存儲(chǔ)和讀取操作,學(xué)習(xí)一個(gè)特殊的文本文件格式CSV。編程方面,學(xué)習(xí)表驅(qū)動(dòng)編程模式和防御性編程。測試方面,學(xué)習(xí)白盒測試的基本技術(shù),繼續(xù)學(xué)習(xí)JUnit的其他測試方法。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院110第4章數(shù)據(jù)處理的軟件構(gòu)造故事5軟件是一個(gè)包含程序、數(shù)據(jù)和用戶的計(jì)算機(jī)系統(tǒng)。一個(gè)軟件可以提供若干功能或模塊,不同用戶可以使用其中的模塊——若干函數(shù)、類或方法。一個(gè)用戶可以利用其他用戶使用軟件產(chǎn)生的結(jié)果(如算式、習(xí)題),繼續(xù)使用軟件完成其他任務(wù)(如批改練習(xí))。不同用戶應(yīng)該可以在不同的時(shí)間產(chǎn)生和使用結(jié)果(數(shù)據(jù))。其中的一個(gè)條件是能夠持久地存儲(chǔ)結(jié)果,其生命期要超過程序運(yùn)行的時(shí)間,即存儲(chǔ)一次程序運(yùn)行的結(jié)果,在程序退出、再次啟動(dòng)后,程序的其他模塊能獲取并使用存儲(chǔ)的結(jié)果。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院111第4章數(shù)據(jù)處理的軟件構(gòu)造實(shí)現(xiàn)數(shù)據(jù)持久性最基本的途徑是文件和數(shù)據(jù)庫。本章討論使用文件實(shí)現(xiàn)圖4.1。首先,討論案例有哪些量大的數(shù)據(jù)需要存儲(chǔ)。其次,簡單解釋文件及Java輸入/輸出流。接著,引入實(shí)現(xiàn)持久性的編程問題及技術(shù)方法。最后,給出案例的分析與實(shí)現(xiàn)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院112第4章數(shù)據(jù)處理的軟件構(gòu)造4.1數(shù)據(jù)及其持久性4.2文件與輸入/輸出流4.3編寫健壯的程序4.4字符串處理與正則表達(dá)式4.5程序中數(shù)據(jù)集的使用4.6基于程序結(jié)構(gòu)的測試4.7運(yùn)用Junit4.8案例分析與實(shí)踐4.9討論與提高4.10思考與練習(xí)題2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1134.1數(shù)據(jù)及其持久性保存在程序之外(如文件、網(wǎng)絡(luò))的數(shù)據(jù)稱為持久數(shù)據(jù)。文件處理是編程語言支持應(yīng)用程序存儲(chǔ)和處理大量持久數(shù)據(jù)的一個(gè)最重要能力。Java等編程語言通常都提供了文件處理和輸入/輸出流的功能。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1144.1數(shù)據(jù)及其持久性字符由比特組成。一組字符或字節(jié)組成字段。一個(gè)字段是傳遞含義的一組字符或字節(jié)。若干字段構(gòu)成記錄。記錄是一組有關(guān)系的字段。一個(gè)文件可以是一組相關(guān)的記錄。組織文件中的記錄有多種不同的方式。最常見的方式是順序文件。一組相關(guān)的文件可以組成數(shù)據(jù)庫。專門用于創(chuàng)建、處理和管理數(shù)據(jù)庫的一組程序稱為數(shù)據(jù)庫管理系統(tǒng)(DBMS)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1154.1數(shù)據(jù)及其持久性一個(gè)應(yīng)用程序如何選擇數(shù)據(jù)的存儲(chǔ)、管理和處理方式,要考慮下面的因素。數(shù)據(jù)的持久性和使用頻次生產(chǎn)和訪問數(shù)據(jù)的難易程度共享與傳輸數(shù)據(jù)的量及管理數(shù)據(jù)的操作方式2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1164.2文件與輸入/輸出流4.2.1文件4.2.2輸入/輸出流4.2.3數(shù)據(jù)序列化4.2.4CSV格式的文本文件2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1174.2.1文件案例的持久性問題,本質(zhì)上是程序之間的一種交互,即一個(gè)程序或模塊產(chǎn)生數(shù)據(jù),另一個(gè)程序或模塊讀取并使用這些數(shù)據(jù)。程序之間可以通過文件實(shí)現(xiàn)輸入/輸出。在操作系統(tǒng)中,文件是組織和管理數(shù)據(jù)的基本單位,也是對(duì)物理輸入/輸出設(shè)備的抽象,使用者不必關(guān)心文件及其內(nèi)容的存取方式、存儲(chǔ)位置、結(jié)束標(biāo)志等。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1184.2.1文件1.字符文件與字節(jié)文件在字符文件中,字節(jié)表示字符,使得人們可以查看、編輯文件。在字節(jié)文件中,字節(jié)不一定表示字符;字節(jié)組還可以表示其他類型的數(shù)據(jù),如整數(shù)、浮點(diǎn)數(shù)或漢字字符。文件都是以二進(jìn)制格式存儲(chǔ)的。字節(jié)文本的存儲(chǔ)無須任何編碼,而使用文本文件時(shí)要考慮字符編碼。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1194.2.1文件2.記錄文件和流式文件文件分為物理文件和邏輯文件。邏輯文件從結(jié)構(gòu)上分兩種:無結(jié)構(gòu)的流式文件,信息不劃分單位,由一串字符流構(gòu)成文件;有結(jié)構(gòu)的記錄文件,信息按邏輯上獨(dú)立的含義劃分信息單位,稱為一個(gè)邏輯記錄(簡稱記錄)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1204.2.2輸入/輸出流程序借助一個(gè)連接內(nèi)存中的程序和外存設(shè)備的通道來操作存儲(chǔ)器中的數(shù)據(jù)。流表示任意輸入的源或輸出的目的地。流即傳輸數(shù)據(jù)的管道,讓外部輸入設(shè)備或存儲(chǔ)器上的數(shù)據(jù)流入內(nèi)存,讓程序中的數(shù)據(jù)流出。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1214.2.2輸入/輸出流在程序中,可以把文件理解成物理概念,流是邏輯概念。程序的輸入/輸出操作是針對(duì)抽象的流來定義的,前提是把該文件與一個(gè)(對(duì)象)流聯(lián)系起來。高級(jí)語言如C、C++、C#、Java等保留了操作系統(tǒng)中的文件,同時(shí)引入了流,執(zhí)行對(duì)文件的讀/寫操作。Java等語言沒有定義文件結(jié)構(gòu),即記錄,所以,程序員必須設(shè)計(jì)文件結(jié)構(gòu)來滿足應(yīng)用的需求。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1224.2.3數(shù)據(jù)序列化1.編寫數(shù)據(jù)序列化代碼“線性化”函數(shù)將結(jié)構(gòu)化數(shù)據(jù)轉(zhuǎn)換為字符串類型的數(shù)據(jù)。當(dāng)程序需要結(jié)構(gòu)化數(shù)據(jù)時(shí),再通過“結(jié)構(gòu)化”函數(shù),把線性化的數(shù)據(jù)按照原先的數(shù)據(jù)結(jié)構(gòu)恢復(fù)成結(jié)構(gòu)化數(shù)據(jù)。如何讀/寫對(duì)象:要把對(duì)象轉(zhuǎn)換成字符串,在Java中類似toString。首先要把具有結(jié)構(gòu)的數(shù)據(jù)元素分解,轉(zhuǎn)換成字符串,然后用特殊分隔符隔離。每個(gè)數(shù)據(jù)對(duì)象還要再以分隔符隔離。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1234.2.3數(shù)據(jù)序列化【例4.1】學(xué)生有姓名、性別、學(xué)號(hào)、身高、體重、生日、學(xué)院、手機(jī)等信息。首先,轉(zhuǎn)換成字符串。姓名可以拼音或中文(如果是外國人的姓名,姓氏和名字之間加一個(gè)空格作為分隔符),生日中的年月日作為一個(gè)數(shù)據(jù)元素,也可以分成三個(gè)數(shù)據(jù)元素年、月、日,中間也需隔離,比如用下畫線1995_02_25,或者斜線1995/02/25,其他的可以當(dāng)作一個(gè)整體,這8個(gè)數(shù)據(jù)元素之間用“?”分隔;每個(gè)學(xué)生數(shù)據(jù)占一行,或者用逗號(hào)、分號(hào)等不同于數(shù)據(jù)內(nèi)部的分隔符。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1244.2.3數(shù)據(jù)序列化從文件中讀入學(xué)生數(shù)據(jù)時(shí),根據(jù)換行符或其他分隔符讀入一個(gè)學(xué)生的數(shù)據(jù),然后再析取每個(gè)學(xué)生的數(shù)據(jù)元素,轉(zhuǎn)換成基本的數(shù)據(jù)類型。對(duì)于C語言,可能要轉(zhuǎn)換成結(jié)構(gòu)體struct。對(duì)于面向?qū)ο笳Z言,需要用這些數(shù)據(jù)構(gòu)造成一個(gè)對(duì)象,因而需要類提供所有成員變量的構(gòu)造方法。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1254.2.3數(shù)據(jù)序列化2.對(duì)象序列化Java、C#等面向?qū)ο笳Z言都有實(shí)現(xiàn)對(duì)象序列化的類或接口(類似Serializable),把對(duì)象數(shù)據(jù)轉(zhuǎn)換成(二進(jìn)制)字節(jié)序列的形式,與外部源共享或傳輸數(shù)據(jù)。程序員不必準(zhǔn)確知道系統(tǒng)是如何表示對(duì)象的字節(jié)序列的。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1264.2.3數(shù)據(jù)序列化序列化(Serialization)是將對(duì)象的狀態(tài)信息(成員變量)轉(zhuǎn)換為可以存儲(chǔ)或傳輸?shù)男问降倪^程。它的逆過程則被稱為反序列化(Deserialization)。在序列化期間,對(duì)象將其當(dāng)前狀態(tài)寫入到臨時(shí)或持久存儲(chǔ)區(qū)??梢酝ㄟ^從存儲(chǔ)區(qū)中讀取或反序列化對(duì)象的狀態(tài),重新創(chuàng)建該對(duì)象。序列化的對(duì)象是對(duì)象的字節(jié)序列,包含對(duì)象數(shù)據(jù)及其類型信息。這樣,信息可以用來再創(chuàng)建內(nèi)存中的對(duì)象。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1274.2.4CSV格式的文本文件逗號(hào)分隔值(Comma-SeparatedValues,CSV)以純文本形式存儲(chǔ)數(shù)字和文本數(shù)據(jù)。CSV文件由任意數(shù)目的記錄組成,記錄之間以某種換行符分隔;每條記錄由字段組成,字段間的分隔符是其他字符或字符串,最常見的是逗號(hào)或制表符。通常,所有記錄都有完全相同的字段序列。CSV是一種通用的、相對(duì)簡單的文本文件格式,在電子表單和數(shù)據(jù)庫中有著廣泛的應(yīng)用。一些程序設(shè)計(jì)語言如R、Go和Python都內(nèi)置了讀/寫CSV格式文件的函數(shù)或類。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1284.2.4CSV格式的文本文件CSV沒有單一的、明確定義的格式。在實(shí)踐中,CSV泛指具有以下特征的任何文本文件:純文本,使用某個(gè)字符集,如ASCII、Unicode、EBCDIC或GB2312;由記錄組成(典型的是每行一條記錄);每條記錄被分隔符分隔為字段(典型分隔符有逗號(hào)、分號(hào)或制表符;有時(shí)分隔符可以包括可選的空格);每條記錄都有同樣的字段序列。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1294.3編寫健壯的程序健壯性(robutness)是指程序?qū)τ谝笾獾妮斎脒M(jìn)行判斷并處理、使程序保持運(yùn)行狀態(tài),即使這有時(shí)可能導(dǎo)致不準(zhǔn)確的結(jié)果。程序的正確性指的是程序絕不產(chǎn)生不準(zhǔn)確的結(jié)果。有時(shí)更希望程序健壯,4.3.1防御性編程4.3.2使用斷言2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1304.3.1防御性編程防御編程的基本思想是:程序員要預(yù)計(jì)其他程序員的過錯(cuò)、無效的輸入、甚至有害的數(shù)據(jù)及使用者的過失,即使這種事情罕見,也要采取適當(dāng)措施保護(hù)自己的程序。保護(hù)程序無效輸入破壞的基本原則:檢查每個(gè)輸入?yún)?shù)的數(shù)據(jù);特別要檢查從程序外部進(jìn)入程序的數(shù)據(jù)。一旦發(fā)現(xiàn)了無效數(shù)據(jù),就要決定處理的方式?;镜姆绞接刑幚礤e(cuò)誤和使用異常。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1314.3.1防御性編程1.處理錯(cuò)誤錯(cuò)誤處理的方式影響軟件滿足正確性、健壯性及其他非功能性需求的能力。數(shù)據(jù)錯(cuò)誤出現(xiàn)時(shí)的一些建議(1)繼續(xù)運(yùn)行程序、返回中性無害的數(shù)據(jù)。(2)用最接近的有效數(shù)據(jù)替換無效數(shù)據(jù)。(3)在日志中記錄警告信息并繼續(xù)運(yùn)行程序。(4)調(diào)用錯(cuò)誤處理程序或?qū)ο?。?)屏幕顯示錯(cuò)誤信息。(6)盡可能在局部處理錯(cuò)誤。(7)返回一個(gè)錯(cuò)誤編碼,讓特定程序處理這個(gè)錯(cuò)誤。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1324.3.1防御性編程2.使用異常異常是處理錯(cuò)誤的一種特殊方式,出現(xiàn)了錯(cuò)誤或異常行為的程序能把錯(cuò)誤傳遞給程序的調(diào)用者,讓它處理。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1334.3.1防御性編程異常處理一般有兩種模型:終止模式和恢復(fù)模式。終止模式假設(shè)錯(cuò)誤非常關(guān)鍵,導(dǎo)致程序無法返回到異常發(fā)生的地方繼續(xù)執(zhí)行。一旦拋出異常,就表明錯(cuò)誤已無法挽回,也不能回來繼續(xù)執(zhí)行?;謴?fù)模式認(rèn)為異常處理程序的工作是修正錯(cuò)誤,重新嘗試調(diào)用出問題的方法,并認(rèn)為二次處理能成功?;謴?fù)模式希望處理異常后程序能繼續(xù)執(zhí)行。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1344.3.1防御性編程3.應(yīng)用舉例定義方法私有的,確保只有開發(fā)者知道,僅僅在參數(shù)合法的情況下才使用該操作。使用語言系統(tǒng)提供的異常類和異常處理機(jī)制,檢查參數(shù)的合法性。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1354.3.2使用斷言斷言是讓程序在運(yùn)行過程中自我檢查的代碼。如果斷言為真,就意味著程序如期望的正常;否則,就表示在代碼中發(fā)現(xiàn)了意外。如,在100以內(nèi)的算式產(chǎn)生函數(shù)中可以插入一個(gè)斷言(以Python語言為例):2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1364.3.2使用斷言編寫代碼時(shí),我們總是會(huì)做出一些假設(shè)。斷言用于在代碼中捕捉這些假設(shè),可以將斷言視為異常處理的一種高級(jí)形式??梢允褂脭嘌栽诖a中記錄一些假設(shè),例如:輸入?yún)?shù)的值在預(yù)期范圍內(nèi);程序運(yùn)行時(shí)文件流已打開或者在開始的地方;指針非空;輸入?yún)?shù)的數(shù)組、表或其他容器已經(jīng)包含了數(shù)據(jù);2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1374.3.2使用斷言斷言的現(xiàn)行形式是一些布爾表達(dá)式,程序員相信在程序中的某個(gè)特定點(diǎn)該表達(dá)式值為真。斷言分為如下三類。前置斷言:代碼執(zhí)行之前必須具備的特性。后置斷言:代碼執(zhí)行之后必須具備的特性。不變斷言:代碼執(zhí)行前后不能變化的特性。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1384.3.2使用斷言斷言的基本用途是調(diào)試和測試程序,編譯器啟動(dòng)斷言檢查后才能使用斷言。程序布署完之后就關(guān)閉斷言。下面是使用斷言的一些建議。對(duì)預(yù)計(jì)出現(xiàn)的條件使用錯(cuò)誤處理,對(duì)不應(yīng)當(dāng)出現(xiàn)的條件使用斷言。錯(cuò)誤處理用于檢查不合理的輸入數(shù)據(jù);斷言則用于檢查代碼中的錯(cuò)誤。避免在斷言中放置可執(zhí)行的代碼。因?yàn)殛P(guān)閉斷言后,編譯器可能會(huì)刪除這些代碼。用斷言來記錄和驗(yàn)證前置條件和后置條件。健壯性要求高的程序使用斷言和錯(cuò)誤處理。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1394.4字符串處理與正則表達(dá)式在操作文本文件時(shí),數(shù)據(jù)都是字符串?;绢愋停ㄈ?2.5)或結(jié)構(gòu)化的數(shù)據(jù)(如32+5),存儲(chǔ)在文本文件中都是字符串“32.5”和“32+5”。編程語言都有基本類型數(shù)據(jù)轉(zhuǎn)換為字符串的內(nèi)置機(jī)制。自定義的數(shù)據(jù)類型或?qū)ο?,則需要用戶自己編寫轉(zhuǎn)換程序。如,C#、Java等需要為自定義的類編寫對(duì)象的字符串顯示方法toString(),覆蓋從根類繼承的默認(rèn)顯示。字符串作為基本的內(nèi)置類型,編程語言也提供了大量的字符串操作,如查找一個(gè)字符、查找一個(gè)字串、置換一個(gè)字串、合并兩個(gè)字串、字符串復(fù)制等??梢允褂镁幊陶Z言提供的基本的字符串操作完成數(shù)據(jù)的構(gòu)造。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1404.4字符串處理與正則表達(dá)式以CSV格式的練習(xí)題文件為例。(1)先把一行字符串讀到數(shù)組,equationLine;(2)把equationLine中以逗號(hào)和換行分隔的算式符號(hào)串識(shí)別出來,存入String[]stringEquations;(3)識(shí)別出“51+11”三個(gè)組成,把數(shù)字轉(zhuǎn)成整型,存入left和right,運(yùn)算符存入字符operator;(4)算式構(gòu)造函數(shù)EquationconstructEquation(intleft,intright,charoperator)。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1414.4字符串處理與正則表達(dá)式程序?qū)λ闶降奈谋靖袷揭髧?yán)格:字符串不能含任何多余的字符,包括空格。如“51+11,□□19+45,92□+8,80+19,73+10□”有任何多余的空格□,程序?qū)⑦\(yùn)行錯(cuò)誤。否則,程序員要仔細(xì)編寫煩瑣的程序,進(jìn)行預(yù)處理,使字符串滿足要求?,F(xiàn)代編程語言提供了更豐富的字符串處理庫,其中重要而又易用的是正則表達(dá)式。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1424.4字符串處理與正則表達(dá)式用正則表達(dá)式及String相關(guān)函數(shù),處理數(shù)據(jù)如“51+11,[19+□□A45,□92+8,?80+19,73+10;□”。符號(hào)串"[\\s\\D\\p{Punct}&&[^\\,+?]]+"就是正則表達(dá)式,把輸入字符串中除數(shù)字、‘+’、‘?’和‘,’之外的字符全部刪除。字符串函數(shù)split(),按正則表達(dá)式"\\,"的模式以逗號(hào)為分隔符,把輸入的符號(hào)串分成一組符號(hào)串。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1434.4字符串處理與正則表達(dá)式正則表達(dá)式正則表達(dá)式(RegularExpressions)是一串字符,它所定義的模式可用來查找、顯示或修改輸入序列中出現(xiàn)的某個(gè)模式的一部分或全部。Java在String類中提供了booleanmatches(Stringregxep)、voidreplaceAll(Stringregxep,Stringreplacement)和String[]split(Stringregxep)三種基本方法,它們的作用分別是匹配、替換全部匹配內(nèi)容、分割。參數(shù)都包含了正則表達(dá)式regxep。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1444.4字符串處理與正則表達(dá)式【例4.2】標(biāo)識(shí)符的正則表達(dá)式:[A-Za-z][A-Za-z0-9]*,方括號(hào)[]表示選取其中任何一個(gè)符號(hào),星號(hào)表示符號(hào)出現(xiàn)0次或多次。如果標(biāo)識(shí)符允許含下畫線,但不能以下畫線結(jié)束。2016秋數(shù)據(jù)科學(xué)與軟件工程學(xué)院1454.4字符串處理與正則表達(dá)式【例4.3】打開文本文件,統(tǒng)計(jì)包含了字符串str的單詞數(shù),不區(qū)分str的大小寫。
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 共青科技職業(yè)學(xué)院《材料表面技術(shù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 小朋友的安全課件
- 《營養(yǎng)苗的培育》課件
- 贛西科技職業(yè)學(xué)院《微波電路》2023-2024學(xué)年第一學(xué)期期末試卷
- 《漫談?wù)n堂教學(xué)的有效性》課件
- 2022年上海市中級(jí)消防設(shè)施操作員《技能操作》近年真題(含答案)
- 小學(xué)生流感防治教育課件
- 三年級(jí)科學(xué)上冊(cè)第四單元1常見材料教案蘇教版
- 三年級(jí)英語上冊(cè)Unit1Hello第5課時(shí)教案人教PEP
- 小學(xué)生模擬法庭教學(xué)課件
- 復(fù)合機(jī)器人行業(yè)分析
- 建立進(jìn)出校園安全控制與管理的方案
- 新課標(biāo)《普通高中化學(xué)課程標(biāo)準(zhǔn)(2022年版)》
- 阿里菜鳥裹裹云客服在線客服認(rèn)證考試及答案
- 水庫防恐反恐應(yīng)急預(yù)案
- 危險(xiǎn)化學(xué)品銷售管理臺(tái)帳
- 五輸穴及臨床應(yīng)用1
- 中國成人急性呼吸窘迫綜合征(ARDS)診斷與非機(jī)械通氣治療指南(2023版)解讀
- 綠植租擺服務(wù)投標(biāo)方案(完整技術(shù)標(biāo))
- 童話知識(shí)競賽課件
- 一氧化氮讓你遠(yuǎn)離心腦血管病第(全書回顧綜合版)
評(píng)論
0/150
提交評(píng)論