軟件工程:理論、技術(shù)及實(shí)踐 課件 第6、7章 軟件設(shè)計(jì)、軟件實(shí)現(xiàn)與測(cè)試_第1頁
軟件工程:理論、技術(shù)及實(shí)踐 課件 第6、7章 軟件設(shè)計(jì)、軟件實(shí)現(xiàn)與測(cè)試_第2頁
軟件工程:理論、技術(shù)及實(shí)踐 課件 第6、7章 軟件設(shè)計(jì)、軟件實(shí)現(xiàn)與測(cè)試_第3頁
軟件工程:理論、技術(shù)及實(shí)踐 課件 第6、7章 軟件設(shè)計(jì)、軟件實(shí)現(xiàn)與測(cè)試_第4頁
軟件工程:理論、技術(shù)及實(shí)踐 課件 第6、7章 軟件設(shè)計(jì)、軟件實(shí)現(xiàn)與測(cè)試_第5頁
已閱讀5頁,還剩129頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第6章軟件設(shè)計(jì)本章學(xué)習(xí)目標(biāo)1.了解軟件設(shè)計(jì)的主要目標(biāo)。2.掌握有關(guān)軟件設(shè)計(jì)的基本概念。3.掌握結(jié)構(gòu)化軟件設(shè)計(jì)的基本方法。4.重點(diǎn)掌握面向?qū)ο笤O(shè)計(jì)方法。5.掌握軟件詳細(xì)設(shè)計(jì)方法。6.掌握人機(jī)交互界面設(shè)計(jì)的基本原則。7.了解軟件設(shè)計(jì)模式的基本概念軟件工程中的設(shè)計(jì)1結(jié)構(gòu)化設(shè)計(jì)2面向?qū)ο蟮脑O(shè)計(jì)3用戶界面設(shè)計(jì)4軟件設(shè)計(jì)優(yōu)化5序言

20世紀(jì)90年代初,MitchKapor發(fā)表的“軟件設(shè)計(jì)宣言”中這樣寫道:什么是設(shè)計(jì)?設(shè)計(jì)就是你身處兩個(gè)世界——技術(shù)世界和人類的目標(biāo)世界,而你嘗試將這兩個(gè)世界結(jié)合在一起……序言軟件設(shè)計(jì)是軟件工程過程中的核心技術(shù)。在這個(gè)階段,軟件工程師設(shè)計(jì)出軟件的“藍(lán)圖”,創(chuàng)建各種軟件模型,讓這些模型能正確反映出客戶的需求,并為系統(tǒng)實(shí)現(xiàn)提供軟件體系結(jié)構(gòu)、數(shù)據(jù)結(jié)構(gòu)、接口和構(gòu)件的細(xì)節(jié)。序言

面向?qū)ο蟮能浖O(shè)計(jì)方法把OOA階段得到的需求模型進(jìn)行逐步擴(kuò)充:把類或?qū)ο筮M(jìn)一步修改和細(xì)化,設(shè)計(jì)屬性、方法,以及類或者對(duì)象之間的聯(lián)系,由一組協(xié)同工作的對(duì)象共同完成整個(gè)系統(tǒng)功能。面向?qū)ο蟮脑O(shè)計(jì)模型一般包括四個(gè)部分:?jiǎn)栴}論域、人機(jī)交互、任務(wù)管理和數(shù)據(jù)管理。6.1軟件工程的設(shè)計(jì)6.1.1設(shè)計(jì)原理

在傳統(tǒng)軟件工程方法學(xué)中形成的軟件設(shè)計(jì)的基本原理,在面向?qū)ο笤O(shè)計(jì)時(shí)依然成立,此外還增加了一些與面向?qū)ο蠓椒ㄌ卣飨嚓P(guān)的新特點(diǎn)。(1)模塊化

在軟件工程領(lǐng)域,軟件可以被劃分成為一系列獨(dú)立命名、可處理的部件,有時(shí)也被稱為模塊。6.1軟件工程的設(shè)計(jì)6.1.1設(shè)計(jì)原理(1)模塊化

在過程化語言中過程、函數(shù)、子程序、宏等都可以看作模塊。在面向?qū)ο蟪绦蛟O(shè)計(jì)中的類或類的方法也可以稱之為模塊。

模塊化將復(fù)雜系統(tǒng)分解為可管理的模塊。這種處理問題的方式體現(xiàn)了設(shè)計(jì)中“關(guān)注點(diǎn)分離”的概念,即希望將復(fù)雜問題分解為可以獨(dú)立解決和(或)優(yōu)化的若干塊,從而使得這個(gè)復(fù)雜問題能夠更容易地被處理。6.1軟件工程的設(shè)計(jì)圖6-1模塊化和軟件成本6.1軟件工程的設(shè)計(jì)(2)抽象

抽象是人類在認(rèn)識(shí)復(fù)雜現(xiàn)象過程中使用的一種思維工具。它把無數(shù)現(xiàn)象中相似的方面集中和概括起來,暫時(shí)忽略它們之間的差異,提取出事物的本質(zhì)特征。抽象通過抑制不必要的細(xì)節(jié),同時(shí)強(qiáng)調(diào)和集中在當(dāng)前重要的細(xì)節(jié)來達(dá)到逐步求精的目標(biāo)。6.1軟件工程的設(shè)計(jì)(3)信息隱蔽信息隱蔽是指在設(shè)計(jì)和確定模塊時(shí),使得一個(gè)模塊內(nèi)包含的信息對(duì)于不需要這些信息的其他模塊來說,是不可訪問的。(4)模塊的獨(dú)立性模塊獨(dú)立性是模塊內(nèi)部各部分及模塊間關(guān)系的一種衡量標(biāo)準(zhǔn)。模塊獨(dú)立性概念是模塊化、抽象概念和信息隱蔽的直接結(jié)果,也是完成模塊設(shè)計(jì)中需要遵循的基本標(biāo)準(zhǔn)。模塊獨(dú)立性可以使用兩個(gè)定性的標(biāo)準(zhǔn)評(píng)估:內(nèi)聚性和耦合性。6.1軟件工程的設(shè)計(jì)

模塊的內(nèi)聚性反映了某個(gè)模塊相關(guān)功能的強(qiáng)度,是信息隱蔽概念的自然擴(kuò)展。一個(gè)內(nèi)聚的模塊執(zhí)行一個(gè)獨(dú)立的任務(wù),與程序的其他部分部件只需要很少的交互。簡(jiǎn)單地說,一個(gè)內(nèi)聚的模塊應(yīng)該只完成一件事情。模塊的耦合性顯示了模塊間的相互依賴性,表明了在軟件結(jié)構(gòu)中多個(gè)模塊之間的相互連接程度。耦合性依賴于模塊之間的接口復(fù)雜性、引用或進(jìn)入模塊所在的點(diǎn)以及什么數(shù)據(jù)通過接口傳遞等因素。6.1軟件工程的設(shè)計(jì)表6-1模塊的內(nèi)聚內(nèi)聚級(jí)別(低到高)內(nèi)聚名稱定義1偶然性內(nèi)聚

如果一個(gè)模塊內(nèi)部各部分之間沒聯(lián)系,即使有也很松散,則稱該模塊為偶然性內(nèi)聚2邏輯性內(nèi)聚

模塊把幾種相關(guān)功能代碼組合在一起,每次調(diào)用時(shí),由傳給模塊的判定參數(shù)來確定該模塊應(yīng)執(zhí)行哪一種功能,則稱該模塊為邏輯性內(nèi)聚模塊3時(shí)間性內(nèi)聚

如果一個(gè)模塊內(nèi)部的幾個(gè)功能必須在同一時(shí)間內(nèi)執(zhí)行(例如一個(gè)初始化模塊),但這些功能只是因?yàn)闀r(shí)間因素關(guān)聯(lián)在一起,則稱該模塊為時(shí)間性內(nèi)聚模塊4過程性內(nèi)聚

如果一個(gè)模塊內(nèi)部的處理成分是相關(guān)的,且必須以特定的次序執(zhí)行,則稱該模塊為過程性內(nèi)聚6.1軟件工程的設(shè)計(jì)續(xù)表6-1模塊的內(nèi)聚內(nèi)聚級(jí)別(低到高)內(nèi)聚名稱定義5通信性內(nèi)聚

如果一個(gè)模塊內(nèi)部的各部分功能使用相同的輸入數(shù)據(jù),或者產(chǎn)生相同的輸出數(shù)據(jù),則稱該模塊為通信內(nèi)聚模塊6功能性內(nèi)聚

如果一個(gè)模塊中各個(gè)部分都是完成某一具體功能必不可少的組成部分,或者說該模塊中所有部分都是為了完成一項(xiàng)具體功能而協(xié)同工作,緊密聯(lián)系,不可分割,則稱該模塊為內(nèi)聚模塊7信息性內(nèi)聚

如果模塊能夠完成多個(gè)功能,各個(gè)功能都在相同的數(shù)據(jù)結(jié)構(gòu)上操作,每一項(xiàng)功能有一個(gè)唯一的入口點(diǎn),代碼相對(duì)獨(dú)立。這個(gè)模塊將根據(jù)不同的要求,確定執(zhí)行哪一個(gè)功能,則稱該模塊為信息性內(nèi)聚模塊6.1軟件工程的設(shè)計(jì)表6-2模塊的耦合耦合級(jí)別(低到高)耦合名稱定義1內(nèi)容耦合

