第4周小组做业:WordCount优化

第4周小组做业:WordCount优化

1、基本任务:代码编写+单元测试

小组github 地址 

https://github.com/iwannastay/WcPro/tree/stage3/stage3 git


 

PSP表格

PSP2.1 PSP阶段 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 60
Estimate 估计任务须要多少时间 30 60
Development 开发 180 240
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
  合计 340 540

接口设计

  • 接口描述

    我负责的模块是单词排序,即由外部传入各单词词频,模块将其排序并输出。github

  • 设计思路

    因为是数目未知的数值元素,故能够将输入输出接口定义为vector<int>数组;数组的排序能够选择多种算法如插入排序、合并排序、基数排序、桶排序、快速排序等,因为处理的文本可能极大,对算法性能要求较高,故此选择随机快排实现该接口;然而本程序包含额外的条件——1.单词词频同步输出,2.同频的单词按照字母顺序排列,故不能仅用单词的词频做为接口,而需将单词自己的索引输入,因为外部数据结构未知,故直接引用单词自己做为参数,即便用vector<pair<string,int>>做为模块外部接口。算法

  • 实现过程

    因为外部存储结构使用map<pair<string,int>>,且map的实现机制是红黑树的平衡二叉树,不支持索引操做,为了便于排序,需进行map->vector的转换。编程

//词频排序
void WcFile::RankProcess()
{
    int count = 0, size = Word_List.size();
    map<string, int>::iterator iter = Word_List.begin();
    while (iter != Word_List.end())
    {
        Rank_List.push_back(*iter);
        iter++;
    }
    //随机快排
    Random_Quick_Sort(Rank_List, 0, Rank_List.size() - 1);
}

 

    排序算法实现数组

 

//快速排序分划程序
int WcFile::Partition(vector<pair<string, int>> &A, int p, int q)
{
    auto x = A[p];
    int i = p;
    for (int j = p + 1; j <= q; j++)
    {
        if (ComparePriority(A[j],x))
        {
            i = i + 1;
            Swap(A[i], A[j]);
        }
    }
    Swap(A[p], A[i]);
    return i;
}

//随机化快速排序分划程序
int WcFile::Random_Partition(vector<pair<string, int>> &A, int p, int q)
{
    int i = rand() % (q - p) + p;
    Swap(A[i], A[p]);
    return Partition(A, p, q);
}

//随机化快速排序
void WcFile::Random_Quick_Sort(vector<pair<string, int>> &A, int p, int q)
{
    if (p < q)
    {
        int i = Random_Partition(A, p, q);
        Random_Quick_Sort(A, p, i - 1);
        Random_Quick_Sort(A, i + 1, q);
    }
}

//交换元素
void WcFile::Swap(pair<string, int> &m, pair<string, int> &n)
{
    pair<string, int> tmp;
    tmp = m;
    m = n;
    n = tmp;
}

//首字母排序
bool WcFile::ComparePriority(pair<string, int> &m, pair<string, int> &n)
{
    if (m.second != n.second)
        return m.second > n.second ? true : false;
    else
        return m.first < n.first ? true : false;
}

 


测试设计

  保证设计的测试用例应至少覆盖函数中全部的可执行语句,同时主要空数组、最差状况、词频排序、字母排序、二者混合等各类状况设计测试用例。数据结构

 


单元测试

试用测试脚本进行单元测试,过程以下:框架

单元测试效果较好,测试结果均正确,且排序性能较高。dom


 

小组贡献

  咱们小组齐心合力,共克难关,积极讨论并指出其余组员的问题,最终得出个人小组贡献分为0.3。函数

 

2、扩展任务:静态测试

1.代码规范

  我选择了代码风格规范中:断行与空白的{}行、分行、命名、下划线、大小写;工具

      代码设计规范中:函数、gogo、错误处理、断言(在其余大型程序中经常使用,在本次做业中未使用)、析构函数、new和delete、类型继承。

  个人编程习惯与以上附录中所述规范大体相同,少量部分持不一样意见。而在其余如代码审查等重要规范上有待提升。


 

2.同组分析

  我分析了组员17027的代码,缩进、断行风格整洁,命名简单明了,逻辑清晰易读,较好地遵照了设计规范。

//导入文件
bool WcFile::LoadFile(const char *_filename)
{
    File_Name = _filename;
    File_Stream.open(File_Name);
    if (!File_Stream)
    {
        cout << "Fail to open the source file:" << File_Name << endl;
        system("exit");
    }
    return true;
}

//保存结果
void WcFile::SaveResult()
{
    File_Stream.close();
    File_Stream.open(ResultFile_Name);
    if (!File_Stream)
    {
        cout << "Fail to open the result file." << endl;
        system("exit");
    }

    for (int i = 0; i < 100 && i < Rank_List.size(); i++)
        File_Stream << Rank_List[i].first << "\t" << Rank_List[i].second << endl;
    File_Stream.close();
}

 


3.静态代码检查工具

  使用Visual Studio 2015 内置检测工具,可在微软官方网站https://www.visualstudio.com/zh-hans/downloads/下载


 

4.扫描结果

以上问题说明代码存在数据丢失以及内存泄漏等问题,应尽可能少使用格式自动转换。


5.小组代码问题说明

  • 数据结构较为冗杂,下降了程序性能,应减小没必要要的类的使用;
  • 异常处理不够全面,应该覆盖大部分的异常状况,以便于检查。

 

 

3、高级任务:性能测试和优化 

  设计,评审,优化

  选择10kb,20kb,50kb大小的txt文件进行测试,程序处理时长以下:

      输入输出:13ms,14ms,16ms

      单词统计:740ms,1500ms,3800ms

      词频排序:11ms,12ms,22ms

  单词统计时间与文件大小呈线性相关,其余两个模块占比较小,故程序性能主要受到文件大小影响。组内共同对代码结构和细节进行详细审查,整理获得优化思路以下:

    1.将统计部分中的大小写转换提取成单个模块,能大幅度减小转换函数的调用次数,随着文件越大效果越明显;

    2.增长单次提取字符数量,减小主框架循环次数;

    3.将字母排序单独提取成一个模块,即将排序算法中的比较函数替换为纯数值比较,减小内存开销,减小排序时间,最后再遍历数组从新调整同频单词顺序,此方法在数组较大时可以提升程序效率。


 

  附加题

   使用MFC开发环境,设计具备图形界面的文件选择工具。

 


  小结

  经过基本任务、扩展任务、到高级任务的完成以及中间遇到的许多困难,体现出了软件测试对于软件开发的重要性。在开发过程当中,使用静态测试工具实时地检测本身的代码,能够改正本身不良的编程习惯,更能防患于未然,减小出现bug的可能;对本身的模块进行单元测试,能够保障本身代码的正确性,更是对其余开发成员和整个任务的负责,使软件开发可以一步一个脚印地稳定开展;对性能的分析与测试,能使软件的质量进一步提升,同事能总结开发经验,使本身设计的模块更加高效。

相关文章
相关标签/搜索