关于提高代码重用度

中山野鬼 发布于 2013/07/05 15:56
阅读 556
收藏 8

无论你是用机器语言,还是用过程语言,或者面向对象语言,无论你是汇编,还是到脚本。有几个问题是需要面对的。

1、资源依赖

2、应对需求

3、代码重用度

重用度不是说你写了最终程序,download给n多人用过了,而是针对开发本身在结构化设计时,作为一个部分,被反复利用在不同的应对需求中。重用度和依赖也有关系。重用度越到,依赖本部分(我即不想用对象也不想用模块的词,保持中立)的其他代码越稳定,反之,依赖重用度低的代码,的程序则稳定性差。

程序本身的设计,原则上是以需求为导向,就是客户要啥就是啥。特别是面向对象出来后,更少的面对设备本身特性,特别是诸如java 之类的语言。

但需求永远是变动的,这是个伪命题,如果需求不变动,程序员很快会全部失业。而好的开发系统,应该是尽量满足更多的变动需求下,尽可能的利用现有代码资源。

显然我说的是更抽象的一个概念,不要指望因为java的包包多,所以可以打天下。如果把c的库函数都搞出来数数,估计不会比java的包包的数量多。资源量越多,意味着相同需求集合下,资源的重用度低。重用度低,需求不变下,意味着你可能做架构设计和写代码的时间,远小于一个个翻可用包包的时间。

通常的情况更多是,手上固定就是这几个包包,然后遇到不同需求,额外写出的代码都是特定的。除了那几个包包外,自己经常写了很多重用度低的新包包。这是典型的结构化架构分析能力不足的表现,无法更好的从差异性需求中分析出共性子模块。但不能怪程序员。包包太多,可能不知道这个功能已经有包包实现,或者总找不到刚好合适切割出来的某个模块的包包,或者一堆包包中,不知道哪个更稳定。这就是包包太多的下场。。

而在mfc下开发,就比较爽,因为是面向桌面物件的开发。这些物件被mfc已经分割的很结构化,mfc下的类并不算多,而且稳定,功能明确。

代码重用度高低,和系统结构非常相关,系统结构切割的好,那么可以尽可能的将差异的需求,通过差异的模块或者包包组合实现,而还有一个已经很多年被忽视的,就是和数据流动相关。这方面,面向对象是个灾难。因为其力求数据封闭。在对数据即可看作对象属性的情况下,这是没什么问题的,特别适合做桌面的开发,并非桌面展示的数据,而是桌面本身。因为桌面是拟现实世界的。把桌面的各种形状看做具备空间属性的对象,无论是平面还是3d。

我通俗的定义这种开发叫做物件开发。对物件本身的开发,同时物件并不完成不属于物件的数据计算工作。别说你的窗口程序显示了多少数据,通常情况下,大多数面向对象开发出来的,只是调用数据库或后台计算引擎来完成。实际计算不是用面向对象实现。即便openCV这种c++的东西,落在数据计算中,仍然不是标准的面向对象思想。

相对物件开发,是面向数据和面向设备开发。操作系统,可以说即面向数据,也面向设备。大多数设备的开发,都是驱动,数据获取或导出,没有其他。因此也可以说是面向数据的开发。

面向数据的开发,程序本身完成的是一个处理数据的工具,而数据并不是这个工具所封闭的属性。如同各种函数中,函数内变量,可以看作属于这个函数的自身数据,但函数的传入数据,属于这个函数工具所处理的数据。

上述这些工作用面向对象是个灾难。严格极端的面向对象应该没有诸如char ,int之类的标准存储结构数据,而全部以类的形势出现,比如字符串类。但简单的一个例子,假设一个字符串 "a b c d",单独一个存储区,8个空间,4个字母,3个空格,一个0。可以有多种处理方式。以0为结尾,以空格为结尾。如果使用严格的面向对象,需要一个以空格为结尾的token类,以及以0结尾的string类。而他们之间从面向对象的思想来说,数据的互传,需要数据的copy动作。而不是简单对通一个数据空间进行实现。那么我们计算长度的工作,需要分别将上述8个字符的空间,copy到对应类中进行识别。而不严格的类的设计,认为本类可以对外部数据进行处理工作,此时实际是把面向对象的核心思想给否定,即封装保护。或许你觉得8个字符空间不算多,但对服务器和面向数据库的大型计算工具的开发,就2个字“等吧”。。如果非要加上个期限,这个很难说。。。

