第4周小组作业:WordCount优化

第4周小组作业:WordCount优化

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

小组github 地址 

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


 

PSP表格

PSP2.1PSP阶段预估耗时(分钟)实际耗时(分钟)
Planning计划3060
Estimate估计任务需要多少时间3060
Development开发180240
Analysis需求分析2030
Design Spec生成设计文档2030
Design Review设计复审2030
Coding Standard代码规范3010
Design具体设计3050
Coding具体编码3040
Code Review代码复审3040
Test测试5010
Reporting报告70240
Test Report测试报告30100
Size Measurement计算工作量2060
Postmortem总结2080
 合计340540

接口设计

  • 接口描述

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

  • 设计思路

    由于是数目未知的数值元素,故可以将输入输出接口定义为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;
}

 


测试设计

  保证设计的测试用例应至少覆盖函数中所有的可执行语句,同时主要空数组、最差情况、词频排序、字母排序、两者混合等各种情况设计测试用例。

 


单元测试

试用测试脚本进行单元测试,过程如下:

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


 

小组贡献

  我们小组齐心协力,共克难关,积极讨论并指出其他组员的问题,最终得出我的小组贡献分为0.3。

 

二、扩展任务:静态测试

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.小组代码问题说明

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

 

 

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

  设计,评审,优化

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

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

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

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

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

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

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

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


 

  附加题

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

 


  小结

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

 

转载于:https://www.cnblogs.com/iwannastay/p/8724015.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值