第2章 模式
实现模式(修订版)
编程中的很多决策是无法复制的。开发网站的方式与开发心脏起搏器控制软件的方式肯定迥然不同。但决策的内容越接近纯技术化,其中的相似性就越多,我不是刚编写过一样的代码吗?程序员为不断重复的琐事耗费的时间越少,他们就有越多的时间来解决好真正独一无二的问题,从而更高效地编程。
绝大多数程序都遵循一组简单的法则。
更多的时候,程序是在被阅读,而不是被编写。
没有“完工”一说。修改程序的投入会远大于最初编写程序的投入。
程序都由一组基本的语句和控制流概念组合而成。
程序的阅读者需要理解程序——既从细节上,也从概念上。有时他们从细节开始,逐渐理解概念;有时他们从概念开始,逐渐理解细节。
模式就是基于这样的共性之上的。比如说,每个程序员都必须决定如何进行迭代遍历。在思考如何写出循环的时候,大部分领域问题都被暂时抛在脑后了,留下的就是纯技术问题:这个循环应该容易读懂,容易编写,容易验证,容易修改,而且高效。
让你操心的这一系列事情,就是模式的源起。上面列出的这些约束,或者叫压力(force),会影响程序中每个循环编写的方式。可以预见到,这样的压力会不断重现,这也正是模式之所以成为模式的原因:它其实是关于压力的模式。
有好几种合理的方式可以写出一个循环,它们分别暗含着对这些约束不同的优先级排序:如果性能更重要,你可能用这种方式来写循环;如果容易修改更重要,你就可能用另一种方式来写循环。
每个模式都代表着一种对压力进行相对优先级排序的观点。大部分模式都由一篇短文来描述,其中列举出解决某一问题的各种方案,以及推荐方案的优点所在。这些模式不仅给出一个建议,而且还讲出背后的原因,这样阅读者就可以自己判断应该如何解决这类重复出现的问题。
正如前面暗示的,每个模式也都带着一个解决方案的种子。关于“循环遍历一个容器”的模式可能会建议说“使用Java 5的for循环来描述遍历操作”。模式在抽象的原则和具体的实践之间架起了一座桥梁。模式可以帮助你编写代码。
模式彼此协作。建议你用for循环的模式,又引出了“如何给循环变量命名”的问题。我们不尝试把所有事情都塞进一个模式里,还有另一个模式专门讲“如何给变量命名”的话题。
模式在本书中有多种不同的展现形式:有时它们有清晰的名称,还有专门的章节来讨论压力和解决方案。但也有时,一些比较小的模式就直接放在更大的模式内部来介绍,一两句话或许就能够把一个小模式讨论清楚了。
使用模式有时会让你感到束手束脚,但确实可以帮你节省时间和精力。打个比方,就好像铺床这件小事,如果每次都必须思考每个步骤怎么做、找出正确的顺序,那就会比习惯成自然的做法耗费更多的精力。正是因为有一组铺床的模式,这件事情才得以大大简化。如果床恰好顶在墙边,或者床单太小,你会根据情况调整策略,但整体来说还是遵循固定模式来铺床,这样你的脑子就可以用来思考更有意思、更有必要的东西。编程也是一样,当模式成为习惯之后,我很开心地发现自己不必再为“如何写一个循环”而展开讨论了。如果整个团队都对一个模式不满,那么他们可以讨论引入新的模式。
没有任何一组模式能够适用于所有情况。本书中列出的模式是我在应用程序开发中亲自用过的,或者看到别人用过并且效果不错的(后文也浅谈了一下框架开发中的模式)。盲目效仿别人的风格,永远都不如思考和实践自己的风格并在团队中讨论交流来得有效。
模式最大的作用就是帮助人们做决定。有些实现模式最终会融入编程语言,就好像setjmp( )/longjmp( )结构变成了如今的异常处理。不过大部分时候,模式需要加以调整才能投入使用。
从这一章开始,我们试图寻找一种更节约、更快速、更省力的方式来解决常见的编程问题。使用模式可以帮助程序员用更合理的方式来解决常见问题,从而把更多的时间、精力和创造力留下来解决真正独一无二的问题。每个模式都涉及一个常见的编程问题,随后我们会讨论其中起影响作用的各种因素,并提出具体的建议:如何快速实现一个令人满意的解决方案。其结果是,这些模式将帮助读者更好、更快、更省力地完成编程工作中乏味的部分,从而留下更多的时间和精力来解决程序中独一无二的问题。
本书中的实现模式共同构筑了一种编程风格,下一章“一种编程理论”将会介绍这种编程风格背后的价值观和原则。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。