重构到模式-序
“模式和重构之间有着天然的联系:模式是你想要到的地方;重构是从另一个地方到达那里的路径。”
--《重构--改善既有代码的设计》
“我们的设计模式取自重构所得的结构……设计模式提供了重构的目标。”
--《设计模式:可复用面向对象软件的基础》
软件模式的伟大之处在于总结了许多有用的设计理念和经验。然而,学了一些模式,就能成为一个优秀的软件设计者吗?在刚学过并使用了模式之后,我想当然过。模式指导我开发了有柔性的框架,构建了可扩展的软件系统。几年过去,我发现我的模式知识和对模式的频繁使用,导致了工作变得“过度工程”(over-engineering)。因为在设计初期就使用模式的话,注意力会被集中到如何使用模式上,而不是如何满足需求上。结果导致了不恰当的设计(过度设计或是设计不充分)。因此,在初始设计中,除非非常有把握(此前有类似的经验),否则我们都应当把精力放在如何满足需求上。
随着设计能力的提高,我发现我正在以一种与以往不同的方式来使用模式:重构到模式,而不是把它作为设计起点或过早的引入代码中。新的模式应用方式避免了“过度工程”(over-engineering)和“欠缺工程”(under-engineering)。
“过度工程”产生的原因是因为过于相信,今天设计的越灵活,就越能调节、适应明天的需求。看起来很有道理。但是一旦你的预测是错误的,那你就是在浪费时间
和金钱
。如果这些代码从来不会被用上,又不删掉(因为已经不方便删?或是舍不得以期哪天能用上?),不必要的过度柔性代码大量堆积,影响到生产力,尤其是影响其他协作成员——在可以放心的扩展和维护之前,不得不花费大量时间去搞懂设计的细节。
“欠缺工程”比“过度工程”更为常见:只求快速的添加更多的功能,不考虑改善设计。一旦代码能够工作,就转移到其他任务上去,不再花费时间来改善它。当然,或许我们也想有时间去改善代码,可是开发任务和客户不给时间啊。不幸的是,这种方式只会导致如下软件开发节奏:“快,慢,更慢”
。
研究优秀设计方案的演进过程
要想成为一名优秀的软件设计者,研究优秀软件设计的演进,会比直接研究优秀设计本身更重要。在演进中蕴含着真正的智慧。演进的结果可能会有所帮助,但是如果不知道为什么演进到如此设计,就可能会滥用误用。模式是面向对象设计的基石,而测试先行编程和无情重构则是设计演进的基石。
重构文献,正可以帮助我们获取对优秀设计方案的理解,方案的每一步演进都会有所启迪。![]()
要真正从模式中获益,就必须关注应用模式的上下文,而不仅仅把模式作为可复用元素。
只针对有需要的设计进行重构
任何时候,请确保重构行为仅仅针对那些确有重构需要的设计。重构需要花费时间和精力,而无用的重构并不能够为软件增加价值。重构的需要来源于两点:一是需求的变更。目前的设计可能无法满足新的需求,因此需要重构。二是对设计进行改进,以得到优秀简洁的设计。除了这两种情况,我们不应该对设计模型进行重构。只有发现某部分的设计需要额外的灵活性来满足需求时,才需要引入模式。
使用文档记录重构的模式
应该承认,模式为设计提供了充分的灵活性。而这些设计部分往往都是模型的关键之处和难点所在,因此需要对模式进行文档化的工作,甚至在必要的时候,对这部分的设计进行培训和指导。确保你的团队能够正确的使用文档来设计、理解、扩展模式。应该尽可能延迟文档的创建,而在设计被重构到模式的时候,我们就需要进行文档化的工作了。因为模式具有灵活性,能够抵御一定的变更风险。
重构并保持模式的一致性
正如上所说,模式并不是一个很容易理解的东西,虽然它保持了设计的灵活性和稳定性。对于面向对象的新手而言,模式简直就像是UFO一样,由于缺少面向对象的设计经验,他们无法理解模式的处理思路,在实践中,我们不只一次的碰到这种情况。我们不得不重头开始教授关于模式的课程。因此,最后我们在软件设计只选用一定数量的模式,并确保在处理相同问题的时候使用相同的模式。这样,适用的模式就成为解决某一类的问题的标准做法,从而在一定程度上降低了学习的曲线。
注:本系列文章是阅读Joshua Kerievsky先生的Refactoring To Patterns的摘译和读书笔记,借鉴了网上(尤其是CSDN)许多翻译文章,不当之处敬请批评指正。
浙公网安备 33010602011771号