在传统的瀑布模型中,整个流程中有一个设计环节,架构师会提供架构(概要)设计,详细设计等文档给开发,开发根据功能模块的设计进行后续的编码工作。
但是Scrum的项目没有一个前期的分析和设计阶段,所有工作发生在迭代的Sprint周期内。然而,这并不意味着,在一个Scrum项目中没有主动的设计。Scrum不鼓励过度设计,而采用涌现式设计。这意味着开始往往不会把技术架构做得大而全,而是鼓励快速出成果。
当然这并不是说程序架构能够设计得很糟糕,而是说不要花太多的精力在未知的事情上,小步快跑。在迭代过程,做到能实现功能的最小设计,在后续的迭代中,不停地根据新功能修改设计。
权限体系实践
看过我们前期文章的朋友可能对讲权限的那一期文章还有点印象,我们AdCloud团队的权限体系就是小步快跑的一个典型案例:
1.我们先是引入了角色的概念(Role)把用户分成普通成员、业务系统管理员和超级管理员,对刚刚搭起来的系统做了最粗粒度的用户划分。
2.等做到系统隔离时,细化权限粒度,引入对系统的不同资源的操作权限。例如:测试人员只能操作测试类型的流水,发布测试域的系统,而生产域的数据由发布人员控制。
3.等到累计了大量用户后,引入了租户的概念。一个租户下有多个系统,是有一组人员开发维护的。每次都需要单独添加系统权限变成了一个重复的工作,于是我们再次对架构做了修改,引入了成员组,可以给某个成员组添加权限。
经过一段时间的权限模型的变更,这种增量的方式的设计的弊端也显现出来了,因为先期没有完善的设计,权限的代码散落在各个方法里面,没有统一管理,于是我们开始对权限的这块功能做了次小重构,当然我们不是整个迭代都去做重构的,是持续性的,把代码调整也分解成任务,每个迭代做一些。
第一个迭代:我们先根据现有代码的几大特点,设计了权限体系新的模型,然后根据系统隔离的特性,建立Key-Value Map体现权限和各个系统之间的关联。使用数据库实时查询方式。
第二个迭代:使用Redis做权限查询缓存,快速查询到用户的权限信息。 在权限被修改时回收缓存。
第三个迭代:使用SpringSecurity注解的方式为各个接口加上权限判断语句。
如果对整合后的权限整体设计感兴趣的,可以查看我们的前期的文章。
除了上述这样比较大的重构外,有时候重构更是碎片化的日常重构,“闻”到了代码的“坏味道”,我们就可以开始了。删除重复代码,修改变量名(方法名),抽取部分代码变成新方法(新类),删除魔法数据等等都属于重构的范围。我们可以通过IDE的提示、Sonar增量扫描、阿里代码规范等手段查看“臭不可闻”的代码,解决多个迭代累计的技术债务。碎片化重构提高了代码的可读性和可扩展性,更加能适应增量设计。
重构的时候我们怎么保证重构的代码不影响系统的正常使用呢?答案是单元测试。在对每一块代码重构以前,我们需要确保有足够的单元测试,覆盖了需要重构的代码逻辑。这样我们对模块代码的修改,可以通过跑单测是否通过来判断重构成功与否。上述的权限重构,我们写了多个单元测试来保证他的质量,下图只是其中之一。
总 结
其实在项目初期,团队成员对单元测试的理解不够,导致覆盖率很低。每次重构总能引入无数的bug,渐渐的大家也不想重构,后来内部多次交流,大家尝试使用单测后,发现磨刀不误砍柴工,渐渐养成了写单测的习惯,重构慢慢变得简单了。大家不要觉得重构有多高大尚,其实只是每天改变一点点,项目的质量却越来越牢固。