一次软件编程技术的探讨之旅:重新理解一切皆对象

面向对象编程,多么熟悉而又遥远的概念啊,我们每天都在进行面向对象的编程,但也许只有刚毕业的,甚至还在大学读书的童鞋们才能说得清楚这个概念。根据我多年的经验,正是那些最简单的、最熟悉的、最令我们不屑一顾的东西,才是我们最没搞懂的、最似是而非的、最容易产生误解的东东。因此,今天,我带领大家重新审视一下这个既熟悉又陌生的概念,相信能带给你完全不同的认识。

一提到面向对象编程,我们就不得不提到面向过程编程。面向对象编程,就是设计出一个又一个的对象,以及它们的属性、方法,以此来运行我们的系统,这是所有人都明白的概念,但问题是,为什么我们要面向对象编程?怎样面向对象编程?它与面向过程编程的差别在哪里?正是因为有太多的程序员没有弄明白这几个问题,因此他们把面向对象的程序写成了面向过程的程序。

面向对象编程,它之所以能够替代面向过程编程,成为目前主流的编程方式,是因为它真实的模拟了现实世界的事物,使我们的软件更易于理解、更方便维护、更容易变更。我们说,软件,特别是管理软件,实质就是对真实世界的模拟。真实世界是什么样子,软件就应当设计成什么样子,这是软件设计的终极目标。然而,真实世界是纷繁复杂的,如实地模拟真实世界往往并不容易。经过前人多年的实践发现,我们的软件系统对真实世界的每个细节模拟得越细致,我们的软件设计就越容易、越易于理解与维护。这种对真实世界中细节的模拟,就是面向对象编程。真实世界中的事物,就是软件世界中的对象;真实世界中事物的特性,就是软件世界中对象的属性;真实世界中对事物所赋予的行为,就是软件世界中对象的方法。同时,软件世界中对象间的相互关系,反映的正是真实世界中这些事物的关系。

那么,什么是软件系统的业务需求变更呢?任何一个软件系统,都只是对真实世界某个部分的模拟,而不可能是对真实世界所有部分的模拟,这是毫无疑问的。这个部分我们称为软件系统的边界。但问题是,真实世界总是在发展变化的,而且是越变越复杂;同时,我们的软件系统也是在发展变化的,它模拟真实世界的范围在越来越扩大。正因为这两个动因,使得我们的软件在发生业务变更。

这个道理是如此的清晰和简单,但为什么我们就那么惧怕业务需求变更呢?许多软件经历几次需求变更以后就变得臃肿不堪而难于维护,为什么?因为当需求变更到来的时候,我们没有对真实世界进行仔细分析就草草开始设计编程。我们没有按照细致模拟真实世界的主线去继续我们的设计,最后的结果就是一处不顺则处处不顺,我们在别扭的设计中一路狂奔,直到无可救药。

说得有些抽象?我们来看看一些具体的场景吧。当你开始实现一段业务需求的时候,你为系统添加了一些类,你有没有思考过你所添加的类合理不合理?随后,你为了实现一些业务流程,为各个类添加了一些方法,但你思考没思考这些方法是应该属于这个类的吗?这些方法的业务流程是否还应该予以进一步拆分?

我见过一个类包含5000行的代码,我也见过一个方法包含2000行的程序。毫无疑问,这些同事误会什么是面向对象编程了,将面向对象编程写成了实质的面向过程编程。人类认识事物,总是随着对事物认识的深入,不停地做着划分。当小孩子认识动物的时候,这是兔子,那是老虎……但随着动物认识的越来越多,开始划分为这是猫科动物,那是灵长动物……我们编程也同样。当一个业务简单时,我们用一个方法就可以了。但是,当这个方法变得越来越复杂时,我们需要根据功能拆分为多个方法,甚至独立划分出多个类出来。

话是这么说,但对于许多初学者来说,常常很难做到这一点,一不小心就写出数千行代码出来。过去我们说编码前要做详细的设计,但我要说,这对于很多人来说是不可完成的任务。怎么办呢?我们不妨曲线救国,采用另一种更加简单的方法,那就是重构。当你写出数千行代码时,没有关系,照写不误。但是,当程序写好测试通过以后,我们开始重构。先把方法中的各个代码划分成功能独立的数个代码段。分析各个代码段间要传递的数据变量。最后将一个一个的代码段剥离出来,形成一个一个的方法,再进一步剥离,形成独立的类。注意,每小改一下,测试通过,再小改一下,再测试通过。通过这样的过程,能让我们的重构更加平稳。

经过重构后的代码无疑功能结构更加清晰,会更易于阅读、更易于复用,也更易于维护。好的面向对象编程讲究的就是高内聚。什么是高内聚?就是在一个类中各个功能高度地相关,说得通俗点儿就是“单一职责原则(SRP)”,是业务需求变化的一个原因。这是一个很大的话题,有许多的原则与思想帮助我们去分析与设计,我们将在后面再详细解读。

一次软件编程技术的探讨之旅

重新理解一切皆对象

重新审视代码复用

(续)

相关推荐