Some quick thoughts on the "Java Tip 68" web page that Rick pointed us to ... Two things seem to be being discussed in this article/pattern. One is a notion of (very strong) decoupling between components and the other is the avoidance of large switch-statements. DECOUPLING ========== As the summary says, registering a callback interface (or "function" in C terms) with the caller decouples the caller from knowing anything about who it is calling ... other than it implements that callback interface (or function) ... which is fine. This enables the caller to issue the the call without really knowing who it is calling (other than having a pointer to it) or what it will do with that call. However, registering the callee with the caller does require the callee having to see the caller ... or at least to see something that implements the relevant caller-registration interface. OK, not too bad. A bigger however, however, is that callback mechanisms give absolutely no protection in the case when caller and callee are in different threads of control. To sort that out, we have to get to grips with synchronized methods ... else suffer race hazards if callee items are changed by the call. Even then, there is no way the callee can *prevent* the caller from making a call when it's not wanted ... so the callee has to accept the call and get involved with wait/notify semantics to undo the mess ... and that's real hard. The problem of caller/callee being in separate threads is not addressed in this article. But the channel interface of CSP processes gives really very good decoupling indeed. Here, neither process knows anything about the other one ... not its name nor any "methods" it might possess. All each process sees are its channels and that's all it needs. Each process works to its own (channel) interface, meeting a specification defined entirely in terms of that interface. The network builder sees only the (channel) interfaces of the processes, declares the necessary channels and plugs things together. She is constrained by only two matters: at a low level, are the channel connections compatible (i.e. input-to-output only and matching protocols) and, at a high level, does it make sense to plug those components together (given their specification which, recall, is in terms only of their channel interfaces). Of course, channel interfaces also give you protection when caller and callee are in different threads. Actually, that's the only way we can use them! Active processes interacting via channel messages gives very strong decoupling between components. It's the model we are used to from real life. An (electric) kettle is a component with a channel interface - plug its cord into the wall socket and it comes alive! AVOIDANCE OF SWITCH STATEMENTS ============================== The article says: `Usage of switch statements during coding is a sign of bad design during the design phase of an object-oreiented project'. Did I miss something? Has there been an article titled: "Switch Statements Considered Harmful"? This article continues: `Commands represent an object-oriented way to support transactions and can be used to solve this [switch-statement] design problem'. Well, their Command pattern certainly uses lots of Objects so I guess that makes it `object-oriented' ... but I'm not at all sure of the taken-for-granted assumption: "if it's object-oriented, it must be good". Can someone say why switch-statements are bad? Surely, it's not a sudden worry about run-time efficiency -- a well-optimised switch-statement compiles to a computed goto ... which has linear execution time ... the same as following a pointer to find the code?? A switch-statement is very easy to understand (maybe you had better `break' at the end of each component though). I like all those long CASE-inputs in my occam programs ;-) Heving said that though, there are some benefits from the ideas in this article. The avoidance of switch statements, though, would not be my major concern. The JCSP library has (CSP) processes wrapping up all the java.awt components. GUI events translate into channel communications from these processes. Configuring a component is done by sending it a message down its configuration channel. A problem is that there are so many possible configuration commands to AWT components. We could have defined a lengthy (occam-like) variant protocol class which the configuring process instantiates and sends to the component. A process in the component interprets this protocol with the equivalent of a CASE-input - i.e. a long switch. The problem is that this protocol would have to be *very* long and, to support Swing and track updates, would get longer and longer. It's this length and maintenance prooblem that's the problem. So, instead, JCSP gives some special protocols for common configurations (e.g. send a Boolean.TRUE or Boolean.FALSE to enable/disable a Button ... or a String to reset the label on a Button) and a catch-all that lets you do anything else. This catch-all uses a trick described in this paper and it's neat (and `object-oriented' ... oh dear). The jcsp.awt.ActiveButton class contains an interface: Interface Configure { public void configure (java.awt.Button button) } A process that wants to do some specialised configuration on an instance of jcsp.awt.ActiveButton creates an instanec of a class that implements the above. With anonymous inner classes, this can be done in-line: . . . ActiveButton.Configure conf = new ActiveButton.Configure { public void configure (java.awt.Button button) { button.setBackground (...); button.setFont (...); ... etc. [use whatever java.awt.Button methods you like] } } Then, all you do is send this `conf' down the channel to the ActiveButton you want so configured. The ActiveButton interprets such a message by invoking its configure method, passing itself (`this') as the argument. Since ActiveButton is a sub-class of java.awt.Button, it all works. This way, completely general configuration of all GUI components is supported without us having to define a protocol and interpret each possible variant. We support the common variants directly, because creating one of these Configure instances is a bit of a drag if you want to do it a lot. [Note: the above is in the still-unreleased coming-real-soon-now version of JCSP ... ] SUMMARY ======= CSP channels give you natural decoupling, and consequently good reusability and maintanability, of components. Sending on-the-fly created objects implementing general configuration (or execution) interfaces is a fairly powerful idea and fits perfectly with channel communicating processes. It save us having to write lots of code and documenting it ... that, rather than the avoidance of a lengthy switch-statement, is the benefit. Peter Welch.