如果一個(gè)模塊直接修改另一個(gè)模塊的數(shù)據(jù),或直接跳轉(zhuǎn)入另一個(gè)模塊,則稱這兩個(gè)模塊之間存在著內(nèi)容耦合2公共耦合

如果兩個(gè)模塊都訪問同一個(gè)公共數(shù)據(jù)環(huán)境,并且該公共數(shù)據(jù)環(huán)境是全局?jǐn)?shù)據(jù)結(jié)構(gòu)、共享的通信區(qū)、內(nèi)存的公共覆蓋區(qū)等,則稱這兩個(gè)模塊之間存在著公共耦合3控制耦合

如果一個(gè)模塊通過傳遞開關(guān)、標(biāo)志、名字等控制信息,明顯地控制選擇另一模塊的功能,則稱這兩個(gè)模塊之間存在著控制耦合4標(biāo)記耦合

如果兩個(gè)模塊通過參數(shù)表傳遞記錄信息,并且這個(gè)記錄是某一數(shù)據(jù)結(jié)構(gòu)的子結(jié)構(gòu),不是簡(jiǎn)單變量,則稱這兩個(gè)模塊之間存在著標(biāo)記耦合6.1軟件工程的設(shè)計(jì)續(xù)表6-2模塊的耦合耦合級(jí)別(低到高)耦合名稱定義5數(shù)據(jù)耦合

如果一個(gè)模塊訪問另一個(gè)模塊,彼此間通過簡(jiǎn)單數(shù)據(jù)參數(shù)來交換輸入、輸出信息,并且這里的簡(jiǎn)單數(shù)據(jù)參數(shù)不同于控制參數(shù)、公共數(shù)據(jù)結(jié)構(gòu)或外部變量,則稱這兩個(gè)模塊之間存在著數(shù)據(jù)耦合6非直接耦合

如果兩模塊間沒有直接關(guān)系,之間的聯(lián)系完全是通過主模塊的控制和調(diào)用來實(shí)現(xiàn)的,則稱這兩個(gè)模塊之間不存在耦合,或者稱為存在非直接耦合

在軟件設(shè)計(jì)中,要盡可能保持模塊內(nèi)部的高內(nèi)聚和模塊之間的低耦合。6.1軟件工程的設(shè)計(jì)6.1.2設(shè)計(jì)過程

軟件設(shè)計(jì)的主要任務(wù)是要解決“如何做”的問題。在軟件設(shè)計(jì)過程中一般要完成數(shù)據(jù)/類、軟件體系結(jié)構(gòu)、接口、構(gòu)件級(jí)和部署級(jí)幾個(gè)基本設(shè)計(jì)模型的創(chuàng)建。

數(shù)據(jù)設(shè)計(jì)或者類設(shè)計(jì):首先以用戶或者客戶看待數(shù)據(jù)的角度來創(chuàng)建數(shù)據(jù)模型和(或)信息模型,然后通過逐步求精將其轉(zhuǎn)化為特定于實(shí)現(xiàn)的表示,例如應(yīng)用級(jí)別的數(shù)據(jù)庫或者業(yè)務(wù)級(jí)別的數(shù)據(jù)倉庫等。6.1軟件工程的設(shè)計(jì)

體系結(jié)構(gòu)設(shè)計(jì):定義軟件主要結(jié)構(gòu)元素之間的關(guān)系、可用于達(dá)到系統(tǒng)所定義需求的體系結(jié)構(gòu)風(fēng)格、設(shè)計(jì)模式以及影響體系結(jié)構(gòu)實(shí)現(xiàn)方式的約束。

接口設(shè)計(jì):定義了軟件和協(xié)作系統(tǒng)之間、軟件和使用人員之間的通信。

構(gòu)件級(jí)設(shè)計(jì):將軟件體系結(jié)構(gòu)的結(jié)構(gòu)元素變換為對(duì)軟件構(gòu)件的過程性描述。構(gòu)件通常是指“系統(tǒng)中模塊化的,可部署和可替換的部件,封裝了實(shí)現(xiàn)并對(duì)外開放一組接口”。

部署級(jí)設(shè)計(jì):規(guī)劃如何將軟件功能和子系統(tǒng)分布在物理計(jì)算環(huán)境中。6.1軟件工程的設(shè)計(jì)圖6-2從需求模型到設(shè)計(jì)模型的轉(zhuǎn)化6.2結(jié)構(gòu)化設(shè)計(jì)6.2.1結(jié)構(gòu)化設(shè)計(jì)主要步驟圖6-3結(jié)構(gòu)化設(shè)計(jì)的基本流程6.2結(jié)構(gòu)化設(shè)計(jì)步驟1:進(jìn)一步分析和審查需求分析階段得到的數(shù)據(jù)流圖。步驟2:根據(jù)系統(tǒng)的數(shù)據(jù)流圖形式來確定系統(tǒng)的數(shù)據(jù)處理方式屬于“變換型”還是“事務(wù)型”。步驟3:根據(jù)不同數(shù)據(jù)處理類型,參照不同的方式,逐步給出初始的系統(tǒng)結(jié)構(gòu)圖。步驟4:利用啟發(fā)式規(guī)則(如模塊的耦合性)多次修改,得到最終的系統(tǒng)結(jié)構(gòu)圖。6.2結(jié)構(gòu)化設(shè)計(jì)步驟5:根據(jù)需求分析階段得到的數(shù)據(jù)字典和實(shí)體關(guān)系圖進(jìn)行數(shù)據(jù)庫設(shè)計(jì)或者是數(shù)據(jù)文件設(shè)計(jì)。步驟6:根據(jù)數(shù)據(jù)流圖中對(duì)加工的說明、輸入輸出說明進(jìn)行模塊的接口設(shè)計(jì)。步驟7:使用詳細(xì)設(shè)計(jì)工具(如程序流程圖、PDL、盒圖等)描述模塊內(nèi)部的詳細(xì)設(shè)計(jì)。步驟8:制定測(cè)試計(jì)劃。

典型的數(shù)據(jù)流類型有變換型數(shù)據(jù)流和事務(wù)型數(shù)據(jù)流,根據(jù)不同數(shù)據(jù)流類型,可以轉(zhuǎn)化成不同的系統(tǒng)結(jié)構(gòu)。6.2結(jié)構(gòu)化設(shè)計(jì)(1)變換型數(shù)據(jù)流映射圖6-4變換型數(shù)據(jù)流圖6.2結(jié)構(gòu)化設(shè)計(jì)(1)變換型數(shù)據(jù)流映射圖6-5具有變換型特征系統(tǒng)的模塊結(jié)構(gòu)圖6.2結(jié)構(gòu)化設(shè)計(jì)(2)事務(wù)型數(shù)據(jù)流映射圖6-6具有事務(wù)處理中心的數(shù)據(jù)流6.2結(jié)構(gòu)化設(shè)計(jì)圖6-7具體有事務(wù)型特征的系統(tǒng)結(jié)構(gòu)圖6.2結(jié)構(gòu)化設(shè)計(jì)

首先對(duì)系統(tǒng)的模塊進(jìn)行劃分,通過系統(tǒng)結(jié)構(gòu)圖來表示模塊之間組成,然后用程序描述語言(ProgramDesignLanguage,簡(jiǎn)稱PDL)來描述模塊內(nèi)部詳細(xì)設(shè)計(jì),并給出數(shù)據(jù)庫表的部分簡(jiǎn)單設(shè)計(jì)。6.2.2結(jié)構(gòu)化設(shè)計(jì)實(shí)例6.2結(jié)構(gòu)化設(shè)計(jì)(1)系統(tǒng)結(jié)構(gòu)圖圖6-8智慧教室管理系統(tǒng)結(jié)構(gòu)圖6.2結(jié)構(gòu)化設(shè)計(jì)(2)模塊詳細(xì)設(shè)計(jì)//用戶管理PDLvoidlogin(String角色,String用戶名,String密碼){switch(角色)case管理員:if(verify(用戶名,密碼)==true){//verify將賬號(hào)密碼與數(shù)據(jù)庫對(duì)應(yīng)信息對(duì)比

