第四次个人作业--结对编程

Github项目地址:点击这里

合作同学作业地址:https://www.cnblogs.com/slothph/p/11643877.html 

小伙伴的学号:201731062323

1.PSP表格

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

 30

 40

· Estimate

· 估计这个任务需要多少时间

 30

 40

Development

开发

1300

 1250

· Analysis

· 需求分析 (包括学习新技术)

 90

 80

· Design Spec

· 生成设计文档

 60

 50

· Design Review

· 设计复审 (和同事审核设计文档)

 60

 70

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

 20

 20

· Design

· 具体设计

 300

 280

· Coding

· 具体编码

 350

 300

· Code Review

· 代码复审

 120

 130

· Test

· 测试(自我测试,修改代码,提交修改)

 300

 320

Reporting

报告

120

 125

· Test Report

· 测试报告

 40

 45

· Size Measurement

· 计算工作量

 20

 20

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

 60

 60

 

合计

 1450

 1415

2.解题思路

  在看到这道题之后因为我个人不是很懂C#,很少用,我和大家可能比较不一样,一开始就在分析题中给的条件。我是在弄懂到底什么是命令行程序。我去CSDN上看了一些简单的C#命令行介绍,自己敲了一两个命令行程序,才弄懂命令行程序是如何传参,接下来才开始专注这一道题。

  因为题中说不考虑汉字,这个减轻了很大的难度,从英文的字符数字出发,根据题中提供英文字母:A-Z,a-z;字母数字符号:A-Z,a-z,0-9我们两个人很快就想到了用正则表达式去匹配题目中所给的各个条件。

  在统计字符这个问题上我们想到的是使用正则表达式中的“/S”——匹配任何非空白字符,但是这个会匹配不到那些符号,比如空格,逗号等等。通过看博客,发现“[S| ]”可以完美解决这个问题。其中一个比较简单的是统计行数,在txt文件中如果不按enter键换行,则会一直在一行里面,所以只需要匹配到enter键则可以检测到行数。

2.2程序流程图

 

2.2如何体现“Design by Contract”、“Information Hiding”、 “Interface Design”、 “Loose Coupling”等原则

  • Design By Contract(契约式设计):

  按照某种规定对一些数据等作出约定,如果超出约定,程序将不再运行。一个契约设计,就是约束了某个方法调用的要求、以及返回的承诺。那么,设计在正确的输入下,能够得到正确的输出,否则程序将报错。

  • Information Hiding(信息隐藏)

  在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是不可访问的。

  • Interface Design(接口设计):

  对接口的名字,功能,接口与接口间的继承关系进行设计;好的接口设计可以增强代码可读性,易用性,可更改性。

  用规范的命名来设计接口的名字,对接口与接口之间的关系进行具体的设计,避免了接口的混乱。

  • Loose Coupling (松耦合)

  软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。

  通过增加接口,根据方法功能增加分类的方式实现松耦合

3.部分代码实现

3.1统计字符串中所有字符总数

 public class CountWord
    {
        /// <summary>
        /// 统计字符串中所有字符总数
        /// </summary>
        /// <param name="text">要统计字符数的字符串</param>
        /// <returns>字符总个数</returns>
        public int charactersNum(string text)
        {
            int ch = 0;
            //S——匹配任何非空白字符(除了空格、换行、制表符等的任何字符)
            //|——匹配二选一
            ch = Regex.Matches(text, @"[S| ]").Count;
            return ch;
        }
    }

3.2统计字符串中所有单词总数

public class CountCharacters
    {
        /// <summary>
        /// 统计字符串中所有单词总数
        /// </summary>
        /// <param name="text">要统计的字符串</param>
        /// <returns>返回一个储存了所有单词的集合包括重复的单词</returns>
        public int wordsNum(List<string> wordString)
        {
            return wordString.Count();
        }
    }

3.3统计字符串中文本行数

