当你尝试构建或者更新一个系统时, 你可能经常需要考虑哪些工作是最重要的
根据以往的经验, 框架选型, 数据库设计, 开发环境的搭建 都会让人觉得很重要, 实际不然
这里 “重要性” 的概念是指 ” 修改成本最大, 维护成本最高, 一旦完成就几乎无法修改 ” 的部分
一个功能,一个模块或者是一个定义好的API, 如果修改它的成本越高, 它的重要性就越大
上面提到的内容中 框架选型和数据库设计 几乎是最重要的 , 改动数据库表结构意味着之前的大量DAO层工作都要重新, 如果你尝试将一个Struts项目更换成springmvc, 那么意味着所有的controller代码都要推倒重来, 在开始设计和构建系统之前,一定要明确 什么才是你系统中 “最重要” 的部分
一般来说(个人意见)
重要的部分包括
- framework的选型
- 数据库设计
- 使用的数据库类型
- 代码的组织结构(是按照层划分还是按照模块划分)
- BO和DAO层
- 核心业务接口
相对重要的部分包括
- 使用的服务器类型
- 构建工具的选择(例如Jenkins)
- 测试工具的选择
- java bean 的数据模型 (基本上和数据库对应)
- release流程
不太重要的部分
- source管理器的选择(SVN或者Git等)
- Jsp页面中不可复用的部分
- controller层的代码
多花一点时间在重要性更大的部分会让你后续的工作更加smooth, 盲目开工只能后患无穷
更近一步”重要性”这个概念其实还影响我们的原始设计
假设我们有3个表
- Company 存储公司信息
- Department 存储公司下属的各个部门
- Employee 存储各个部门下的员工
这3个表一次构成一对多的关系
我们假设有一个重要需求是通过 员工 来获取 这个员工所在的公司
在数据库设计中(下图) , Department 表包含一个company_id 列, 构成1对多, Employee 表包含一个department_id列, 构成1对多

如果要通过员工获得所属公司的信息 sql 应该是
select company_info from company
join department on company.id = department.company_id
join employee on department.id = employee.department_id
where employee.id = “1024”
这样你需要join两个表, employee只有通过department表才能知道自己所在的公司,由于实际上员工在公司内部并不会频繁更换部门或者公司,那么这3个表的关系就应该更倾向于
“面向读取” 优化
将数据库结构改成

这样你只需要一次join就能获得想要的信息
select company_info from company
join employee on company.id = employee.company_id
这样的改动的根本原因在于, 数据库表关系实际上是”重要性”非常高的部分, 一旦一个数据库关系确定, 你就不能频繁改动它, 也就没有必要”为将来的修改进行优化”
之所以将department表和company表相关联基于以下两点考虑
- 数据库表结构不会频繁变化
- 表中的数据不会频繁被更新
(如果频繁更新的话员工更换公司时需要改动company_id和department_id, 不关联的情况只需要改动department_id,不过因为可以在一个sql语句中更新,性能开销几乎可以忽略,这里只是举个例子)
以上是对于”重要性”较高的数据库设计的样例, 那么对于”重要性”较低的java 对象之间的关系要如何设计呢
首先java对象之间相互调用的性能损耗几乎可以忽略不计, 而java代码一般往往需要经常改动, 所以反而要避免这种设计, 对于”重要性” 较低的部分, 应该围绕”为了修改优化”展开
试想如果java对象之间完全照搬数据库设计, 在Employee类中加入 getCompany() 方法 和 getDepartment() 方法, 一旦 Company 和 Department 两个类中有任何改动, 可能都会对Employee类造成影响, 如果Employee 方法只包含getDepartment() 方法, 你可以使用employee.getDepartment().getCompany() 来获得company信息, 当且仅当Department类改动时才有可能影响到Employee

目的不同,设计也就不同, 在设计初期区分”重要性”可以更有效的帮助完成更好的设计, 降低项目风险, 节约开发成本