頁面跳轉(zhuǎn)到"管理員頁面";}else{

頁面跳轉(zhuǎn)到錯(cuò)誤頁面;}break;case用戶或操作員或調(diào)度員或維修員:if(verify(賬號(hào),密碼)==true){//verify將賬號(hào)密碼與數(shù)據(jù)庫對(duì)應(yīng)信息對(duì)比

頁面跳轉(zhuǎn)到對(duì)應(yīng)角色頁面;}else{

頁面跳轉(zhuǎn)到錯(cuò)誤頁面;}}6.2結(jié)構(gòu)化設(shè)計(jì)(2)模塊詳細(xì)設(shè)計(jì)booleanregister(String用戶類型,String用戶名,String密碼){if(userIsExist()){returnfalse;}else{//add_to_database將信息添加到數(shù)據(jù)庫add_to_database(用戶類型,用戶登錄名,密碼);returntrue;}}

UserInfosaveUser(String用戶名){UserInfouserInfo=null;userInfo=save_database(用戶名);returnuserInfo;}6.2結(jié)構(gòu)化設(shè)計(jì)(2)模塊詳細(xì)設(shè)計(jì)booleanupdateUser(String用戶類型,String用戶登錄名,String密碼,其他信息){if(userIsExist()==false){//用戶是否存在returnfalse;}else{//更新數(shù)據(jù)庫信息update_database();returntrue;}}booleandeleteUser(String用戶名){//更新數(shù)據(jù)庫信息if(userIsExist()==false){//用戶是否存在returnfalse;}else{update_database();returntrue;}}6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-3學(xué)生表結(jié)構(gòu)字段名字段類型描述約束studentIdvarchar學(xué)號(hào)主鍵namevarchar姓名不為空passwordvarchar密碼不為空sexvarchar男or女stateinteger用戶狀態(tài)(可用/不可用)不為空gradeClassvarchar學(xué)生所在班級(jí)faceFeatureblob人臉特征avatarvarchar頭像permissionvarchar權(quán)限phoneNumbervarchar手機(jī)號(hào)6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-4教師表結(jié)構(gòu)字段名字段類型描述約束teacherIdvarchar學(xué)號(hào)主鍵namevarchar姓名不為空passwordvarchar密碼不為空sexvarchar男or女stateinteger用戶狀態(tài)(可用/不可用)不為空faceFeatureblob人臉特征avatarvarchar頭像permissionvarchar權(quán)限phoneNumbervarchar手機(jī)號(hào)6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-5樓管表結(jié)構(gòu)字段名字段類型描述約束buildingIdvarchar學(xué)號(hào)主鍵namevarchar姓名不為空passwordvarchar密碼不為空sexvarchar男or女stateinteger用戶狀態(tài)(可用/不可用)不為空locationvarchar樓管管理的大樓permissionvarchar權(quán)限phoneNumbervarchar手機(jī)號(hào)6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-6系統(tǒng)管理員表結(jié)構(gòu)字段名字段類型描述約束adminIdvarchar工號(hào)主鍵namevarchar姓名不為空passwordvarchar密碼不為空sexvarchar男or女stateinteger用戶狀態(tài)(可用/不可用)不為空permissionvarchar權(quán)限6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-7教室表結(jié)構(gòu)字段名字段類型描述約束roomIdinteger教師號(hào)主鍵locationvarchar教室所在大樓位置不為空statusinteger狀態(tài)(可用/正在使用)不為空字段名字段類型描述約束deviceIdinteger設(shè)備編號(hào)主鍵namevarchar設(shè)備名不為空typevarchar設(shè)備類型不為空runStatusvarchar是否正在運(yùn)行不為空roomIdinteger所在房間id外鍵表6-8設(shè)備表結(jié)構(gòu)6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-9課程表結(jié)構(gòu)字段名字段類型描述約束courseIdinteger課程號(hào)主鍵namevarchar課程名稱不為空teacherIdinteger責(zé)任教師id外鍵couresHoursinteger課時(shí)creditfloat學(xué)分introvarchar課程簡(jiǎn)介6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-10教學(xué)班表結(jié)構(gòu)字段名字段類型描述約束classIdinteger教學(xué)班號(hào)主鍵namevarchar教學(xué)班名稱不為空courseIdinteger課程號(hào)不為空、外鍵studentNuminteger學(xué)生數(shù)量不為空classRoomIdinteger上課房間號(hào)外鍵teacherIdinteger主講教師id外鍵Scheduledatatime上課時(shí)間不為空6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-11云課堂表結(jié)構(gòu)字段名字段類型描述約束cloudIdinteger云課堂編號(hào)主鍵classIdinteger教學(xué)班id外鍵startTimedatetime開始時(shí)間不為空endTimedatetime結(jié)束時(shí)間不為空videoPathvarchar視頻路徑文件不為空字段名字段類型描述約束noteIdinteger白板筆記編號(hào)主鍵cloudIdinteger云課堂id外鍵imgPathvarchar圖片文件路徑不為空noteTimedatetime筆記時(shí)間不為空表6-12白板筆記錄表結(jié)構(gòu)6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-13考勤記錄表結(jié)構(gòu)字段名字段類型描述約束attenIdinteger記錄編號(hào)主鍵userIdinteger學(xué)生id外鍵classIdinteger教學(xué)班id外鍵arrTimedatetime到課時(shí)間不為空stateinteger狀態(tài)(正常/申訴/接受申訴/拒絕申訴)不為空6.2結(jié)構(gòu)化設(shè)計(jì)(3)數(shù)據(jù)設(shè)計(jì)表6-14請(qǐng)假記錄表結(jié)構(gòu)字段名字段類型描述約束leaveIdinteger記錄編號(hào)主鍵userIdinteger學(xué)生id外鍵classIdvarchar教學(xué)班id外鍵infodatetime請(qǐng)假說明不為空createTimedatatime請(qǐng)假時(shí)間stateinteger狀態(tài)(未審核/批準(zhǔn)/拒絕)不為空6.3面向?qū)ο蟮脑O(shè)計(jì)面向?qū)ο笤O(shè)計(jì)的步驟概括如下:步驟1:細(xì)化重組類。步驟2:細(xì)化和實(shí)現(xiàn)類間關(guān)系,明確其可見性。步驟3:增加屬性,指定屬性的類型與可見性。步驟4:分配職責(zé),定義執(zhí)行每個(gè)職責(zé)的方法。步驟5:對(duì)消息驅(qū)動(dòng)的系統(tǒng),明確消息傳遞方式,避免對(duì)象之間的關(guān)系數(shù)目日益膨脹,形成復(fù)雜的網(wǎng)狀結(jié)構(gòu)。步驟6:利用設(shè)計(jì)模式進(jìn)行優(yōu)化設(shè)計(jì)步驟7:畫出詳細(xì)的類圖與時(shí)序圖。6.3.1面向?qū)ο筌浖O(shè)計(jì)的步驟6.3面向?qū)ο蟮脑O(shè)計(jì)面向?qū)ο笤O(shè)計(jì)還有如下啟發(fā)式規(guī)則:(1)設(shè)計(jì)結(jié)果應(yīng)該清晰易懂①用詞一致。②使用已有的協(xié)議。③減少消息模式的數(shù)量。④避免模糊的定義。(2)一般—特殊結(jié)構(gòu)的深度應(yīng)適當(dāng)6.3面向?qū)ο蟮脑O(shè)計(jì)(3)設(shè)計(jì)簡(jiǎn)單的類①避免包含過多的屬性。②有明確的定義。③盡量簡(jiǎn)化對(duì)象之間的協(xié)作關(guān)系。④不要提供太多服務(wù)。(4)使用簡(jiǎn)單的消息傳遞(5)使用簡(jiǎn)單的服務(wù)(6)把設(shè)計(jì)變動(dòng)減至最小6.3面向?qū)ο蟮脑O(shè)計(jì)(1)類的調(diào)整和詳細(xì)設(shè)計(jì)6.3.2面向?qū)ο筌浖O(shè)計(jì)實(shí)例表6-15智慧教室系統(tǒng)中的部分實(shí)體類及其重要屬性、基本方法類名屬性基本方法方法說明用戶User-userId:String-name:String-sex:String-password:String-state:integer-userType:String-permission:List-faceFeature:Blob-faceInfo:String+login():void+getPermission():List+getFaceFeature():Blob+getFaceInfo():String+setUserInfo():void登錄驗(yàn)證獲取權(quán)限獲取人臉特征獲取人臉信息設(shè)置用戶信息6.3面向?qū)ο蟮脑O(shè)計(jì)續(xù)表6-15智慧教室系統(tǒng)中部分實(shí)體類類名屬性基本方法方法說明學(xué)生Student(父類:User)-gradeClass:String-avatar:String-phoneNumber:String+getgradeClass():String+setStudentInfo():void獲取學(xué)生班級(jí)設(shè)置學(xué)生信息教師Teacher(父類:User)-avatar:String-phoneNumber:String+getRelClass():String+setTeacherInfo():void獲取相關(guān)課程設(shè)置教師信息樓管BuildingManagement(父類:User)-location:String+getLocation():String+updateLocation():boolean+setBuildingManagementInfo():void獲取管理大樓更改管理大樓設(shè)置樓管信息系統(tǒng)管理員SystemManagement(父類:User)+insertUser():boolean+deleteUser():boolean+updateUser():boolean+returnUserInfo():String+setSystemManagementInfo():void新建一個(gè)用戶刪除一個(gè)用戶修改用戶信息返回用戶信息設(shè)置系統(tǒng)管理員信息6.3面向?qū)ο蟮脑O(shè)計(jì)續(xù)表6-15智慧教室系統(tǒng)中部分實(shí)體類類名屬性基本方法方法說明設(shè)備Device-deviceId:integer-name:String-type:String-runStatus:boolean-roomId:String+freshStatus():boolean+updateStatus():boolean+insertDevice():boolean+deleteDevice():boolean+getDeviceInfo():String+setDeviceInfo():void+checkDevice():boolean+repairDevice():boolean刷新設(shè)備狀態(tài)更改設(shè)備狀態(tài)增添設(shè)備刪除設(shè)備返回設(shè)備信息設(shè)置設(shè)備信息檢查設(shè)備維修設(shè)備環(huán)境設(shè)備EnvironmentDev(父類:Device)-direction:integer+getTemperature():float+getHumidity():float+setEnvironmentDeviceInfo():void獲取環(huán)境溫度獲取環(huán)境濕度設(shè)置環(huán)境設(shè)備信息6.3面向?qū)ο蟮脑O(shè)計(jì)續(xù)表6-15智慧教室系統(tǒng)中部分實(shí)體類類名屬性基本方法方法說明攝像頭Camera(父類:Device)-direction:integer+openCamera():boolean+stopCamera():boolean+setDirection():void+setCameraInfo():void開啟攝像頭關(guān)閉攝像頭設(shè)置攝像頭角度設(shè)置攝像頭信息教室ClassRoom-roomId:integer-location:String-status:integer-relDev:List+updateStatus():boolean+updateRoom():boolean+getRoomInfo():String+insertRoom():boolean+getRelDev():List+updateRelDev():boolean+setClassRoomInfo():void更新使用狀態(tài)更新教室信息返回教室信息添加教室獲取設(shè)備列表更新設(shè)備列表設(shè)置教室信息6.3面向?qū)ο蟮脑O(shè)計(jì)續(xù)表6-15智慧教室系統(tǒng)中部分實(shí)體類類名屬性基本方法方法說明教室ClassRoom-roomId:integer-location:String-status:integer-relDev:List+updateStatus():boolean+updateRoom():boolean+getRoomInfo():String+insertRoom():boolean+getRelDev():List+updateRelDev():boolean+setClassRoomInfo():void更新使用狀態(tài)更新教室信息返回教室信息添加教室獲取設(shè)備列表更新設(shè)備列表設(shè)置教室信息課程Course-courseId:integer-teacherId:integer-name:String-courseHours:integer-credit:float-intro:String+insertCourse():boolean+deleteCourse():boolean+updateCourse():boolean+getCourseInfo():String+setCourseInfo():void添加課程刪除課程更新課程信息獲取課程信息設(shè)置課程信息6.3面向?qū)ο蟮脑O(shè)計(jì)續(xù)表6-15智慧教室系統(tǒng)中部分實(shí)體類類名屬性基本方法方法說明教學(xué)班Class-classId:integer-name:String-classRoomId:integer-courseId:integer-studentId[]:integer+addStudent():boolean+getStudentList():List+setClassInfo():void增加學(xué)生獲取學(xué)生列表設(shè)置教學(xué)班信息人臉庫FaceDB-faceId:integer-faceFeature:Blob+addFaceFeature():boolean+deleteFaceFeature():boolean+setFaceDBInfo():void添加人臉特征刪除人臉特征設(shè)置人臉庫信息6.3面向?qū)ο蟮脑O(shè)計(jì)續(xù)表6-15智慧教室系統(tǒng)中部分實(shí)體類類名屬性基本方法方法說明考勤Attendance-attenId:integer-userId:integer-courseId:integer-arrTime:datetime-state:integer+insertAtten():boolean+updateAtten():boolean+deleteAtten():boolean+analysisAtten():String+appealAtten():boolean+acceptAtten():boolean+setAttendanceInfo():void添加到課記錄更新到課記錄刪除到課記錄獲取統(tǒng)計(jì)結(jié)果申訴到課記錄接受申訴到課設(shè)置考勤信息

在確定每一個(gè)類的具體屬性后,在設(shè)計(jì)相關(guān)類的具體方法時(shí)需要注意如下幾點(diǎn):①需考慮所有用戶信息的增、刪、改、查功能,設(shè)定相應(yīng)的方法。6.3面向?qū)ο蟮脑O(shè)計(jì)②確認(rèn)上課時(shí)首先將所有學(xué)生考勤狀態(tài)設(shè)置為缺勤,將已請(qǐng)假并通過審批的學(xué)生考勤狀態(tài)設(shè)置為已請(qǐng)假。上課過程中攝像頭自動(dòng)捕捉學(xué)生頭像進(jìn)行匹配,匹配后更新當(dāng)前課堂對(duì)應(yīng)學(xué)生的考勤記錄。//用戶類詳細(xì)設(shè)計(jì)publicclassUser{privateStringuserId;//用戶IDprivateStringname;//用戶名稱privateStringsex;//用戶性別privateStringpassword;//用戶密碼privateStringstate;//用戶狀態(tài)privateStringuserType;//用戶類型privateStringpermission;//用戶權(quán)限privateStringfaceFeature;//人臉特征privateStringfaceInfo;//人臉信息6.3面向?qū)ο蟮脑O(shè)計(jì)publicvoidlogin(Stringname,Stringpassword,StringuserType){switch(用戶類型)case學(xué)生:if(verify(賬號(hào),密碼)==true){//verify將賬號(hào)密碼與數(shù)據(jù)庫對(duì)應(yīng)信息對(duì)比

頁面跳轉(zhuǎn)到"學(xué)生頁面";}else{

頁面跳轉(zhuǎn)到錯(cuò)誤頁面;}break;case教師或樓管或系統(tǒng)管理員:if(verify(賬號(hào),密碼)==true){//verify將賬號(hào)密碼與數(shù)據(jù)庫對(duì)應(yīng)信息對(duì)比

頁面跳轉(zhuǎn)到對(duì)應(yīng)角色頁面;}else{

頁面跳轉(zhuǎn)到錯(cuò)誤頁面;}}6.3面向?qū)ο蟮脑O(shè)計(jì)publicListgetPermission(Stringname,StringuserType){if(userIsExist()==false){//用戶是否存在returnnull;}else{permissionList=getUserPermissionByType(name,userType);returnpermissionList;//根據(jù)用戶和類型返回權(quán)限列表}}

publicStringgetFaceFeature(Stringname,StringuserTpye,Stringpermission){if(userIdExit()==false){//用戶是否存在returnnull;}elseif(userHasPermission()==false){//用戶是否有權(quán)限r(nóng)eturnnull;}else{StringfaceFeature=getUserFaceFeature(name,userType,permission);returnfaceFeature;//根據(jù)用戶類型和權(quán)限返回人臉特征}}6.3面向?qū)ο蟮脑O(shè)計(jì)publicStringgetFaceInfo(Stringname,StringuserTpye,Stringpermission){if(userIdExit()==false){//用戶是否存在returnnull;}elseif(userHasPermission()==false){//用戶是否有權(quán)限r(nóng)eturnnull;}else{StringfaceInfo=getUserFaceInfo(name,userType,permission);returnfaceInfo;//根據(jù)用戶類型和權(quán)限返回人臉信息}}

publicvoidsetUserInfo(Useruser){if(userIdExit()==true){//用戶是否存在setUserInfo(user);//設(shè)置有用信息}}}6.3面向?qū)ο蟮脑O(shè)計(jì)表6-16智慧教室系統(tǒng)中的部分控制類設(shè)計(jì)類名屬性基本方法方法說明云課堂CloudClass-cloudId:integer-courseId:integer-startTime:datetime-endTime:datetime+insertCloud():boolean+deleteCloud():boolean+getVideo():Blob+analysisCloud():List添加一條課堂信息刪除一條課堂信息獲取課堂錄像獲取統(tǒng)計(jì)分析結(jié)果人臉考勤FaceAttendance-unsignStudents:List-signStudents:List+getFaceMatch(StringstudentId):boolean+addFaceFeature():boolean+deleteFaceFeature():boolean+matchFace():int+getStudentByFace():Student+saveToAttendance():void返回指定學(xué)生是否考勤添加人臉特征刪除人臉特征匹配人臉圖像根據(jù)人臉獲取學(xué)生信息保存學(xué)生考勤信息6.3面向?qū)ο蟮脑O(shè)計(jì)續(xù)表6-16智慧教室系統(tǒng)中的部分控制類設(shè)計(jì)類名屬性基本方法方法說明用戶管理UserManage-userType:integer+addUser(Stringname,Stringinfo,IntegeruserType):boolean+updateUser(Stringuserid,Stringinfo,IntegeruserType):boolean+deleteUser(Integeruserid,IntegeruserType):boolean+searchUser(Integeruserid,IntegeruserType):String+changePassword(Stringusername,Stringpassword,IntegeruserType):boolean+changePermission(Stringname,Stringpermission,IntegeruserType):boolean添加用戶更新用戶信息刪除用戶查詢用戶信息修改用戶密碼修改用戶權(quán)限6.3面向?qū)ο蟮脑O(shè)計(jì)//matchFace方法:將視頻單幀圖片的人臉信息與學(xué)生信息庫的當(dāng)前課堂應(yīng)到學(xué)生人臉數(shù)據(jù)進(jìn)行匹配,得到考勤記錄publicintmatchFace(Listfaces,ListsignStudentFaces){foreach(faceinfaces){FaceAttendancefaceAttendance=newFaceAttendance();if(isInUnsignStudents(face,signStudentFaces)){//若該人臉在未簽到的學(xué)生人臉集合中unsignStudents.remove(face);//從未簽到的學(xué)生人臉集合中移除Studentstudent=faceAttendance.getStudentByFace(face);//根據(jù)人臉獲取學(xué)生信息signStudents.add(student);//將該學(xué)生添加至已簽到學(xué)生集合中

}}faceAttendance.saveToAttendance(signStudents);//存儲(chǔ)到考勤信息庫

returnfaceAttendance.count();}6.3面向?qū)ο蟮脑O(shè)計(jì)(2)協(xié)作圖的精化圖6-9教師查詢考勤記錄協(xié)作圖迭代6.3面向?qū)ο蟮脑O(shè)計(jì)(3)順序圖的精化圖6-10精化后的人臉考勤用例順序圖6.4用戶界面設(shè)計(jì)

用戶界面又稱人機(jī)界面,是人與計(jì)算機(jī)之間傳遞和交流信息的媒介。用戶界面設(shè)計(jì)是一項(xiàng)涉及技術(shù)、藝術(shù)和心理學(xué)等學(xué)科交叉融合的工作,最終實(shí)現(xiàn)用戶對(duì)計(jì)算機(jī)系統(tǒng)的應(yīng)用。6.4用戶界面設(shè)計(jì)TheoMandel在1997年提出了界面設(shè)計(jì)的三條黃金規(guī)則。

(1)用戶操縱控制

允許用戶操作控制的原則:

①以不強(qiáng)迫用戶進(jìn)入不必要的或不希望的動(dòng)作的方式來定義交互

模式。

②提供靈活的交互。

③允許用戶交互可以被中斷和撤消。

④當(dāng)用戶技能級(jí)別增加時(shí),界面設(shè)計(jì)應(yīng)該變得更加流暢和高效,并

允許定制交互。

⑤使用戶與內(nèi)部技術(shù)細(xì)節(jié)隔離開來。

⑥設(shè)計(jì)應(yīng)允許用戶與出現(xiàn)在屏幕上的對(duì)象直接交互。6.4.1黃金規(guī)則6.4用戶界面設(shè)計(jì)(2)減少用戶的記憶負(fù)擔(dān)

減少用戶記憶負(fù)擔(dān)的設(shè)計(jì)原則:

①減少對(duì)短期記憶的要求。

②建立有意義的缺省。

③定義直觀的快捷方式。

④界面的視覺布局應(yīng)該基于真實(shí)世界的象征。

⑤以不斷進(jìn)展的方式揭示信息。6.4用戶界面設(shè)計(jì)(3)保持界面一致

幫助保持界面一致性的設(shè)計(jì)原則:

①允許用戶將當(dāng)前任務(wù)放入有意義的語境。

②在應(yīng)用系列內(nèi)保持一致性。

③如過去的交互模型已建立起了用戶期望,除非有迫不得已

的理由,不要改變它。6.4用戶界面設(shè)計(jì)

分析和設(shè)計(jì)用戶界面時(shí)要考慮四種不同的模型:軟件工程師創(chuàng)建的設(shè)計(jì)模型、工程師創(chuàng)建的用戶模型、終端用戶的心理模型(終端用戶對(duì)未來系統(tǒng)的假想)、系統(tǒng)實(shí)現(xiàn)后得到的實(shí)現(xiàn)模型(系統(tǒng)映象)。

這四種模型可能相差甚遠(yuǎn),界面設(shè)計(jì)人員的任務(wù)就是消除這些差距,導(dǎo)出一致的界面表示。6.4.2用戶界面設(shè)計(jì)過程6.4用戶界面設(shè)計(jì)

用戶界面的分析和設(shè)計(jì)過程是迭代的,包括四個(gè)框架性活動(dòng):用戶、任務(wù)和環(huán)境分析及建模;界面設(shè)計(jì);界面構(gòu)造;界面確認(rèn)。

用戶界面開發(fā)始于一組分析任務(wù):用戶分析、任務(wù)分析、顯示內(nèi)容分析和環(huán)境分析。6.4.2用戶界面設(shè)計(jì)過程6.4用戶界面設(shè)計(jì)(1)用戶分析:設(shè)計(jì)人員要抓住用戶的特征,發(fā)現(xiàn)用戶的需求。(2)任務(wù)分析:需要定義用戶任務(wù)和行為。(3)顯示內(nèi)容分析:界面顯示內(nèi)容是在用戶任務(wù)分析確認(rèn)后對(duì)不同數(shù)據(jù)對(duì)象進(jìn)行的描述。(4)環(huán)境分析:需要清楚界面必須操作的物理結(jié)構(gòu)和社會(huì)結(jié)構(gòu)。6.4用戶界面設(shè)計(jì)界面設(shè)計(jì)過程的步驟可以概括如下:(1)使用界面分析中獲得的信息,通過創(chuàng)建和分析用戶場(chǎng)景來定義一組界面對(duì)象和作用于對(duì)象上的動(dòng)作,為創(chuàng)建屏幕布局提供基礎(chǔ)。(2)定義導(dǎo)致用戶界面狀態(tài)發(fā)生變化的事件,并對(duì)行為建模。(3)按照最終用戶實(shí)際看到的那樣,描述每個(gè)界面狀態(tài),并進(jìn)行屏幕布局。(4)簡(jiǎn)要說明用戶如何從界面提供的信息來獲得系統(tǒng)狀態(tài)的解釋。

在這個(gè)過程中,用戶界面的設(shè)計(jì)具體內(nèi)容可能包括:系統(tǒng)啟動(dòng)封面設(shè)計(jì)、軟件框架設(shè)計(jì)、軟件按鈕設(shè)計(jì)、軟件面板設(shè)計(jì)、菜單設(shè)計(jì)、標(biāo)簽設(shè)計(jì)、圖標(biāo)設(shè)計(jì)、滾動(dòng)條設(shè)計(jì)、狀態(tài)欄設(shè)計(jì)、安裝過程設(shè)計(jì)以及產(chǎn)品包裝等。6.4用戶界面設(shè)計(jì)

目前主流的交互方式是WIMP交互界面。WIMP是窗口(Windows)、圖標(biāo)(Icon)、選單(Menu)、指針選取(PointingDevice)這4個(gè)英文單詞的縮寫,表示W(wǎng)IMP交互界面中所依賴的4種元素。6.4.3

GUI設(shè)計(jì)規(guī)則6.4用戶界面設(shè)計(jì)6.4.3

GUI設(shè)計(jì)規(guī)則

圖形用戶界面設(shè)計(jì)的基本原則是要遵循用戶需求,具體實(shí)施的原則每個(gè)機(jī)構(gòu)可能有所不同,一般都會(huì)要求遵循以下規(guī)則:

(1)一致性

(2)通用性

(3)功能性

(4)視覺組織結(jié)構(gòu)

(5)減輕短期記憶負(fù)擔(dān)

(6)預(yù)防操作錯(cuò)誤,有效反饋

(7)風(fēng)格創(chuàng)新性,鼓勵(lì)探索6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化

為了讓這些類的設(shè)計(jì)在未來能更適應(yīng)變更并減少變更帶來的副作用的傳播,在面向?qū)ο蠓椒ㄑ芯恐行纬闪巳缦禄镜脑O(shè)計(jì)原則。

