结对项目作业
合作者:201631062114,201631062602
代码地址:https://gitee.com/Changyu-Guo/pairing_project
作业链接:http://www.cnblogs.com/guochangyu/p/9804719.html
一、PSP表格
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
100 |
120 |
· Estimate |
· 估计这个任务需要多少时间 |
100 |
120 |
Development |
开发 |
1520 |
1830 |
· Analysis |
· 需求分析 (包括学习新技术) |
20 |
15 |
· Design Spec |
· 生成设计文档 |
30 |
35 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
20 |
20 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
50 |
60 |
· Design |
· 具体设计 |
100 |
150 |
· Coding |
· 具体编码 |
1000 |
约1300 |
· Code Review |
· 代码复审 |
200 |
140 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
100 |
110 |
Reporting |
报告 |
220 |
250 |
· Test Report |
· 测试报告 |
100 |
85 |
· Size Measurement |
· 计算工作量 |
20 |
15 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
100 |
150 |
合计 |
1840 |
2200 |
二、代码规范
经过讨论,我们的项目主要是使用C/C++结合node.js进行开发,因此我们从网络上查找了相关的编码规范:
C/C++:C/C++编码规范
Node.js:JavaScript 风格指南/编码规范(Airbnb公司版)
三、代码自审和互审
制定了相关的代码规范后,就按照代码规范对自己的代码进行审查,由于自己很早之前就对代码规范进行过了解,因此在审查过程中并没有发现太多的问题。
进行过代码自审过后,接下来就是代码互审,由于第一作业的代码比较简单,经双方商议后我们决定对命令处理模块、字符统计模块、单词统计模块、行数统计模块进行代码互审,过程中出现的问题如下:
- 我的代码问题:代码在基本的风格比如缩进,变量命名上面并没有太大问题,主要就是代码的耦合性太高,各个功能模块代码相互关联,并且出现多个逻辑功能出现在同一函数里面的情况,不利于接下来的结对合作,需要对相应的模块进行抽离。
- partner代码问题:代码同样出现了耦合性过高的问题,其实就是变量及函数的命名有的不符合驼峰命名法,其他的都比较好(毕竟编译器自带代码格式化);
四、设计过程
经过双方的商讨和对原始代码的分析过后,并考虑到要使用图形界面,决定用node.js搭建一个后端服务器,如果命令里面存在-x选项,则启动服务器,并打开相应的页面,由用户发送ajax数据,后端接受后拼接成相应的字符串后,调用wc.exe并传入命令字符串即可得到结果,如果没有,则不用打开服务器和网页,直接调用wc.exe得到相应结果即可。代码的具体流程如下:
wc模块的流程为:
五、关键代码分析
首先是node处理代码:
1 // 判断是否存在-x选项 2 if (process.argv.indexOf('-x') === -1) { 3 // 如果不存在,就拼接命令字符串并执行 4 process.argv.shift(); 5 process.argv.shift(); 6 process.argv.forEach(val => { 7 cmdStr += ' '; 8 cmdStr += val; 9 }); 10 exec(cmdStr, function (err, stdout, stderr) { 11 if (err) { 12 console.log("执行错误,请检查命令是否合法"); 13 return; 14 } 15 }); 16 } else { 17 // 如果存在-x指令,就启动服务器,并打开网页 18 app.listen(3000, function () { 19 console.log('app is running at port 3000.'); 20 }); 21 open('http://127.0.0.1:3000'); 22 }
这段代码是入口程序代码,首先要做的是判断是否有-x指令,如果没有,就遍历指令数组,将指令拼接成字符串,然后调用C++程序并将字符串作为参数传进去。如果有-x指令,就启动服务器,并用浏览器打开网页。网页的效果如下:
用户通过图形化的界面输入相关参数,然后后台获取数据后拼接成字符串,调用C++程序进行处理,后台代码如下:
1 app.get('/', function (req, res) { 2 res.type('html'); 3 res.render('index.html'); 4 }); 5 6 app.post('/data', function (req, res) { 7 // 拼接选项 8 for (var i = 0; i < req.body['options[]'].length; i++) { 9 cmdStr += ' '; 10 cmdStr += req.body['options[]'][i]; 11 } 12 // 拼接输入文件 13 cmdStr += ' '; 14 cmdStr += req.body.filepath; 15 cmdStr += ' '; 16 cmdStr += '-o'; 17 cmdStr += ' '; 18 cmdStr += path.dirname(req.body.filepath); 19 cmdStr += '\\'; 20 cmdStr += req.body.outfile; 21 if (req.body.isStop !== '') { 22 cmdStr += ' '; 23 cmdStr += '-e'; 24 cmdStr += ' '; 25 cmdStr += req.body.stopPath; 26 } 27 exec(__dirname + cmdStr, function (err, stdout, stderr) { 28 cmdStr = '.\\wc.exe'; 29 if (err) { 30 console.log('err'); 31 return res.status(500).json({ 32 message: '服务器错误' 33 }); 34 } 35 return res.status(200).json({ 36 message: '成功' 37 }); 38 }); 39 });
C++程序主函数代码:
1 int main(int argc, char *argv[]) { 2 3 char commandStr[MAX_COM_LENGTH] = ""; 4 for(int i=1;i<argc;i++){ //将用户输入的指令拼接成一个完整的字符串传给程序 5 strcat(commandStr, argv[i]); 6 strcat(commandStr, " "); 7 } 8 9 Command command; 10 analyseCommand(commandStr, command); //解析用户指令 11 12 SourceFile *head = new SourceFile(); 13 if (command._s) getFileName(command.filePath, head); //递归寻找目录下的文件 14 else { //否则直接利用相对路径查找文件 15 SourceFile *p = new SourceFile(); 16 p->next = head->next; 17 head->next = p; 18 strcpy(p->fileName, command.filePath); 19 strcpy(p->filePath, command.filePath); 20 } 21 22 wordCount(head, command.stopFile); //统计单词数 23 24 outPut(head, command); //结果输出到文件 25 26 delete head; 27 return 0; 28 }
main函数是逻辑处理的核心,node程序调用C++程序后,首先进入main函数,然后main函数将传进来的参数拼接成字符串,将字符串传入相关函数进行解析,解析后会得到一个链表,这个链表存储了所有文件的相关信息,最后将链表传入统计函数和输出函数进行相应的处理。
六、总结
这是我人生中第一做结对项目,有很多收获,自己一个人写代码的时候,有很多考虑不周全的地方,但是有了partner的提醒和帮助,就能够设计出更加有逻辑和更加规范的代码结构,而且在编码的过程中,有很多问题比如某个功能不知道怎么写,但是和partner商讨过后就能很容易的解决。总体上来说,我觉得结对编程还是很大程度上提高了编码效率。