面向对象的语言都基本上含有字符串类或者包,这些类或者包,我不知道是否都是在处理时,需要将对应字符存储空间的内容copy到本对象内才可行。当然可以加上一堆扩展约束,使得本对象可以和其他对象共享数据。但这样会另系统结构的设计更加混乱,或者说某个模块的设计更加混乱。

linux操作系统,不用c++开发,我支持。如果用c++开发,我一样会高喊两字“扯淡”,如果理性的不愤青的说则是“灾难”,当然是基于严格面向对象思想,所有数据全部封在类的对象中。而所谓灵活的变通方式,其实确实不错,但是只是针对局部,针对整个系统,则是灾难。因为这样是在降低代码的重用度。

什么样的语言思想没有对错,看你主要做什么。是为了设计一个物件,还是为了设计一个加工数据的工具。他们之间并非不能相互利用,关键是接口和数据格式。

一直说hadoop是个玩具,也有这方面的意思,如果它是个前端或手持设备上的应用支撑平台,java是很不错的。因为是面向物件开发。但其是后台服务器特别是集群的工具,用java设计,只能说三个字“爱折腾”。。。




加载中
0
翟志军
翟志军
老鬼。我一直想知道C是如何做到模块化的?我没有诋毁C的意思。
0
中山野鬼
中山野鬼

引用来自“陈真诚”的答案

老鬼。我一直想知道C是如何做到模块化的?我没有诋毁C的意思。

数据是数据,处理数据的逻辑代码和数据无关。哈。当然,打包一群逻辑代码,成为一个封闭的模块,这个里面本身有为了维护模块而必要的数据,从这个角度有点像面向对象,但不一样地方在于,这些数据,类似一个函数的内部变量,而实际模块面对的数据是类似函数外部的变量。。

简单说,模块面向特定数据类型的特定处理逻辑而存在,存在多个模块关联,依次流水处理一批数据,但并不存在模块依次嵌套,如同对象继承那种思维。有点插件的概念。。但我觉得更形象的解释是:

我们在做架构框图时,特别是流程图时,你可以勾勒出数据流的轨迹。而实际流程图勾勒出的是计算轨迹,比如什么情况下,跳转等等。如果把流程图当作一个地图,那么直接勾勒出来的轨迹,就是把cpu的alu当作一个小车子,在这个逻辑框图中来回转。但这个是逻辑流程。

其实对应的还有个流程图,是数据流程,比如我们要做两个文件的比较。传统的代码设计就会有一堆如果怎么样,就跳转到哪什么的。而数据流程的描述应该是

空间a载入文件1,

空间b载入文件2,

空间c

空间a 和空间b进行比较计算,

计算结果导出到空间c中。

这里不强调逻辑,而强调数据怎么流动的,数据来源无非外部,如同文件等,也包括内部计算得到的。如同空间c存储的数据。

这种面向数据的数据流的架构分析,最终就可以获得模块化的需求。由此可以明确出各种模块的边界。

模块实际是为数据服务的。而采用逻辑流程图很难分解清楚。

简单说,假设只是面向一个数据,例如压缩算法,这边进,那边出,本质上是两个数据空间。无非一堆模块,要么单独处理源数据空间,要么单独处理目标数据空间,要么在两个数据空间中搬来搬去。

这个面向对象的思维,以及根据功能和逻辑流程进行自顶向下设计的思维并不一致。当然只是针对复杂数据处理的开发设计有优势。

由此,c代码设计的模块,要提供重用度,就是要明确处理什么类型的数据,处理哪些逻辑。每个模块如同起子或锤子一样,只是为了加工数据而独立存在。那么面向模块的设计,本质是面向数据的分析。把数据的处理逻辑分解成足够小的任务,转而对应不同的模块。

这个和功能逻辑进行的逻辑流程图分析,进行模块切割是不同的思维。。

0
宏哥
宏哥

就是两句话:

1: 有个好名字

2: 实现可重用的输入输出.

返回顶部
顶部