现代科技的设计方法

在一个论坛上看关于单元测试的辩论时 ,有几个回复关于如何从一个基础理论,通过机制和策略的反复,层层抽象,最终设计出复杂产品的过程,非常精彩,故转载过来


DD教、UML教还有面向对象教最大的问题,就是搞出种种清规戒律、却逃避甚至排斥“作出简单到明显没有错误的方案”方向的任何努力。而后者才是解决软件质量问题的正确方向。
所以才说:软件的质量不是测试出来的,而是设计和维护出来的。

现实本身就是复杂到没有明显的错误, 所以如果作为对现实的一种映射的代码是简单到明显没有错误, 那么很明显代码是简单到反映不了现实情况.
这种说法就跟老金的”无招胜有招”,老子的”无为而无不为”一样, 听着挺有道理,看着也挺有道理,可就是现实中行不通.

现实本身就是复杂到没有明显的错误

我不知道你这个结论是从哪得来的。

现实本身,至少从目前的认识来看,牛顿三大运动定律本身基本就可以囊括一切了;更变态一点的需求,可以通过相对论修正(比如GPS。但相对论本身不过是两句话和两个变换公式);至于量子力学,它的修正现在基本用不到——即使用到,它也不过就是一句话罢了。

至于化学,早在上百年前就已经可以归结为物理了。

————————————————————————————
很显然,现实本身是如此简单明了;也正因为其简单,我们才可以自牛顿力学开始,逐步深入,搞出现代文明体系。

牛顿力学的确并非现实的精确表述,在一些极端情况下,它需要打一些补丁。

而目前需要打上的补丁,也不过是为极端情况加上简单的两个修正(广义/狭义相对论),量子力学暂时尚无用武之地。

————————————————————————————
牛顿三大定律是机制;由它构成某种复杂系统则是策略。

——类似软件核心设计的“提供机制但不提供策略”理念一样,谈及策略,就必须具体到某个行业。

以汽车发动机设计举例,其后台机制仍然是牛顿三大运动定律,实现策略是汽缸/活塞/曲轴/连杆/轴承/齿轮:举凡机械,没有什么超越以上构件范围的。

显然,这也就是说,到了发动机上,无非是:基于牛顿三大定律这个库,提供了汽缸/活塞/曲轴/连杆/轴承/齿轮这个新的基础库;而如何利用汽缸/活塞/曲轴/连杆/轴承/齿轮等等机制以实现特定的机械,需要工程师设计另外的“策略”——而这个策略,显然不是汽缸/活塞/曲轴/连杆/轴承/齿轮库所应提供的。

如此反复,层层抽象,每层都很简单;等到了汽车整车上,就是“利用发动机/变速箱/轮胎/车身这个库提供的机制”,以某种“策略”实现特定车型了——显然,这仍然很简单。

正是基于以上思路,现代工业才成为可能。
——————————————————————————————

很显然,正因为你和另外一些人根本理解不了现代科学的根本理念,这才会把它和“无招胜有招”这种扯淡相混淆。

更具体点说,接受了现代科学根本理念的人,自然会把库-机制-策略看做吃饭喝水一样平常,他们自然懂的“怎样才能把软件搞简单”:无非是合理分层、正确抽象、区分机制和策略罢了。

相反,脑子仍然被“道可道,非常道”这种垃圾充满的,他们除了哭“现实如此复杂”,还能做什么?
面对“复杂的现实”,他们要能找到哪怕一丝脉络,那才叫白日见鬼了。

正是这种人,才会去不着边际的吹捧TDD教/UML教以及面向对象教——严肃的后三者的确是利器,但不应被没有自控力的小孩子接触。

会者不难,难者不会,这句话精辟的描募出了掌握正确规律者和稀里糊涂者在面对问题时的不同。

invalid
2012年10月8日13:55 | #4
回复 | 引用
用一个例子来展示“如何设计简单到明显没有错误”的软件吧——以office为例。

从哪开始呢?

——————————————————————————————————
100年前,甚至更早,人们已经认识到计算是可以机械化的了。于是,他们发明了算盘、计算尺、手摇计算机……甚至积分电路。

不过,以上种种都只能解决一个方面的简单问题;通用计算机?对不起,没门。世界是如此复杂……

然后,图灵大神诞生了。

——————————————————————————————————
图灵其实只是做了这么个工作:
1、用数字为操作编码,并把这些被编码的操作看做一台机器的基本零件
2、利用这些编码构建代码序列
3、输入代码序列,机器就按次序逐个执行代码序列中的编码对应的操作;而精心设计的、按次序执行的操作就可以完成某种功能(这是专用计算器,还不是通用计算机)
4、证明支持特定编码的机器,可以通过代码序列模拟任何其它机器——这种机器就被认为是图灵完备的,它就是通用计算机。

简单来说,图灵是说:实现一个根据指令代码序列做对应操作的机器,只要这个机器提供的操作指令之集合能达到“图灵完备”的程度,它就是通用计算机。

然后?基于这个“执行操作序列”的机制,请脑补如下策略:
1、把操作定义为数学运算指令和跳转指令(以后简称为指令)
2、用这些指令写程序吧
3、执行程序
4、证明1里面定义的操作是图灵完备的

这就是基于图灵机制的、以数学运算和跳转指令这个策略实现的通用计算机。

比如,x86就定义了一套指令;而arm则定义了另一套;power pc则又是一套……
它们都可以处理任何可计算问题。

所以:
1、图灵机是机制
2、具体的x86指令集是策略
3、x86指令集解决的,是“高效率支持图灵所预言的通用计算能力”问题
———————————————————————————————————

