最近在设计一个项目的二期方案。相对于一期过程驱动的实现,二期则更加模糊了过程的边界,需要通过分析业务的当前状态和历史状态去推理上下文,虽然硬件上相对简单了,但对于软件逻辑来说,却提出了更多挑战。所以原来偏重于面向过程风格的实现方法显得有点力不从心,是时候“面向对象”了,呵呵。
我们知道,现有的编程范式主要是:面向过程编程、面向对象编程、函数式编程(也有的书上将面向过程编程用结构化编程替代)。函数式编程目前使用的比较少,此处搁置不表。
面向过程编程以过程(可理解为方法、函数、操作)作为组织代码的基本单元,以数据(可以理解为成员变量、属性)与方法相分离为最主要的特点。面向过程风格是一种流程化的编程风格,通过拼接一组顺序执行的方法来操作数据完成某一个业务。
面向对象编程以类或对象为组织代码的基本单元,并具备封装、抽象、集成、多态四个特性,作为代码设计和实现的基石。面向对象编程语言是支持类或对象的语法机制,能方便地实现面向对象编程的四大特性。
面向对象风格编程和面向过程风格编程的明显区别就是组织代码的方式不同。面向过程风格的代码一般被组织成一组数据结构及其方法集合,数据和方法互相分开;而面向对象风格的代码,则被组织成一组类(Class),同一个类的方法和数据被绑定在一起,定义在同一个数据结构(类)中。
那么,面向对象编程,相对于面向过程编程,有哪些优势呢?
1. 面向对象编程更适合大规模复杂程序的开发
对于流程清晰的简单程序,一般只有一条流程主线,很容易被划分成顺序执行的几个步骤,面向对象编程和面向过程编程没有太大差别,并且面向过程编程常常比面向对象编程更加直观高效。但当我们面对一个大型的复杂程序,由于其错综复杂的流程和交互关系,很难将其简单地拆分成一条主线串成的简单步骤,而通常表现为一个网状关系结构。这个时候,面向过程编程的这种流程化和线性化的思维方式就会显得比较吃力,而面向对象编程的优势就比较明显了。这是因为,对于面向对象编程来说,我们首先要做的不是流程分解,而是为业务建模。我们需要思考的是,如何将业务需求抽象成对象,并且为不同的对象建立方法,如何设计不同对象之间的联系。设计好对象(类)之后,我们就可以将不同的类按照关系和流程组装起来,形成整个程序。这种思维模式,让我们在面对复杂问题的时候,能够更清晰地分解问题并创建模型,相应地,也提供了一种更为清晰和模块化的代码组织方式。
2. 面向对象编程风格的代码更容易复用、扩展和维护
为什么这么说?这是因为面向对象编程提供的封装、抽象、继承和多态这些特性,能够更容易地帮我们写出易于复用、扩展和维护的代码。
首先来看封装特性。由于面向对象编程将数据和方法绑定在同一个类中,并提供了访问权限控制,外部调用者只能通过类暴露出的有限方法去访问某些数据,而不会向面向过程编程那样,数据可以被任意方法随意修改,因此,相比于面向过程编程,面向对象编程有更好的代码易维护性。
其次是抽象特性。不抽象,无对象。抽象是一种对现实世界的提炼,它将现实对象映射成系统对象,抽象的内容包含数据、属性和行为。一个好的抽象,可以让我们形成更好的软件结构和代码风格,使得我们的代码更容易理解,也更易维护。
其次,看看继承特性为我们带来了什么。继承和多态,是面向对象编程相比于面向过程编程所特有的两个特性。由于可以将不同类的相同属性和方法抽取到父类中,让子类继承父类的方法,也可以重用父类的代码,从而提高了代码的可复用性。
最后,来看一下多态特性。多态特性允许我们在修改或添加某个功能的时候,可以定义一个新的子类,在子类中重写父类的方法和功能逻辑,并在具体的应用中用子类替代父类,而不是所有新的需求都需要重写原有的代码和功能逻辑。这种设计方式遵从了软件设计的开闭原则(OCP),能够极大地提高代码的可扩展性。
3. 面向对象编程语言更高级、更人性化
了解编程语言发展历史的同学肯定知道,编程语言一直是向着更接近自然语言的方向发展。从最开始的二进制指令、汇编语言到面向过程的编程语言,再到如今的面向对象编程语言,编程思维和编程套路也从最初的机器思维方式逐步过渡到接近于人类的思维方式。在机器思维方式下,程序员需要针对某项任务设计一组指令,让机器逐一执行这组指令去操作某些地址下的数据,从而完成某项计算任务;而高级语言让我们从指令设计中解放出来,以倾向于人类大脑的思维方式,将注意力聚焦到如何为业务建模,将真实世界映射为对象,从而能够实现更大规模和更加复杂的程序。
说了这么多面向对象编程的好处,那在开发过程中,为什么工程师们更容易写出面向过程风格的代码呢?是否面向过程编程就彻底被淘汰了呢?
由于人类的思考惯性,已经习惯了用流程化和线性化的思维方式去解决问题。在面对一个任务的时候,我们往往想的是如何把它分解成一系列可执行的简单步骤,然后再按照步骤去一一执行并完成任务。这种思维方式与面向过程编程的思维方式不谋而合,通常也是工程师在工作早期的直线思维的结果。而面向对象编程是一种自底向上的思考方式,首先关注的不是步骤,而是为任务建立模型,将任务分解成一个个独立的模块(类),并设计类之间的交互,最后再按照流程和关系将类组装起来实现整个任务。这种思维方式并不是很符合人类的思维习惯。由于有一点“反人类”的特性,面向对象的思维方式比面向过程的思维方式显得更难,需要工程师的经验和技巧来支撑。所以经验欠缺的工程师往往更容易选择相对容易的面向过程编程风格。
但也并不是说,所有的编程都要采用面向对象的方法。在实际使用中,我们只要根据业务类型和程序规模,选择合适的编程风格即可。并且,面向对象和面向过程也不是非黑即白非此即彼的,常常在面向对象编程语言开发的软件中,也会写出面向过程风格的代码;而面向过程的编程语言,也能够组织出面向对象风格的代码。不管哪种语言,哪种风格,我们最终的目的都是要写出易读、易维护、易复用和易扩展的高质量代码。