(1)單一職責(zé)原則(SimpleResponsibilityPrinciple,簡(jiǎn)稱SRP)

就一個(gè)類而言,應(yīng)該僅有一個(gè)引起它變化的原因。

(2)開—閉原則(Open-ClosedPrinciple,簡(jiǎn)稱OCP)

一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。6.5.1軟件設(shè)計(jì)原則6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化

(3)里氏代換原則(LiskovSubstitutionPrinciple,簡(jiǎn)稱LSP)

一個(gè)軟件實(shí)體如果使用的是一個(gè)基類的話,那么一定適用于其

子類。應(yīng)當(dāng)盡量從抽象類繼承,而不是從具體類繼承。

(4)依賴倒置原則(DependenceInversionPrinciple,簡(jiǎn)稱DIP)

抽象不應(yīng)當(dāng)依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)當(dāng)依賴于抽象。

(5)接口隔離原則(InterfaceSegregationPrinciple,簡(jiǎn)稱ISP)

一個(gè)類對(duì)另外一個(gè)類的依賴是建立在最小的接口上,使用多個(gè)

專門的接口比使用單一的總接口要好。6.5.1軟件設(shè)計(jì)原則6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化

(6)合成/聚合復(fù)用原則(Composite/AggregateReuse Principle,簡(jiǎn)稱CARP)

