系统设计一个很重要的目的就是为了重用﹐而要做到重用﹐低耦合是最有效的手段。本文将通过web应用系统中一个最常见的主题--权限设计﹐来说明解耦的应用。要解耦﹐首先就要进行抽象﹐权限究竟能不能抽象?
我认为通常意义上的权限应该分为2类﹕
一类是用户是否有权进行某项动作﹐如管理员可以删贴﹐人事考勤员可以修改考勤数据。这种权限就是最简单的有或无问题﹐毫无疑问﹐这是可以抽象出来单独进行设计的。另一类我将它称为数据权限﹐如某某人可以查看某某部门的人员信息﹐某某人审核某某厂别的订单﹐某某人具有某某报表的下载权限等﹐这种权限与具体的应用系统有关﹐与具体的应用逻辑有关﹐需要在系统分析时解决的﹐并在程序中嵌入这些代码﹐当业务逻辑发生改变时﹐常常需要修改这些代码逻辑。当然这种权限应用也可以进行抽象﹐但是其耦合程度相对较高﹐抽象后进行的重用是在coding级别的﹐比如封装了权限的分配﹐移除和获取代码﹐但是需要new 一个权限类﹐并在业务系统中使用该权限类。本文着重通过第一类权限的应用的说明来阐述解耦的应用.第一类权限其实是应用最为广泛的权限﹐对此类权限设计最常见的就是分角色﹐如一个BBS﹐有管理员﹐斑竹﹐普通用户﹐匿名用户4种角色。每个人员是一种角色﹐每种角色可访问的菜单﹐页面或按钮是不一样的。
一些小型的﹐逻辑相对简单﹐应用已稳定的系统使用此种方法可大大减化权限的设计。但是它毕竟是耦合的。举个最简单的例子﹐例如在贴子列表页面上﹐斑竹可能在每个贴子后面会多一个删除按钮﹐而普通用户则不会有此按钮。程序员经常需要这样编码﹕
if(user is 管理员 或 斑竹)
删除按钮.visible = true
else
删除按钮.visible = false
乍看这样的代码﹐是看不到有什么问题的。但至少有一点ugly的就是出现了程序员最忌讳的HardCode代码:user is 管理员 或 斑竹﹐可能有人说这一点点不会有太大影响。但是这至少让我们的系统有了如下的假定﹕1﹕只有管理员或斑竹才能删除贴子﹐这种假设是很难站住脚的﹐系统不断变化﹐很容易哪天出现了一个"代斑竹"或"副斑竹"的角色﹐它们也可以删贴...2﹕系统建立在这几种固定的角色之上﹐相信除了这个页面的判断角色代码外﹐系统的其它地方一定也会充斥这样的代码﹐一旦要改﹐那就只好将此类代码全部找出来...一旦这些假设变化了﹐系统就会被这种耦合”拖累”在我几年的程序设计生涯里﹐碰到的这种权限修改要求可谓数不胜数﹐某个主管打电话过来﹐能不能帮我开放一下考勤查询权限﹐我想看到我们部门的考勤状况。天啦﹐考勤查询是考勤员才能查的呀﹐开放这个给他可以呀﹐但更多的只有人事考勤员才能操作的功能都"不安全"的暴露在他面前了﹐谁知道它会不会去点点里面的哪个按钮?你也许会说﹐当初开发程序时﹐需求分析就应该做清楚﹐现在请按正常的系统维护流程来做。不单说他是主管﹐也可能是客户﹐我们就无法拒绝。更重要最终我们还要是改程序﹐还是要面对哪些散落在系统各个角落的权限判断代码﹐为什么当初我们就不留下一个心眼呢?解决的方法就是将权限抽象﹐与具体的业务系统解耦﹐开发系统的时候完全不去考虑这个系统有哪些角色﹐他们哪些人可以做什么﹐哪些人又可以做什么。而是将这部分需求撇开。比如我们在编写删除贴子的代码时﹐就完全不用写下if(has 删除权限) //删除贴子代码而是直接就写删除﹐我管你有没有删除权限﹐但你代码既然执行到了这里﹐那我假定你肯定就有删贴子的权限﹐至于你是管理员﹐斑竹﹐副斑竹﹐甚至是普通用户我也不管﹐也许你高兴﹐让某个普通用户也暂时可以删贴子(客户或主管要求嘛)这样我们就把整个系统的功能全部开发出来了。现在﹐任何人进入系统﹐映入它眼帘的就是所有菜单﹐所有按钮﹐太舒服了。好了﹐现在我们再来考虑用户的权限要求吧﹕用户要求分4种角色﹕管理员﹐斑竹﹐普通用户﹐匿名用户管理员什么事情都可以做斑竹只可以删贴普通用户可以撤斑竹匿名用户只能进入浏览页面建几个表﹐做一下对应﹐然后写一个方法﹐传入userid和功能﹐返回true或false就可以了(我以前的贴子有介绍过一种具体的方案)。这个权限管控放在哪里呢?很简单﹐只要不要和你的业务代码放在一起就可以了﹐也许你可以通过AOP这种时髦的方式来完成﹐或者最简单的﹐就写一个类﹐在每次调用方法时﹐统一判断权限。
在web系统中就最简单了﹐只要做一个访问的url和功能的对应关系﹐然后利用一个httpmodule在每次request时﹐先把url转换成功能﹐然后再调用上述权限判断方法﹐返回true就进﹐false就转向错误页面。
可以看出﹐我们的应用系统很干净﹐我们的权限模块也很干净。最后再提一下﹐在这种权限方案做web页面时经常碰到的一种情形﹐就是我刚刚提到的同一个页面可能有不同权限的情形﹐你无论如何都回避不了那行
if(user is 管理员 或 斑竹)
删除按钮.visible = true
else
删除按钮.visible = false
的代码。
是这样的
但是换过一个角度我们就能理解了﹐我们不把这种权限看作业务逻辑﹐我现在只是在提供功能﹐需要提供2种功能﹐浏览和管理﹐那好﹐我写两支程序。一支show.aspx﹐一支manage.aspx
别人会说你有病
确实有病﹐明明是差不多完全一样的代码﹐为什么要写两支程序﹐这不找抽吗?
没办法﹐我就写一支程序
postlist.aspx
但是两个功能的访问地址分别是﹕
post.aspx?type=show
post.aspx?type=manage
那行代码也巧妙地变为了﹕
if(request["type"]=="manage")
删除按钮.visible = true
else if(request["type"] == "show")
删除按钮.visible = false
这样你就看到了﹐程序员在写这个页面的代码时﹐完全占据了主动﹐再也不会去问系统分析师﹕老大﹐究竟谁才有删贴子的权限呢?
而只要对老大说﹐老大﹐你要的程序已经写好了﹐浏览和管理的页面分别是...
你爱怎么用就怎么用吧﹐什么? 权限? 管我什么事?
本文作者:未知