RAD User Management Example
Note:
This example does not reflect the user management modules in Oracle Solaris.Object or interface granularity is subjective. For example, imagine an interface for managing a user. The user has a few modifiable properties:
-
name property of type string
-
shell property of type string
-
admin property of type boolean
The interface for managing this user might consist solely of a set of attributes corresponding to these properties. Alternatively, it could consist of a single attribute that is a structure containing fields that correspond to the properties. A possibly more efficient implementation would read or write all properties together. The object implementing this might be named as follows:
com.example.users:type=TheOnlyUser
If instead of managing a single user you need to manage multiple users, you have a couple of options. One option would be to modify the interface to use methods instead of attributes, and to add a "username" argument to the methods, for example:
setUserAttributes(username, attributes) throws UserError attributes getUserAttributes(username) throws UserError
This option is sufficient for a single user, as well as provides support to other global operations such as adding a user, deleting a user, getting a list of users and so on. This option could use a more appropriate name, for example:
com.example.users:type=UserManagement
However, suppose users have more properties and you want to perform more operations, such as, sending them email, giving them a bonus and so on. As the server functionality grows, the UserManagement's API becomes cluttered and the API will have code for both global and per-user operations. The need to specify a user and the associated errors for each per-user operation would start looking redundant.
username[] listUsers() addUser(username, attributes) giveRaise(username, dollars) throws UserError rif(username) throws UserError sendEmail(username, message) throws UserError setUserAttributes(username, attributes) throws UserError attributes getUserAttributes(username) throws UserError
A better alternative would be to create two interfaces that separate the global operations from the user-specific operations. The UserManagement object would use the global operations interface:
username[] listUsers() addUser(username, attributes)
A separate object for each user would implement the user-specific interface:
setAttributes(attributes) attributes getAttributes() giveRaise(dollars) rif() sendEmail(message)
Note:
Ifrif
operates more on the namespace than the user, it should be present in UserManagement where it would need to take a username argument.
Finally, the different objects would be named such that each object could be directly accessed by the client:
com.example.users:type=UserManagement com.example.users:type=User,name=ONeill com.example.users:type=User,name=Sheppard ...
This example also highlights a situation where you do not want the RAD server to enumerate all objects when a client issues a LIST
request. Pulling down a list of potentially thousands of objects on every LIST
call does not benefit the majority of clients.