一个小功能让我懂得了设计模式的重要性

leader让我开发一个项目排期的功能,一个看似很简单的功能,我却栽了坑,并从中学到了设计模式及算法的重要性。

一、功能点

目前平台已有项目管理功能,需要增加一个项目排期的功能,其实就两个页面,一个排期的编辑页面,一个按照团队展示团队人员项目排期的甘特图。

一个小功能让我懂得了设计模式的重要性_第1张图片


一个小功能让我懂得了设计模式的重要性_第2张图片

二、原来做法

我不怎么会前端,一开始把精力都放在前端甘特图绘制上了,忽略了设计的重要性。

我只是简单的建了一张表,把项目、人员、排期一股脑放在了一张表里,与项目表、人员表存在紧耦合,不符合数据库设计原则。表结构如下

id schedule_name schedule_duration start_time end_time staff_name project_id project_name note
1 开发设计 4 2016-10-20 2016-10-28 张三,李四,赵红 21 项目一 开发开发
2 测试评审 6 2016-10-29 2016-11-12 小张,小王 100 项目二 测试测试

这样设计表时,排期的增删改查很容易,就按照上图一输入的填写的数据表里就可以。但是在第二个页面,按照团队展示时,就遇到问题了,先查到团队下所有的人员,然后一个for循环,不停的http请求去获取每个人的排期,性能很差,后来我的做法是取出所有的人员,取出所有的排期,代码里面处理逻辑,这样满足基本需求,时间复杂度为o(n*m)

三、新需求

后来leader提出新的要求,要求对每个人下面的排期进行分组,时间上没有交集的排期放在一个分组,我在原来的处理逻辑循环里,对每个人的任务进行一个分组处理,分组处理的时间复杂度为o(t*t),再加上外层的循环,复杂度为o(m*n*t*t)。页面展示根本刷不出来,一直超时。但是基于上面的表结构设计,又没办法优化算法。

四、重构

不得已,必须进行重构。

(1)拆表

首先是拆表,按照数据库设计规范,即那几个范式

第一范式:要求所有的域都应该是原子性的。我原来的设计,staff_name一列放n多人名,其实是不合理的

第二范式:要求数据库表中的每个实例或记录必须是可以唯一的区分

第三范式:要求一个关系中不包含已在其他关系已包含的非主键字信息。如我上面的表中,project_name,staff_name都是非主关键字,不应该出现在排期表中。

于是,将上面的表拆成两张表

排期表

id

schedule_name

schedule_duration

start_time

end_time

project_id

note

   

 

 

 

 

 

 项目表主键

 

   
通过project_id与项目表关联

排期-人员关系表

id

schedule_id

Staff_id

gmt_time

 

 

 人员表主键

 

通过schedule_id与排期表关联

通过staff_id与员工表关联

(2)使用事务

拆成多个表后,为了保证数据的一致性,就要使用事务,只有一部分成功时要进行回滚,当所有的操作都ok时,才commit

(3)通过mysql的一些函数及用法,减少业务代码量

主要使用了concat、group_concat、ifnull函数,使用了多表查询,使用了group by等用法

使用group_concat时还遇到一个小问题,就是group_concat有个默认长度是1024,超过这个长度字符串会被截断,可以通过设置group_concat_max_len=-1为不限制长度。

(4)优化算法

对于那个新需求,对排期分组,我原来的算法复杂度是o(t*t),将其优化为o(t)

这样,经过上面操作后,时间复杂度由原来的o(m*n*t*t)变成了o(m*t),性能大大提升。



心得体会:处处皆学问,做任何事情前都得思考!


你可能感兴趣的:(个人总结)