软件真的好难做啊

软件真的好难做啊

还记得以前本站的那一篇“编程好难啊”吗,那是一篇众程序员调侃程序新手的文章,有恶搞的成分在里面。今天要和大家说的这个事没有一些恶搞和调侃的意思,是比较严肃的话题,你一定可以从中收获一些东西。这个话题来自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)

在设计软件时,我们需要考虑各种各样的用户案例,比如如下的东西:

  • 私生子的问题
  • 一夫多妻或一妻多夫,同父异母,同母异父
  • 就算一夫多妻制违反法律,也会有离异再婚的情况
  • 同性恋的问题,虽然不能繁衍,但可以领养。
  • 换妻活动
  • 各种乱伦关系——这种东西那个民族都不少,尤其是古时候,比如:
    • 先后嫁了两个人其是父子关系(昭君)
    • 达尔文同学和他的表妹,爱因斯坦的二婚是和他的表姐,埃及艳后嫁了她的弟弟,……
    • 顺治同学娶了四个老婆,这四个人还是一家人:姑姑,侄女,妹妹,女儿。(参看这里
    • 刘邦同学的母后干出来的事,相当变态(参看这里
    • 中国古代的“扒灰老” (类似于楼主那个问题的Use Case)

不想再列下去了,人类真TMD恶心,有点要吐了

——————————为了缓解一下恶心的气氛,请允许我插入一个搞笑短文——————————

一位自杀者在他的遗书里讲述了他自杀的原因,听起来实在让人头痛。遗书这样写道:“我和一个寡妇结了婚,她有一个已成年的女儿,我父亲跟我妻子带过来的女儿结了婚。所以我父亲就成了我的女婿,女儿就成了我的后母,我管父亲叫爸爸,而我父亲也管我叫爸爸;我女儿管我叫爸爸,但我却管她叫妈妈;我还得管我妻子叫姥姥,因为她是我后母的母亲。不久我女儿,也就是我后母生了一个儿子,他是我同父异母的弟弟,他也得管我叫姥爷,因为他也是我的外孙。后来我妻子,也就是我姥姥生了一个儿子,他是我后母的弟弟,我是他的外甥,所以儿子管我叫爸爸,我管儿子叫舅舅。另外我是我妻子,也就是我姥姥的外孙,同时也是我姥姥的丈夫,所已我也是我的外祖父。又因为我妻子是我的外祖母,我的儿子,也就是我的舅舅是我的弟弟和我女儿的弟弟,所以我……我的天哪,这么复杂的关系实在让我伤透了脑筋,我只有一死才能得以解脱……”

————————————————————————插入完毕————————————————————

看完上面这个短文,不知道你是否和我一样,觉得这么一个简单的程序将是如此难做啊。另外,我决定在下一次的面试中让应聘者来设计Family Tree的程序

我又说多了,现在还是让我们回到技术上来。除了上面那几个观点,我在回复中还看到了如入一些有意思的回复:

  • “我的软件没有bug,是你的生活有bug”——让我想到了程序员惯用的借口
  • “算法中不应该加太多的限制,限制多了反而让算法不灵活。”
  • “移除断言,并不代表就不出错,对于这种rare case,我们最好给一个Warning提醒用户,让用户确认确实是这样的。”
  • “关于解决这个问题,移除那个断言,如果显示上会有问题的话,那就复制一下有不同关系的人就可以了”
  • “你真的应该想想你的软件的价值是什么?市场在哪里?你真的要照顾这样的用户吗?”

挺好的,相信你对软件开发又学到了一些东西。

(转载时请勿用于商业目的,并请注明作者和出处)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

好烂啊有点差凑合看看还不错很精彩 (30 人打了分,平均分: 4.27 )
Loading...

软件真的好难做啊》的相关评论

  1. 作为一个初级程序员,读了此文真是学到了不少,以前总是”作了错误的假设”
    PS:此文还好是自家博客产出,要是写于别人家的一定会被和谐地~_~

  2. 我感觉这个问题和文件系统管理文件有类似的地方。如何让一个文件是另一个文件夹的子文件的同时又和他是同一层的?好像可以通过引入硬链接来完成。不知道这样可以解决不呢?

  3. 博主还没有考虑到外星人的情况;机器人的情况;变异人的情况,等等。

    如果是我,会给那个用户专门开发一个定制版。

  4. 遇到这种问题或类似的问题,我第一反应就是 oh !my God!………然后沉默着 纠结好久 好久….最后还是不知道怎么解决。。

    记得以前看的一本叫”编程之道“ 还是“编程之禅”的书里说过的:“一个客户关系软件和一个操作系统,你觉得哪个好做。回答是:操作系统.. 因为人类的世界太复杂”

  5. 既然这是生活中的异常,那么就把它作为软件中的异常,有些问题不是能不能,而是有没有必要去解决。这次这个问题本身就是问题,同意 coolshellfuns 同学所说的“编程不是解决所有问题的钥匙!!”。或许博主这一次过度思考,过度引申了:)

  6. Family Tree这个提法导致了必然有bug,因为这个实际上是Family graph,不是tree

  7. 大笑 不止!话说,这真的是个严肃的技术博客吗?

    把中心数据结构从树状结构改为一个有向图,他的麻烦好像很大啊!

    还有,谁能保证marriage一定是两个人?如果是人兽恋、克隆人……

  8. family tree只是英文,本来就不是数据结构的tree。这样搞本来就很搞笑,居然还严肃讨论。
    “酷壳是一个技术博客,应该是收获技术方面的东西。” 楼主气场越来越强大了。

  9. @coolshell funs
    同意楼上的说法!
    简要总结我的想法:
    * 软件设计不应该与”人生体验”以及”非工程技术类问题”相混淆
    1.1. “软件难做”, 可以理解为一种技术困难, 或项目经验不足的表现
    1.2. “软件真的好难做啊!”, 可以理解为一种情绪发泄, 是一种难得的人生阅历, 对某些喜欢简单生活的人是坏事, 对于喜欢修炼心性的人是好事
    1.3. “错误假设和用户案例”, 虽然从标题的字面上看是技术的解决途径, 但从内容的展开来看, *有一部分*却是在”狗拿耗子”. 力图把天文历法(2/30), 伦理规范(Gay/换妻/乱伦), 行业监管(y2k)等其它领域的难题纳入技术的解决框架下来。

    如果这些问题都可以用”工程技术手段”妥善解决, 或者都可以在各自的领域中得到妥善解决, 那么就不会有战争, 次贷危机, 恐怖主义, GFW, 高房价。。。。

    但是, 楼主敢于妥善解决一切问题的精神, 是我无比赞赏的. 我甚至认为, 如果有更多的人追求”解决一切问题”, 世界也会变得更好.

  10. 软件成银弹了?
    太过于特殊的,发生概率极小的事情,特殊情况特殊处理.

    难道不知道80/20法则吗?

    除非上帝出来做软件,否则一个软件就仅适合于部分人,不可能适合所有人.

  11. 软件开发者是上帝吗?不是,所以他开发出来的东西仅会适合部分人.
    所有当自己是上帝的软件开发者最终都会被上帝惩罚.

  12. friedvan :
    我感觉这个问题和文件系统管理文件有类似的地方。如何让一个文件是另一个文件夹的子文件的同时又和他是同一层的?好像可以通过引入硬链接来完成。不知道这样可以解决不呢?

    这确实是个解决方案嘛。

  13. 为什么要解决?Family Tree就是Tree。

    像这种情况,还有那些乱七八糟的情况,一律不予处理。

    这个问题其实有另外一个解释,就是你软件为什么要解决所有的问题?

  14. +1
    先了解需求,然后再开始设计。博主过度思考了。

    helloworld :
    既然这是生活中的异常,那么就把它作为软件中的异常,有些问题不是能不能,而是有没有必要去解决。这次这个问题本身就是问题,同意 coolshellfuns 同学所说的“编程不是解决所有问题的钥匙!!”。或许博主这一次过度思考,过度引申了:)

  15. 这样子的话,树的问题变成了 图。

    两个人之间的关系,变成了 遍历两节点间的所有路径。
    倒也不是不能解决。

  16. 在最开始对自己软件的定位很重要,你需要确认你是否需要满足多大限度的用户需求,当然,在有需求后加入一定的代码实现也并不是一个无法容忍的错,当然,有这样的想法很重要。

  17. 同意16楼的说法,这个不是tree了,是一个网。
    这还只是两个人,那某些国家或地区允许一夫多妻,
    假设这些妻出现了各种xxxx的问题,和其夫的这位亲戚那位亲戚整出各种名堂来,
    我看你的软件怎么写和怎么处理…..

    话说回来,我也想不出该怎么处理。根据我上面提出的假设,我先面壁半小时去吧

  18. 穿越了……
    让我想起时间旅行的例子。
    如果同一时空中同时存在两个我,其中一个我是从未来穿越到现在的。虽然两个都是我,但却有不是同一个我。
    就想题目中“其发现X即是Y的爸爸,又是Y的爷爷”,X同时具具有了爸爸跟爷爷的身份。身份不同却是同一个人。

  19. 大哥,您网站右边中部的“标签”内容字体大小不一样,有点错乱了,把源程序的该行标签内容的CSS的line-height属性改成1.2-1.5呗!

  20. 撒,本来就是一个很简单的问题,何必“这种问题是corner case不需要解决”呢?还什么“LZ过度思考了”,说到底就是程序员懒嘛(其实我也是)。不过话说回来,一个读过历史的正常人都知道family tree不是tree,一开始硬要做成tree就是活该啊,回去看自己老家的族谱去。

  21. @vczh
    这表明软件设计不够完备,没有精准的反映问题的实质
    建议你读一下这篇文章提到的Gay marriage: the database engineering perspective

  22. 设计的时候考虑的过于“全面”,对程序员来说是噩梦,对老板来说是多余,对用户来说是迷茫。在软件界,没有绝对的完善,只有绝对的合适。

回复 crowball 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注