在一個(gè)新的對(duì)象里面使用一些已有的對(duì)象,使之成為新對(duì)

象的一部分;新對(duì)象通過向這些對(duì)象的委派達(dá)到復(fù)用的目的。

(7)迪米特法則(LawofDemeter,簡(jiǎn)稱LoD)

一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其他對(duì)象有盡可能少的了解。6.5.1軟件設(shè)計(jì)原則6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化

軟件設(shè)計(jì)模式是為特定設(shè)計(jì)環(huán)境中重復(fù)出現(xiàn)的設(shè)計(jì)問題提供的一個(gè)解決方案,是面向?qū)ο筌浖脑O(shè)計(jì)經(jīng)驗(yàn)總結(jié)。通常一個(gè)軟件設(shè)計(jì)模式有四個(gè)基本要素:

(1)模式名稱(patternname):助記名,用來描述模式的問題、解決方案和效果。

(2)問題(problem):描述了應(yīng)該在何時(shí)使用該模式。

(3)解決方案(solution):描述了設(shè)計(jì)的組成成分,它們之間的相互關(guān)系及各自的職責(zé)和協(xié)作方式。

(4)效果(consequences):描述了模式應(yīng)用的效果及使用模式應(yīng)權(quán)衡的問題。6.5.2軟件設(shè)計(jì)模式6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化

