四則運算之GUI


四則運算之GUI

Coding克隆地址:https://git.coding.net/lvgx/pair_programming.git
 

目錄:

一、前言

二、計划時間——PSP

三、接口設計

四、接口實現

五、性能分析

六、單元測試

七、異常處理

八、模塊設計

九、模塊對接

十、她

十一、結對編程思考

十二、實際時間——PSP

 


一、前言

首先我很感謝我的隊友——呂國馨(www.cnblogs.com/lvgx/p/8733486.html),謝謝她清明假期仍在認真的敲代碼,放棄自己休息的時間。第二我要感謝一位大佬,當我對GUI沒絲毫頭緒時,大佬的一篇博客給了我啟發。

下面帶上大佬博客:www.cnblogs.com/mafx/p/8536796.html

二、計划PSP

 

PSP

任務內容

計划時間(min)

Planning

計划

30

     Estimate

    估計這個任務需要多少時間,並規划大致工作步驟

30

Development

開發

35*60+25

    Analysis

    需求分析

60

    Design Spec

    生成文檔

0

    Design Review

    設計復審

2*60

    Coding Standard

    代碼規范

10

    Design

    具體設計

12*60

    Coding

    具體編碼

2*8*60

    Code Review

    代碼復審

4*60

    Test

    測試

15

Reporting

報告

5.5*60

    Test Report

    測試報告

60

    Size Measurement

    計算工作量

30

   Postmortem& ProcessImprovement Plan

    事后總結, 並提出過程改進計划

4*60

尤其在編程GUI時候,花費了大量的時間。

三、接口設計

1、Information Hiding

信息隱藏是指在設計和確定模塊時,對於用不到的信息是禁止訪問的。封裝:比如求圓的面積,你只需要調用getArea(r);即可,不需要知道他是如何運行的。宏定義:可以用宏定義對信息進行隱藏,比如#define PI 3.1415926。當你需要使用π時,直接使用PI就行了,你不需要知道PI的具體值。

我們的設計:進行模塊化設計,通過對函數的封裝。只可以調用方法,不可以改變內部變量。界面化設計:你只需要知道如何使用它,不需要知道界面內部是如何運行的。變量設置為私有的。

2、Interface Design, Loose Coupling

 接口設計和低耦合是相輔相成的,接口化設計能大大降低程序的耦合度,低耦合一定離不開接口化設計。個人理解:接口化設計就是模塊化設計,讓不同方法放入到不同類中,並且使得各個類相互獨立,減少關聯性。低耦合和接口化設計差不多,使得各個模塊之間減少依賴性,從而提高容錯率。

我們的設計:我們已經盡我最大的努力,來進行模塊化設計了,比如界面生成和算式生成是相互獨立的,優先級判斷、計算結果和算式生成又是相互獨立的。但是我們的程序還有很多不足,比如界面設計,我們的五個界面都在同一個函數中實現的。原本我們盡力讓他們在不同函數中,但是在繼承時過程中,總是出現錯誤,最后我們還是放棄了。Java的繼承我們還要再學一學。

四、接口實現

 本次界面程序一共用到了9個類,14個函數,此9個類的調用關系如下圖:

我們此界面程序的關鍵之處在於監聽器的運用,大概用到了3個監聽器,分別是復選框監聽器、按鈕監聽器、文件監聽器,本打算使用時間監聽器,來計算當前時間和用時,但是發現可以直接調用java中自帶的類,方便起見,就沒有使用。代碼的獨特之處在於:界面套界面。即是亮點又是污點,亮點在於方法簡單,實現方便,容易掌握(靈感來源於:www.cnblogs.com/mafx/p/8536796.html)。同時這也是一個不好之處,導致程序無法分解,耦合度太高,后期維護困難。

五、性能分析

說句實話,自我感覺能完成這個項目就很不錯了,還要什么性能優化呀。。。但是我們已經盡力優化性能了,比如挺高代碼利用率了。比如Puanduan類,和Yunsuan類,我們把它兩生成兩個類,其他類直接調用,減少代碼長度。盡量減少內存開支,比如不定義數組,改用容器,因為數組的每個存儲單元利用率不高。一般數組我們都往大的開,因為怕其不夠用,但是這種方法會導致,大量內存單元沒有被利用。題目要求最大生成10000到題目,如果你開10000大小的數組,當我們只生成10道題時,會有99990個內存沒被利用。我們還盡量減少循環套循環,從而減少時間的消耗。

如何性能分析?百度上說是,進行溢出測試,將代碼進行死循環,使得當CPU達到100%時,查看時間,時間越短,性能越好。

我們的分析方法是:通過JProfiler,進行性能分析。

總體分析圖:包括CPU,內存,線程等等。

性能分析過程:

我們用三組數據分別對三個主要函數進行時間上的測試:

函數一:Algorithm函數,他用時最短,只用了11640微妙,且30%的原因在於文本的輸入與輸出,這是無法避免的,所以未進行優化。

函數二:Algorithm2函數,用時37789微妙,此函數30%的用時是在調用JiSuan函數上,JiSuan的用時主要是在出棧上,也是無法避免的。

函數三:Algorithm1函數用時最長,用時60390微妙,此函數用時主要是循環,此函數中有一個三重循環和大量二重循環,導致了時間過長。從圖像也可以看出,橙色占的比例接近90%(橙色代表,阻礙與消耗,不是正常運行程序時間)。

 

性能優化:對於循環過多的Algorithm1函數,進行了優化,減少了幾個循環,之后,我們又減少了大量循環,因為老師的需求降低(中間過程可以保證不再范圍之內,這使得我們的程序,更加簡潔)

 

可見,時間明顯降低!

我們還對界面程序的性能進行分析,和優化,改進,文件也通過ps.close();進行關閉,按F4再一次查看,內存占用率明顯減少,文件也都關閉了,但是仍有內存沒釋放,我們會繼續改進的,性能分析結果如下。

六、單元測試

測試單元代碼:

 1 public class Test {
 2     
 3     private static int n=10;
 4     private static int m1=1;
 5     private static int m2=50;
 6     private static int o=4;
 7     private static int c=0;    
 8     private static String s="11+(43-(35-(14+26)))";
 9     
10     public static void main(String[] args) {
11         // TODO Auto-generated method stub
12         Command.main(null);// 主界面
13         System.out.println(Algorithm.Algorithm(n, m1, m2, c, o)); //生成題目函數一
14         System.out.println(Algorithm.Algorithm(n, m1, m2, c, o)); //生成題目函數二
15         System.out.println(Algorithm.Algorithm(n, m1, m2, c, o)); //生成題目函數三
16         GUI.main(null);  // 中文界面
17         GUI1.main(null); // 英文界面
18         //JiSuan.JiSuan(s);
19     }
20 
21 }

我們對9個類進行了測試:采用結合或者獨立的測試方法,來分別觀察其代碼覆蓋率。(表中分別為:函數名、覆蓋率、執行行數、錯過行數、總行數)

第一組數據:

Command.java:這是一個語言選擇窗口。

Algorithm.java:是一個可以生成加減乘除並且帶有括號式子的類。

JiSuan.java:是一個可以計算式子,並且返回結果的類。

Panduan.java:是一個判斷運算符優先級的類

測試結果如下:

第二組數據:

GUI.java和GUI1.java:分別是生成漢語出題窗口和英語出題窗口、漢語上傳文件和英語上傳文件的窗口。測試結果如下:

第三組數據:

YunSuan.java:一個進行簡單加減乘除運算的類。測試結果如下:

第四組數據:

Algorithm1.java:是一個能生成乘除不帶括號和不帶乘除不帶括號式子的類。測試結果如下:

Algorithm2.java:是一個生成不帶乘除帶括號式子的類。測試結果如下:

 

總體來說,代碼覆蓋率為:91.47%

七、異常處理

 異常處理一:就是對輸入出題數、運算符個數、范圍等進行判斷,判斷其是否合法或者超出其范圍。(只展示了,出題數的代碼,其他雷同)

 1 try {
 2     n1 = Integer.parseInt(n.getText());
 3     if (n1 <= 0 || n1 > 10000) {
 4         n.setText("n的范圍不在[1,10000]內,請重新輸入");
 5         return;
 6     }
 7     flag0 = 1;
 8 } catch (Exception a) {
 9     n.setText("n的格式不合法,請重新輸入!");
10 }

對應場景:

異常處理二、文件異常處理

1 try {
2     ps = new PrintStream("result.txt");// 生成文件
3     System.setOut(ps);
4 } catch (Exception e) {
5     System.out.println("文件生成錯誤");// 提示
6 }

