代码改变世界

WordCount扩展实现——结对编程

2018-10-16 22:09  1987kong  阅读(286)  评论(0编辑  收藏  举报

合作者:

  201631062221,201631062514

地址:

  代码地址

本次作业地址:

  https://edu.cnblogs.com/campus/xnsy/2018Systemanalysisanddesign/homework/2188

正文:

 1.PSP表格:

 

2.互审代码情况:

  审查的罗博伦的WordCount的基础功能实现代码。
  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 }
View Code

基础功能类:

  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可以优化,但是不影响功能的完整运行。