• WorldCount 结对项目


    合作者:201631062129,201631062501

    队友博文

    代码地址

    本次作业链接地址



    一、PSP

    PSP2.1 PSP阶段 预估耗时(分钟) 实际耗时(分钟)
    Panning 计划 100 150
    .Estimate .估计这个任务需要多少时间 120 200
    Development 开发 3000 3600
    .Aanlysis .需求分析(包括学习新技能) 60 40
    .Design Spec .生成设计文档 100 180
    .Design Review . 设计复审 (和同事审核设计文档) 30 40
    .Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 40
    .Design .具体设计 200 300
    .coding .具体编码 2500 3000
    .Test . 测试(自我测试,修改代码,提交修改) 240 300
    Reporting 报告 60 100
    .Test Report . 测试报告 60 70
    .Size Measurement .计算工作量 60 60
    .Postmortem & Process Improvement Plan .事后总结, 并提出过程改进计划 30 40
    合计 3100 3750


    二、代码互审

    • 队友:
      • 代码中硬编码地方较多,程序的扩展性不强;
      • 代码缺少注释,功能实现完成,但是缺少编程规范。
      • 程序流程和结构清晰
    • 自己:
      • 程序结构清晰但流程复杂,代码注释少且不够清晰;
      • 多出使用接口,提高了程序的扩展性,但是增加了系统的复杂度;
      • 想的太多,程序边界分不清楚。


    二、设计过程

    • 主要类:
      • WorldCount类。该类主要用于接受用户的输入和处理结果输出。
      • Analyzer类。该类主要用于分析参数和处理参数的缺省,错误等问题。
      • Processor类。该类接受Analyzer类消息,并根据消息执行相应的功能。
      • Format类。该类接受Processor类的处理结果,并对结果进行格式化处理。
      • Command,抽象类。所有选项(如:-s、-w等)对用的功能执行类都要继承该类。
      • Filter,接口。对用户输入的选项和参数进行过滤,判断是否是合格的数据。

    • UML简图

    - **代码实现:** - CommandA:统计源文件空行数、注释行数和代码数: - 点击查看 - CommandE:停词功能: - 点击查看 - CommandS:递归分析: - 点击查看
    - **运行效果:** - 选项:-s - 点击查看 - 选项:-a - 点击查看
    - <span id="et">选项:-e</span>
        - <a style="text-decoration: none" href="#es">点击查看</a>
    


    三、总结:

    准确的说在这次对结编程项目中,我们并没有完全遵循结对编程的要求。原因是第一次使用结对编程的方法没有经验,不知怎么进行;并且在先前的项目中,我们两人的编程语言不同,程序设计不同;还有两个人的空闲时间不一样。最终结对编程的方式不是很成功。
    但是在这次项目中,我也体会到了交流的好处。在项目的最后阶段,我与同伴各自交流自己的程序设计。俗话说,一个苹果交换一个苹果最后还是得到了一个苹果;但是思想交换得到了思想确是大于二的。在不断地交流中,我学到了很多,同时也迸发出来新的思想。遗憾的是这次结对编程不是那么的成功。(;′⌒`)(╯︵╰)
    


    四、图片:


    - 选项:-s - 点击返回 - 文件: ![](https://img2018.cnblogs.com/blog/1489868/201810/1489868-20181017194610708-1010250324.png) - 结果: ![](https://img2018.cnblogs.com/blog/1489868/201810/1489868-20181017194628562-1035003202.png)
    - 选项:-a - 点击返回 - 文件: ![](https://img2018.cnblogs.com/blog/1489868/201810/1489868-20181017194645482-685781478.png) - 结果: ![](https://img2018.cnblogs.com/blog/1489868/201810/1489868-20181017194657710-461173570.png)
    - 选项:-e - 点击返回 - 文件: ![](https://img2018.cnblogs.com/blog/1489868/201810/1489868-20181017194949345-277780938.png) - 结果: ![](https://img2018.cnblogs.com/blog/1489868/201810/1489868-20181017194959156-1104058122.png)

    五、部分代码

    //统计空行数
    	public boolean blankLine(String line) {
    		if(line.length() > 1) {  //字符串是否大于0
    			return false;
    		}
    		//判断“{”或“}”独占一行
    		if(line.length() == 1) {
    			char ch = line.charAt(0);
    			if(ch != '}' && ch != '{') {
    				return false;
    			}
    		}
    		return true;
    	}
    	
    	//统计注释行数
    	public int annotationLine(String line, int annotationStatus) {
    		char[] chars = line.toCharArray();
    		boolean leftQuotation = false;
    		
    		if(annotationStatus == annotation_start) {
    			for(int i = chars.length - 1; i > 0; --i) {
    				if(chars[i] == '/') {  //判断字符串是否存在“/”
    					if(chars[i - 1] == '*') { //判断在“/”前面是否存在“*”
    						return annotation_end;  //返回当前注释部分统计结束
    					}
    				}
    			}
    			return annotation_start;  //返回注释统计开始
    		}
    		
    		//注释统计中间过程
    		for(int i = 1; i < chars.length; ++i) {
    			if(chars[i] == '"') {  //防止双引号里的转义字符
    				leftQuotation = !leftQuotation;
    			}else if(chars[i] == '/'){
    				if(!leftQuotation) {
    					if(chars[i - 1] == '/'){
    						return annotation_end;
    					}
    				}
    			}else if(chars[i] == '*'){  // 判断是否是多行注释
    				if(!leftQuotation) {
    					if(chars[i - 1] == '/') {
    						i ++;
    						for(int j = chars.length - 1; j > i; --j) {
    							if(chars[j] == '/') {
    								if(chars[j - 1] == '*') {
    									return annotation_end;
    								}
    							}
    						}
    						return annotation_start;
    					}
    				}
    			}
    		}
    		return annotation_none;
    	}
    	
    	//统计代码行数
    	public boolean codeLine(String line) {
    		
    		if(line.length() > 2) {
    			if((line.charAt(line.length() - 1) != '/') && (line.charAt(line.length() - 2) != '*')) {
    				return true;
    			}else {
    				if(line.charAt(0) != '/' && line.charAt(1) != '*') {
    					return true;
    				}
    			}
    		}
    		return false;
    	}
    	
    	
    	@Override
    	public Status execute() {
    		int annotationState = annotation_end;
    		
    		Data dataf = (Data)(this.getProcessor().getPool().getData(Option.option_f));
    		String[] strings = (String[])dataf.getValue(true);
    		
    		for(int i = 0; i < strings.length; ++i) {
    			String temp = strings[i].trim();
    			
    			if(blankLine(temp)) {
    				blankLines ++;
    				continue;
    			}
    			
    			if((annotationState = annotationLine(temp, annotationState)) != annotation_none) {
    				annotatinLines ++;
    				if(annotationState == annotation_start) {
    					if(annotationStartCount > 0) {
    						continue;
    					}
    					annotationStartCount ++;
    				}else if(annotationStartCount == annotation_end){
    					annotationStartCount = 0;
    				}
    			}
    			
    			if(codeLine(temp)) {
    				codeLines++;
    				continue;
    			}
    			
    		}
    		
    		return Status.OVER;
    	}
    

    @Override
    	public Status execute() {
    		
    		if(regex == null) {
    			return Status.OVER;
    		}
    		messages.clear();  //清空CommandE对象的数据存储器
    		//获取CommandF的对象的数据存储器
    		Data dataf = (Data)(this.getProcessor().getPool().getData(Option.option_f));
    		String[] messBuiders = (String[])dataf.getValue(true);  //获取数据的值
    		StringBuilder builder = new StringBuilder("");
    		
    		
    		//使用正则表达式除去停用词,再添加到本对象的数据存储器中
    		for(int i = 0; i < messBuiders.length; ++i) {
    			String temp = messBuiders[i];
    			String[] mess = temp.toString().split(regex);
    			
    			for(int j = 0; j < mess.length; ++j) {
    				builder.append(mess[j]);
    			}
    			messages.add(builder.toString());
    			builder.delete(0, builder.length());
    		}
    		
    		return Status.OVER;
    	}
    

    //递归读取文件,类似树的先序遍历
    	private Status fileRecurseRead() {
    		int count = 0;
    		File[] files = innerFiles.files;  
    		
    		while(innerFiles != null){  //递归读取文件结束标志
    			while(innerFiles.index < files.length) {  //判断当前文件的子文件是否读完
    				if(files[innerFiles.index].isDirectory()) {
    					File[] filesTemp = files[innerFiles.index ++].listFiles();
    					if(filesTemp.length > 0) {  //判断是否存在子文件
    						InnerFile inFile = new InnerFile();
    						//交换节点
    						inFile.files = filesTemp;
    						inFile.parent = innerFiles; 
    						innerFiles = inFile;
    						
    						files = filesTemp;
    					}
    				}else {
    					if(count < capacity) {
    						count++;
    						//把递归到的文件当作参数传给CommandF对象
    						commandF.addArgument(files[innerFiles.index ++].getPath());
    					}else {
    						return Status.PAUSE;  //文件暂停
    					}
    				}
    			}
    			
    			//放回到上一个文件
    			innerFiles = innerFiles.parent;
    			if(innerFiles != null) {
    				files = innerFiles.files;
    			}
    		}
    		return Status.OVER;  //文件递归完毕
    	}
    
  • 相关阅读:
    python升级安装后的yum的修复
    leetCode 47.Permutations II (排列组合II) 解题思路和方法
    MySQL源代码解读
    MySQL快速建立测试表
    MySQL登陆小问题
    MySQL查看当前用户、存储引擎、日志
    【博客编辑工具】
    mysql5.7执行sql语句出现only_full_group_by错误
    mysql查询出来的某一列合并成一个字段
    动态生成多选框
  • 原文地址:https://www.cnblogs.com/guilinyunya/p/9800347.html
Copyright © 2020-2023  润新知