1.3 重用

    回顾软件开发的历程,我们经历了从最初的二进制编程,然后到汇编语言的编程,最后到高级语言编程的过程,在这个过程中,我们不断提高着语言指令的模块化:汇编语言模块化了机器指令,一条汇编指令可能是多条机器指令的组合;高级语言进一步模块化了汇编语言(例如for循环等)。

    使用高级语言编程的过程,其实就是重用这些大结构的模块指令的过程,效率得到大大提升。它们解决了语言到机器的映射问题,却没有针对我们要解决的问题域(Problem domain/Problem space)思考问题,于是对问题域进行建模开始发展。

    我们使用结构体和方法来建立模型,这些结构体粒度小,抽象程度不高,可重用程度也不高。随后出现了面向对象的编程,对象是方法和结构体的集合,抽象程度更高,我们可以通过重用对象功能协作解决更复杂的问题。

    随着计算机的发展,一个系统的代码也由原来的几百行增加至现在的动辄上百万行,如果从头到尾编写这些代码,那不仅是软件开发人员的噩梦,而是整个软件行业乃至所有使用软件的行业的噩梦。于是,重用从方法、结构体、类的重用,上升到软件的重用。

    然而要使用OOP来设计可重用的软件并不容易,尽管面向对象的编程有如此之多的好处,但仍然有很多人倾向于使用PP/FP(Procedural Programming/Functional Programming)进行编程,他们列举很多使用OOP的反面例子,例如最常见的一个是关于使用switch语句的例子,他们认为使用switch语句非常直观和简洁,而如果使用OOP的状态模式(State Pattern)替换,便会产生了大量文件和代码。其实这个驳斥只是溢于表面,没看到状态模式带来的易阅读易扩展等好处。另外,他们也喜欢列举继承所带来的坏处来证明使用OOP进行开发还不如使用PP/FP,其实在OOP开发过程中,我们更愿意使用合成而非继承(Favor Composition over Inheritance),这些不足正是我们在OOP编程过程中应该避免的。

    从种种问题来看,敌视OOP的原因归根结底是由于很多人理解了一些面向对象的基本概念和OOP相关语言的语法,却还没领会和掌握面向对象的开发设计方法。在开发设计过程中,往往求助于以前使用的过程式开发设计和简单的面向对象的特征(例如继承性),因而并未享受面向对象编程所带来的模块化的好处、粗粒度的好处、封装的好处、易于抽象的好处、代码重用的好处……。

    如何使用面向对象的编程方法进行软件开发便成了问题的关键。其实,有经验的OOP开发人员并不会从头解决问题,他们往往会使用之前的成熟的解决方案来解决类似的问题。如果能够重用前人的经验和思想设计软件,那就好比站在前人的肩膀上解决问题——模式就能够让我们从思想上重用有经验的开发人员的解决方案来解决问题。

    重用是指一切知识信息的重用。我们可以看到,对于软件编程,重用非常重要。经过过去几十年的发展,重用包括指令集的重用、方法的重用、代码的重用、服务的重用、软件的重用、设计的重用、思想的重用等。要实现重用并不那么简单,软件发展至今,开发人员一直在重用上摸索着前进,终于迈出了一步。

    笔者从开始学习编码至今,一直致力于把“重用”应用于软件开发,本书将会和读者一起探讨重用和如何编写可重用的软件。