public class LineNum
    {
        /// <summary>
        /// 统计字符串中文本行数
        /// </summary>
        /// <param name="text">要统计的字符串</param>
        /// <returns>字符串行数</returns>
        public int linesNum(string text)
        {
            int lines = 0;
            //
——匹配硬回车符
            lines = Regex.Matches(text, @"
").Count + 1;
            return lines;
        }
    }

3.4词组-m统计函数

public class Cizu
    {
        public string numOfCiZu(List<string>wordString, int m)
        {
            
            List<String> ans = new List<string>();
            Dictionary<string, int> letter = new Dictionary<string, int>();
            string ret = null;
            int len = wordString.Count();
            for (int i = 0; i <= len - m; i++)
            {
                string tem = null;
                for (int j = i; j < i + m; j++)
                {
                    //if (j >= len-m)
                    //    break;
                    tem += wordString[j] + " ";
                }
                if (tem != null)
                    ans.Add(tem);
            }
            foreach (string str in ans)
            {
                if (letter.ContainsKey(str))
                {
                    letter[str]++;
                }
                else
                {
                    letter[str] = 1;
                }
            }
            foreach (KeyValuePair<string, int> kvp in letter)
            {
                ret += kvp.Key + ": " + kvp.Value.ToString() + "
";
            }


            return ret;
        }
    }

4.代码复审部分

由于有一部分我们两个是分开写的,虽然在之前就已经规定了代码的命令格式,但是在代码的规范性上我们还有很大的不足,我们在对代码进行改进之后发现了很多复审后的好处

  • 对变量命名进行了规范,让程序更加易读懂
  • 在复审过程中我们对对方的代码更能更加熟悉
  • 发现了一些逻辑错误
  • 降低了后期的维护

代码规范:

C#代码规范:https://wenku.baidu.com/view/b5be911b6bd97f192279e9bd.html

5.单元测试部分

对于我们的函数我们分别测试了数字符个数与数单词个数的两个函数。通过Assert.Arequal断言函数进行测试,手动提前输入好一段有效的英文,用Assert.Arequal函数提前设定好结果,测试发现结果无误,代码通过

测试通过:

 6.异常处理

命令行程序的异常处理:对输入的字符进行判断

 

 窗口程序的异常处理:

  

7.效能测试及性能改进

这是第一个版本在未进行代码改进

 

 函数时间图

 

 改进后:

 

 

9.描述结对的过程

  我们两个找了没课的星期三的下午,找了一个明理楼的教室。在进行题目的分析之后,我们进行了初步的程序方向敲定。根据PSP表格预估时间,讨论出项目需求,代码设计。首先我们完成代码的自省,然后交换代码进行复审,最后将类、方法等汇总生成可运行文件进行实例测试、单元测试,并不断提交进度,最后撰写博客。结对现场如下:

10.附加功能的实现

第一张图演示在“提交内容框”没有输入的情况下,提示输入字符

第二张图演示在执行指令的时候,指令有误的情况下会提示你“指令有误,重新输入”。

 

第三张图演示的是在所有指令正确的情况下,点击“执行指令”按钮后,可以看到右边输出框输出我们想要的内容

第四张图演示导出功能,点击输出框下的“结果导出”,程序会提示“已成功导出”

 

 可以从该文件名和txt文件内容看出,这个文件就是我们输出框导出的内容。

总结:

  通过这次的作业可以说是收获满满,上一次作业对单元测试还有点不懂但是这一次让我加深了对单元测试的理解。在编码的过程中,由于要用到正则表达式,所以对这方面的知识也进行了一次复习,然后就是最后一步命令行转用户界面程序,我上一次用窗口应用还是在大一的暑假,最开始我都没觉得我可以把程序转为GUI模式,但是自己慢慢尝试,过程中虽然也有不少问题,但是我发现还是可以做下去,最后还是完成了这一次的工作。真的是一次成就感满满的作业啊。完结❀✿✿ヽ(°▽°)ノ✿

 

原文地址:https://www.cnblogs.com/cyh0813/p/11645041.html