总结
就本次作业中的几个问题说明如下:
- readme的要求在题目中明确给出,但是很多同事还是没有能够做好。另外,多看看一些开源代码,能够帮助大家理解如何写好readme;readme的作用:不是说明实现原理,技术细节,而是使用步骤,编译步骤等。
- 可执行文件的问题。提交的作业,点击exe基本上不可执行。有两位同事基本考虑到这个问题,一位是余海,一位是王焕林,但是做的还不够好;
- 关于“错误码的定义和错误信息的定义必须一一对应”问题,有方桂烽、潘唐磊两位同事有这个问题,这里应该是可以优化的;
- 关于“Debug和warning级别也使用错误码的形式实现”问题,有李泽奇、彭京思、王焕林、阎煦洲四位同事是这样实现的,这和题目的要求不明确可能有问题,但是我们不建议,也不欣赏这样的实现。因为debug和warning级别的信息输出,一般是工程师为了调试代码,跟踪流程时候使用的,最后这部分代码都不会被编辑到可执行文件中。在调试开发中,如何还要先定义枚举值,再定义错误信息,使用起来会特别麻烦。所以debug和warning部分应该像使用printf一般方便。而error的信息一般会编译到我们发布的可执行文件中,记录产品在使用过程中特殊情况下出现的重大错误,并且以文件的信息保存下来。这部分信息一般会对信息进行编号,也就是大家熟悉的error Number。
-
关于“大量使用对TRUE,FALSE值的封装。使用的这种封装值得商榷”问题,有李泽奇、万义康两位同事这样实现,但是我个人是不建议如此。原因有一下两点:1.影响代码阅读的连贯性,有时候,还真不好理解,让代码晦涩;2.调试起来并不方便,例如我在知道了
ipVersion
的值不正确之后,我最想知道的就是这个值现在是什么,那么,怎么调试呢? - 关于“大片调试信息的输出问题,例如使用for循环输出packet的内容”。建议单独使用函数输出,这一点彭京思做的很好。彭彬可以参考他的实现。
这次主要是看过大家的readme和源代码。对大家的完成情况作一个评比:
优秀:钟奕涛
良好:余海、彭彬、付大军、陈可
其他未上榜的同事的就是属于一般。
周川添
- readme写得不够好
- 很奇怪,在test.c文件和getTcpHeader.c文件中没有使用封装的调试函数
- printf函数的封装考虑太复杂,其实无需考虑每个级别的信息输出是什么,什么时候应该用哪个级别,这在实际代码中由编程人员决定
钟奕涛
- readme写的不错
-
基本上完全符合题目要求,并且将三个调试宏进行了合并,在代码中使用更加方便,这一点在题目中没有给出明确要求。可见钟仔细的阅读了所有资料。
/*将三个级别的调试信息封装成统一的形式*/ #define DebugPrintf(DebugType, Message, args...) \ do{\ switch(DebugType)\ {\ case DEBUGTYPE:\ DEBUG_M(Message, ##args);\ break;\ case WARNINGTYPE:\ WARNING_M(Message, ##args);\ break;\ case ERRORTYPE:\ ERROR_M(Message, ##args);\ break;\ default:\ break;\ }\ }while(0)
- 代码中还有许多printf未被替换掉,最好替换
- 错误码使用到了c99中的规则实现
余海
- readme的编译部分未做详细说明
- 将cygwin1.dll文件放置到了exe的当前路径,但是没有考虑程序结束信息显示问题
- 宏定义时最好使用大写
阎煦洲
- readme的编译部分未做详细说明
- Debug和warning级别也使用错误码的形式实现,其实这是没有必要的。因为debug和warning级别的信息输出,一般是工程师为了调试代码,跟踪流程时候使用的,最后这部分代码都不会被编辑到可执行文件中。在调试开发中,如何还要先定义枚举值,再定义错误信息,使用起来会特别麻烦。所以debug和warning部分应该像使用printf一般方便。而error的信息一般会编译到我们发布的可执行文件中,记录产品在使用过程中特殊情况下出现的重大错误,并且以文件的信息保存下来。这部分信息一般会对信息进行编号,也就是大家熟悉的error Number。
王焕林
- readme的编译部分未做详细说明
- Debug和warning级别也使用错误码的形式实现,道理同上。并且,还使用了些复杂的结构,使用起来会特别麻烦。
万义康
- readme的编译部分未做详细说明
- 使用数据代替输入参数,稍稍有点儿不那么好
-
大量使用对TRUE,FALSE值的封装。使用的这种封装值得商榷,有些老同事也比较喜欢使用这种封装,例如水哥。好处不用再说了,封装的好处。但是又下面几点我使用过程中遇到的问题:1.影响代码阅读的连贯性,有时候,还真不好理解,让代码晦涩;2.调试起来并不方便,例如我在知道了
ipVersion
的值不正确之后,我最想知道的就是这个值现在是什么,那么,怎么调试呢?/* 求得IP Version */ ipVersion = ((UINT)(ipHeadLen & 0xF0) >> 4); TH_CHK_VAL_RET_NULL(IP_VERSION4 != ipVersion); TH_CHK_VAL_RET_NULL((IP_PROTO_TYPE_ICMP == ipProtoType) || \ (IP_PROTO_TYPE_IGMP == ipProtoType) || \ (IP_PROTO_TYPE_UDP == ipProtoType));
-
使用了下面这样的封装,能够有出处吗?
#define TH_DB_DEBUG(fmt, ...) \ do {\ if (1 == (debugLevel & DEBUG_LEVEL_DEBUG)) \ { \ printf(fmt, ##__VA_ARGS__); \ } \ } while (0)
彭京思
- readme太多,写的不怎么好,应当简单明了
- 单独看readme,为什么“#为个人设置结束标识符”?
- Debug和warning级别也使用错误码的形式实现,道理同上。
- 对一些特殊的调试信息,例如报文内容的输出,使用了单独的调试函数printFile,printDebug实现,这一点很好。但是这命名确实不明确。
彭彬
- readme的编译部分未做详细说明
- 出现了下面的情况,这种情况其实在代码中我们大家都没有好的处理方式,如果还用封装的宏去处理,总觉得不伦不类。一般这个情况下,最好是使用单独的函数进行处理,参考彭京思的实现。
int i; for (i = 0; i < 6; i ++) { DEBUG_PRINTF("%02x ", frameHeader->MAC_dst[i] & 0xff); } DEBUG_PRINTF("\nMAC source: "); for (i = 0; i < 6; i ++) { DEBUG_PRINTF("%02x ", frameHeader->MAC_src[i] & 0xff); } DEBUG_PRINTF("\nType: %04x\n", frameHeader->type);
潘唐磊
- 错误码部分是硬伤,错误码的定义和错误信息的定义必须一一对应。这样使用起来会很不方便。
李泽奇
-
使用了和万义康一样的封装,道理同上。
#define TH_CHK_VAL(flag, v) #define TH_API_CALL(f) #define TH_API_CALL_RV(r, f)
- Debug和warning级别也使用错误码的形式实现,道理同上。
付大军
- readme的编译部分未做详细说明
- 错误码使用到了c99中的规则实现
方桂烽
- readme的编译部分未做详细说明
-
错误码部分是硬伤,错误码的定义和错误信息的定义必须一一对应。这样使用起来会很不方便。
#define PRIN_ERR(type,fmt,args...) \ do{\ if (tcpErrorOn)\ {\ printf("%s:%d:%s:"fmt"\n",__FUNCTION__,__LINE__,tcpErrorDescription[type],##args);\ }\ }while(0);
陈可
- 无