一星期8天

Eight Days a Week - by The Beatles & 小陆

Keep It Simple and Stupid

Keep It Simple and Stupid, 就是KISS原则. 简单是软件设计之美, 简单的设计使得软件产品易于开发, 易于维护. 简单代表着高质量, 少加班, 每个人都希望自己的工作是简单的.

在KISS原则之外, 应该有一个更重要的原则: Useful. 满足需求是一切产品的低限. 也许需求本身也应该KISS, 简单的需求意味着底成本, 高效率. 可惜客户有时候很难克制自己的欲望. 也许站在客户角度看见的KISS和我们开发者眼中的KISS不完全是一个概念. 有人说: 好的设计是客户做出来的, 开发者其实只是在帮助客户做设计.

Keep
It Simple and Stupid, 最难的在于Keep. 一个人做一个Simple的设计并不难, 难的是让这个设计在需求变化的过程中保持简单. Keep是关键, Keep的时间就是这个设计的生命. 当一个产品无法再Keep Simple的时候, 维护就变的越来越困难, 渐渐的无法加入任何变化, 他的生命也就快结束了. 升级意味着重新做一个.

Keep Simple就是要抵抗需求的变化, 一开始的需求总是比较简单, 比如这样: 设计一个汽车驾驶程序, 他会在遇到红灯的时候停下来, 绿灯的时候向前进.

方案一:

if red_light then
    
stop()
else if green_light then
    go()
end if


这是一个简单的需求, 给出的解决方案也很简单. But, 如果遇到这样的情景: 红灯已经亮了, 但是车前面有个人正在过马路, 他走的很慢. 这个时候当然不能go, 应该按响车喇叭, 等他走过去. 方案一必须要修改: 

if red_light then
    
stop()
else if green_light then
    
if people_ahead then
        ring()
    
else
        go()
    
end if
end if


现实的情况仍然可能发生变化, 比如: 前面尽管是绿灯, 但是横向路口一辆救护车开过来, 或者前面有一个路牌"道路维修请绕行"......种种情况, 其结果就是要在原来的if-else里面加上一个新的判断.

这是一个Simple的设计, 但是很难Keep Simple. 当这个代码片断不断增加, 长度突破500行的时候, 任何相关的需求变更都是一场恶梦. 在软件开发中更复杂的情况我想大家都遇到过.

方案二
:

想象有一个叫做策略的东西, 他有下面的特征: 他有一个名称, 一个优先级, 他可以判断某种情景, 返回在这个情景中应该采取的行为. 红灯停, 绿灯行, 有人在前面要按喇叭, 都是具体的策略. 就是下面这个结构:

还应该有一个Action, 代表策略判断后应该采取的行为. 前进, 停止, 按喇叭都是具体的行为, 这样的结构:

最后的程序运行过程就是这样: 先初始化一个stratage list, 将需要判断的策略都放在里面. 在需要的地方一一判断这些策略, 执行优先级最高的策略所返回的行动就可以了.

dim action as new Action
for each stratage in stratage_list
    
if stratage.Priority < action.Stratage.Priority then
        
'如果当前的策略优先级小于行为的策略的优先级,就不用判断这个策略了
        continue
    
end if
    stratage.Judge(action, env)
next
action.
Do()

这样的设计, 随着需求的变化, 策略日益复杂, 只要添加新的stratage, 赋予合适的优先级, 再视情况派生新的action就可以了. 程序的复杂程度不会随之增加.

Quick & Dirty vs 过度设计

设计应该始于简单, 保持简单. 作出一个简单的设计, 当需求发生变化, 首先应该做的就是重构设计, 使之重新变得简单, 然后再加上新的功能. 简单不是quick and dirty. 简单的东西也许会变得复杂, 复杂的东西也许本质上是更加的简单. 这首先需要对需求充分的理解, 当然还有一点点的技巧. 过分的设计也是一个问题, 但是考虑一下维护人员的痛苦, 一个过度设计的系统通常要比一个quick and dirty的系统更加便于维护.

posted on 2005-07-14 13:48 小陆 阅读(2230) 评论(8)  编辑 收藏 所属分类: 开发技术

评论

#1楼  2005-07-14 14:23 Nineteen@newsmth [未注册用户]

好文!但是,对于一个简单的需求来说,如果一开始就采用一些并不那么简单的模式、模型,也可以使得越来越复杂的需求变得简单化,欢迎用户需求发生变化,欢迎用户增加新的需求,是一个成功软件的重点。   回复  引用    

#2楼  2005-07-14 16:24 birdshome      

参看“学习模式之我见 ”。你的文章有些观点是经不起推敲的,"满足需求是一切产品的低限",这个"需求"是什么?用户的需求本身就是无底洞,根本没有什么底线的说法。很多时候能否堵住用的需求根本不是技术问题,而是公司的公关水平。
"作出一个简单的设计, 当需求发生变化, 首先应该做的就是重构设计, 使之重新变得简单, 然后再加上新的功能." 这个地方有个非常重要的度的把握问题,过于simple&stupid的设计,会使任何的改动都是噩梦。简单了,质量高?只是因为都没有可以制造错误的地方了。
对于这样频繁的重构,还妄想少加班?重构对于提高软件的整体结构和质量确实有很大的帮助,但是重构不同于debug,重构基本会浪费掉Test Team对原有代码的所有测试开销,debug的对tester的影响相对就小多了。那么我们就肆意的容忍被修改的乱成一坨屎的设计和代码吗?对于产品的重构,真的要少加班,除了出现不能发布的缺陷,都要顶到下一个版本再重构,否则公司的资源也经不起折腾。
回过头来看设计,也就是不管你怎么simple&stupid,应该保证在一个版本或次版本中,你的设计要基本经得起用户需求的摧残。
  回复  引用  查看    

#3楼 [楼主] 2005-07-14 17:40 小陆      

re: birdshome
需求:需求是用户认为给了我们钱应该买到的东西,也是我们认为能为客户提供的东西.这应该不是一个无底洞,最多有一个含糊性.确实也有公司业务的因素,总的来说应该是有标准的,实在是不能做,或者是价钱太低,就不应该签这个合同.要是签了,就是大家的不幸了.

重构:重构确实不同于debug,但是也绝对不是重写一遍,一般来说,应该有测试程序.重构的过程要依靠测试程序来保障,保证模块之间的接口有一定的稳定性,确定影响的范围.我觉得重构要求系统具有一个比较灵活的结构,一个差的系统,想重构也是比较难的,说不定就等于重写了.   回复  引用  查看    

#4楼  2005-07-15 09:09 阿浪      

Mark,关注.   回复  引用  查看    

#5楼  2005-07-16 00:30 飞刀      

其实没有什么好争论的。
我现在已经看开了,太多人浮在表面上了。
OOP叫喊了这么久,有很多人虽然用着java ,用着c#,但是连对象设计的基本原则都搞不清楚,有时候真是无奈,我都选择沉默了。   回复  引用  查看    

#6楼  2005-07-21 16:59 Nethome [未注册用户]

能不能把过红绿灯的实例,用stratage模式实现出来,好让我理解一下,我现在看得不是很明白   回复  引用    

#7楼 [楼主] 2005-07-21 17:57 小陆      

to Nethome:
如果我没记错的话,stratage模式是要在多个stratage中选择一个进行应用,文中的例子是要应用所有的stratage,然后实施优先级最大的stratage返回的action.   回复  引用  查看    

#8楼  2005-07-28 15:51 许多 [未注册用户]

疑问: 在你的例子中,你所谓的策略的优先级是怎么确定的?   回复  引用    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2005-10-14 22:53 编辑过


相关链接: