楼主

79515发表于 2019-11-28 09:18:25
只看该作者楼主

【综合】现实世界与软件设计 [复制链接]

作者:HW-HM


现实世界和软件设计都是复杂而有趣的事情,我们都希望它们变得简单,这样我们就不用活得这么累。可现实世界就是这么复杂,每个人揣着不同的目的,彼此互动,或齐心协力,或明争暗斗,或坑蒙拐骗,所以每个人都希望知道得多点,省得吃亏,因为现实世界不是自己可以控制的,只能采取保护自己的手段。 希望知道得多点里面,也包括了软件设计的知识,为的是把软件做得简单点,省得自己受累。


现实世界和软件设计有很多相似的地方。

先谈合作的问题,这可是个大问题。碰到陌生人在路上递给你一只烟,你可能不会接,就算接了,你也会小心翼翼检查一番,省得中了迷药,钱财两空。陌生人不可信,所以我们时刻防御着,而如果是朋友递过来的烟,拿过来就抽,连打火机都省了,效率多高啊。现实中的陌生人也容易合作,他们之间没有信任,但是可以彼此签合同(契约),签了合同大家就得按合同办事了,因为有法律保障,有纠纷法院会作出仲裁,扯皮的事就少了。软件的世界里,没有法律保障,所以只存在可信不可信的问题,如果可信,大家就按约定办事,省了很多不必要的检查。但是始终不检查,对方因疏忽没满足约定就会出问题,所幸软件的世界里,可以进行任意次的预演(调测版本),于是就在预演时进行检查,真正演出(发布版本)时去掉检查,这样疏忽杜绝了,演出效率还高,两全其美。这就是契约式设计的思想。软件的世界里,不可信的很多,譬如网络数据、用户输入,你和它们之间不可能有约定,事实上,它们可能就是黑客提供的,所以对这些你都得小心翼翼处理,进行仔细地检查,不管它怎么折腾,你都不会出差错,这就是防御式编程,和我们对陌生人的防御是一样一样的。对于可信的,不建议这么做,这样就过度防御了,关起门来都是一家人,何必呢?

再谈制造的问题。今年准备买车,就说汽车的制造吧。汽车有很多部件,底盘、车身、车轮、内饰、发动机等,通常一款汽车,譬如迈腾,车身和地盘是一样的,这样才容易看出是哪一款。但是同一款的发动机和内饰却不一样,发动机排量可以是1.8、2.0的,有的内饰只要豪华版才有,有的内饰豪华版比普通版的要高级。不过同一款车发动机和各内饰的位置都是固定的,并且怎么安装上去的方式也是固定的,通常是通过螺丝钉固定,只要这些部门能够按照这种方式装上去就可以随意替换,这使得汽车生产保持了灵活性。事实上汽车的所有微小部件都是用螺丝钉拧上去的,每个部件的功能非常单一,这使得这些小部件可以交给不同的厂商生产。软件设计也是一样的,从软件的观点看汽车,车身和底盘是高层模块(逻辑),同一款车的高层逻辑是固定的,它决定了各部件的安装位置以及配合关系,但是它不依赖于某个具体的部件(例如1.8的发动机),只依赖于这些部件安装上去的方式,这个安装方式就是高层模块(底盘)和底层模块(发动机)之间的接口,这就是依赖倒置原则,高层和底层都依赖于安装方式。非常多的小部件,反应的是单一职责原则,如果将多个变化整到一起,想独立替换就会比较麻烦,每个部件对应了一种变化,也就是职责。这些原则的最终目的就是封装变化,使可能变化的部分能够灵活替换,这就是软件设计的终极原则,开放封闭原则。


现实世界和软件设计有很多不同的地方,我们很容易按现实世界的直觉来做软件。

先说说交往的问题。现实世界中,我们总是希望多认识些人,多知道别人的底细,在家靠父母,出门靠朋友,这对我们有好处,因为我们指不定哪天就需要别人帮助自己点什么,同时三教九流各阶层的人我们都希望认识,我们与这些人黏得越紧,能获得的好处通常越多。而在软件的世界里,需求是知道的,我们可以控制软件按照我们的意图做事,如果这些软件实体(类)彼此知道太多黏得太紧,却不是好事情,对于完成我们的意图并没有帮助,只会增加复杂性(耦合)从而导致更多的错误,这就是最少知识原则。在软件的世界里,强调阶级制度,不希望三教九流互相联系,因为这样会导致复杂,高层模块可以调用底层模块,反过来就不行,如果它们互相依赖形成环,就更糟糕了,这是非法联盟,这与包的无环依赖原则是违背的。等级制度是最简单清晰的的,最好是上层只与下一层打交道(调用下一层的接口)。


再说说父子的问题。现实世界,判断一个人是不是另一个人的儿子,通常做DNA鉴定,判断一个具体动物是不是属于某个物种,也是看得内在属性,而不是外貌。不过在软件的世界里,正方形是一种特殊的长方形,却不是长方形的子类,因为对于一个长方形,设置长为5,宽为3,那么面积就应该是15,而正方形不满足这个期望。在软件的世界里,判断儿子(子类)看的是表现出来的行为,老爹有的行为它都有,才是子类,这就是里氏替换原则。

现实世界中的人很懒,而软件却很勤快,天天都在运行。有时,我们觉得新增一个文件或者类太麻烦,于是就把一个函数或一段代码加在一个现有的类或者文件当中了,我自己就这么搞过,还不止一次,这样的东西,我觉得有个规定还是不错的,有规定别人指出我违反了,我就不好意思不改。现实中的人们为了生活四处奔波,我们通过移动电话或者网络才能找到。而软件世界中的实体,不应该四处漂泊,它应该在它应该存在的地方,而不是可以存在的地方,这样我们就很容易找到它,容易找到,才不会重复制造轮子。现实世界中人们对自己总是往好处想,“只修改了一行代码不会出错吧”,于是直接提交了,“是测试的哥们用法不对,而不是我的程序有bug吧”,我们总是抱着侥幸的心里。可是在软件的世界里,一点点错误都可能导致不可用,少一个分号,就会编译不过,报一堆的错误;越界写一个字节,程序都可能coredump。软件需要的是逻辑严谨、毫无暇疵,所以不能只靠大脑和眼睛,因为它们经常会欺骗自己。

总结:现实世界太复杂,不可控,所以我们要知道得尽可能多(包括软件设计知识),以能应对。而软件是可控的,所以我们要让它变得更加简单。现实中的生产和软件设计相通的道理就是封装变化,使其可以独立地被替换,这是软件设计的终极原则。


可怜的码农门在复杂而有趣的现实世界和软件世界中同时折腾。



举报
发表于 2019-11-28 13:51:38
只看该作者沙发

很有趣的分析

举报
楼主发表于 2019-11-28 16:55:20
只看该作者板凳
举报
楼主发表于 2019-11-28 16:55:30
只看该作者地板
举报
楼主发表于 2019-11-28 16:55:52
只看该作者5 #
举报
楼主发表于 2019-11-28 16:56:05
只看该作者6 #
举报
楼主发表于 2019-11-28 16:56:38
只看该作者7 #
举报
楼主发表于 2019-11-28 16:56:47
只看该作者8 #
举报
楼主发表于 2019-11-28 16:57:00
只看该作者9 #
举报
楼主发表于 2019-11-28 16:57:16
只看该作者10 #
举报

您需要登录后才可以回帖

登录注册
发表回复