软件真的好难做啊
还记得以前本站的那一篇“编程好难啊”吗,那是一篇众程序员调侃程序新手的文章,有恶搞的成分在里面。今天要和大家说的这个事没有一些恶搞和调侃的意思,是比较严肃的话题,你一定可以从中收获一些东西。这个话题来自StackOverflow上的一个问题——Cycle in Family Tree Software,这个程序员问了下面这个问题:
我是一个写家族族谱软件的程序员(我用的是C++和Qt),这个软件基本上没有什么问题,直到有一天有个用户报告了一个bug。这个问题是这样的——我这个用户和他女儿生了两个孩子。
于是,我程序员的一些断言和硬性条件导致程序报错,因为我的程序在处理这个关系的时候,其发现X即是Y的爸爸,又是Y的爷爷,所以只能报错。
请问,在不需要移除我的断言和数据验证的情况下,我怎么才能解决这个问题?
看到这里,请重点阅读一下下面的两点:
- 如果你看到这里开始兴奋了,请你为你阴暗的心理去面壁反省10分钟,因为这是一个很技术的问题。
- 如果你开始陷入了深深的思考如何解决这个问题,那么你绝对是一个合格的程序员,因为你已陷入技术已经很深了,有点呆了。
我在前面说过,“这个是一个严肃的话题,你可以从中收获一些东西”,当然,我并不希望你来收获乱伦的知识和心得,酷壳是一个技术博客,应该是收获技术方面的东西。
从技术的角度上来说,这是我们经常在设计软件时犯的错误——
1)作了错误的假设(Assumption)
Assumption是软件设计的重大天敌,Assumption的动词Assume意为Ass u me – Ass you and me 。你的假设做得越多,你的设计就越不靠谱。这里的假设是——我们以为family tree是一个tree,其实并不是tree。Assumption是魔鬼。
还有一些经典的Assumption如下所示
- 最著名的就是那个y2k臭虫。
- 不要以为没有2月30日,在瑞典1712年有2月30日
- 一分钟有60秒?闰秒呢?
- 双胞胎的生日是同一天吗?
- 双胞胎的父亲是同一个?
- 性别只有男和女?
- 婚姻只能是异性? 关于这一点,推荐一篇强文——Gay marriage: the database engineering perspective (同性婚姻:数据库工程)
2)没有认真分析用户案例(Use Case)
在设计软件时,我们需要考虑各种各样的用户案例,比如如下的东西:
- 私生子的问题
- 一夫多妻或一妻多夫,同父异母,同母异父
- 就算一夫多妻制违反法律,也会有离异再婚的情况
- 同性恋的问题,虽然不能繁衍,但可以领养。
- 换妻活动
- 各种乱伦关系——这种东西那个民族都不少,尤其是古时候,比如:
不想再列下去了,人类真TMD恶心,有点要吐了。
——————————为了缓解一下恶心的气氛,请允许我插入一个搞笑短文——————————
一位自杀者在他的遗书里讲述了他自杀的原因,听起来实在让人头痛。遗书这样写道:“我和一个寡妇结了婚,她有一个已成年的女儿,我父亲跟我妻子带过来的女儿结了婚。所以我父亲就成了我的女婿,女儿就成了我的后母,我管父亲叫爸爸,而我父亲也管我叫爸爸;我女儿管我叫爸爸,但我却管她叫妈妈;我还得管我妻子叫姥姥,因为她是我后母的母亲。不久我女儿,也就是我后母生了一个儿子,他是我同父异母的弟弟,他也得管我叫姥爷,因为他也是我的外孙。后来我妻子,也就是我姥姥生了一个儿子,他是我后母的弟弟,我是他的外甥,所以儿子管我叫爸爸,我管儿子叫舅舅。另外我是我妻子,也就是我姥姥的外孙,同时也是我姥姥的丈夫,所已我也是我的外祖父。又因为我妻子是我的外祖母,我的儿子,也就是我的舅舅是我的弟弟和我女儿的弟弟,所以我……我的天哪,这么复杂的关系实在让我伤透了脑筋,我只有一死才能得以解脱……”
————————————————————————插入完毕————————————————————
看完上面这个短文,不知道你是否和我一样,觉得这么一个简单的程序将是如此难做啊。另外,我决定在下一次的面试中让应聘者来设计Family Tree的程序。
我又说多了,现在还是让我们回到技术上来。除了上面那几个观点,我在回复中还看到了如入一些有意思的回复:
- “我的软件没有bug,是你的生活有bug”——让我想到了程序员惯用的借口
- “算法中不应该加太多的限制,限制多了反而让算法不灵活。”
- “移除断言,并不代表就不出错,对于这种rare case,我们最好给一个Warning提醒用户,让用户确认确实是这样的。”
- “关于解决这个问题,移除那个断言,如果显示上会有问题的话,那就复制一下有不同关系的人就可以了”
- “你真的应该想想你的软件的价值是什么?市场在哪里?你真的要照顾这样的用户吗?”
挺好的,相信你对软件开发又学到了一些东西。
(转载时请勿用于商业目的,并请注明作者和出处)
(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)
《软件真的好难做啊》的相关评论
作为一个初级程序员,读了此文真是学到了不少,以前总是”作了错误的假设”
PS:此文还好是自家博客产出,要是写于别人家的一定会被和谐地~_~
可以体会到这一点。
不要靠巧合编程,不要做太多的假设
还是没说,如何在不移除断言的前提下解决这个bug?
遇到这种情况,如果我是软件作者,我会直接给那个人退钱……
我感觉这个问题和文件系统管理文件有类似的地方。如何让一个文件是另一个文件夹的子文件的同时又和他是同一层的?好像可以通过引入硬链接来完成。不知道这样可以解决不呢?
编程不是解决所有问题的钥匙!!
生活太复杂,程序不能解决所有的问题。
博主还没有考虑到外星人的情况;机器人的情况;变异人的情况,等等。
如果是我,会给那个用户专门开发一个定制版。
哈哈,你看懂我的文章了。
遇到这种问题或类似的问题,我第一反应就是 oh !my God!………然后沉默着 纠结好久 好久….最后还是不知道怎么解决。。
记得以前看的一本叫”编程之道“ 还是“编程之禅”的书里说过的:“一个客户关系软件和一个操作系统,你觉得哪个好做。回答是:操作系统.. 因为人类的世界太复杂”
所以要保持程序的扩展性。社会/人生太复杂了。;D
发不了评论。。。
既然这是生活中的异常,那么就把它作为软件中的异常,有些问题不是能不能,而是有没有必要去解决。这次这个问题本身就是问题,同意 coolshellfuns 同学所说的“编程不是解决所有问题的钥匙!!”。或许博主这一次过度思考,过度引申了:)
原来邮件地址顶级域名不合规范发不了评论
Family Tree这个提法导致了必然有bug,因为这个实际上是Family graph,不是tree
适合的才是好的,未必一定要很通用,毕竟乱伦是少的。
大笑 不止!话说,这真的是个严肃的技术博客吗?
把中心数据结构从树状结构改为一个有向图,他的麻烦好像很大啊!
还有,谁能保证marriage一定是两个人?如果是人兽恋、克隆人……
family tree只是英文,本来就不是数据结构的tree。这样搞本来就很搞笑,居然还严肃讨论。
“酷壳是一个技术博客,应该是收获技术方面的东西。” 楼主气场越来越强大了。
那个搞笑短文,其实是有歌的:I’m My Own Grandpa- Ray Stevens ( with family tree diagram)
http://www.youtube.com/watch?v=eYlJH81dSiw
@coolshell funs
同意楼上的说法!
简要总结我的想法:
* 软件设计不应该与”人生体验”以及”非工程技术类问题”相混淆
1.1. “软件难做”, 可以理解为一种技术困难, 或项目经验不足的表现
1.2. “软件真的好难做啊!”, 可以理解为一种情绪发泄, 是一种难得的人生阅历, 对某些喜欢简单生活的人是坏事, 对于喜欢修炼心性的人是好事
1.3. “错误假设和用户案例”, 虽然从标题的字面上看是技术的解决途径, 但从内容的展开来看, *有一部分*却是在”狗拿耗子”. 力图把天文历法(2/30), 伦理规范(Gay/换妻/乱伦), 行业监管(y2k)等其它领域的难题纳入技术的解决框架下来。
如果这些问题都可以用”工程技术手段”妥善解决, 或者都可以在各自的领域中得到妥善解决, 那么就不会有战争, 次贷危机, 恐怖主义, GFW, 高房价。。。。
但是, 楼主敢于妥善解决一切问题的精神, 是我无比赞赏的. 我甚至认为, 如果有更多的人追求”解决一切问题”, 世界也会变得更好.
这个貌似叫乱伦呀。
软件成银弹了?
太过于特殊的,发生概率极小的事情,特殊情况特殊处理.
难道不知道80/20法则吗?
除非上帝出来做软件,否则一个软件就仅适合于部分人,不可能适合所有人.
软件开发者是上帝吗?不是,所以他开发出来的东西仅会适合部分人.
所有当自己是上帝的软件开发者最终都会被上帝惩罚.
这确实是个解决方案嘛。
为什么要解决?Family Tree就是Tree。
像这种情况,还有那些乱七八糟的情况,一律不予处理。
这个问题其实有另外一个解释,就是你软件为什么要解决所有的问题?
我表示面壁10分钟后被瑞典的2月30号给雷到了!
+1
先了解需求,然后再开始设计。博主过度思考了。
自从经历了与中国TW的口水战,博主已经成神了
约束/假设和灵活性是软件的基本问题/矛盾吧。
受不了了,
没有规矩不成方圆
太有个性的情况就搞定制版吧
这样子的话,树的问题变成了 图。
两个人之间的关系,变成了 遍历两节点间的所有路径。
倒也不是不能解决。
说是严肃的讨论,结果文章分类是“轶事趣闻”,情何以堪。
楼上没发现,文章本身还真是轶事趣闻。几本没扯点正事。
在最开始对自己软件的定位很重要,你需要确认你是否需要满足多大限度的用户需求,当然,在有需求后加入一定的代码实现也并不是一个无法容忍的错,当然,有这样的想法很重要。
同意16楼的说法,这个不是tree了,是一个网。
这还只是两个人,那某些国家或地区允许一夫多妻,
假设这些妻出现了各种xxxx的问题,和其夫的这位亲戚那位亲戚整出各种名堂来,
我看你的软件怎么写和怎么处理…..
话说回来,我也想不出该怎么处理。根据我上面提出的假设,我先面壁半小时去吧
穿越了……
让我想起时间旅行的例子。
如果同一时空中同时存在两个我,其中一个我是从未来穿越到现在的。虽然两个都是我,但却有不是同一个我。
就想题目中“其发现X即是Y的爸爸,又是Y的爷爷”,X同时具具有了爸爸跟爷爷的身份。身份不同却是同一个人。
为什么要用树呢?用图不可以么?
虽然说做假设是不对了,这个family Tree的bug也没有必要深究
很少有人理解楼主的意思呀。
家谱确实是一个复杂的问题……
http://www.tenchi-web.com/fcmemo/kakei/kakeizu-2.jpg
不得不承认我太不严肃了……
大哥,您网站右边中部的“标签”内容字体大小不一样,有点错乱了,把源程序的该行标签内容的CSS的line-height属性改成1.2-1.5呗!
程序设计缺陷是医方面,但我认为这是用户群分析不足导致的。
撒,本来就是一个很简单的问题,何必“这种问题是corner case不需要解决”呢?还什么“LZ过度思考了”,说到底就是程序员懒嘛(其实我也是)。不过话说回来,一个读过历史的正常人都知道family tree不是tree,一开始硬要做成tree就是活该啊,回去看自己老家的族谱去。
用户需求分析就是一门不容易的课
@vczh
这表明软件设计不够完备,没有精准的反映问题的实质
建议你读一下这篇文章提到的Gay marriage: the database engineering perspective
极端的情况考不考虑,只为了需求服务,没这个需求也就没这些极端情况
@Babylon5
實際情況還是會發生的,那個楊振寧和他的岳父的關係,大家可找找.呵呵.
设计的时候考虑的过于“全面”,对程序员来说是噩梦,对老板来说是多余,对用户来说是迷茫。在软件界,没有绝对的完善,只有绝对的合适。