数据在任何产品的开发和设计中, 始终要摆放在首要位置。 跟数据贴近的两个概念是: 数据库, 数据结构. 这两个概念最终都是数据结构。数据库的表结构就是数据结构。 程序 = 数据结构 + 算法 这一经典的公式, 导致我们误读为: 数据结构和算法的地位是等同的. 但实则不然. 对数据结构的态度已经决定你的架构的优劣。 本文想通过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. 所有的功能都直接从文件获取接口,以方便彼此间解耦和重用 .