软件真的好难做啊
文/陈皓
还记得以前本站的那一篇“编程好难啊”吗,那是一篇众程序员调侃程序新手的文章,有恶搞的成分在里面。今天要和大家说的这个事没有一些恶搞和调侃的意思,是比较严肃的话题,你一定可以从中收获一些东西。这个话题来自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提醒用户,让用户确认确实是这样的。”
- “关于解决这个问题,移除那个断言,如果显示上会有问题的话,那就复制一下有不同关系的人就可以了”
- “你真的应该想想你的软件的价值是什么?市场在哪里?你真的要照顾这样的用户吗?”
挺好的,相信你对软件开发又学到了一些东西。