第四周做業之wcPro核心模塊的實現

第四周做業之wcPro核心模塊的實現

1、基本任務:代碼編寫+單元測試

小組github地址

https://github.com/SkateCloud/wcProjava

PSP表格

PSP2.1 PSP階段 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 30 60
Estimate 估計任務須要多少時間 30 60
Development 開發 120 180
Analysis 需求分析 20 30
Design Spec 生成設計文檔 20 30
Design Review 設計複審 20 30
Coding Standard 代碼規範 30 10
Design 具體設計 30 50
Coding 具體編碼 30 40
Code Review 代碼複審 30 40
Test 測試 50 10
Reporting 報告 70 240
Test Report 測試報告 30 100
Size Measurement 計算工做量 20 60
Postmortem 總結 20 80
  合計 280 480

接口設計

  • 接口描述

本人負責的是核心模塊,即對輸入的文件讀取後的結果進行單詞排序並存入List結構中準備輸出git

  • 設計思路

對從輸入模塊獲取的數據存入hashMap中,再將Map結構轉變成List結構進行單詞排序,爲輸出模塊準備接口github

  • 實現過程

先使用Map<String, Integer>結構對輸入模塊傳來的數據進行存儲.編程

HashMap<String,Integer> words = new HashMap<>();
        String str = readFile(args[0]);
        {
            int state = 0;
            int beginIndex = -1;
            for (int i = 0; i <= str.length(); ++i) {
                char ch = i == str.length() ? ' ' : str.charAt(i);
                boolean isWordChar = ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '-';
                if (state == 0 && isWordChar && ch != '-') {
                    beginIndex = i;
                    state = 1;
                } else if (state == 1 && !isWordChar) {
                    String word = str.substring(beginIndex, i).toLowerCase();
                    words.put(word, words.getOrDefault(word, 0) + 1);
                    state = 0;
                }
            }
        }

因爲外部存儲機構使用的是Map.Entry<String, Integer>,不便於排序等操做,因此將map轉化爲List結構,進行排序數組

List<Map.Entry<String, Integer>> list = new ArrayList<>();
        list.addAll(words.entrySet());
        list.sort((lhs, rhs) -> {
            int cmp = -lhs.getValue().compareTo(rhs.getValue());
            if (cmp != 0) return cmp;
            else return lhs.getKey().compareTo(rhs.getKey());
        });

測試設計

保證設計的測試用例應至少覆蓋函數中全部的可執行語句,同時主要空數組、最差狀況、詞頻排序、字母排序、二者混合等各類狀況設計測試用例。多線程

附件2截圖

單元測試

使用測試腳本進行單元測試,過程以下模塊化

測試腳本運行截圖

單元測試效果良好,沒有報錯函數

小組貢獻

咱們小組齊心合力, 攻克難關,積極討論,指出問題,我認爲個人小組貢獻分是0.4工具

二.擴展任務:靜態測試

1. 代碼規範

我選擇了代碼風格規範中:斷行與空白的{}行、分行、命名、下劃線、大小寫;性能

代碼設計規範中:函數、錯誤處理、new和delete、類型繼承,模塊化

個人編程習慣與以上附錄中所述規範大體相同。而在其餘如代碼審查等重要規範上有待提升。

2. 同組分析

我分析了本身的代碼,縮進、斷行風格整潔,命名簡單明瞭,邏輯清晰易讀,但在代碼設計規範上,模塊化不足,不易於進行團隊的coding工做,常常在git操做上發生衝突.

最後決定將團隊代碼進行整合重構,重構任務由我完成,故最終貼出組長的重構代碼

public class wordcount {
    public static void main(String[] args) {
        long t1 = System.currentTimeMillis();
        new wordcount().start(args);
        long t2 = System.currentTimeMillis();
        long dt = t2 - t1;
        System.out.println(("Elapsed " + dt + "ms"));
    }

    private void start(String[] args) {
        HashMap<String,Integer> words = new HashMap<>();
        String str = readFile(args[0]);
        {
            int state = 0;
            int beginIndex = -1;
            for (int i = 0; i <= str.length(); ++i) {
                char ch = i == str.length() ? ' ' : str.charAt(i);
                boolean isWordChar = ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ch == '-';
                if (state == 0 && isWordChar && ch != '-') {
                    beginIndex = i;
                    state = 1;
                } else if (state == 1 && !isWordChar) {
                    String word = str.substring(beginIndex, i).toLowerCase();
                    words.put(word, words.getOrDefault(word, 0) + 1);
                    state = 0;
                }
            }
        }

        List<Map.Entry<String, Integer>> list = new ArrayList<>();
        list.addAll(words.entrySet());
        list.sort((lhs, rhs) -> {
            int cmp = -lhs.getValue().compareTo(rhs.getValue());
            if (cmp != 0) return cmp;
            else return lhs.getKey().compareTo(rhs.getKey());
        });

        try (FileWriter fout = new FileWriter("result.txt")) {
            int maxsz = Math.min(list.size(), 100);
            for (int i = 0 ; i < maxsz; ++ i) {
                Map.Entry<String, Integer> item = list.get(i);
                fout.write(item.getKey());
                fout.write(' ');
                fout.write(item.getValue().toString());
                if (i != maxsz - 1)
                    fout.write('\n');
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    private String readFile(String path) { // 讀文件
        try {
            byte[] encoded = Files.readAllBytes(Paths.get(path));
            return new String(encoded, "UTF-8");
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

}

3. 靜態代碼檢查工具

使用的是IDEA的插件Ant Build中的檢錯功能
Ant Build是一個Java自動化生成工具,其檢錯功能用來檢查類或者jar文件,用來發現可能的問題。檢測完成以後會生成一份詳細的報告,藉助這份報告能夠找到潛在的bug.

檢測範圍

  • 常見代碼錯誤,序列化錯誤
  • 可能致使錯誤的代碼,如空指針引用
  • 國際化相關問題:如錯誤的字符串轉換
  • 可能受到的惡意攻擊,如訪問權限修飾符的定義等
  • 多線程的正確性:如多線程編程時常見的同步,線程調度問題。
  • 運行時性能問題:如由變量定義,方法調用致使的代碼低效問題

4. 掃描結果

掃描結果

檢測結果在右上角,能夠看出僅有少許警告,根據IDEA紅線標註可發現大可能是聲明方式不是按照目前使用的java標準,沒有發生內存泄露等問題.

5. 小組代碼問題說明

  • 因爲進行了整合重構,因此模塊化程度下降,不易維護,但程序執行效率上升
  • 異常處理的不夠全面,應該覆蓋大部分的一場狀況,以便於檢查與調試

三. 高級任務:性能測試和優化

設計,評審,優化

選擇10kb,50kb,182kb大小的txt文件進行測試,程序處理時長以下:

      輸入輸出:1ms,1ms,2ms

      單詞統計:20ms,150ms,540ms

      詞頻排序:6ms,8ms,10ms

  單詞統計時間與文件大小呈線性相關,其餘兩個模塊佔比較小,故程序性能主要受到文件大小影響。組內共同對代碼結構和細節進行詳細審查並與其餘組程序對比,整理獲得以下觀點:

    1.整合重構是正確的,不只增長了代碼的可讀性和規範性,還大幅增長了程序的性能

    2.將大部分功能模塊彙集在一個類方法中,雖然會致使代碼耦合度增高,不易於團隊維護和再開發,可是減小了模塊間相互調用的開銷和隨之產生的內存開銷

小結

經過基本任務、擴展任務、到高級任務的完成以及中間遇到的許多困難,體現出了軟件測試對於軟件開發的重要性。在開發過程當中,使用靜態測試工具實時地檢測本身的代碼,能夠改正本身不良的編程習慣,更能防患於未然,減小出現bug的可能;對本身的模塊進行單元測試,能夠保障本身代碼的正確性,更是對其餘開發成員和整個任務的負責,使軟件開發可以一步一個腳印地穩定開展;對性能的分析與測試,能使軟件的質量進一步提升,同事能總結開發經驗,使本身設計的模塊更加高效。

相關文章
相關標籤/搜索