按照設(shè)計(jì)模式目的——即反映模式是干什么的,可以將23種設(shè)計(jì)模式分成三類:

(1)創(chuàng)建性模式(creational):這類模式封裝動(dòng)態(tài)產(chǎn)生對(duì)象的過程和所使用的類的信息,解決系統(tǒng)在創(chuàng)建對(duì)象時(shí),抽象化類的實(shí)例化過程。

(2)行為性模式(behavioral):這類模式處理類和對(duì)象間的交互方式和任務(wù)分布,主要解決算法和對(duì)象之間的責(zé)任分配問題,描述對(duì)象或類以及它們之間的通信模式。

(3)結(jié)構(gòu)性模式(structural):這類模式考慮如何組合類和對(duì)象構(gòu)成較大的結(jié)構(gòu)。使用繼承來組合接口或?qū)崿F(xiàn)新類,或使用對(duì)象合成來實(shí)現(xiàn)新功能。6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化

以外觀模式(Facade)來舉例說明。

外觀模式(又稱門面模式)提供一個(gè)高層次的接口,使得子系統(tǒng)更易于使用。就如同接待員一樣,外觀模式的門面類將客戶端與子系統(tǒng)的內(nèi)部復(fù)雜性分隔開,使得客戶端只需要與門面對(duì)象交互,而不需要與子系統(tǒng)內(nèi)部的很多對(duì)象交互。圖6-11外觀模式結(jié)構(gòu)圖6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化

以智慧教室管理子系統(tǒng)的一個(gè)例子來說明外觀模式的作用。智慧教室管理子系統(tǒng)由用戶管理系統(tǒng)、教室管理系統(tǒng)、考勤管理系統(tǒng)和設(shè)備管理系統(tǒng)組成。智慧教室管理子系統(tǒng)的操作人員需要經(jīng)常審核、調(diào)配各個(gè)子系統(tǒng)的內(nèi)容。6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化圖6-12不使用外觀模式的類圖6.5面向?qū)ο筌浖O(shè)計(jì)優(yōu)化圖6-13使用外觀模式的類圖總結(jié)1.了解軟件設(shè)計(jì)的主要目標(biāo)。2.掌握有關(guān)軟件設(shè)計(jì)的基本概念。3.掌握結(jié)構(gòu)化軟件設(shè)計(jì)的基本概念。4.重點(diǎn)掌握面向?qū)ο笤O(shè)計(jì)方法。5.掌握軟件詳細(xì)設(shè)計(jì)方法。6.掌握人機(jī)交互界面設(shè)計(jì)的基本原則7.了解軟件設(shè)計(jì)模式的基本概念第7章

軟件實(shí)現(xiàn)與測(cè)試?掌握軟件質(zhì)量的概念?了解代碼規(guī)范?了解代碼重構(gòu)?理解軟件測(cè)試的相關(guān)概念和模型?理解測(cè)試自動(dòng)化?掌握幾種重要的黑盒和玻璃盒測(cè)試方法?了解測(cè)試驅(qū)動(dòng)的開發(fā)TDD?了解軟件集成方式軟件實(shí)現(xiàn)并不等同于編碼。軟件實(shí)現(xiàn)包括編碼、代碼審查、單元測(cè)試、集成測(cè)試、缺陷跟蹤和糾錯(cuò)等一系列過程。學(xué)習(xí)目標(biāo)高質(zhì)量軟件開發(fā)基本方法1代碼規(guī)范2軟件測(cè)試3測(cè)試驅(qū)動(dòng)開發(fā)TDD4集成57.1高質(zhì)量軟件開發(fā)的基本方法軟件質(zhì)量是貫穿軟件生命周期的一個(gè)極為重要的問題。(1)建立軟件過程規(guī)范

一個(gè)軟件過程定義了軟件開發(fā)中采用的方法,還包含該過程、

中應(yīng)用的技術(shù)方法和自動(dòng)化工具。(2)軟件復(fù)用

復(fù)用(Reuse)簡(jiǎn)單來說就是指“利用現(xiàn)成的東西”。早期的軟件復(fù)用主要是代碼級(jí)復(fù)用,后來逐步擴(kuò)大到需求、設(shè)計(jì)、代碼、文檔、領(lǐng)域知識(shí)、開發(fā)經(jīng)驗(yàn)、設(shè)計(jì)決策、體系結(jié)構(gòu)等與軟件產(chǎn)品相關(guān)的各方面。(3)軟件評(píng)審

軟件評(píng)審(Review)是在軟件生命周期內(nèi)所實(shí)施的對(duì)軟件本身的評(píng)審,是對(duì)軟件元素或者項(xiàng)目狀態(tài)的一種評(píng)估,以確定其是否與計(jì)劃的結(jié)果保持一致,并使其得到改進(jìn)。評(píng)審方法已經(jīng)被業(yè)界廣泛采用并取得了很好的效果,它被普遍認(rèn)為是軟件開發(fā)的最佳實(shí)踐之一。評(píng)審可以比測(cè)試更早地發(fā)現(xiàn)并消除工作成果中的缺陷,而越早消除缺陷就越能降低開發(fā)成本。7.1高質(zhì)量軟件開發(fā)的基本方法(4)軟件測(cè)試

軟件測(cè)試(SoftwareTesting)是一種實(shí)際輸出與預(yù)期輸出之間審核或者比較的過程。測(cè)試與評(píng)審的主要區(qū)別是前者要運(yùn)行軟件而后者不必執(zhí)行軟件。(5)軟件質(zhì)量保證

軟件質(zhì)量保證的目的是提供一種有效的人員組織形式和管理方法,通過客觀地檢查和監(jiān)控“過程質(zhì)量”與“產(chǎn)品質(zhì)量”,從而實(shí)現(xiàn)持續(xù)地改進(jìn)質(zhì)量。軟件質(zhì)量保證小組在項(xiàng)目開始時(shí)就一起參與建立計(jì)劃、標(biāo)準(zhǔn)和過程。7.1高質(zhì)量軟件開發(fā)的基本方法7.2代碼規(guī)范7.2.1代碼規(guī)范的重要性每一個(gè)高質(zhì)量代碼的背后,一定存在著一份優(yōu)秀的代碼規(guī)范。代碼規(guī)范是針對(duì)特定編程語言約定的一系列規(guī)則,包括開發(fā)約定、編程實(shí)踐、編程原則和最佳實(shí)踐等。代碼規(guī)范的重要性體現(xiàn)在以下幾個(gè)方面:

(1)促進(jìn)團(tuán)隊(duì)合作

(2)有效減少軟件缺陷數(shù)量、降低維護(hù)成本

(3)有助于代碼審查

(4)有助于程序員自身的成長代碼規(guī)范7.2.2常見的代碼規(guī)范代碼規(guī)范的制定往往包含命名規(guī)則、格式、控制語句、面向?qū)ο缶幊蹋∣OP)規(guī)約、集合處理、并發(fā)處理、注釋、異常處理、日志、數(shù)據(jù)庫相關(guān)規(guī)約等多個(gè)方面,部分可能的代碼規(guī)范。

1)命名規(guī)范①類名使用UpperCamelCase風(fēng)格(大駝峰形式)。例如TonyHall、XmlService、TcpUdpDeal,避免使用tonyHall、XMLService、TCPUDPDeal。②方法名、參數(shù)名、成員變量、局部變量都統(tǒng)一使用lowerCamelCase風(fēng)格(小駝峰形式)。例如localInput、getMessage()、outputUserId。7.2代碼規(guī)范③常量命名全部大寫,單詞間用下劃線隔開。例如MAX_USER_COUNT。④抽象類命名使用Abstract或Base開頭;異常類命名使用Exception結(jié)尾;測(cè)試類命名以它要測(cè)試的類的名稱開始,以Test結(jié)尾。⑤包名統(tǒng)一使用小寫,點(diǎn)分隔符之間有且僅有一個(gè)自然語義的英語單詞。例如com.baidu.map.util。⑥如果使用到了設(shè)計(jì)模式,建議在類名中體現(xiàn)出具體模式,有利于代碼閱讀者快速理解架構(gòu)設(shè)計(jì)思想。例如ProductFactory(工廠模式)、DataObserver(觀察者模式)。

