关于考试系统用户数据权限的设计
管理员在配置在线考试、课程或题库训练时,希望只针对部分学员开放,如:考试只针对某些小范围的学员进行; 这个人员范围的设置是一个通用的需求、不管是考试、课程、题库或者我们后续开发的新功能,都会用到此需求,所以,我们决定将此人员范围的设置单独提取为一个模块,供全部功能调用;
需求要求:
1、完全公开场景
即为不做任何限制,只需要简单标识,无需做任何数据处理
2、指定人员场景
指定人员包含指定部门、指定群组、指定具体人员,这三类为平行关系,最终结果为指定的部门+指定的群组+具体的人员;
设计思路:
1、完全公开只需保存标识,不需要深入讨论;
2、指定人员场景较为复杂、需要为主体挂上部门列表、群组列表和人员列表三个子表;
方案1:
直接为主体挂上部门列表、群组列表、人员列表,如:
a) 部门A、部门B
b) 群组A、群组B
c) 人员A、人员B
我们可以直接创建三个子表,用于保存实体对应的部门、群组、人员;在查询时,查询任意满足条件的数据即可,如下伪SQL查询:
部门权限IN(部门A、部门B)或 群组权限IN(群组A、群组B) 或 人员权限IN(人员A、人员B)
方案优点:
简单直接、实时性高、部门或群组人员增减后直接就能查询到;
方案缺点:
SQL语句相对复杂,每个查询都需要加过滤条件,针对某些场景需要固定人员的不能满足(即:创建考试后固定人员、后面加入部门或群组的人员无权查看)
方案2:
通过方案1的思路,我们可以发现,人员限制最终目的是人员,无论设置部门还是群组,最终都是为具体圈定某些具体的人员范围,人员关系如下:
a) 部门A、部门B : 人员1、人员2、人员3
b) 群组A、群组B : 人员3、人员4、人员5
c) 人员A、人员B : 人员A、人员B
我们最终可以得出,我们圈定的人员应为:人员1、人员2、人员3、人员4、人员5、人员A、人员B,总计7位人员,其中人员3重复出现于部门和群组,只记录一次即可;
得出人员后,我们查询满足条件的数据则会变得简单,如下伪SQL查询:
人员IN(人员1、人员2、人员3、人员4、人员5、人员A、人员B)
如上方案,每次在保存数据时,通过系统任务异步生成圈定的人员列表;
其它讨论:
部门和群组增加了人员怎么办呢, 需要自动更新相关的映射吗?
根据自身的需求来决定,如果需要实时处理,则在部门或群组人员变更后,都需要调用异步任务进行数据更新,如有100场考试都指定了某个部门,此时部门新来一个人员,那么在人员添加后,需要为这100场考试更新人员映射,这会是一个比较大的性能开支。
我们可以通过业务层面,尽可能的减少更新:
1、已经过期的数据
已经过期的数据,如:已考试完成的考试、已经停止的课程学习、已经截止的报名等,应该将此类数据标记为断开更新,即不再更新人员映射;
2、业务中不必更新的数据,如以下场景:
场景1:考试已经完成,所有圈定的人员都完成了考试,并且已经产生的统计数据,此时应人员范围需要完全固定下来,不会随着指定的部门或群组的人员变更而变化;
场景2:考试安排已下发,由现有部门或群组固定的人员参与,后续进入部门和群组的人员不参与考试;
3、针对不确定的业务,可以手动更新
增加一个手动更新按钮,由管理员决定是否需要更新人员映射
方案优点:
异步圈定人员范围,使业务查询更简单;能够满足固定人员范围场景(即人员固定后不再变化)
方案缺点:
需要异步任务来圈定人员范围、人员的变更更加复杂;系统开销大,设计复杂。
具体使用那种方案,还需要根据具体的业务来确定。