编写程序为了完成现实的功能,为了能够编写出更好的代码,开发人员不断地进行抽象,提取,复用,并且在此基础上设计个优良的软件架构。
一般的软设计认为系统是整体的,耦合的,所以设计的思路是在现实需求的基础上进行一些提取,将功能点进行抽象,从而达到解耦和模块化的目的。
现实编程恰恰相反,认为系统是本身就是模块的,解耦的,因此设计的思路也不同,并不刻意要求去进行抽象,而是尽可能的用软件去描述系统本身,很多时候不是进行向上的抽像,而是向下的分解。
现实编程的好处是能够将快速需求转化为可用的软件,同时能够获得一个不错的软件架构——高内聚低耦合的系统,具有较好的可拓展性和可维护性。
现实编程之所以速度快是因为不需要花多大的时间进行设计,甚至不需要进行设计。在完成一个软件的时候有你甚至可以直接进行编程,而不需要先设计出一个基本的框架, 这在那些需求不明确,频繁变化的系统开发中很有价值。
系统的需求越贴近现实世界,这种方法的效果越好,反之效果越差。
一般常用的软件设计思路是这样的:
- 当我们拿到原始需求以后进过分析,将整个需求分解成多个小的需求。
- 从小的需求中提取抽象,划分成多个功能块。
- 根据这些功能块划分出软件需要的模块。
- 根据整个软件的架构优化模块,直到软件架构的成型。
请注意,上图中的需求,功能和模块之间的连线使用的虚线,这说明它们并不是一一对应的,它们的关系是多对多的关系。
举个例子来说,我们需要制作一个贪吃蛇游戏。
一般的思路可以画出如下的图:
根据这张图你会设计出对应的类,然后设计好每个类的交互方式,最后一个系统的就完成了。
它是可以工作的,如果便面后续的需求能够按照你设计的方向来变化的话,它应该具备不错的拓展性。不过不幸的是,需求的变化往往超出我们预想的范围。系统第一个版本出来以后,原有的架构会在各种各样的需求的变化过程中不断地腐化。
现实编程的思路与之不同,现实编程使用代码尽可能地描述真实的事物,并以此为依据完成软件的设计。
注意上面图中的模块不是我们随意想象出来的,而是现实中实际存在的划分。
对于贪食蛇来说,系统的图划分如下
我们可以看到,所有的模块都不是我们自己杜撰出来的,而是对真实的事物进行的分解。这样功能自然而然的被分配到每个模块中。
现实编程的好处:
- 能够使软件架模块天然的解耦。前面提到,现实编程认为系统本身就是解耦的。在现实世界中,所有的事物都可以相互影响,同时却又保持了完全的独立。比如说,一个人可以和周围的一切事物相互影响——人,空气,阳光,水等等,但是同时人却又是一个完全的独立的个体。这就好比是软件中的模块,既要和其他的模块进行交互,同时又要保持自己的独立性。架构师们费尽心思想要的实现的高内聚,低耦合。在现实世界却是常见的现象。所以我们不是抽象现实,而是模拟现实。
- 更加容易实现的设计。开发人员经常会遇到一个问题,这个类放到哪个模块?这个功能放到那个类?这个方法应该对外暴漏吗?这样的问题在至始至终就困扰着所有人。同时令人遗憾的是,人们总是在这样的问题上做出了错误的决定。所以,想象现实中的系统是怎么实现的?它有这个功能吗?它是怎么交互的?模拟它,会让我们减少很多的麻烦。
- 更好的可读性的代码。在软件中经常会看到各种各样的抽象类。比如说XXXManager,XXXHelper等。这些类能够帮助我们更加容易的实现功能,但是如果数量过多的话就会变成一场灾难。它会让代码的可读性变得非常差,架构变得异常复杂,难以维护。现实编程中这种类会变得非常的少。
- 更快的开发速度。减少了设计时间同时又能拥有一个天然解耦的架构,开发速度自然会提高不少。