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:

If rif 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.