Base Roles for Parts

8/29/99 - Jack Harich - Go Back

We suspect that system design can be reduced to variations on a finite number of base parts, just as all matter consists of a finite number of elements. This document explores the possibilities....

The Question

How in the world do we approach a tough cookie like discovering a "natural form" like Base Roles for Parts? Hmmmmm, well we can draw inspiration from the Periodic Table of Chemistry. This shows over 100 elements organized by the number of protons and number of electron shells. Its usefulness lies is several areas - behavior/property groups, the ability to predict undiscovered elements, relative behavior due to position, and understanding of chemical elements as a whole.

Stationary Parts

In the above model we've organized Stationary Parts by input and output Message types. This allows a simplistic but useful 4 by 4 grid of 16 part roles.

Message Types - None means that the part receives (or sends) no Message. A Notify Message notifies the listeners something has happened. An Acquire Message attempts to acquire a value. A Command Message has the intention of commanding some action to occur, such as deleting a file or committing a transaction.

Role Colors - Note the yellow part roles. These have either no input or no output Message, and so are probably communicating with another system to do their work. The purple part roles are not very useful, though we are young and guessing about the "Low Use" roles. We may find good uses and names for them as time goes by. The green part roles communicate only within a system, a practice we recommend most of the time. The valuable roles are the yellow and green ones, which interestingly make up 11 out of 16 grid spots. Is it possible that these 11 are the proverbial base roles we're looking for? Will they solve all the problems in the universe? Probably not.... :-)

Now lets discuss the basic roles this grid reveals, using a RoleName (What in , What out) style.

Useless (None in, None out) - Since the part receives and sends no Messages, it's not collaborating with the rest of the system. It could do something all by itself, but is probably useless to the system.

Sensor (None in, Notify out) - This receives no input messages but does send Notify Messages to the system. This part is probably sensing input from another systems, and so serves as a sensor for this system. Examples are serial ports, email received, TCP/IP, and speech input.

A variation of this is a timer that sends periodic Notify Messages. This is obviously not a sensor but a signaler. Then again, the timer mechanism itself is actually handled by another system, the operating system or a device. Thus is really is a sensor.

Provider (None in, Acquire out) - Here the part receives no input but sends an Acquire Message to get something, obviously for another system to use. Thus the part is "providing" data for another system.

Complier (None in, Command out) - This part is complying with what another system wants done by sending a Command Message to the system. (Is "Servant" a better name?) The other "system" could be another UHR system, a resource such as a window or file, or a port. For example the part could be listening to a data stream and turning that into Commands, or receiving instructions from another system to make certain chess moves.


Emitter (Notify in, None out) - The part behaves kinda as a black hole, receiving Notify Messages but sending nothing out. Therefore it's probably sending something to another system, and so is an "emitter" for this system. An example is a sophisticated wave source.

Relay (Notify in, Notify out) - All this part does is receive and send Notify Messages. Thus its role is to "relay" Messages on to their destination. It may of course translate, split, combine or even reroute them using various policies set by its DK. A Relay can be very powerful.

A Relay can be a combination of a Sensor and Emitter, handling I/O to another system such as TCP/IP.

Low Use (Notify in, Acquire out) - We really can't imagine what this role would be useful for. What could it possibly do with what it acquired?

Reactor (Notify in, Command out) - This role "reacts" to a Notify Message by deciding what to do and sending a Command to do it. This is a very common role. An example is a Button part that receives a MouseDown Notify and sends a Command to draw a depressed image. Another example is a Business Logic part that receives a "UserChanged" notification, and sends Commands to "SetUserDesktop", "ShowUserHomePage" and "EnterUserLogEntry". Then again, these Commands could also be done with just Notify Messages, which appears to be a better design. This would become a Relay role.


Independent Policy (Acquire in, None out) - Suppose a part wants to acquire something that is fairly independent of system state, such as a credit limit or preferred screen location. The part would send an Acquire Message to get the answer. That Message would be handled by an Independent Policy part, whose sole role is to answer policy questions on demand.

Low Use (Acquire in, Notify out) - We can't yet imagine a use for this role. One possible use would be as an Independent Policy where other parts were interested in being notified whenever certain acquire requests were made. We shall see....

Dependent Policy (Acquire in, Acquire out) - This is just like an Independent Policy role, except that to figure out the answer, the part has to acquire something itself. Thus in is dependent on the rest of the system to determine policy questions.

Independent and Dependent Policy roles encourage the isolation of Business Rules to Policy type parts, which is much better than sprinkling it around a system. It makes it far easier to configure a system or parts for different customers, domains or versions.

Low Use (Acqure in, Command out) - We can't imagine a use for this role, but we shall see....


Sender (Command in, None out) - This role is a black hole for commands on what to do. Since it is not sending any output Messages, it is either ignoring the commands or using another system to perform them. Examples would be writing to a file, doing various GUI things, or sending data using a port.

Model (Command in, Notify out) - Here we have an obvious role, long identified by the Mode View Controller Pattern. An MVC Model contains data, has mutator methods, and fires events when internal changes occur. In UHR, incoming Command Messages are the mutator methods and outgoing Notify Messages are the events fired.

Low Use (Command in, Acquire out) - Since this part is not communicating with another system, what could it possibly do with the Command? Well, it could be communication with another system, but that would enlarge its responsibilities too much for good reuse.

Commander (Command in, Command out) - An example is receiving an "ExitSystem" Message and sending various shutdown Messages like "ClosePorts", "WriteAllBuffers" and "ReleaseResources".


Comments

Now that we've explained the roles, examine them to see if they reflect what you belive to be good roles. Can they express your designs?

Note how the classic MVC Pattern uses the Model, Sensor and Reactor roles. That such a common, powerful pattern maps directly to these roles is somewhat validating.

We recommend that only yellow roles communicate with other systems. This makes such communication far more reusable, makes systems far more configurable, and increases high cohesion. But it's not always possible, as the Relay role shows.

The rest of the model is some rough notes for possible future use. The Filters are very interesting, because the use of Messages makes certain behavior so easy. For example nearly transparent transactions, metric monitoring and policy implementations become duck soup. :-)

Consider this document a mere exploration....