个人作业-week2(代码复审)
一、代码复审check list
- 概要部分
- 代码符合需求和规格说明吗?
符合要求和规格说明,-s指令和-c指令都能实现需求。并且能够处理非法输入。 - 代码设计是否有周全的考虑?
程序的main函数中对各种输入情况都有考虑且做出了处理,例如对超过范围的输入数字和非法的参数都输出错误提示。同时,代码具有良好的可扩展性,因其设计为面向对象的,对象要实现的功能都提炼成函数。 - 代码可读性如何?
程序分为数独生成类,数独解决类和输出类,逻辑清晰,且包含很多注释。在数独生成类中,每个函数都有其规格,规格中包括Description, Input, Require, Concrete function部分,让人对程序的功能一目了然。 - 代码容易维护么?
代码的逻辑清晰,将需求切割得较为精细,也就保证了每个类和类中的每个函数功能单一。这也就使代码的可维护性更强。 - 代码的每一行都执行并检查过了吗?
程序中包含冗余的代码,例如数独输出类中有四个print方法,但仅使用了一个,因此冗余代码应当注释或删除。
- 代码符合需求和规格说明吗?
- 设计规范部分
- 设计是否遵从已知的设计模式或项目中常用的模式?
代码设计中没有用到设计模式,但使用了面向对象的模式,逻辑功能的划分清晰。 - 有没有硬编码或字符串/数字等存在?
在对数独矩阵做循环时出现了数字9,对矩阵做行列等价变换时出现了一些行号列号数字。但等价交换部分的数字在函数的规格中做出了解释。 - 代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)?
代码中没有使用十分大的int数字,因此不会出现int溢出的现象,在x86环境和x64环境都能正常运行且都能满足需求。因此不存在依赖32位或64位平台的现象。 - 开发者新写的代码能否用已有的Library/SDK/Framework中的功能实现?在本项目中是否存在类似的功能可以调用而不用全部重新实现?
在生成数独时,数独第一行的全排列可以使用algorithm库中的next_permutation函数实现,但开发者使用自行实现的递归函数generateMatrix来生成第一行。 - 有没有无用的代码可以清除?(很多人想保留尽可能多的代码,因为以后可能会用上,这样导致程序文件中有很多注释掉的代码,这些代码都可以删除,因为源代码控制已经保存了原来的老代码。)
该程序包含比较多的代码注释,以及几个不使用的print函数,在最终版本中应该将这些代码删除。sudo类中的print函数放在头文件中是不合适的,应该在头文件中声明,在源代码文件中定义实现。
- 设计是否遵从已知的设计模式或项目中常用的模式?
- 代码规范部分
- 修改的部分符合代码标准和风格么(详细条文略)?
代码风格总体标准且一致,数独生成类的函数规格十分规范漂亮,注释清晰。但是存在左花括号换行与不换行同时存在的代码,存在运算符左右空格与不空格同时存在的代码。
- 修改的部分符合代码标准和风格么(详细条文略)?
- 具体代码部分
- 有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常?
对输入做了检查,对于不合法的输入会输出错误信息,生成超过一百万数独时也会提示错误信息。进行文件操作前,检查了打开的文件是否存在,写入文件前检查了文件是否可以写入。并且在最后将文件输入输出流关闭。
if ((f = fopen(filepath, "r")) == NULL || (fp = fopen("sudoku.txt", "w")) == NULL)
{
printf("cannot open file\n");
exit(0);
}
......
fclose(fp);
fclose(f);- 参数传递有无错误,字符串的长度是字节的长度还是字符(可能是单/双字节)的长度,是以0开始计数还是以1开始计数?
参数传递时没有错误,且传递的参数数量较少,多为一到三个参数,参数意义明确。项目中的计数都是以0开始的。项目中没有涉及字符串长度的处理。 - 边界条件是如何处理的?Switch语句的Default是如何处理的?循环有没有可能出现死循环?
程序中对超过范围的请求输出错误信息,对于边界条件,可以和正常数据一样做处理并得到结果,因此除了输入检查外没有做其他的边界条件处理。switch语句最后都加上了default,且每条case语句的结尾都使用了break语句,防止程序发生错误。循环中都有明确的结束条件,可以保证不会发生死循环的现象。 - 有没有使用断言(Assert)来保证我们认为不变的条件真的满足?
在单元测试中使用了assert来对测试结果进行验证。在工程代码中没有使用assert来确定条件真正满足。并且我认为在最终完成的版本中不应该包含assert。 - 对资源的利用,是在哪里申请,在哪里释放的?有没有可能导致资源泄露(内存、文件、各种GUI资源、数据库访问的连接,等等)?有没有可能优化?
程序中有两处使用了动态申请内存。第一部分是在循环中创建sudoSolver对象,在其生命周期结束后使用delete清空了其占用的内存。只是sudoSolver类的析构函数为空,可能会无法释放类中动态申请的空间。在当前版本的sudoSovler类中没有使用动态申请,故不会存在问题。第二部分是在创建char数组保存写入到文件中的字符串,但没有释放这一部分空间。但由于仅需申请了一次,在程序结束后会自动释放内存,故不存在大的内存泄漏。 - 数据结构中是否有无用的元素?
代码中没有定义数据结构。
- 有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常?
- 效能
- 代码的效能(Performance)如何?最坏的情况是怎样的?
程序生成数独使用的方法是通过交换模板数字位置的方式生成母数独,然对母数独做等价变换生成数独。这种做法免去了大量的判断是否满足数独要求和回溯的消耗。在解数独时,使用递归回溯的方法。当我们构造一个神奇的数独时,程序将尝试几乎所有可能的解,造成解数独的效能变得很差。这是回溯法都会面临的问题。 - 代码中,特别是循环中是否有明显可优化的部分(C++中反复创建类,C#中string的操作是否能用StringBuilder 来优化)?
在解决数独的部分, 程序存在反复创建soduSolver类解数独的情况。可以将其修改为以此创建解数独的类,然后多次调用类中回溯解数独的方法,进而优化循环的性能。 - 对于系统和网络调用是否会超时?如何处理?
代码中不存在网络调用。系统调用仅适用文件操作,不存在超时的可能性。
- 代码的效能(Performance)如何?最坏的情况是怎样的?
- 可读性
- 代码可读性如何?有没有足够的注释?
代码的可读性很好,有足够且逻辑清晰的注释。在数独的生成类中,每个函数都有其规格,包含了Description, Input, Require, Concrete function部分,让人对程序的功能一目了然。
- 代码可读性如何?有没有足够的注释?
- 可测试性
- 代码是否需要更新或创建新的单元测试?
代码的单元测试对关键函数做了黑盒测试,在不修改关键函数的需求和输入输出的情况下对代码更新以后,不需要更新或创建新的单元测试。 还可以有针对特定领域开发(如数据库、网页、多线程等)的核查表。
该项目不涉及数据库,网页或多线程,故没有核查表。二、设计一个代码规范
- 代码是否需要更新或创建新的单元测试?
- 使用c++编码,参考谷歌的代码规范。
- 工具提供的代码规范和你个人的代码风格有什么不同?
- 规范中提倡不使用宏定义。因为宏定义会使人看到的代码和编译器看到的代码不一致。且宏定义是全局的,与c++提倡的命名空间有冲突。一般对于常量的宏定义用const代替,函数用inline来代替。这样做也可以保证数据类型的吻合。
- 常量定义在google的规范中是以k开头的,之后是每个单词的第一个字母大写。
- 工具提供的代码规范里有哪些部分是你之前没有想到的?
- 变量的声明尽可能的置于最小作用域内,且要做初始化。
- 传递对象时用引用而不用copy。
- 所有按引用传递的参数在函数参数定义时必须加上const,可以保证在函数中不会对这个引用修改。
- 前置自增即++i比后置自增效率高。
- 使用的代码规范
- 代码风格规范整理
- 缩进以及不同单词之间的空隙完全由VS工具自动调整的结果为准
- 命名:(1)类型命名首字母大写,不含下划线(2)变量命名一律小写,单词之间用_连接,类的成员变量最后加_(3)常量以k开头,首字母大写不加下划线(4)常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配(5)特殊的命名再做商议
- 注释:(1)尽量为每个类都写一份注释声明(2)为复杂函数前加上注释声明(3)注释要上下对齐
- 代码设计规范整理
- 不用goto语句
- 尽可能的把清理工作放在析构函数中
- 构造函数尽可能的简短
- 仅在必要时再使用类的继承
- 代码风格规范整理
个人作业-week2(代码复审)的更多相关文章
- 个人博客作业week2——代码复审
1.代码规范 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 代码规范并不是从官僚制度下产生,它是为了提高项目团队开发效率而产生的一种工具,能够极大的增强代码可读 ...
- 个人作业 - Week2 - 代码复审
代码复审Check List 概要部分 代码能符合需求和规格说明么? 能完成1~1000000个数独的求解与生成,并能处理异常输入,满足需求. 代码设计是否有周全的考虑? 为输入单独开设了一个输入检测 ...
- 个人博客作业-Week2 (代码规范, 代码复审)
代码规范: 1.这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 编码规范它包含了代码格式,还包括了编码风格和其他规范,通常涉及:缩进.空格使用.Tab使用 注释. ...
- 个人作业week3——代码复审
1. 软件工程师的成长 感想 看了这么多博客,收获颇丰.一方面是对大牛们的计算机之路有了一定的了解,另一方面还是态度最重要,或者说用不用功最重要.这些博客里好些都是九几年或者零几年就开始学习编 ...
- [2017BUAA软工]第二次博客作业:代码复审
〇.comment链接 https://github.com/hanayashiki/Sudoku/issues/1 一.代码复审 1.概要部分 (1)代码能符合需求和规格说明么? 经测试,对于合法输 ...
- 个人博客作业Week2(代码规范,代码复审)
Q:是否需要有代码规范 首先我们来搞清楚什么是“代码规范”,它和“代码风格”又有什么关系.依据个人的审美角度,我可能更喜欢在函数与函数之间空出一行,可能在命名习惯和代码注释上更加的internatio ...
- 作业三: 代码规范、代码复审、PSP
分) 对于是否需要有代码规范,请考虑下列论点并反驳/支持: 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 我是个艺术家,手艺人,我有自己的规范和原则. 规范不能 ...
- 作业三 代码规范 代码复审 PSP
1.是否需要有代码规范(5分) 对于是否需要有代码规范,请考虑下列论点并反驳/支持: 1这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 反对.我并不认为代码规范都 ...
- 个人作业Week 2 ----------代码的规范和代码复审
1.是否需要有代码规范 从个人理解的角度出发,我认为代码规范还可以细分为代码的风格还有代码的结构设计(就好比排版一类的) 以前在上C语言课程的时候就看到过,老师会在打“{”的时候进行一个换行,但是有些 ...
随机推荐
- BZOJ2428_均分数据_KEY
题目传送门 这道题可以用C++的random_shuffle屮过去. random数列插入顺序,每次都插入数值和最小的那一组. #include <cmath> #include < ...
- SQL Server 创建带返回值的存储过程
--drop procedure zcstest; create procedure zcstest ( @tableName varchar(max), @dataCount int output ...
- LeetCode总结
LeetCode总结 所有代码见我的github.不过一般leetcode上答案也一大堆,最好还是自己动动手,收获比较大. 100 知识点:递归,二叉树 难度Easy,主要是注意对当p和q均为null ...
- 测试模型---V模型
软件测试&软件工程 软件测试是软件工程不可缺少的一部分. 一.V模型简介 需求分析 验收测试 概要设计 系统测试 详细设计 集成测试 编码 单元测试 (1)单元测试: 又称模块测试,针对软 ...
- c#多线程中Lock()关键字的用法小结
本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段 ...
- CHAPTER 38 Reading ‘the Book of Life’ The Human Genome Project 第38章 阅读生命之书 人体基因组计划
CHAPTER 38 Reading ‘the Book of Life’ The Human Genome Project 第38章 阅读生命之书 人体基因组计划 Humans have about ...
- 一种利用ADO连接池操作MySQL的解决方案(VC++)
VC++连接MySQL数据库 常用的方式有三种:ADO.mysql++,mysql API ; 本文只讲述ADO的连接方式. 为什么要使用连接池? 对于简单的数据库应用,完全可以先创建一个常连接(此连 ...
- 【Docker】第一篇 Docker的初始化安装部署
一.Docker基础 Dacker倡导的理念:一个容器一个进程 Docker的版本了解: Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE. 社区版是免费提供给个人 ...
- Python函数式编程中map()、reduce()和filter()函数的用法
Python中map().reduce()和filter()三个函数均是应用于序列的内置函数,分别对序列进行遍历.递归计算以及过滤操作.这三个内置函数在实际使用过程中常常和“行内函数”lambda函数 ...
- Vue 事件处理
原生的js事件处理 原生的js事件处理,可以分为:直接内联执行代码,或者绑定事件函数. 在内联的事件处理函数内部或者事件绑定的方法内部的作用域中的this都是指向当前的dom对象.如何在vue绑定的元 ...