WordCount扩展实现——结对编程
2018-10-16 22:09 1987kong 阅读(271) 评论(0) 编辑 收藏 举报合作者:
201631062221,201631062514
地址:
本次作业地址:
https://edu.cnblogs.com/campus/xnsy/2018Systemanalysisanddesign/homework/2188
正文:
1.PSP表格:
2.互审代码情况:
审查的罗博伦的WordCount的基础功能实现代码。
CommandScanner类:这个类的注释较少,代码比较冗杂。
myFunction类:逻辑比较清楚,但可以优化一下逻辑,减少内存的开辟,代码复用性可以提高一下,可以抽象出相近的一些方法。
CommandScanner类:这个类的注释较少,代码比较冗杂。
myFunction类:逻辑比较清楚,但可以优化一下逻辑,减少内存的开辟,代码复用性可以提高一下,可以抽象出相近的一些方法。
我发现,在最初的基础功能实现逻辑上,我们两个都会出现的问题是,完全忽略掉了面向对象的几大设计原则,没有考虑到整个系统的扩展性,
因此,在实现扩展功能的时候,我们花费了较多的时间去调整整个项目的结构。
3.设计过程:
4.代码说明:
逻辑处理类

1 public class Main { 2 public static File outFile; 3 public static File stopFile; 4 public static File inputFile; 5 6 /* 7 * 用于标记是否输入了相关文件 8 */ 9 public static boolean inputFileFlag = false; 10 public static boolean outFileFlag = false; 11 public static boolean stopFileFlag = false; 12 public static boolean operateFileTypeFlag = false; 13 14 /* 15 * 相关功能类 16 */ 17 18 public static BaseCount baseCount = new BaseCount();; 19 public static ExtendCount extendCount = new ExtendCount(baseCount); 20 public static FileOutputer fileOutputer = new FileOutputer(baseCount, 21 extendCount); 22 public static CommandGetter commandGetter; 23 24 public static String[] commands; 25 26 public Main(String[] commands) { 27 // TODO Auto-generated constructor stub 28 this.commands=commands; 29 } 30 31 public static void originalMain() { 32 commandGetter = new CommandGetter(commands); 33 34 /* 35 * 获取是否输入相应的文件 36 */ 37 inputFileFlag = commandGetter.setInputFile();// 标识是否输入源操作文件 38 outFileFlag = commandGetter.setOutFile();// 标识是否指定输出文本文件 39 stopFileFlag = commandGetter.setStopFile();// 标识是否输入停用词文件 40 operateFileTypeFlag = commandGetter.setOperateFileType();// 标识是否输入批量操作文件的类型 41 42 /* 43 * 得到相关文件 44 */ 45 outFile = commandGetter.getOutFile(); 46 inputFile = commandGetter.getInputFile(); 47 stopFile = commandGetter.getStopFile(); 48 49 try { 50 if (inputFile.exists()) { 51 chooiseCommand(inputFile); 52 } else { 53 System.out.println("输入的操作源文件不存在!"); 54 } 55 manageScommand(); 56 } catch (IOException e) { 57 // TODO Auto-generated catch block 58 e.printStackTrace(); 59 } 60 61 } 62 63 /** 64 * 65 * 管理基本的操纵命令,根据不同的命令调用不同的方法 66 * 67 * @param targetFile 68 * 操作源文件 69 * @throws IOException 70 */ 71 public static void chooiseCommand(File targetFile) throws IOException { 72 73 if (inputFileFlag) { 74 for (String str : commandGetter.getCommandStrings()) { 75 switch (str) { 76 case "-c": 77 baseCount.countChar(targetFile); 78 break; 79 case "-l": 80 baseCount.countLine(targetFile); 81 break; 82 case "-w": 83 baseCount.countWord(targetFile); 84 break; 85 case "-a": 86 extendCount.countEveryLine(targetFile); 87 // 加入统计代码行数、空行数、注释行数的方法 88 break; 89 case "-e": 90 if (stopFileFlag) { 91 if (stopFile.exists()) { 92 extendCount.afterIgoreWordsCount(stopFile, 93 targetFile); 94 } else { 95 System.out.println("输入的停用词文件不存在!"); 96 } 97 } else { 98 System.out 99 .println("-e 必须与停用词文件名同时使用,且停用词文件必须紧跟在-e参数后面,不允许单独使用-e参数。"); 100 } 101 break; 102 default: 103 break; 104 } 105 } 106 manageOcommand(); 107 108 } else { 109 System.out.println("请输入源文件"); 110 } 111 } 112 113 /** 114 * 115 * 判断命令行中是否存在输出指令以及指定输出的文本文件,并作出相应的回应 116 * 117 * @throws IOException 118 */ 119 public static void manageOcommand() throws IOException { 120 if (commandGetter.checkOcommand()) { 121 if (outFileFlag) { 122 fileOutputer.outputFile(outFile); 123 } else { 124 System.out 125 .println("-o 必须与文件名同时使用,且输出文件必须紧跟在-o参数后面,不允许单独使用-o参数!"); 126 } 127 } else { 128 fileOutputer.outputFile(new File("result.txt")); 129 } 130 } 131 132 /** 133 * 判断输入的命令行中是否存在递归处理该目录下相关文件的指令,并作出相应的回应 134 * 135 * @throws IOException 136 */ 137 public static void manageScommand() throws IOException { 138 boolean sCommandExist = commandGetter.checkScommand(); 139 if (sCommandExist) { 140 if (operateFileTypeFlag) { 141 // 加入递归处理文件的方法 String fileType 142 143 ArrayList<File> files; 144 String fileType = commandGetter.getFileType(); 145 String fileDir=commandGetter.getFileDir(); 146 if (extendCount.setTargetFileList(fileType, fileDir)) { 147 files = extendCount.getTargetFileList(); 148 for (File f : files) { 149 chooiseCommand(f); 150 } 151 } else { 152 System.out.println("该类型文件在本目录下不存在!"); 153 } 154 155 } else { 156 System.out.println("请输入要批量处理的文件格式!"); 157 } 158 } else if (operateFileTypeFlag) { 159 System.out.println("请指定-S操作符!"); 160 } 161 } 162 }
基础功能类:
1 package com.kong.base; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 8 9 /** 10 * 实现WC的基础功能,统计字符数,单词数,行数 11 * 12 * @author 孔绍坤 13 * @version 1.0 14 * @since 最低的JDK版本 15 * 16 * 17 */ 18 public class BaseCount { 19 private static int c = -1; 20 private static int w = -1; 21 private static int l = -1; 22 private static File file; 23 24 /** 25 * 26 * 统计总的字符数 27 * 28 * @param inputFile 29 * 指定的目标操作文件 30 * @return c 返回统计的字符数 31 * @throws IOException 32 */ 33 public int countChar(File inputFile) throws IOException { 34 file = inputFile; 35 if (inputFile.exists()) { 36 FileInputStream fip = new FileInputStream(file); 37 InputStreamReader reader = new InputStreamReader(fip); 38 StringBuffer sBuffer = new StringBuffer(); 39 while (reader.ready()) { 40 sBuffer.append((char) reader.read()); 41 } 42 43 c = sBuffer.length(); 44 reader.close(); 45 fip.close(); 46 return c; 47 } else { 48 System.out.println("统计字符:输入的源文件不存在!"); 49 return -1; 50 } 51 } 52 53 /** 54 * 统计总的行数 55 * 56 * @param inputFile 57 * 接收一个目标操作文件 58 * @return l 返回统计的行数 59 */ 60 public int countLine(File inputFile) throws IOException { 61 if (inputFile.exists()) { 62 file = inputFile; 63 FileInputStream fip = new FileInputStream(file); 64 InputStreamReader reader = new InputStreamReader(fip); 65 StringBuffer sBuffer = new StringBuffer(); 66 while (reader.ready()) { 67 sBuffer.append((char) reader.read()); 68 } 69 String str = sBuffer.toString(); 70 char[] ch = str.toCharArray(); 71 l = 0; 72 for (char c : ch) { 73 if (c == '\n') { 74 l++; 75 } 76 } 77 reader.close(); 78 fip.close(); 79 return l; 80 } else { 81 System.out.println("统计行数:输入的源文件不存在!"); 82 return -1; 83 84 } 85 86 } 87 88 /** 89 * 统计总的单词数 90 * 91 * @param inputFile 92 * 接收一个目标操作文件 93 * 94 * @return w 返回统计的单词数 95 */ 96 public int countWord(File inputFile) throws IOException { 97 if(inputFile.exists()) 98 { 99 file = inputFile; 100 FileInputStream fip = new FileInputStream(file); 101 InputStreamReader reader = new InputStreamReader(fip); 102 StringBuffer sBuffer = new StringBuffer(); 103 while (reader.ready()) { 104 sBuffer.append((char) reader.read()); 105 } 106 String str = sBuffer.toString(); 107 char[] ch = str.toCharArray(); 108 w = 0; 109 for (char c : ch) { 110 if (c == '\n' || c == '\r' || c == ' ' || c == ',' || c == ';' 111 || c == '.') { 112 w++; 113 } 114 } 115 reader.close(); 116 fip.close(); 117 return w; 118 }else { 119 System.out.println("统计单词数:输入的源文件不存在!"); 120 return -1; 121 } 122 } 123 124 public int getC() { 125 return c; 126 } 127 128 public int getW() { 129 return w; 130 } 131 132 public int getL() { 133 return l; 134 } 135 136 public File getFile() 137 { 138 return file; 139 } 140 }
文件输出类:
1 package com.kong.base; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.OutputStreamWriter; 7 8 /** 9 * 文件输出类,处理输出信息,输出信息到文件 10 * 11 * @author kong 12 * @version 1.0 2018/10/9 13 * 14 */ 15 public class FileOutputer { 16 17 private BaseCount baseCount; 18 private ExtendCount extendCount; 19 20 /** 21 * 22 * @param baseCount 23 * 基础功能类 24 * @param extendCount 25 * 扩展功能类 26 */ 27 public FileOutputer(BaseCount baseCount, ExtendCount extendCount) { 28 this.baseCount = baseCount; 29 this.extendCount = extendCount; 30 // TODO Auto-generated constructor stub 31 } 32 33 /** 34 * 判断输入的操作源文件是否存在 35 * 36 * @return 如果存在,则返回true否则返回false 37 */ 38 public boolean checkInputFileExist() { 39 if (baseCount.getFile().exists()) { 40 return true; 41 } else { 42 return false; 43 } 44 } 45 46 /** 47 * 48 * 将统计结果输出到文本文件中 输出详细的文本文件的统计结果 49 * 50 * @see com.kong.base.BaseCount 51 * @see ExtendCount 52 * 53 * @param outputFile 54 * 输出文本文件 55 * @throws IOException 56 */ 57 public void outputFile(File outputFile) throws IOException { 58 boolean inputFileExist = checkInputFileExist(); 59 if (inputFileExist) { 60 File f = outputFile; 61 FileOutputStream fop = new FileOutputStream(f, true); 62 OutputStreamWriter writer = new OutputStreamWriter(fop); 63 if (baseCount.getC() >= 0) { 64 65 writer.append(baseCount.getFile().getName() + ",总字符数:" 66 + baseCount.getC() + "\r\n"); 67 } 68 if (baseCount.getW() >= 0) { 69 writer.append(baseCount.getFile().getName() + ",总单词数:" 70 + baseCount.getW() + "\r\n"); 71 } 72 if (baseCount.getL() >= 0) { 73 writer.append(baseCount.getFile().getName() + ",总行数:" 74 + baseCount.getL() + "\r\n"); 75 } 76 if (extendCount.getCodeLine() >= 0) { 77 writer.append(extendCount.getFile().getName() 78 + ",代码行数\\空行数\\注释行数:" + extendCount.getCodeLine() 79 + "\\" + extendCount.getEmptyLine() + "\\" 80 + extendCount.getCommentLine() + "\r\n"); 81 } 82 if (extendCount.getAfterIngoreWords() >= 0) { 83 writer.append(extendCount.getFile().getName() + ",不统计的单词有:"); 84 for (String temp : extendCount.getStopWords()) { 85 writer.append(temp + " "); 86 } 87 writer.append("结果单词数:" + extendCount.getAfterIngoreWords() 88 + "\r\n"); 89 } 90 writer.close(); 91 fop.close(); 92 } 93 } 94 }
命令获取提取类:
1 package com.kong.base; 2 3 import java.io.File; 4 5 /** 6 * 7 * 8 * 获取输入的命令行,并且提取出,源操作文件,停用词文件, 指定输出文件,批量操作文件的类型 9 * 10 * @author 孔绍坤 11 * @version 1.0 2018/10/9 12 * @since 不清楚 13 * 14 */ 15 public class CommandGetter { 16 private File outFile; 17 private File stopFile; 18 private File inputFile; 19 private String fileType; 20 private String[] commandStrings; 21 22 /** 23 * 新加的 24 */ 25 26 private String fileDir; 27 28 /** 29 * 获取输入的命令行 30 * 31 * @param commandStrings 32 * 输入的命令行 33 */ 34 /* 35 * private CommandGetter() { 36 * 37 * } 38 */ 39 public CommandGetter(String[] commandStrings) { 40 // TODO Auto-generated constructor stub 41 this.commandStrings = commandStrings; 42 } 43 44 public String getFileDir() { 45 setFileDir(); 46 return fileDir; 47 } 48 49 /** 50 * 此处是为了配合新的需求(用户指定操作目录添加的得到文件目录的方法) 实现方法跟之前的不同,可能不够严谨 51 */ 52 public void setFileDir() { 53 54 /* 55 * 添加获取command中的指定文件目录 56 */ 57 boolean flag = false; 58 for (int i = 0; i < commandStrings.length; i++) { 59 if (commandStrings[i].equals("-s")) { 60 fileDir = commandStrings[i + 1]; 61 flag = true; 62 break; 63 } 64 } 65 if (!flag) 66 { 67 fileDir = "."; 68 } 69 70 } 71 72 /** 73 * 设置操作源文件 74 * 75 * @return 成功读取到文件 返回true,否则返回false 76 */ 77 public boolean setInputFile() { 78 for (String temp : commandStrings) { 79 if (temp.endsWith(".java")) { 80 /* 81 * 内部的判断语句用于区分输入格式为*.java以及.java 82 */ 83 if (!temp.equals("*.java")) { 84 this.inputFile = new File(temp); 85 return true; 86 } 87 } else { 88 inputFile = null; 89 } 90 } 91 return false; 92 } 93 94 /** 95 * 设置批量操作文件的类型 96 * 97 * @return 成功读取到文件类型 返回true,否则返回false 98 */ 99 public boolean setOperateFileType() { 100 for (String temp : commandStrings) { 101 if (temp.startsWith("*.")) { 102 String[] strs = temp.split("\\."); 103 this.fileType = strs[strs.length - 1]; 104 return true; 105 } 106 } 107 return false; 108 } 109 110 /** 111 * 设置输出文本文件 112 * 113 * @return 成功读取到文件类型 返回true,否则返回false 114 */ 115 public boolean setOutFile() { 116 for (int i = 0; i < commandStrings.length; i++) { 117 if (i < commandStrings.length - 1) { 118 if (commandStrings[i + 1].endsWith(".txt") 119 && commandStrings[i].equals("-o")) { 120 outFile = new File(commandStrings[i + 1]); 121 return true; 122 } else { 123 outFile = null; 124 } 125 } 126 } 127 return false; 128 } 129 130 /** 131 * 检查S命令符是否输入 132 * 133 * @return 成功读取到S命令 返回true,否则返回false 134 */ 135 public boolean checkScommand() { 136 for (String temp : commandStrings) { 137 if (temp.equals("-s")) { 138 return true; 139 } 140 } 141 return false; 142 } 143 144 /** 145 * 检查O命令符是否输入 146 * 147 * @return 成功读取到O命令 返回true,否则返回false 148 */ 149 public boolean checkOcommand() { 150 for (String temp : commandStrings) { 151 if (temp.equals("-o")) { 152 return true; 153 } 154 } 155 return false; 156 } 157 158 /** 159 * 设置停用词文件 160 * 161 * @return 成功读取到停用词文件 返回true,否则返回false 162 */ 163 public boolean setStopFile() { 164 for (int i = 0; i < commandStrings.length; i++) { 165 if (i < commandStrings.length - 1) { 166 if (commandStrings[i + 1].endsWith(".txt") 167 && commandStrings[i].equals("-e")) { 168 stopFile = new File(commandStrings[i + 1]); 169 return true; 170 } 171 } else { 172 stopFile = null; 173 174 } 175 } 176 return false; 177 } 178 179 /** 180 * 181 * @return 获取指定输出文件 182 */ 183 public File getOutFile() { 184 return outFile; 185 } 186 187 /** 188 * 189 * @return 获取停用词文件 190 * 191 */ 192 public File getStopFile() { 193 return stopFile; 194 } 195 196 /** 197 * 198 * @return 获取源操作文件 199 */ 200 public File getInputFile() { 201 return inputFile; 202 } 203 204 /** 205 * 206 * @return 207 * 208 * 获取批量操作文件的类型 209 */ 210 public String getFileType() { 211 return fileType; 212 } 213 214 /** 215 * 216 * @return 获取输入的命令行 217 */ 218 public String[] getCommandStrings() { 219 return commandStrings; 220 } 221 222 }
进行测试的部分代码:
1 package com.kong.base; 2 3 import static org.junit.Assert.*; 4 5 import java.util.Arrays; 6 import java.util.Collection; 7 8 import org.junit.Before; 9 import org.junit.Test; 10 import org.junit.runner.RunWith; 11 import org.junit.runners.Parameterized; 12 import org.junit.runners.Parameterized.Parameters; 13 14 /** 15 * 16 用 @RunWith(Parameterized.class) 来注释 test 类。 17 创建一个由 @Parameters 注释的公共的静态方法,它返回一个对象的集合(数组)来作为测试数据集合。 18 创建一个公共的构造函数,它接受和一行测试数据相等同的东西。 19 为每一列测试数据创建一个实例变量。 20 用实例变量作为测试数据的来源来创建你的测试用例。 21 22 * @author 孔绍坤 23 * 24 */ 25 @RunWith(Parameterized.class) 26 public class CommandGetterTest { 27 private String[] commands; 28 private String[] expectedResult; 29 private CommandGetter commandGetter; 30 31 /* 32 *特备说明:expectedResult存数的都boolean的数据,为了使所有的方法都可以同时进行参数化测试 33 */ 34 @Before 35 public void Init() 36 { 37 commandGetter=new CommandGetter(commands); 38 } 39 40 public CommandGetterTest(String[] commands,String[] expectedResult) { 41 this.commands=commands; 42 this.expectedResult=expectedResult; 43 // TODO Auto-generated constructor stub 44 } 45 46 @Parameters 47 public static Collection primeData() { 48 49 //模拟命令 50 String[] str1={"test.java","-o","-s"}; 51 String[] str2={"-c","-l","-w","test1.java","-o","out1.txt"}; 52 String[] str3={"-o","out.txt","test.java","*.c","-s","-e","stop.txt"}; 53 String[] str4={"*.c","-s","-e"}; 54 55 //调用的方法返回值集合 56 String[] bool1={"true","false","false","true","true","false"}; 57 String[] bool2={"true","false","true","false","true","false"}; 58 String[] bool3={"true","true","true","true","true","true"}; 59 String[] bool4={"false","true","false","true","false","false"}; 60 Object[][] object=new Object[][]{ 61 {str1,bool1}, 62 {str2,bool2}, 63 {str3,bool3}, 64 {str4,bool4} 65 }; 66 return Arrays.asList(object); 67 } 68 69 70 @Test 71 public void testSetInputFile() { 72 System.out.println("This is testSetInputFile :"); 73 assertEquals(expectedResult[0], ((Boolean)commandGetter.setInputFile()).toString()); 74 } 75 76 @Test 77 public void testSetOperateFileType() { 78 System.out.println("This is testSetOperateFileType :"); 79 assertEquals(expectedResult[1], ((Boolean)commandGetter.setOperateFileType()).toString()); 80 } 81 82 83 @Test 84 public void testSetOutFile() { 85 System.out.println("This is testSetOutFile :"); 86 assertEquals(expectedResult[2], ((Boolean)commandGetter.setOutFile()).toString()); 87 } 88 89 @Test 90 public void testCheckScommand() { 91 System.out.println("This is testCheckScommand :"); 92 assertEquals(expectedResult[3], ((Boolean)commandGetter.checkScommand()).toString()); 93 } 94 95 @Test 96 public void testCheckOcommand() { 97 System.out.println("This is testCheckOcommand :"); 98 assertEquals(expectedResult[4], ((Boolean)commandGetter.checkOcommand()).toString()); 99 } 100 101 102 @Test 103 public void testSetStopFile() { 104 System.out.println("This is testSetStopFile :"); 105 assertEquals(expectedResult[5], ((Boolean)commandGetter.setStopFile()).toString()); 106 } 107 108 }
其他具体代码详参gittee.
5.总结:
这次结对编程让我认识到结对编程是一个渐进的过程,有效的结对编程不是一天就能够做到的。结对编程是一个相互学习,相互磨合的渐进的过程。我们需要时间来适应这种新的开发模式。这次结对编程让我意识到有些时候还是1+1>2的,就是把很多复杂的工作分离成小工作,分工合作完成的时候,效率很快,但是在完整的开发过程中有时候是1+1<2的,那就是沟通不流畅的时候,这里的沟通指的是有时候不能坐在一起沟通,只能通过沟通工具沟通的时候,能够很明显感觉到需求说不出,或者是说出了对方理解不了的情况,这也是这个项目拖延得比较久的原因,今天大部分功能完成的时候,大家坐到一起时马上就解决了之前几天遗留的问题,项目运行也完成了,还有一些逻辑的优化、界面的友好度和一些小bug可以优化,但是不影响功能的完整运行。