Background
Weekly we will get some users calling out for help why thy can't do X on form Y. Because of complex business rules, we often have to revert looking in the code ourselves to know why that particular action is not available at that time. Are there any proven strategies to deal with this?
How does one collect all the information from the GUI, business rules and/or security that leads to disabling a button?
Example
The user can't remove a measurement from the measurement overview form because
GUI
- there is no measurement selected in the form.
- there are multiple measurements selected in the form.
Business rules
- the selected measurement has been used in a calculation.
- the selected measurement is linked to (what we call) a productfiche.
Security
- the current user is not a member of the group of analysts responsible for that particular measurement.
- the current user is not an analyst.
Edit
Regarding the valid comments about the fact that we've already made a calculation to decide if the control should be disabled.
We use a home brew ACL to handle security. These are the steps to decide if a control should be disabled
- A Global ACL is retrieved (currently from a database). If a
Write ACE
in the ACL for the measurement property is present, this indicates that the current user has the right to change the measurement. - A measurement business object gets a copy of this global ACL. The business object puts his business rules on top of the retrieved ACL. If the business rules dictate that the measurement should not be writable, it adds a
Deny Write ACE
to the ACL.
Note that a business object can only make the security more restrictive. If global security dictates it can't be done, it can't be done. - The coupling with the business object's ACL and the GUI is done through what we call our GuiMap object. This object retrieves a copy of the ACL from the business object and allows the developer to add function pointers returning booleans to it to add
Gui rules
on top off the business objects ACL.
Now to determine if a button should be enabled, the GuiMap evaluates every function passed to it in combination with the security determined by the ACL of the business object and in extremis with the security of the user.
- If the user has no rights, the result is always disabled.
- else if the business rules say it should be disabled, it is disabled.
- else if any one Gui rule says it should be disabled, it is disabled.
So in fact, every layer builds on top of the previous to determine the final outcome. It is not like there will be one calculation to determine if a button or anything else should be enabled.
The beauty if you like is this: as ACL's hand out copies, the copies attach themselves to the master and get notified when their master ACL get's updated. This allows us to
- let every control get updated if a users logs off/on in anyone screen.
- let every control get updated on a change in the business object demands it.
This works quite well for us, except that it is hard to know why something is disabled.