现在,我们开始设计高级语言——此时x86指令集是机制,我们设计的语言是一套策略,它将为常用软件的设计者提供一套机制:这套机制可以使得他们可以高效开发软件。

高级语言的示例之一就是C。它把x86/arm/power pc等等指令抽象为少量关键字/运算符,使得写程序像写英文、写数学公式一样简单。

———————————————————————————————————
终于到可以设计软件的时候了。我们写一套office软件吧……

嗯,这个真是太复杂了……

别急。

———————————————————————————————————
具体到我们这个需求上,c的能力太弱了。它提供的机制虽然足以让我们做任何事,但到office上,这就相当于要求我们要利用它的机制实现无限复杂的策略——而这是无法容忍的。

所以,第一步,先写一套glibc,封装基本的数据结构和算法吧——glibc是基于C提供的机制实现的一组算法/数据管理算法(策略)。

当然,对很多人来说,算法很难。不过,具体到某一个算法上,它并非不可理解。还是那句话,难者不会,会者不难。

好在,有glibc(以及其它很多库),写高层应用已经很少需要理睬那些基本算法了。

————————————————————————————————————
即使有了glibc,仍然不到写office的时候——虽然只靠C甚至机器指令也一定能做到——我们需要更强悍的机制。

基于glibc提供的机制(上一层次实现的一组策略,到下一层次就成了机制,这事实在太常见了),我们可以写个GTK。
GTK将抽象显示器上的一块块区域(窗口),并抽象用户(通过鼠标/键盘/其它输入设备)和它们的交互(消息)。

然后,窗口(以及消息)是机制,具体的某种widget是策略……

进一步的,抽象数据存储为model,抽象窗口为view,抽象动作逻辑为control——这就是MVC架构。
熟悉GUI的应该知道从微软的MFC架构到经典的MVC架构,GUI库的设计理念发生了多少改变——这里就可以看出,写“明显没有错误”的软件有多难了。

当然,有了GTK,基于GTK提供的机制,实现office就容易太多了。

而GTK本身虽然称得上庞大,但核心其实也就那么几个类以及简单的几个逻辑而已;其它五花八门的种种widget,其实不过是基于核心那几个类/算法提供的机制实现的一些策略罢了。

换言之,如果你深入分析GTK源码的话,轻易就会发现它内部其实也是分层的,每层实现若干策略,这些策略的作用是给更上层提供简单好用的机制……“上一层次实现的一组策略,到下一层次就成了机制”,这句话应该不会这么快就忘掉吧?

这种特点,决定了GTK可以成为高效、稳定的基础库。
—————————————————————————————————————

然后?开始写office吧?

别急,别急。首先我们需要定义一套文档格式,为了兼容,最好用xml格式;而xml本身需要一套库来存取(封装解析);此外,组成office的word/excel等应用需要相互调用,这需要某种通信机制甚至是OLE/COM(当然,这两个抽象很糟糕)……

总之,很明显,即便有了GTK等框架库,到office的路依旧漫长。我们仍然需要步步为营,作出一层层漂亮的抽象。但一旦这样做了,那么到了最后,就好像在程序中内嵌浏览器一样,简单到只有一步而已。

当然,这中间的过程,尚须从实践出发,一点点补足。但至少有一点可以预言:它必然是分层的,且提供的抽象必须尽可能基本,否则就会带来不必要的复杂度——比如从SDK到MFC到MVC,简化程度不啻于从地心说到日心说:注意地心说并非不能解释行星运动,只是相对于日心说,它太复杂了。

事实上,请自行研读著名开源项目的代码,甚至就是从微软的sdk里,都能随时随地发现以上设计原则的痕迹——对这个原则的应用水平是另一回事。

——————————————————————————————————

很显然,好的软件设计,依靠的不是什么TDD、UML、OO,而是发现规律、抽象规律、精简规律;只有到最后一步实现规律时,才可能用到OO之类提供的机制(而不是它的方法论)。

所谓简单到明显没有错误,其实就是:尽量让每一层都抽象出尽量少而基本、但同时还必须完备的规律(机制),让程序的正确性由规律来保证。这样,只要规律抽象没问题,程序就不会有问题——而规律是否正确,是非常容易考察的。

当然,每一层规律的具体抽象方式,可能都需要一个甚至多个地心说到日心说的演变过程才能走向完善。不合理的规律会带来基于这个规律的实现策略的复杂度(比如用地心说去描述行星运动)。这就是写“明显没有错误的软件”如此困难的根本原因。

至少在现在,这种抽象只能由人来完成,人工智能都无从染指。TDD之类机械的方法论要有用,把它写成一秒上亿步的人工智能多好?又快又不会出错,早就该替代设计师了。

——很明显,TDD/UML/OO之类的方法论根本就没资格在设计这个领域发言。虽然它们在具体实现某个东西时可能很犀利,但它们不是设计。它们甚至都提不出地心说,更不可能帮你从地心说优化到日心说。

拿它们来掺和软件设计,这不是错误,这是笑话。它的可行度,一点都不比“请一大群猴子随机敲键盘来输入莎士比亚全集”高。

当然,相比于那些完全不知规律为何物、只知道现实很复杂、复杂到超出他们掌控的人来说,TDD/UML/OO等方法论的确是一根不错的救命稻草……它至少使得一些人在装着做什么事时,能够更像神殿祭司而不是跳大神:这两者的唯一区别是前者有章法、后者随心所欲。但也就如此而已。


原文地址:http://coolshell.cn/articles/8209.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值