免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 77h2_eleven
打印 上一主题 下一主题

[函数] 大家在项目代码中会大量使用断言么?  关闭 [复制链接]

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
31 [报告]
发表于 2008-07-02 13:02 |只看该作者
讲个小故事娱乐一下吧。


话说 microhard、某个做freeware的菜鸟、另一个做freeware的老鸟 还有 xx面业集团有限公司同时进入字处理软件领域展开了激烈的竞争。


为了争夺用户,他们都为自己的软件增加了正则表达式查找功能;但由于某个unicode特殊字符的原因,他们的某个内部辅助函数都出现了空指针……


microhard的做法是: 此函数因空指针而崩溃;异常无法得到合适处理,软件崩溃了;一个窗口自动跳出,帮用户自动提交了此时的栈数据。

做freeware的菜鸟的做法是: 此函数因空指针而崩溃;异常无法得到合适处理;但这个菜鸟学习很努力,知道要尽可能“优雅地退出”。程序保存了用户数据,退出了。

做freeware的老鸟的做法是:此函数因空指针而崩溃;异常无法得到合适处理;但由于漂亮的模块划分,老鸟知道是find出了某种未知问题。于是提示用户重新搜索(当然会再次出错)。连续几次后,程序自动弹出一个表单,要求用户填写他都干了什么,然后自动提交。

而xx面业集团有限公司的做法是: 此函数发现了空指针(他没有用像以上三位一样用assert),返回arg error;但上层也不知道该怎么办,错误就这样被一层层向上传递着,同时又被扭曲着(从原始的null->arg error->xxx error->yyy error->zzz fault。。。);直到某个设计只能返回true或false函数,被归一为false返回——问题就这样莫名其妙的消失了;他们的程序理所当然的告诉用户“你要找的东西没有找到”。


最后:
microhard的软件最容易崩溃,补丁最多,但用户也最多。(用户:虽然它不稳定,但用起来就是顺手!)

freeware菜鸟的软件虽然看似比microhard稳定,但更新太慢;大量的bug一直赖着不改(其实是因为他不知道)。

freeware老鸟的软件最好,最稳定,更新也快,深受专业用户的喜爱;但所有用户都认为那不是一般人能用的——比如发生错误后那个吓人的考卷。

至于xx面业集团公司的软件,它简直稳定极了,而且一直都没什么bug被发现;但用户总觉得它什么都做不了(记者:请给xx面业集团公司的软件一个评价。 用户:这是个面子工程。他们就是做了几个窗口放在那里,只要看起来像,上级就会给他们拨款。老实说,这玩意儿我也会做【镜头:用户打开VB,正在窗口中放置控件……】)。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
32 [报告]
发表于 2008-07-02 13:05 |只看该作者
支持 shan_ghost 的观点。因为这是一种从全局出发考虑的观点。

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
33 [报告]
发表于 2008-07-02 13:19 |只看该作者
原帖由 benjiam 于 2008-7-2 12:51 发表
这种面条代码,说穿了就是一种“踢皮球”游戏: 发生错误了,没有人知道错误究竟在哪里,也不知道错误处理路径是什么;但无论如何,这个错误不能在我手里炸掉。

第一个接皮球的人 就该处理,他不处理 错误就 ...


从你这个回复里,我可看不到“立即处理”的影子:

如果有个逻辑错误,偶尔的发生, 影响到了3-5格模块的内容, 其他的逻辑错误都是返回错误。但是没有的异常错误, 最后在strcpy 里面爆发了。你想定位就慢慢花时间吧。


————————
assert的作用,就在于让“立即处理”不再是个可选项。这点显然我们已经取得了共识。


另外,请注意不同“错误”必须不同处理。
比如,申请mutex失败,就是系统问题;可能需要重试,也可能只能走放弃逻辑。
这类问题包括网络故障、磁盘访问故障等等,它们都是应该用代码逻辑处理的。

而给strcpy传递null,如果不是内存耗尽,那么就必定是逻辑问题。这绝不应该用对待普通错误的方式处理。而必须考察代码执行逻辑。
即使是内存耗尽,也必须在new之后第一时间处理,而不能让其继续扩散。

这种问题当然不可能绝对避免。但避免的方式应当像freeware老鸟那样,甚至像microhard那样都行;类似xx面业集团公司的做法只能是自寻死路。



另:
作为一个程序员,如果别人三言两语表明了逻辑,他的脑子里还浮现不出代码,显然是说不过去的。
在下就比较讨厌一问三不知,问急了“看代码”的人。
如果你连自己想做什么都说不清楚,你的代码逻辑可能是清晰的吗?
别人早把逻辑说的通通透透,你还是想要代码——请问,你是懒,想拷贝粘帖呢,还是实在听不懂人话?

当然,如果是想抠我回字写法上的错误,你显然是要失望了。
在下虽然不才,但也不会耗费时间去做毫无意义的低级重复工作——不知您是否每天都在写strcpy?

论坛徽章:
0
34 [报告]
发表于 2008-07-02 13:40 |只看该作者
而如何处理,如何将运行流程处理好是难度, 处理得不好 那就会象瀑布一样 流得到处都是。那时候 就是几百个分流 处理起来就真的要命了。  这才是面条问题。  在处理流程的时候,有些问题要急时的掐断它,否则 它会弄出很多分流,擦起屁股就很困难了。

在处理流程的时候,有些问题要急时的掐断它 不让他流出这个模块 就是定位。 该定位的时候就定位。 将一个错误一级级的反馈上去。 那里是头? 根据模块大小功能和设计,就可以确定。 如果无限的将错误反应上去, 后果就是 在最后的总体处理层面 将面对所有异常和错误情况。这样的情况的出现 只能说你整体把握能力不强,没有该掐断就掐断。

至于所谓的不同错误 不同处理 都是些嘴皮子的功夫,说来说去都是些大道理,只是些设计思想。没什么意义。就好像文科生能更好的背出20种内存分配策略,但是他什么都不会写。


而xx面业集团有限公司的做法是: 此函数发现了空指针(他没有用像以上三位一样用assert),返回arg error;但上层也不知道该怎么办??

但上层也不知道该怎么办。 那就是设计师水平问题,不是设计问题。已经错了 你不处理即时调整。 strcpy 返回错了, 调用者就应该处理掉。


最后结果
三者的搜索都不能用,而正常结果下都是能用的。 如果面页的程序 在错误条件下仍然不崩溃而返回一个错误代码。 我们仍然感到欣慰 ,至少我们不需要重新启动一次程序。还可以继续用下去。

无论是谁,看到一个蓝屏窗口。或者告诉你某某模块有问题 都没什么好感,都一样。错误对使用者来说没有太多区别。就好像 我的车坏了 是发动机坏了 还是水箱坏了,对我有区别吗? 我只知道车不能开了。

[ 本帖最后由 benjiam 于 2008-7-2 13:52 编辑 ]

论坛徽章:
0
35 [报告]
发表于 2008-07-02 13:45 |只看该作者
原帖由 shan_ghost 于 2008-7-2 13:02 发表
讲个小故事娱乐一下吧。


话说 microhard、某个做freeware的菜鸟、另一个做freeware的老鸟 还有 xx面业集团有限公司同时进入字处理软件领域展开了激烈的竞争。


为了争夺用户,他们都为自己的软件增加了 ...


基本同意你的观点。你说的面条代码实际上就是隐藏错误,而且产生大量的冗余代码。

一般而言,对于逻辑上不应该出现的错误应该使用断言。但有些情况还是要区别对待。比如,面向用户的程序,如果由于用户的不当操作;底层程序,外部设备出现干扰或异常。对于大型系统,这些都是无法完全避免的,总需要在某一层调用里做出错处理并返回错误信息,而不是在Debug版里抛出异常了事。

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
36 [报告]
发表于 2008-07-02 13:59 |只看该作者
原帖由 benjiam 于 2008-7-2 13:40 发表
而xx面业集团有限公司的做法是: 此函数发现了空指针(他没有用像以上三位一样用assert),返回arg error;但上层也不知道该怎么办??

但上层也不知道该怎么办。 那就是设计严密问题。不是设计问题。


或许吧。这必须根据具体情况区分。

但对strcpy来说,把一个错误由明确的null point变为arg error,不正是所谓的“设计严密”问题吗?

assert,让它炸。上层就知道该怎么办了:我的错,指针有问题,马上改……
返回arg error,上层当然就可以不知道该怎么办了。

ps: 设计严密问题 和 设计问题 有何区别?望先生教我。



最后结果
三者的搜索都不能用,而正常结果下都是能用的。 如果面页的程序 在错误条件下仍然不崩溃而返回一个错误代码。 我们仍然感到欣慰 ,至少我们不需要重新启动一次程序。还可以继续用下去。

无论是谁,看到一个蓝屏窗口。或者告诉你某某模块有问题 都没什么好感,都一样。错误对使用者来说没有太多区别。就好像 我的车坏了 是发动机坏了 还是水箱坏了,对我有区别吗? 我只知道车不能开了。


差别大了。
microhard和freeware老鸟的都可以保证每个功能都正确可靠,有故障立刻被发现,被修复,软件做的越来越好;
而xx面业集团的东西却永远无法找到bug,但也永远不能正确使用——你会发现,你的文档保存总是失败或者提示成功却丢失了所有信息;当你添加/删除了几个字符,忽然又能保存了。没等你欢呼,一个字体加粗又引来了显示错乱;鼠标一点,忽然又正常了……你暴跳如雷;然而他们的客服重复了你所能想到的一切操作,故障却再也没有出现……
这种东西,你敢用吗?

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
37 [报告]
发表于 2008-07-02 14:09 |只看该作者
原帖由 Wind-Son 于 2008-7-2 13:45 发表

一般而言,对于逻辑上不应该出现的错误应该使用断言。但有些情况还是要区别对待。比如,面向用户的程序,如果由于用户的不当操作;底层程序,外部设备出现干扰或异常。对于大型系统,这些都是无法完全避免的,总需要在某一层调用里做出错处理并返回错误信息,而不是在Debug版里抛出异常了事。


这些正是我一直强调的“以明确逻辑处理不可抗拒原因引起的故障”。

严格的说,assert只能用于找代码逻辑故障;异常则应用来处理不可抗拒原因造成的问题。


这样,会炸掉的都是编码逻辑问题(发行版一样可以使用异常捕获之,如freeware老鸟的做法);抛异常的都是底层/硬件错误;用户不当操作则应当用以预先设计的逻辑处理——做个图形界面的应该都知道根据情况灰掉按钮或菜单项有多重要吧。

论坛徽章:
0
38 [报告]
发表于 2008-07-02 14:38 |只看该作者
差别大了。
microhard和freeware老鸟的都可以保证每个功能都正确可靠,有故障立刻被发现,被修复,软件做的越来越好;
而xx面业集团的东西却永远无法找到bug,但也永远不能正确使用——你会发现,你的文档保存总是失败或者提示成功却丢失了所有信息;当你添加/删除了几个字符,忽然又能保存了。没等你欢呼,一个字体加粗又引来了显示错乱;鼠标一点,忽然又正常了……你暴跳如雷;然而他们的客服重复了你所能想到的一切操作,故障却再也没有出现……
这种东西,你敢用吗?


看来先生认为崩溃,而且每次都崩溃是一个发现故障,找到故障的好办法。


你会发现,你的文档保存总是失败或者提示成功却丢失了所有信息。

如果每次都能得到同一个错误码,定位是很快的。 的确 定位不如 崩溃来得直接和震感。

当然如果代码逻辑本身写得烂, 每次错误原因都不一样,那就没什么好说的。


然而他们的客服重复了你所能想到的一切操作,故障却再也没有出现 。
microhard和freeware老鸟 也可能出现这种情况, 如果偶尔崩溃,偶尔不崩溃。 定位是同样困难的。 只是2者表现形式不一样.

从产品角度来说, 出错给个出错的日志 是客户比较接收的方式, 崩溃,对于客户而言,即使你好,他们无法接收。所以更多时候我们
只能靠日志来调试。而不是一个崩溃。




返回arg error,上层当然就可以不知道该怎么办了。 如果是这样的想法,  我建议在strcpy 里面 先判断 是否为NULL 是的话 直接write stderr ,exit(0) 这样定位更好。


还有一个bug, 是我们产品中的, 说出来不怕丢人,
c++ builder 的每次会出现一个异常窗口。..... 无法找到调用点。 每次都是死在那里,出现的情况,次数,条件都是偶然的。 无论调试 环境还是日志 都无法记录这个异常的调用者。调用堆栈为空,日志一切正常。
最后我们只能起个看门狗,点掉窗口, 然后重启程序, 写上日志。

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
39 [报告]
发表于 2008-07-02 15:02 |只看该作者
入鲍鱼之肆,久而不知其臭

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
40 [报告]
发表于 2008-07-02 15:34 |只看该作者
原帖由 benjiam 于 2008-7-1 11:24 发表
假设你现在正在面试,主考不紧不慢地给出下一道题目:“请用C语言写一个类似strcpy的函数。
正在装载数据……
要考虑可能发生的异常情况。” 你会怎么做呢?很明显,对方不是在考察你的编程能力,因为复制字符 ...

我们的项目中用的都是第三种情况. 第一种确实不好,如果是守护进程里的,那有可能信息就没法看到了.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP