標籤:
一、實驗內容
1. 初步掌握單元測試和TDD
2. 理解並掌握物件導向三要素:封裝、繼承、多態
3. 初步掌握UML建模
4. 熟悉S.O.L.I.D原則
5. 瞭解設計模式
二、實驗要求
1.沒有Linux基礎的同學建議先學習《Linux基礎入門(新版)》《Vim編輯器》 課程
2.完成實驗、撰寫實驗報告,實驗報告以部落格方式發表在部落格園,注意實驗報告重點是運行結果,遇到的問題(工具尋找,安裝,使用,程式的編輯,調試,運行等)、解決辦法(空洞的方法如“查網路”、“問同學”、“看書”等一律得0分)以及分析(從中可以得到什麼啟示,有什麼收穫,教訓等)。報告可以參考範飛龍老師的指導
3. 嚴禁抄襲,有該行為者實驗成績歸零,並附加其他懲罰措施。
4. 請大家先在實驗樓中的~/Code目錄中用自己的學號建立一個目錄,代碼和UML圖要放到這個目錄中,中沒有學號的會要求重做,然後跟著下面的步驟練習。
三、實驗步驟
(一)單元測試
(1) 以“百分制轉五分制”為例,介紹三種代碼
(1)虛擬碼 (2)產品代碼 (3)測試代碼
需求:我們要在一個MyUtil類中解決一個百分製成績轉成“優、良、中、及格、不及格”五級製成績的功能。
//虛擬碼:
百分制轉五分制:
如果成績小於60,轉成“不及格”
如果成績在60與70之間,轉成“及格”
如果成績在70與80之間,轉成“中等”
如果成績在80與90之間,轉成“良好”
如果成績在90與100之間,轉成“優秀”
其他,轉成“錯誤”
//產品代碼:
翻譯好的MyUtil.java如下:
public class MyUtil{
public static String percentage2fivegrade(int grade){
//如果成績小於60,轉成“不及格”
if (grade < 60)
return "不及格";
//如果成績在60與70之間,轉成“及格”
else if (grade < 70)
return "及格";
//如果成績在70與80之間,轉成“中等”
else if (grade < 80)
return "中等";
//如果成績在80與90之間,轉成“良好”
else if (grade < 90)
return "良好";
//如果成績在90與100之間,轉成“優秀”
else if (grade < 100)
return "優秀";
//其他,轉成“錯誤”
else
return "錯誤";
}
}
//測試代碼:
public class MyUtilTest {
public static void main(String[] args) {
// 百分製成績是50時應該返回五級制的“不及格”
if(MyUtil.percentage2fivegrade(50) != "不及格")
System.out.println("test failed!");
else
System.out.println("test passed!");
}
}
(2) TDD(Test Driven Devlopment, 測試驅動開發)
先寫測試代碼,然後再寫產品代碼的開發方法叫“測試驅動開發”(TDD)。TDD的一般步驟如下:
- 明確當前要完成的功能,記錄成一個測試清單
- 快速完成編寫針對此功能的測試案例
- 測試代碼編譯不通過(沒產品代碼呢)
- 編寫產品代碼
- 測試通過
- 對代碼進行重構,並保證測試通過(重構下次實驗練習)
- 迴圈完成所有功能的開發
基於TDD,我們不會出現過度設計的情況,需求通過測試案例表達出來了,我們的產品代碼只要讓測試通過就可以了。 Java中有單元測試工具JUnit來輔助進行TDD,我們用TDD的方式把前面百分制轉五分制的例子重寫一次,體會一下有測試載入器支援的開發的好處。 開啟Eclipse,單擊File->New->Java Project建立一個TDDDemo的Java項目:我們在TDDDemo項目中,把滑鼠放到項目名TDDDemo上,單擊右鍵,在彈出的菜單中選定New->Source Folder建立一個測試目錄test,我們把滑鼠放到test目錄上,單擊右鍵,在彈出的菜單中選定New->JUnit Test Case建立一個測試案例類MyUtilTest,
我們增加第一個測試案例testNormal,注意測試案例前一定要有註解@Test,測試案例方法名任意,輸入以下代碼:
import org.junit.Test;
import junit.framework.TestCase;
public class MyUtilTest extends TestCase {
@Test
public void testNormal() {
assertEquals("不及格", MyUtil.percentage2fivegrade(55));
assertEquals("及格", MyUtil.percentage2fivegrade(65));
assertEquals("中等", MyUtil.percentage2fivegrade(75));
assertEquals("良好", MyUtil.percentage2fivegrade(85));
assertEquals("優秀", MyUtil.percentage2fivegrade(95));
}
}
輸入完畢
紅叉說明代碼存在語法錯誤,原因很簡單,MyUtil類還不存在,類中的percentage2fivegrade方法也不存在,我們在TDDDemo的src目錄中建立一個MyUtil的類,並實現percentage2fivegrade方法
現在測試代碼沒有語法錯誤了,我們把滑鼠放到MyUtilTest.java上,單擊右鍵,選擇Run as->JUnit Test
測試結果出現了一個綠條(green bar),說明測試通過了。
TDD的編碼節奏是:
- 增加測試代碼,JUnit出現紅條
- 修改產品代碼
- JUnit出現綠條,任務完成
(二)物件導向三要素
(1)抽象
(2)封裝、繼承與多態
- 步驟:
用UML中的類圖來描述類Dog,首先在實驗樓的環境中開啟shell,在命令列中輸入umbrello,開啟UML建模軟體umbrello;
先單擊工具列上的類表徵圖,再在class diagram(類圖)中單擊一下,會彈出一個聖誕框,輸入類名Dog;
把滑鼠放到Dog類上,單擊右鍵,選擇Properties,在彈出的對話方塊中的Display中去掉Public Only選項;
把滑鼠放到Dog類上,單擊右鍵,選擇New->Attribute,在彈出的對話方塊中的填好Type,Name,並選好Visibility;
把滑鼠放到Dog類上,單擊右鍵,選擇New->Operation,在彈出的對話方塊中的填好Type,Name,並選好Visibility。
在UML 裡,一個類的屬效能顯示它的名字,類型,初始化值,屬性也可以顯示private,public,protected。 類的方法能顯示它們的方法名,參數,傳回型別,以及方法的private,public,protected屬性。其中:
- +表示public
- #表示 protected
- -表示 private
- (三)設計模式初步
(1)S.O.L.I.D原則
物件導向三要素是“封裝、繼承、多態”,任何物件導向程式設計語言都會在文法上支援這三要素。如何藉助抽象思維用好三要素特別是多態還是非常困難的,S.O.L.I.D類設計原則是一個很好的指導:
- SRP(Single Responsibility Principle,單一職責原則)
- OCP(Open-Closed Principle,開放-封閉原則)
- LSP(Liskov Substitusion Principle,Liskov替換原則)
- ISP(Interface Segregation Principle,介面分離原則)
- DIP(Dependency Inversion Principle,依賴倒置原則)
(四)練習
1使用TDD的方式設計關實現複數類Complex。
2.實驗報告中統計自己的PSP(Personal Software Process)時間
步驟 |
耗時 |
百分比 |
需求分析 |
1h |
10% |
設計 |
1h |
10% |
代碼實現 |
2h |
20% |
測試 |
1h |
10% |
分析總結 |
1h |
10% |
3. 實現要有虛擬碼,產品代碼,測試代碼。
4.總結單元測試的好處
四、實驗代碼
備忘:建立檔案夾儲存代碼最後的
(一)三種代碼
一、虛擬碼
二、測試碼
三、產品代碼
(二)、物件導向的三要素
五、練習題
一、使用TDD的方式設計關實現複數類Complex。
//虛擬碼
//複數類
類有虛部實部
複數的加法運算
複數的減法運算
複數的乘法運算
複數的除法運算
//產品代碼
public class ComplexDemo {
// main方法
public static void main(String[] a) {
Complex b = new Complex(2, 5);
Complex c = new Complex(3, -4);
System.out.println(b + "+" + c + "=" + b.add(c));
System.out.println(b + "-" + c + "=" + b.minus(c));
System.out.println(b + "*" + c + "=" + b.multiply(c));
System.out.println(b + "/" + c + "=" + b.divide(c));
}
}
// Complex類
class Complex {
private double m;// 實部
private double n;// 虛部
public Complex(double m, double n) {
this.m = m;
this.n = n;
}
// add
public Complex add(Complex c) {
return new Complex(m + c.m, n + c.n);
}
// minus
public Complex minus(Complex c) {
return new Complex(m - c.m, n - c.n);
}
// multiply
public Complex multiply(Complex c) {
return new Complex(m * c.m - n * c.n, m * c.n + n * c.m);
}
// divide
public Complex divide(Complex c) {
double d = Math.sqrt(c.m * c.m) + Math.sqrt(c.n * c.n);
return new Complex((m * c.m + n * c.n) / d, Math.round((m * c.n - n * c.m) / d));
}
public String toString() {
String rtr_str = "";
if (n > 0)
rtr_str = "(" + m + "+" + n + "i" + ")";
if (n == 0)
rtr_str = "(" + m + ")";
if (n < 0)
rtr_str = "(" + m + n + "i" + ")";
return rtr_str;
}
}
//測試代碼
public static ComplexTest{
public static void main(String[] args){
class Complex {
private double m;// 實部
private double n;// 虛部
public Complex(double m, double n) {
this.m = m;
this.n = n;
}
public String toString() {
String rtr_str = "";
if (n > 0)
rtr_str = "(" + m + "+" + n + "i" + ")";
if (n == 0)
rtr_str = "(" + m + ")";
if (n < 0)
rtr_str = "(" + m + n + "i" + ")";
return rtr_str;
}
}
}
}
二、實驗報告中統計自己的PSP(Personal Software Process)時間
步驟 |
耗時 |
百分比 |
需求分析 |
1h |
14.2% |
設計 |
1。5h |
21。4% |
代碼實現 |
2h |
28.6% |
測試 |
1.5h |
21.4% |
分析總結 |
1h |
14.2% |
六、實驗中遇到的問題及解決辦法1、在實驗一中,由於網路不穩定,經常出現卡網、斷網的情況,在做測試3代碼的時候由於時間不夠又不小心錯過延時只能重新再做。剛開始測試代碼運行不出來,後來發現只有當虛擬碼和測試代碼同時存在時才能運行。 在進行產品代碼調試的時候,第一次assertEquals出現問題,後來又重新做了一遍,發現是TextCase填寫錯誤。2、在實驗二中,shell不知道如何開啟,後來請教了同學才順利的完成了實驗。
七、實驗總結及體會 本次實驗比起第一次實驗我有了很大的突破,更加熟練的運用了虛擬機器。單元測試對我的協助也很大,更加突破了自己,在遇到問題的時候自己學會了一步一步的反覆調試解決,敢於嘗試的同時也培養了自己的恒心和耐心,對TDD這種具有一定難度的代碼有了認識和瞭解。物件導向的三要素之前在視頻中學習過,通過這次實驗又溫習鞏固了一遍,更好的掌握和運用這方面的知識。在以後的實驗中,我也會按照老師黑出的步驟先需求分析,再設計,不能急於求快的一味編寫代碼。 通過這次實驗,我更敢於去編寫代碼了,並且打牢了運用虛擬機器的基礎知識,在學習編程的過程中,更培養了自己持之以恒的品質。 綠色通道: 好文要頂 關注我 收藏該文與我聯絡
實驗二 Java物件導向程式設計