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