7.2代碼規(guī)范2)格式規(guī)范①大括號(hào)的使用約定。如果是大括號(hào)內(nèi)為空,則寫成{}即可,不需要換行;如果是非空代碼塊則:左大括號(hào)前不換行;左大括號(hào)后換行;右大括號(hào)前換行;右大括號(hào)后還有else等代碼則不換行;右大括號(hào)后為空必須換行。②if/for/while/switch/do等保留字與左右括號(hào)之間必須加空格。③任何運(yùn)算符左右必須加一個(gè)空格。運(yùn)算符包括賦值運(yùn)算符、邏輯運(yùn)算符、加減乘除符號(hào)等。④代碼塊縮進(jìn)4個(gè)空格。⑤單行字符數(shù)不超過120個(gè),超出需要換行,換行時(shí)相對(duì)上一行縮進(jìn)4個(gè)空格。⑥方法參數(shù)在定義和傳入時(shí),多個(gè)參數(shù)逗號(hào)后邊必須加空格。7.2代碼規(guī)范(3)OOP規(guī)范(針對(duì)Java編程語言)①避免通過一個(gè)類的對(duì)象引用訪問此類的靜態(tài)變量或靜態(tài)方法,直接用類名訪問即可。②所有的覆寫方法,必須加@Override注解。③所有的相同類型的包裝類對(duì)象之間值的比較,全部使用equals方法比較。④構(gòu)造方法里面禁止加入任何業(yè)務(wù)邏輯,如果有初始化邏輯,放在init方法中。⑤類成員與方法訪問控制從嚴(yán):a.如果不允許外部直接通過new來創(chuàng)建對(duì)象,構(gòu)造方法必須是private。b.類非static成員變量并且與子類共享,必須是protected。c.類非static成員變量并且僅在本類使用,必須是private。d.類static成員變量如果僅在本類使用,必須是private。e.若是static成員變量,必須考慮是否為final。f.類成員方法只供類內(nèi)部調(diào)用,必須是private。g.類成員方法只對(duì)繼承類公開,那么限制為protected。7.2代碼規(guī)范(4)控制語句規(guī)范①在一個(gè)switch塊內(nèi),每個(gè)case或者通過break/return來終止,或者利用注釋說明程序?qū)⒗^續(xù)執(zhí)行到哪一個(gè)case為止;在每個(gè)switch塊內(nèi),都必須包含一個(gè)default語句并且放在最后,即使該語句后沒有代碼。②在if/else/for/while/do語句中必須使用大括號(hào),即使只有一行代碼,避免使用下面的形式:if(condition)statements。③循環(huán)體中的語句要考量性能,以下操作盡量移至循環(huán)體外處理,如定義對(duì)象、變量、獲取數(shù)據(jù)庫連接、不必要的try-catch操作。④當(dāng)一個(gè)條件判斷(if、while)比較復(fù)雜,請(qǐng)寫好注釋。⑤盡量少采用取反邏輯運(yùn)算符。取反邏輯不利于快速理解。例如使用if(x<365)來表達(dá)x小于365,避免使用if(!(x>=365))。7.2代碼規(guī)范(5)注釋規(guī)范(針對(duì)Java編程語言)①類、類屬性、類方法的注釋必須使用/*內(nèi)容*/格式。②所有的抽象方法(包括接口中的方法)必須要注釋、除了返回值、參數(shù)、異常說明外,還必須指出該方法做什么事情,實(shí)現(xiàn)什么功能。③方法內(nèi)部單行注釋,在被注釋語句上方另起一行,使用//注釋。方法內(nèi)部多行注釋使用/**/注釋,注意與代碼對(duì)齊。④所有的枚舉類型字段必須要有注釋,說明每個(gè)數(shù)據(jù)項(xiàng)的用途。⑤代碼修改的同時(shí),注釋也要進(jìn)行相應(yīng)的修改。⑥謹(jǐn)慎注釋掉代碼。⑦注釋力求精簡(jiǎn)準(zhǔn)確、表達(dá)到位,避免過多過濫的注釋。7.2代碼規(guī)范7.2.3代碼重構(gòu)代碼重構(gòu)通常是指在不改變代碼對(duì)外表現(xiàn)的情況下,修改代碼的內(nèi)部功能特征,從而改善軟件質(zhì)量,使程序的設(shè)計(jì)模式和架構(gòu)更趨合理,更容易被理解,提高軟件的可擴(kuò)展性和可維護(hù)性。很多人認(rèn)為重構(gòu)浪費(fèi)時(shí)間,影響項(xiàng)目進(jìn)度,其實(shí)重構(gòu)不僅可以讓代碼更加健壯,而且從長遠(yuǎn)來看,還可以加快項(xiàng)目進(jìn)度。7.2代碼規(guī)范(1)以查詢?nèi)〈R時(shí)變量:圖7-1以查詢?nèi)〈R時(shí)變量7.2代碼規(guī)范(2)搬移函數(shù)或字段:圖7-2搬移函數(shù)或字段7.2代碼規(guī)范(3)提煉類:圖7-3提煉類7.2代碼規(guī)范(4)以常量取代字面數(shù)值:圖7-4以常量取代字面數(shù)值7.2代碼規(guī)范(5)簡(jiǎn)化嵌套條件表達(dá)式:圖7-5簡(jiǎn)化嵌套條件表達(dá)式7.2代碼規(guī)范(6)使用異常替換返回錯(cuò)誤碼:圖7-6使用異常替換返回錯(cuò)誤碼7.27.3軟件測(cè)試GlenfordJ·Myers在《軟件測(cè)試的藝術(shù)》中提出了關(guān)于軟件測(cè)試的多個(gè)重要觀點(diǎn),對(duì)該領(lǐng)域產(chǎn)生了深遠(yuǎn)的影響:(1)測(cè)試是為了發(fā)現(xiàn)程序中的錯(cuò)誤而執(zhí)行程序的過程。(2)好的測(cè)試方案在于它能發(fā)現(xiàn)迄今為止尚未發(fā)現(xiàn)的錯(cuò)誤。(3)成功的測(cè)試是發(fā)現(xiàn)了至今為止尚未發(fā)現(xiàn)的錯(cuò)誤的測(cè)試。(4)測(cè)試并不僅僅是為了找出錯(cuò)誤。(5)沒有發(fā)現(xiàn)錯(cuò)誤的測(cè)試也是有價(jià)值的。

7.3.1軟件測(cè)試介紹軟件測(cè)試為了盡可能發(fā)現(xiàn)軟件中的錯(cuò)誤,提高軟件產(chǎn)品的質(zhì)量,在軟件測(cè)試的實(shí)踐中應(yīng)把握以下基本測(cè)試原則:(1)測(cè)試用例中的一個(gè)必需部分是對(duì)預(yù)期輸出或結(jié)果進(jìn)行定義。(2)程序員應(yīng)當(dāng)避免測(cè)試自己編寫的程序。(3)編寫軟件的組織不應(yīng)當(dāng)測(cè)試自己編寫的軟件。(4)應(yīng)當(dāng)徹底檢查每個(gè)測(cè)試的執(zhí)行結(jié)果。7.3軟件測(cè)試(5)測(cè)試用例的編寫不僅應(yīng)當(dāng)根據(jù)有效和預(yù)期的輸入情況,而且也應(yīng)當(dāng)根據(jù)無效和未預(yù)料到的輸入情況。(6)檢查程序是否“未做其應(yīng)該做的”僅是測(cè)試的一半,測(cè)試的另一半是檢查程序是否“做了其不應(yīng)該做的”。(7)應(yīng)避免測(cè)試用例用后即棄,除非軟件本身是一個(gè)一次性的軟件。(8)計(jì)劃測(cè)試工作時(shí)不應(yīng)默許假定不會(huì)發(fā)現(xiàn)錯(cuò)誤。(9)程序某部分存在更多錯(cuò)誤的可能性,與該部分已發(fā)現(xiàn)錯(cuò)誤的數(shù)量成正比。7.3軟件測(cè)試廣義的軟件測(cè)試必須貫穿在軟件生命周期的始終,測(cè)試對(duì)象應(yīng)該包括軟件設(shè)計(jì)開發(fā)的各個(gè)階段的內(nèi)容。狹義的軟件測(cè)試的分類,即開發(fā)階段的測(cè)試和程序測(cè)試,如下:(1)按照開發(fā)階段劃分

①單元測(cè)試

②集成測(cè)試

③系統(tǒng)測(cè)試

④確認(rèn)測(cè)試

⑤驗(yàn)收測(cè)試

7.3.2軟件測(cè)試分類7.3軟件測(cè)試(2)按照測(cè)試實(shí)施組織劃分

①開發(fā)方測(cè)試:也叫α測(cè)試

②用戶測(cè)試:也叫β測(cè)試

③第三方測(cè)試(3)按照測(cè)試與需求的關(guān)系劃分

①功能測(cè)試

②非功能測(cè)試7.3軟件測(cè)試(4)按照是否需要運(yùn)行程序劃分

①靜態(tài)測(cè)試

②動(dòng)態(tài)測(cè)試(5)按照測(cè)試技術(shù)劃分

①玻璃盒測(cè)試

②黑盒測(cè)試

③灰盒測(cè)試7.3軟件測(cè)試為了節(jié)省人力、時(shí)間或硬件資源,提高測(cè)試效率,自動(dòng)化測(cè)試往往是十分必要的。但是自動(dòng)化測(cè)試不適用于一些特殊定制型項(xiàng)目、周期很短的項(xiàng)目以及包含有復(fù)雜業(yè)務(wù)規(guī)則的項(xiàng)目,或者其涉及物理交互的部分。目前對(duì)自動(dòng)化測(cè)試?yán)斫膺€存在如下誤區(qū):(1)自動(dòng)化測(cè)試可以完成一切測(cè)試工作。(2)測(cè)試工具可適用于所有的測(cè)試。(3)測(cè)試工具能使工作量大幅降低。(4)測(cè)試工具能實(shí)現(xiàn)百分百的測(cè)試覆蓋率。(5)自動(dòng)化測(cè)試工具容易使用。

7.3.3自動(dòng)化測(cè)試7.3軟件測(cè)試自動(dòng)化測(cè)試工具有很多,其大致分類如下:(1)負(fù)載壓力測(cè)試工具(2)功能測(cè)試工具(3)玻璃盒測(cè)試工具(4)網(wǎng)絡(luò)測(cè)試工具(5)測(cè)試管理工具

7.3軟件測(cè)試測(cè)試模型將測(cè)試活動(dòng)進(jìn)行抽象,明確了測(cè)試與開發(fā)之間的關(guān)系,是軟件測(cè)試管理的重要依據(jù)。(1)V模型

7.3.4軟件測(cè)試模型單元測(cè)試集成測(cè)試系統(tǒng)測(cè)試驗(yàn)收測(cè)試編碼詳細(xì)設(shè)計(jì)概要設(shè)計(jì)需求分析圖7-7V模型7.3軟件測(cè)試(2)W模型圖7-8W模型開發(fā)組工作測(cè)試組工作詳細(xì)設(shè)計(jì)測(cè)試編碼實(shí)現(xiàn)單元測(cè)試集成測(cè)試系統(tǒng)測(cè)試驗(yàn)收測(cè)試概要設(shè)計(jì)測(cè)試需求測(cè)試模塊集成系統(tǒng)構(gòu)建系統(tǒng)安裝詳細(xì)設(shè)計(jì)概要設(shè)計(jì)需求分析7.3軟件測(cè)試(3)H模型圖7-9H模型7.3軟件測(cè)試(1)黑盒測(cè)試

①等價(jià)類劃分法等價(jià)類劃分主要解決如何選擇適當(dāng)?shù)臄?shù)據(jù)子集來代表整個(gè)數(shù)據(jù)集的問題,通過降低測(cè)試用例的數(shù)量去實(shí)現(xiàn)合理的“覆蓋”,以此來發(fā)現(xiàn)更多的軟件缺陷。例如:一個(gè)基于整數(shù)運(yùn)算的簡(jiǎn)單計(jì)算器程序。當(dāng)需要測(cè)試它是否能正確運(yùn)行時(shí),如果程序能夠正確地計(jì)算“1+1”和“2+3”的和,那么是否還有必要測(cè)試“8+9”的和,或者“80000+90000”的和呢?

7.3.5黑盒和玻璃盒測(cè)試7.3軟件測(cè)試②邊界值分析法長期的測(cè)試經(jīng)驗(yàn)告訴我們,大量的錯(cuò)誤是發(fā)生在輸入或輸出范圍的邊界上,而不是發(fā)生在輸入或輸出范圍的內(nèi)部。邊界值(BoundaryValues)分析法就是對(duì)輸入或輸出的邊界值進(jìn)行測(cè)試的一種黑盒測(cè)試方法。7.3軟件測(cè)試邊界值分析法與等價(jià)類劃分的區(qū)別為:a.邊界值分析不是從某等價(jià)類中任意選擇一個(gè)作為代表,而是使這個(gè)等價(jià)類的每個(gè)邊界都要作為測(cè)試條件。b.邊界值分析不僅要考慮輸入條件,還要考慮輸出空間產(chǎn)生的邊界情況。例如程序包含一個(gè)輸入值,其合法取值是從1到10的數(shù)字,那么顯然邊界值測(cè)試會(huì)取0和11這兩個(gè)不合法的數(shù)字,以及1和10這兩個(gè)“剛好”合法的數(shù)字,來驗(yàn)證位于輸入邊界附近的數(shù)值會(huì)不會(huì)被系統(tǒng)接受。7.3軟件測(cè)試(2)玻璃盒測(cè)試玻璃盒測(cè)試關(guān)注的是測(cè)試用例執(zhí)行的程度或覆蓋程序邏輯結(jié)構(gòu)的程度。玻璃盒測(cè)試的測(cè)試方法有代碼檢查、靜態(tài)分析法、邏輯覆蓋法、基本路徑測(cè)試法、符號(hào)測(cè)試等。邏輯覆蓋包括語句覆蓋、判定覆蓋、條件覆蓋、判定/條件覆蓋、條件組合覆蓋。publicvoidRoutine(intA,intB,intX){ if(A>1&&B==0) X=X+B; if(A==2||X>1) X=X*A;}7.3軟件測(cè)試①語句覆蓋最初的邏輯覆蓋想法是將程序中的每條語句至少執(zhí)行一次,即語句覆蓋。這雖然是玻璃盒測(cè)試中較弱的覆蓋標(biāo)準(zhǔn),但是同樣也具備了初步檢查出錯(cuò)誤的能力。要實(shí)現(xiàn)語句覆蓋,上述程序只需要一個(gè)測(cè)試用例,(A=5,B=0,X=8)就可以遍歷到每一條語句。②判定覆蓋判定覆蓋(也稱分支覆蓋)相對(duì)語句覆蓋而言是較強(qiáng)一些的邏輯覆蓋。判定覆蓋要求必須編寫足夠的測(cè)試用例,使得每一個(gè)判斷都至少有一個(gè)為真和為假的輸出結(jié)果。也就是說,每條判定路徑都必須至少遍歷一次。在小程序Routine中,滿足判定覆蓋的兩個(gè)測(cè)試用例可以是(A=3,B=0,X=3)和(A=1,B=0,X=1)。7.37.4測(cè)試驅(qū)動(dòng)開發(fā)TDD

測(cè)試驅(qū)動(dòng)開發(fā)(TestDrivenDevelopment,簡(jiǎn)稱TDD)是敏捷開發(fā)中的一項(xiàng)核心實(shí)踐和技術(shù)。測(cè)試驅(qū)動(dòng)開發(fā)的基本思想就是在開發(fā)功能代碼之前,先編寫測(cè)試代碼,然后只編寫使測(cè)試通過的功能代碼,從而以測(cè)試來驅(qū)動(dòng)整個(gè)開發(fā)過程的進(jìn)行。這種開發(fā)方式與傳統(tǒng)開發(fā)方式剛好相反。在明確要開發(fā)某個(gè)功能后,TDD首先要思考如何對(duì)這個(gè)功能進(jìn)行測(cè)試,并快速編寫出針對(duì)該功能的測(cè)試代碼,測(cè)試代碼只定義這個(gè)功能的外部接口,而非具體的實(shí)現(xiàn)細(xì)節(jié)。7.4.1TDD基本概念測(cè)試驅(qū)動(dòng)開發(fā)TDD7.4.2TDD實(shí)施步驟開始成功增加一個(gè)測(cè)試運(yùn)行一個(gè)測(cè)試改變一些代碼運(yùn)行這個(gè)測(cè)試失敗失敗成功圖7-10TDD開發(fā)過程7.4測(cè)試驅(qū)動(dòng)開發(fā)TDD7.4.3基于單元測(cè)試的TDD實(shí)例(Java)需求描述:通過一個(gè)矩形的長和寬來計(jì)算其面積和周長。(1)打開Eclipse。(2)創(chuàng)建RectangleTest類。publicclassRectangleTestextendsjunit.framework.TestCase{}7.4測(cè)試驅(qū)動(dòng)開發(fā)TDD(3)根據(jù)需求描述,在RectangleTest中創(chuàng)建矩形對(duì)象,分別添加計(jì)算矩形面積和周長的測(cè)試方法,以及長和寬分別為2和3的具有正確輸入和輸出的測(cè)試用例。publicclassRectangleTestextendsjunit.framework.TestCase{Rectanglerectl=newRectangle();publicvoidtestArea(){assertEquals(6,rectl.Area(2,3));}publicvoidtestPerimeter(){assertEquals(10,rectl.Perimeter(2,3));}}7.4測(cè)試驅(qū)動(dòng)開發(fā)TDD(4)運(yùn)行測(cè)試用例,編譯失敗,錯(cuò)誤提示為缺少Rectangle類的定義。于是增加Rectangle類的定義,創(chuàng)建Rectangle.java文件。publicclassRectangle{publicintArea(intlength,intwidth){return0;}publicintPerimeter(intlength,intwidth){return0;}}(5)編譯成功,但是運(yùn)行這個(gè)程序,斷言顯示測(cè)試用例失敗,因?yàn)橛?jì)算面積和周長的方法的返回值始終為0。7.4測(cè)試驅(qū)動(dòng)開發(fā)TDD(6)先“傻瓜式”地修改兩個(gè)函數(shù)的返回值,改為return6和return10。重新編譯、運(yùn)行,斷言結(jié)果為通過。publicclassRectangle{publicintArea(intlength,intwidth){return6;}publicintPerimeter(intlength,intwidth){return10;}}7.4測(cè)試驅(qū)動(dòng)開發(fā)TDD

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論