對應場景:

點擊出題時,如果文件生成錯誤,將不再生成。

異常處理三:文件過濾

1 FileNameExtensionFilter filter = new FileNameExtensionFilter("war", "xml", "txt", "doc", "docx");

對應場景:

只能找到此格式的文件,其他格式文件,都被過濾了。

異常處理四:編碼異常

1 InputStreamReader read = new InputStreamReader(new FileInputStream(f), "UTF-8");

對應場景:

只能處理UTF-8文件,要不會出現亂碼。

異常處理五:用戶不存在異常

如果你沒有注冊,即文件中沒你的用戶信息,會報用戶不存在異常。

 1 int flag = yanZheng(user.getText(), password.getText());
 2 if (flag == 1) {
 3     GUI.main(null);
 4 } else if (flag == 0) {
 5     user.setText("密碼錯誤!");
 6     return;
 7 } else {
 8     user.setText("賬號不存在!");
 9     return;
10 }

對應場景:

 

  異常處理六:用戶和密碼不匹配

即當用戶存在時,但是密碼輸入和注冊時的不同時,會報密碼錯誤。代碼如上:

對用場景:

  異常處理七:用戶已存在

即當注冊過程中,如果該用戶已存在,會報用戶已存在錯誤。

1 int temp = yanZheng(user.getText(), password.getText());
2 if(temp==0||temp==1)
3 {
4     user.setText("賬號已存在,請重新注冊!");
5     return ;
6 }

對應場景:

異常處理八:注冊信息不合法

注冊時,對賬號和密碼有一定限制,當超出限制時,會報錯。

 1 try {
 2     int user1 = Integer.parseInt(user.getText());
 3     if (user1 <= 0 || user1 >= 1000000) {
 4         user.setText("用戶名多余6位,或者不合法!");
 5         return;
 6     }
 7 } catch (Exception a) {
 8     user.setText("賬號有多余字符(只能是數字),請重新注冊!");
 9     return;
10 }
11 try {
12     int password1 = Integer.parseInt(password.getText());
13 } catch (Exception a) {
14     user.setText("密碼有多余字符(只能是數字),請重新注冊!");
15     return;
16 }

  為了方便起見,限制有點嚴格,必須是數字字符串,而且不能超過6位,其實不太合理,但是程序實現很簡單。

對應場景:

八、模塊設計

1、首先先設計一個語言選擇功能,可以進行語言選擇,通過按鈕和調用函數來實現。

 1 private JButton jcChina = new JButton("中文");//兩個按鈕,分別生成兩種不同語言的界面
 2 private JButton jcEnglish = new JButton("English");//可以用一個數組,存入多種語言,實現多語言轉化
 3 jcChina.addActionListener(new ActionListener() {//按鈕監聽器,為了實現中文界面
 4     @Override
 5     public void actionPerformed(ActionEvent e) {
 6         GUI.main(null);
 7     }
 8 });
 9 jcEnglish.addActionListener(new ActionListener() {//按鈕監聽器,為了實現英文界面
10     @Override
11     public void actionPerformed(ActionEvent e) {
12         GUI1.main(null);
13     }
14 });

2、然后進行出題界面設計,此界面就是簡單的GUI界面設計。

 1 JPanel p1 = new JPanel();
 2 p1.setLayout(new GridLayout(4, 2, 5, 5));
 3 p1.add(new JLabel("出題數[1,10000]:"));
 4 p1.add(n);
 5 p1.add(new JLabel("數值左邊界[1,100]:"));
 6 p1.add(m1);
 7 p1.add(new JLabel("數值右邊界[50,1000]:"));
 8 p1.add(m2);
 9 p1.add(new JLabel("運算符數[1,10]:"));
10 p1.add(o);

3、然后進行上傳文件的界面設計,此界面可以直接調用,java中已經有了。

1 JFileChooser chooser = new JFileChooser();
2 chooser.setMultiSelectionEnabled(true);
3 // 過濾文件類型 
4 FileNameExtensionFilter filter = new FileNameExtensionFilter("war", "xml", "txt", "doc", "docx");
5 chooser.setFileFilter(filter);

