1、设计过度和设计不足同样不可取
所谓的过度设计,顾名思议就是代码的灵活性、复杂性超出所需。这个问题在一些没有项目责任心的人身上是不会发生的,因为他不会去为了让项目更灵活、功能更强大而去仔细的设计这个系统,反而在一些有心将项目设计好的人身上经常发生。产生这种问题的原因,其实还是对于模式这个东西的真正意义没有理解。模式是用来将系统变简单的,而不是用来将系统变复杂的。
设计一个灵活的、能够满足未来需求变化的系统这个出发点是很好的,但是必须正视现实:如果对未来的需求预计不正确,预期中的需求根本不会变成现实,那么按此编写的代码又怎样呢?毕竟我们都无法未卜先知。
如果我们遇见某个模块将来可能会发生需求变化,我们需要根据这个可能性的概率、要投入的成本以及将带来的收益去衡量一下。
一般的系统,生命周期达到3年而不做大重构的,已经非常不容易了。那么,我们在做一般软件的时候,就完全没有必要考虑到5年、10年以后的问题。距离现在越远,需求的可测量性就越小,自己对需求的猜测正确性就越低,现在的设计还能满足需求的概率就越小。
况且,我们可以先做一些小的工作,使得将来一旦需求变化,我们只需要重构模块内部而不会对周围模块产生大的影响,就可以了。
事实上,设计模式并没有标准的模型,每种模式在不同的场景下实现的途径都可能会不同,怎样实现模式与实际环境密不可分。因此,有意义的模式都是通过重构产生的,而重构往往会产生模式。
这,也就是“演进式设计”。
就好像我们要改造一个房子,我们要把一堵墙全部换成隔音砖。那,我们是一小块一小块区域的换呢,还是一下子把一堵墙拆了重新砌墙呢?呵呵,小心房子倒掉哦~~^_^
2、设计欠账
假设你去请求开发经理给你一些时间以重构现有代码以“改善其设计”,他会有何反应呢?可能是斩钉截铁的说不:应付没完没了的需求和bug就已经够难了,哪里还有时间让你“一段时间啥功能都没完成”。
使用重构的语言和大多数管理人员沟通,效果往往都不好。不过,我们可以用设计欠账来隐喻。
人类无法一次性就写出完美的代码。我们会自然而然的累积设计欠账。所以问题就变成“应该什么时候偿还设计欠账”?
用金融术语来说,如果不偿还债务,就会产生滞纳金。如果不偿还滞纳金,滞纳金就会越来越多,而去是按照复利计算的。随着时间的转移,债务就像滚雪球或者我们所说的驴打滚一样,越来越多。设计欠账也是如此。
因此,定期的清理设计欠账,是必要的。
3、模式的真正价值只是一种思想,而不是一个框图。
对设计模式过于痴迷的人往往会走向另外一个极端。如果一个简单的HelloWorld程序,有人用了Factory、Command、Observer、Templete Method来实现,你看了会如何呢?说到这里,使我想起了微软的PetShop网站。这个网站,用了大量的设计模式——实际上这个网站就是微软设计模式系列在线培训的例程。之前面试的很多人,都提到说看过PetShop。但问及里面的模式是用来解决什么问题的,就一问三不知了。甚至有人说,仿造PetShop做过系统——这个有用么?数据库教材里面有提到第二范式第三范式甚至第N范式,我们在设计数据库的时候也要遵循第N范式么?那样设计出来的,不是系统,而是花瓶。
实际上,PetShop只是用来演示“模式能够达到什么目的”的,而不是用来演示“模式应该在什么时候用”的。
之前面试时很多人在问到设计模式的时候,就会把设计模式教程上那些框图说出来。事实上,设计模式只是一个思想,他只是一些最佳实践,真正的价值在于告诉你“遇到某种情景,可以怎样解决”,而不是告诉你“遇到某种情景,应该怎样解决”。真正优秀的系统设计,往往是跟教程上那些框图对应不起来的。
4、模式是否会使得代码更加复杂
本书的作者提到了一个现实中我们经常遇到的相同的问题,呵呵。
某人A使用设计模式很好的改造了一个模块。在作者看来,这个改造使得这个模块变得灵活、可扩展、清晰简单。而另外一个不了解设计模式的B看到这个重构后,大叫“现在的代码太复杂了!我更喜欢原来的代码!”。而在作者教B学习和掌握了这个模式后,B勉强同意代码没有他原来以为的那么复杂,但仍然表示重构后的代码并不比原先的更好。
是啊。作者对于设计模式的熟悉,使得在作者的眼里这个重构是优秀的。这件事说明,人们对于模式的熟悉程度决对于他们如何看待基于模式的重构将起到决定性的作用。因此,开发小组需要进一步学习这些模式,另一方面,某些模式的实现确实会使得代码过分复杂,如果出现这种情况,返回或者进一步重构就非常有必要。