数据在任何产品的开发和设计中, 始终要摆放在首要位置。 跟数据贴近的两个概念是: 数据库, 数据结构. 这两个概念最终都是数据结构。数据库的表结构就是数据结构。 程序 = 数据结构 + 算法 这一经典的公式, 导致我们误读为: 数据结构和算法的地位是等同的. 但实则不然. 对数据结构的态度已经决定你的架构的优劣。 本文想通过J2EE的项目和普通的C/S架构的项目, 来说明一下, 数据结构为中心的思路, 带来的架构上的优雅性。

 

第一:关于软件产品, 数据结构, 算法的一个简单的比喻

软件产品的核心, 都是对数据进行处理。 举例几个常见的例子: 人力资源管理系统, 最终的目的, 就是将公司的人力资源数据做一些必要的处理, 如增加, 删除, 查找, 涉及到人事变动, 如晋升, 离职, 这些, 都是对人力数据的调整; ERP管理系统, 对公司的进出口数据进行管理; Google公司, 它自己的核心理念, 也是对全球数据进行整合。用户传入查询的数据信息, Google网页将返回查询结果的数据信息.... 等等,这些, 都无外乎数据。 所以说, 软件的核心是数据处理。

 

数据在其中的重要作用, 可以用日常生活中的:"巧妇难于无米之炊"来形容。 数据就相当于这里的“米”.  我们提到的数据结构, 就是如何存放这些“米”, 可以用不同的容器: 比如锅, 电饭煲, 微波炉等. 存放数据的容器, 就是我们的数据结构。

 

数据结构的存放方式, 直接影响到数据的处理方式, 同样用“米”来做比方。 假如我们的软件是一个将“生米煮成熟饭”这样一个数据处理系统, 我们有三种方式:

 

方法序号                     数据结构                   算法                              应用范围和效果

1                                普通的铁锅                 燃气灶加热                      不常用, 不方便控制

2                                微波炉                       通电加热                         基本不用,  耗电大, 时间太长

3                                电饭煲                       通电加热                         常用, 易于控制

 

 

这里想传达的意思是, 达到目的"把饭煮熟", 可以用很多方式来实现, 通过组合数据结构和算法, 便可以达到我们的目的.

 

为了达到更好的目的, 当然我们可以优化算法 , 我们可以这么做:

第一种方法, 用普通铁锅, 我们可以调节火焰的高度, 增加火焰的利用率, 比如用一个圈圈盖在火焰的周围,使得热量集中于铁锅

第二种和第三分钟方法, 我们可以加大电压, 增加电流的方式, 实现快速加热

 

当然还可以修改数据结构,

第一种方法: 买一口更好的锅, 受热更好的镍铁合金锅, 锅底是凸型的, 更容易受热

第二种和第三种方法: 买更好的电饭煲和微波炉.

 

如果是你, 你会选择调整盛米的容器, 还是调节加热的方法呢! 如果你不知道, 问问身边的家庭主妇可以得到不错的答案.

 

  (我想我们只会选择电饭煲, 通过通电的方式, 实现“把饭煮熟”这样的目的。 如果要优化, 我们会选择一个更好的电饭煲)

 

同样, 作为程序员的你, 你觉得在软件设计中, 应该将精力集中在算法, 还是在数据结构上?

 

(我赞同的答案是花更多的经历设计数据库和数据结构.)

 

做一个声明, 并不排斥算法设计, 但始终认为有什么样的数据结构, 才会出现什么样的算法. 脱离数据结构去谈算法, 是不可接受的。

 

 

第二:经典著述中对数据结构和算法的探讨.

这里将引用《Unix编程艺术》以及《代码大全》中, 关于这部分的理解

 

 

第三:数据为中心的架构带来的简单设计

a. J2EE中数据为中心带来的简单性

 

b. 自己经历的两次软件设计,一次成功, 一次失败。 得出的结论, 数据为中心的结构设计, 让架构更容易理解, 项目更容易维护

                              -----------------------------一个 UI 和数据纠结的项目 .

项目介绍 :

1.       功能

实现一个计算通信设备功耗的工具 , 通信设备包括基站, RNC 之类的产品 .

2.       主要的功能

a)         16 种类型以上的设备 , 选择一个或者多个设备类型 , 以此为基础,用户进行配置 . 每种配置包含 20 个左右的参数 . 参数之间存在逻辑关系 , 比如一个参数决定另外一个参数是否出现,出现的值应该是多少 .

 

b)        可以导入一些实际已经存在的参数文件,根据用户选择的模型,把参数填入到用户配置好的数据中。

 

c)        UI 显示数据 , 并体现各个参数之间的逻辑关系

 

 

d)        UI 更新完毕之后,对配置完好的“数据三”进行计算的操作 , 并在界面上展示结果 .

 

e)         其它的一些非常 BT 的问题 .

                         i.              当时该项目是某个主项目的二次开发 , 带来的问题是,主项目存在较多缺陷,提供的接口非常不友好 , 比如 b) 中提及到的 xls 数据源的问题 , 实质上该 xls 是对该主项目的接口 . 但里面存在非常多的无用和冗余数据需要本项目处理 .

                       ii.              数据中可能存在错误信息,需要本项目去处理 . 这样可能会带来一个严重的问题,数据上的问题,最终将会导致 UI 和计算模块出错 .

                      iii.              当前项目要考虑主项目任何形式的更改 . 满足维护上的简易性。

 

前后期版本架构上做了很大的改变 :

1.       前期没有将 XML 结构的数据完全独立成一个类 , 而是直接用 xml 的方式进行解析和数据提供,即使提供了众多的方法 , xml 解析器根本无法代替数据结构,作为一个数据的 API 接口 . 提供对外使用相当困难 . 第二个版本 , 独立出一个 MemoryData, 将树状结构的 xml 梳理成数据结构 , 统一提供对外使用。

2.       各个模块,直接提供文件接口直接解耦和 . 导入 xls 的功能 , 数据立即写入文件 , 当 UI 取数据的时候,不是通过内存获取,而是从数据文件中获取 , 这样,导入功能和 UI 展示功能完全解耦和 ( 可能很多人觉得,这样降低了效率 , 但这个牺牲显然是值得的 ). 对计算模块更是如此 .

3.       以数据为中心的接口设计 , 当主项目更新的时候 , 当前项目,只需要在源头设计一个过滤器 , 将格式做调整即可,后续的计算模块, UI 模块,都不受影响,极大的提高了可扩展性。

架构图如下所示 :

 

 

可以看出,整个过程,都是以数据为中心的方式进行设计 , 重申一下这个系统的特点 :

1.       所有功能围绕数据进行接口 , 可以想象成为一个过滤器

2.       所有的功能都直接从文件获取接口,以方便彼此间解耦和重用 .