提取禁用控件的规则

时间:2010-02-09 10:12:59

标签: user-interface design-patterns

背景

每周我们会让一些用户呼唤帮助,为什么你不能在表格Y上做X. 由于复杂的业务规则,我们经常不得不重新查看代码,以了解为什么当时没有特定的操作。有没有经过验证的策略来解决这个问题?

如何从GUI,业务规则和/或安全性中收集导致禁用按钮的所有信息?

实施例

用户无法从测量概览表单中删除测量值,因为

GUI

  • 表格中未选择任何测量值。
  • 表格中选择了多个测量值。

业务规则

  • 所选测量已用于计算中。
  • 所选择的衡量标准与(我们称之为)产品形式相关联。

安全

  • 当前用户不是负责该特定测量的分析师组的成员。
  • 当前用户不是分析师。

修改

关于我们已经做出计算以确定是否应该禁用控件这一事实的有效评论。

我们使用家庭酿造ACL来处理安全问题。这些是决定是否应禁用控件的步骤

  • 检索全局ACL(当前来自数据库)。如果测量属性的ACL中存在Write ACE,则表示当前用户有权更改测量。
  • 测量业务对象获取此全局ACL的副本。业务对象将其业务规则置于检索到的ACL之上。如果业务规则规定测量不应该是可写的,则会向ACL添加Deny Write ACE 请注意,业务对象只能使安全性更具限制性。如果全球安全要求无法完成,则无法完成。
  • 与业务对象的ACL和GUI的耦合是通过我们称之为GuiMap对象的方式完成的。此对象从业务对象检索ACL的副本,并允许开发人员添加返回布尔值的函数指针,以便在业务对象ACL的顶部添加Gui rules

现在要确定是否应该启用一个按钮,GuiMap将结合由业务对象的ACL确定的安全性以及具有用户安全性的extremis来评估传递给它的每个函数。

  • 如果用户没有权限,则始终禁用结果。
  • 如果业务规则说应该禁用它,则禁用它。
  • 如果任何一条Gui规则说它应该被禁用,则禁用它。

事实上,每一层都建立在前一层之上,以确定最终结果。这与一个计算不同,以确定是否应启用按钮或其他任何内容。

如果你愿意的话就是这样:当ACL发出副本时,副本会将自己附加到主服务器上,并在主ACL更新时得到通知。这允许我们

  • 如果用户在任何屏幕中注销/开启,则让每个控件都更新。
  • 让每个控件都能更新业务对象的变更需要它。

这对我们来说非常有效,除了很难知道为什么某些东西被禁用。

4 个答案:

答案 0 :(得分:2)

如果我理解正确,你有两个不同的问题:

1)每层中的检查只返回一个指示启用/禁用的布尔值,并且不返回原因。

您必须更改它,以便每个检查也返回原因;例如你可以返回一个元组(enabled, reason),其中access是你现在拥有的布尔值,并说明它被禁用的原因(例如作为一个字符串)。

根据您所处的环境,更改所有访问检查的返回类型可能不可行;如果你想避免这种情况,你可以报告“带外”的原因,例如:将其存储到全局(或更确切地说是线程局部)变量,UNIX中的la errno或Windows中的GetLastError。那不是那么优雅,当然会被许多人不赞成: - (

或者,您可以更改检查以抛出异常(使用描述性消息)而不是返回布尔值。同样,在许多环境中这都会令人不悦......

2)您的业务层将条目添加到对象的访问控制列表中。当您稍后检查访问权限时,您知道哪个条目拒绝访问,但您不知道为什么已添加此条目。

解决此问题,您可以向ACE添加reason字段。当业务层添加ACE时,它会设置原因以描述拒绝访问的原因。然后,访问控制检查从此处读取原因并将其传递到GUI层,如上所述。

答案 1 :(得分:1)

我总是会明显地禁用控件,让用户在点击时通过悬停提示或对话框知道原因(如果你的GUI允许监听禁用控件上的事件)。

答案 2 :(得分:1)

如果文档中没有解释它并且在GUI上不清楚,我认为不得不查看代码。我已经完成了这一千次,所以我真的对这里发布的任何替代方案感兴趣:)

也许我们可以在每次禁用/启用按钮时将原因写入日志。例如:

  • 已禁用按钮A,因为用户执行此操作 没有安全权限ABC
  • 启用按钮B,因为全部需要 信息现已可用

答案 3 :(得分:1)

Lieven,我个人会建议您使用 oefe 给出的解决方案。

但是,由于您不满意,我在下面添加不同的方法。仅当您的GUI屏幕呈现过程是幂等的(即不会更改系统状态并且可以多次调用而不影响系统)时,这将起作用。

  1. 使用装饰器模式创建一个 包装你的规则的包装规则 原始业务规则。包装纸 规则将执行原始规则 以及如果访问是添加原因 拒绝。
  2. 使用策略模式获取实例 规则。根据参数, 策略应该是使用原创 业务规则或包装业务 规则。
  3. 禁用时在客户端屏幕上 单击控件,异步 调用以前使用的相同过程 最初构建屏幕。 但是这次加了额外的 参数,即控件的id和 您想知道的原因指标 各自控制的原因 禁用。
  4. 原因指标参数为时 目前,使用的策略 包装即可。这个包装器增加了原因 到ACE。最后,为了给定 控制,检索原因 需要的控制ID并将其返回。
  5. 当客户端的原因是异步时 响应,显示它。
  6. <强>缺点:

    • 屏幕启动必须是 幂等
    • 为规则包装更多工作
    • 有关规则的更多工作 实例化(使用策略)
    • 如果规则不是幂等的或不能 用于包装,你会 需要创建并行层次结构 规则。

    <强>优点:

    • 默认情况下未填充原因
    • 仅当用户请求原因时 然后进行额外的处理。

    <强>更新

    或者对于原始但更简单的方法,您可以在一个时间递增一个模块,重构现有规则并使它们对控制的id和原因指示符参数敏感。如果存在原因指标参数,则规则本身应该填充原因。