结对编程
合作者:201631062319,201631062424
代码地址:https://gitee.com/this-hui/WordCount
一、结对的PSP表格
PSP阶段 | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|
计划 |
30 |
60 |
估计这个任务需要多少时间 |
20 |
20 |
开发 |
100 |
150 |
需求分析 |
30 |
30 |
生成设计文档 |
20 |
20 |
设计复审 |
30 |
20 |
代码规范 |
20 |
20 |
具体设计 |
30 |
30 |
具体编码 |
60 |
90 |
代码复审 |
30 |
30 |
测试 |
30 |
40 |
报告 |
20 |
20 |
测试报告 |
20 |
20 |
计算工作量 |
10 |
20 |
事后总结 |
20 |
30 |
合计 |
470 |
600 |
在做项目的时候,我们自己预先估计的时间与实际时间之间还是存在着一些问题,比如在做项目计划
的时候,我们预先估计的是30分钟,没有想到由于两个人之间的分歧,导致我们用了60分钟才完成。
还有就是编程的时间也超过了我们的预期时间。
二、互审代码情况
1.代码复审前
在代码复审前,我们各自确定我们的代码能够在自己的机子上进行编译成功,然后各自对自己的
代码进行了测试,测试完成后,我们便开始了代码复审。
2.复审时
在代码复审时,我们每个人提供了新的代码,查看了双方代码的时间复杂度和空间复杂度。在复
审我的代码的时候,我控制着流程,讲述了修改代码的前因后果,我的合作者逐一提供了反馈意见。
同样,在审查他的代码的时候也是一样。
3.复审结果
我们代码复审的结果就是双方达成了一致的意见,再总结出了一份双方一致同意的程序代码。
三、设计过程
1.确定编程语言及编程工具
我们两人都对java比较熟悉,所以这次我们的程序决定用java语言来写,对于我们来说,eclipse
编程工具是我们最熟悉的,所以我们都选择了这个编程工具。
2.思考创建类的个数
在思考怎么编程的时候,我们考虑了创建5个类,分别是Creat_data类、test类、ToolUtil类、
View类、WordCount类。
3.实现项目功能
程序包含5个类,分别是Creat_data类、test类、ToolUtil类、View类、WordCount类。下面,
我会依次讲述每个类的功能及如何实现的。
四、代码说明
Creat_data类
用于创建文件列表
1 import java.io.BufferedReader; 2 import java.io.FileInputStream; 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.util.HashSet; 7 import java.util.Set; 8 9 public class Creat_data { 10 11 12 Set<String> all_file =new HashSet<String>();//创建文件列表 13 String Output_file = "result.txt"; 14 String Result ="";//创建结果的字符集 15 boolean F_Characters=false; 16 boolean F_Lines =false; 17 boolean F_wods =false; 18 public boolean F_difine=false; 19 public boolean F_NULL=false; 20 public boolean F_Code=false; 21 22 String result = ""; 23 //创建可以操作的IO流 24 FileInputStream in = null; 25 InputStreamReader isr = null; 26 BufferedReader bis = null; 27 FileOutputStream os = null; 28 public int Count=0; 29 30 31 //关闭IO流 32 public void Close() { 33 34 try { 35 in.close(); 36 isr.close(); 37 bis.close(); 38 } catch (IOException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 43 } 44 }
WordCount类
用于检查字符数、行数、单词数、代码行、注释行、空行
1 import java.io.IOException; 2 3 public class WordCuont { 4 //主程序用于判断 5 public static void main(String [] args) { 6 Creat_data data =new Creat_data();//创建的数据类 7 ToolUtil toolUtil = new ToolUtil();//创建的工具类 8 for(int i=0 ;i<args.length;i++) 9 { 10 11 if(args[i].startsWith("-")) { 12 13 switch (args[i]) 14 { 15 case "-c"://检查字符数 16 data.F_Characters=true; 17 break; 18 case "-l"://检查行数 19 data.F_Lines=true; 20 break; 21 case "-w"://检查单词数 22 data.F_wods=true; 23 break; 24 case "-a"://检查代码行,注释行,空行, 25 data.F_difine=true; 26 break; 27 28 case "-o": 29 if(!args[i+1].startsWith("-")) 30 { 31 data.Output_file=args[i+1]; 32 i++; 33 }else { 34 System.out.println("Your intput is illigal!"); 35 System.exit(0); 36 } 37 break; 38 default: 39 System.out.println("Your intput is illigal!"); 40 break; 41 42 } 43 } 44 else data.all_file.add(args[i]); 45 46 47 } 48 //判断然后传入数据 49 if(data.F_Characters) 50 { 51 data.Result+=toolUtil.ReturnChara(data.all_file)+"\r\n"; 52 } 53 if(data.F_Lines) 54 { 55 data.Result+=toolUtil.ReturnLines(data.all_file)+"\r\n"; 56 57 } 58 if(data.F_wods) 59 { 60 data.Result+=toolUtil.ReturnWords(data.all_file)+"\r\n"; 61 } 62 if(data.F_difine) 63 { 64 try { 65 data.Result+=toolUtil.difflineGUI(data.all_file)+"\r\n"; 66 } catch (IOException e) { 67 // TODO Auto-generated catch block 68 e.printStackTrace(); 69 } 70 } 71 72 73 System.out.println(data.Result); 74 toolUtil.OutpuFile(data.Output_file,data.Result); 75 } 76 77 }
ToolUtil类
用于创建检查字符数,行数,单词数,空行,注释行的方法
1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.util.Set; 9 import java.util.regex.Pattern; 10 11 public class ToolUtil { 12 //创建检查字符数,行数,单词数,空行,注释行的方法 13 public String ReturnChara(Set<String> all_file) { 14 // TODO Auto-generated method stub] 15 Creat_data data_R=new Creat_data(); //调用数据类创建数据和IO流 16 byte [] S_byte=new byte[20*1024]; 17 int len =S_byte.length; 18 int Byetes=0; 19 try { 20 for(String all_file1:all_file) 21 { 22 23 data_R.in =new FileInputStream(all_file1); 24 while((Byetes = data_R.in .read(S_byte,0,len))!=-1) 25 { 26 data_R.Count+=Byetes; 27 } 28 data_R.result+=all_file1+",字符数:"+data_R.Count+" "; 29 data_R.Count =0; 30 } 31 }catch(FileNotFoundException e) 32 { 33 System.out.println("文件输入错误请检查后重新输入"); 34 System.exit(0); 35 36 }catch(IOException e) { 37 e.printStackTrace(); 38 }finally 39 { 40 try { 41 data_R.in.close(); 42 } catch (IOException e) { 43 // TODO Auto-generated catch block 44 e.printStackTrace(); 45 } 46 } 47 48 return data_R.result; 49 50 } 51 52 public String ReturnLines(Set<String> all_file) { 53 // TODO Auto-generated method stub 54 Creat_data data_L=new Creat_data(); 55 try 56 { 57 for(String all_file1:all_file) 58 { 59 data_L.in=new FileInputStream(all_file1); 60 data_L.isr=new InputStreamReader(data_L.in); 61 data_L.bis=new BufferedReader(data_L.isr); 62 while(data_L.bis.readLine()!=null) 63 { 64 data_L.Count++; 65 } 66 data_L.result+=all_file1+",行数:"+data_L.Count+" "; 67 data_L.Count=0; 68 69 } 70 }catch(FileNotFoundException e) 71 { 72 System.out.println("文件输入错误请检查后重新输入"); 73 System.exit(0); 74 75 }catch(IOException e) { 76 e.printStackTrace(); 77 }finally 78 { 79 data_L.Close(); 80 } 81 82 return data_L.result; 83 84 } 85 86 public String ReturnWords(Set<String> all_file) { 87 // TODO Auto-generated method stub 88 Creat_data data_W=new Creat_data(); 89 StringBuffer saveString = new StringBuffer(); 90 String tmp = ""; //缓存字符串 91 92 try { 93 94 for(String all_file1:all_file) 95 { 96 data_W.in=new FileInputStream(all_file1); 97 data_W.isr=new InputStreamReader(data_W.in); 98 data_W.bis=new BufferedReader(data_W.isr); 99 while((tmp=data_W.bis.readLine())!=null) 100 { 101 saveString.append(tmp); 102 } 103 tmp =saveString.toString(); 104 String [] all= tmp.split("[\\s+,\\.\n]"); 105 data_W.Count = all.length; 106 data_W.result+=all_file1+",单词数:"+data_W.Count+" "; 107 } 108 109 110 }catch(FileNotFoundException e) 111 { 112 System.out.println("文件输入错误请检查后重新输入"); 113 System.exit(0); 114 115 }catch(IOException e) { 116 e.printStackTrace(); 117 }finally 118 { 119 data_W.Close(); 120 } 121 122 123 return data_W.result; 124 } 125 126 public boolean OutpuFile(String output_file, String Result) { 127 // TODO Auto-generated method stub 128 File OUtputFile =new File(output_file); 129 FileOutputStream os =null; 130 byte[] b=null; 131 try { 132 if(!OUtputFile.exists()) 133 { 134 OUtputFile.createNewFile(); 135 } 136 os = new FileOutputStream(OUtputFile); 137 b= Result.getBytes(); 138 os.write(b); 139 }catch(IOException e) 140 { 141 e.printStackTrace(); 142 }finally 143 { 144 try 145 { 146 os.close(); 147 }catch(IOException e) 148 { 149 e.printStackTrace(); 150 } 151 } 152 return true; 153 } 154 String difflineGUI(Set<String> all_file) throws IOException { 155 int Sode_Line = 0; 156 int Code_Line = 0; 157 int Null_Line = 0; 158 Creat_data data_n =new Creat_data(); 159 BufferedReader bufr = null; 160 for (String all_files : all_file) { 161 bufr = new BufferedReader(new InputStreamReader(new FileInputStream(all_files))); 162 163 Pattern nodeLinePattern = Pattern.compile("((//)|(/\\*+)|((^\\s)*\\*)|((^\\s)*\\*+/))+", 164 Pattern.MULTILINE + Pattern.DOTALL); 165 String line = null; 166 while((line = bufr.readLine()) != null) { 167 if (nodeLinePattern.matcher(line).find()) { 168 169 Sode_Line++; 170 171 } 172 else if(line.matches("^\\s*$")){ 173 174 Null_Line ++; 175 176 } 177 else 178 Code_Line ++; 179 } 180 181 182 183 data_n.result+=all_files+",代码行:"+Code_Line+",注释行:"+Sode_Line+",空行数:"+Null_Line+" "; 184 185 } 186 return data_n.result; 187 } 188 }
五、单元测试
单元测试代码:
1 import java.io.IOException; 2 import java.util.HashSet; 3 import java.util.Set; 4 5 import org.junit.Test; 6 7 8 public class test { 9 @org.junit.Test 10 public void testDifine() { 11 Set<String> all_files = new HashSet<String>(); 12 String file1 = "D:test.java"; 13 all_files.add(file1); 14 try { 15 16 System.out.println(new ToolUtil().difflineGUI(all_files)); 17 18 19 } catch (IOException e) { 20 // TODO Auto-generated catch block 21 e.printStackTrace(); 22 } 23 } 24 25 @org.junit.Test 26 public void testReturnCharacters() { 27 Set<String> all_files = new HashSet<String>(); 28 String file1 = "D:test.java"; 29 all_files.add(file1); 30 System.out.println(new ToolUtil().ReturnChara(all_files)); 31 } 32 33 @org.junit.Test 34 public void testReturnWords() { 35 Set<String> all_files = new HashSet<String>(); 36 37 String file1 = "D:test.java"; 38 all_files.add(file1); 39 System.out.println(new ToolUtil().ReturnWords(all_files)); 40 } 41 42 @org.junit.Test 43 public void testReturnLines() { 44 Set<String> all_files = new HashSet<String>(); 45 String file1 = "D:test.java";//哈哈哈哈 46 all_files.add(file1); 47 System.out.println(new ToolUtil().ReturnLines(all_files)); 48 } 49 50 51 @org.junit.Test 52 public void testOutputFile() { 53 String all_files = "result.txt"; 54 String context = "OutPutFile test !"; 55 new ToolUtil().OutpuFile(all_files, context); 56 } 57 58 }
六、可视化界面:
可视化界面代码:
1 import java.awt.Color; 2 import java.awt.GridLayout; 3 import java.awt.event.ActionEvent; 4 import java.awt.event.ActionListener; 5 import java.io.IOException; 6 import java.util.HashSet; 7 import java.util.Set; 8 9 import javax.swing.JButton; 10 import javax.swing.JFrame; 11 import javax.swing.JLabel; 12 import javax.swing.JPanel; 13 import javax.swing.JTextField; 14 15 public class View { 16 17 18 19 20 public static void main(String[] args) { 21 JFrame frame = new JFrame("WordCount"); 22 frame.setResizable(false);//固定大小 23 24 JPanel panel = new JPanel(); 25 panel.setBackground(new Color(250,250,250)); 26 panel.setLayout(new GridLayout(10,10,1,1)); 27 28 29 JLabel text1 = new JLabel("文件:"); 30 JLabel text3 = new JLabel("单词数,字符数:"); 31 JLabel text2 = new JLabel("行数:"); 32 33 JLabel text5 = new JLabel("代码行,注释行,空行数:"); 34 JTextField FileInput = new JTextField(""); 35 JTextField Words = new JTextField(""); 36 JTextField Line = new JTextField(""); 37 JTextField Char = new JTextField(""); 38 JTextField Code = new JTextField(""); 39 40 JButton bt = new JButton("结果"); 41 42 43 frame.setBounds(300, 300, 210, 250); 44 panel.setBounds(0, 0, 200, 200); 45 46 panel.add(text1); 47 panel.add(FileInput); 48 panel.add(text2); 49 panel.add(Words); 50 panel.add(text3); 51 panel.add(Line); 52 panel.add(text5); 53 panel.add(Code); 54 panel.add(bt); 55 56 frame.add(panel); 57 frame.setVisible(true); 58 ToolUtil tool =new ToolUtil(); 59 60 bt.addActionListener(new ActionListener() { 61 62 @Override 63 public void actionPerformed(ActionEvent e) { 64 // TODO Auto-generated method stub 65 66 JButton bt = (JButton) e.getSource(); 67 try{ 68 Set<String> all_files = new HashSet<String>(); 69 String file1 = FileInput.getText(); 70 all_files.add(file1); 71 Words.setText(tool.ReturnWords(all_files)); 72 Line.setText(tool.ReturnLines(all_files)+tool.ReturnChara(all_files)); 73 Code.setText(tool.difflineGUI(all_files)); 74 75 } catch(NumberFormatException n) 76 { 77 FileInput.setText("你输入的文件!"); 78 } catch (IOException e1) { 79 // TODO Auto-generated catch block 80 e1.printStackTrace(); 81 } 82 83 } 84 }); 85 } 86 87 }
七、运行结果展示:
创建1个文件1.txt,在文件中输入以下内容
运行程序,在文件这个运行框中定位文件位置D:1.txt,点击结果按钮
八、总结
就我们这次实验的编程而言,我觉得我学到了很多东西,也提高了我们编程的效率,可以说是事半功倍,
绝对是1+1>2的。有了领航员的存在,我们在完成代码后,几乎没有花什么时间在修改Bug上,甚至很多阶
段性的代码都是一次通过,这大大提高了我们编程的效率,而且我们二人一起讨论出来的编程思路,也使得
我们的代码功能更全面,效率更高。我们认为,结对编程的优势主要就在于设计思路的共享,和我们互相为
对方避免错误。总的来说,自己在编程时犯下的错误,有些尽管很简单,但却难以发现,而这些在另一个人
眼中,却会十分明显。当然结对编程也有不适用的地方,对于有不同习惯的编程人员,可以在起工作会产生
麻烦,甚至矛盾。有时候,程序员们会对一个问题各执己见,争吵不休,反而产生重大内耗。两个人在一起
工作可能会出现工作精力不能集中的情况。程序员可能会交谈一些与工作无关的事情,反而分散注意力,导
致效率比单人更为低下。结对编程可能让程序员们相互学习得更快。有些时候,学习对方的长外,可能会和
程序员们在起滋生不良气氛一样快。比如,合伙应付工作,敷衍项目。面对新手,有经验的老手可能会觉得
非常的烦躁。不合适的沟通会导到团队的不和谐。有经验的人更喜欢单兵作战,找个人来站在他背后看着他
可能会让他感到非常的不爽,最终导致编程时受到情绪影响,反而出现反作用。以上就是我对于我们这次结
对编程的看法,确实提高了我们编程的效率,我也感受到了结对编程的好处,但是由于我们都是学生,还没
有参加工作,在工作中结对编程还是有一些我们还没有感受到的问题。