4、然后設計答題界面設計,此界面和出題界面類似,但是調用方法不同,在下面我會講到。

 1 JPanel panel2 = new JPanel();
 2 JTextField text = new JTextField(10);
 3 panel2.setLayout(new GridLayout(3, 2, 5, 5));
 4 label.setText(addProblem());
 5 panel2.add(label);
 6 panel2.add(new JLabel("/*為了美觀*/"));
 7 panel2.add(new JLabel("請輸入答案:"));
 8 panel2.add(text);
 9 panel2.add(jbnext);
10 panel2.add(jbsubmit);

5、統計頁面設計,內容設計,改用調用list實現。

1 JPanel panel = new JPanel();
2 panel.add(new JLabel(
3         "做題總數: " + size + " " + "  正確數:" + rightAnswer + "  用時(S):" + (t2 - t1) / 1000));
4 setLayout(new GridLayout(100, 1, 5, 5));
5 for (int i = 0; i < size; i++) {
6     panel.add(new JLabel(list.get(i)));
7 }
8 resultFrame.add(panel);

九、模塊對接

1、語言選擇功能

 

相當於主函數,它通過按鈕調用GUI和GUI1類

2、出題功能

它也是通過按鈕調用做題界面和上傳界面。

 

 

3、做題功能

通過下一題按鈕進行判斷和再次出題,通過按鈕調用統計界面。

 

4、統計和計時

最終頁面,不進行調用。代碼如下:

 

5、上傳文件及解析

代碼如下:

 

調用提交和下一題按鈕,代碼和上面一樣,但是會有一個上傳成功的提示,代碼如下:

 6、用戶注冊和登錄功能

沒有注冊的用戶必須注冊后才能進入程序進行答題和出題界面。

通過按鈕對模塊之間進行連接。

十、她

我們原本打算做前端,即Web的四則運算程序,而且她已經完成了,前端開發,如圖:

 

但是由於我不會套頁,即不能和后端連起來。所以最后放棄了Web項目,改做GUI。讓她白做了一場,慚愧(就當給她個機會,讓她練習練習前端知識了,嘻嘻)。

1、她:優點:技術強;聰明;樂觀。缺點:做事不認真。

2、我:優點:認真,上進,創造性思維強。缺點:模塊化思維欠缺。

十一、對編程思考

結對編程有好處:

一、可以減輕兩個人的壓力。

二、相互學習、相互指正。

三、增強兩個人的關系,增強合作能力、增強代碼理解能力。

四、分工明確,增加辦事效率。

結對編程有壞處:

一、如果交流不到位,那所做的項目將會功虧一簣。比如這次項目,因為我們前期交流沒有到位,導致Web項目進行到一半,就進行不下去了。

二、兩個人各做各的,導致后期兩者的項目結合比較困難。

三、兩人的分工不均勻,比如技術強的人可能做得就比較多,技術差可能就會抱大腿。

四、要花費大量時間進行交流和解釋項目,畢竟代碼不好看懂。

十二、實際PSP

 

PSP

任務內容

完成時間(min)

Planning

計划

60

     Estimate

    估計這個任務需要多少時間,並規划大致工作步驟

60

Development

開發

45*60

    Analysis

    需求分析

45

    Design Spec

    生成文檔

0

    Design Review

    設計復審

3*60

    Coding Standard

    代碼規范

15

    Design

    具體設計

12*60

    Coding

    具體編碼

3*8*60

    Code Review

    代碼復審

4*60

    Test

    測試

60

Reporting

報告

9*60

    Test Report

    測試報告

0

    Size Measurement

    計算工作量

60

   Postmortem& ProcessImprovement Plan

    事后總結, 並提出過程改進計划

8*60

 

 


 

對於附加功能多語言,我們實現了兩種語言的轉換,其實可以通過數組實現多種語言轉換,也可以通過我這種方法實現,即在生成一個界面。這種方法的好處在於簡單,壞處在於代碼比較多,還瑣碎。

對於附加功能多用戶,我們的這個GUI界面程序,可以多人下載,多人使用,實現多用戶同時在線。用戶必須登陸后才能進行上傳題目、出題、做題等功能的使用,還可以統計用戶人數。

參考網站:

www.cnblogs.com/mafx/p/8536796.html  //基本的GUI語法

https://zhidao.baidu.com/question/184288577.html  //上傳文件語法

https://www.cnblogs.com/happyzm/p/6530384.html //覆蓋率教程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM