Implicit Invocation

What is Implicit Invocation?

The objective of an implicit invocation (II) design style (and languages) is to improve a software engineer's ability to separate conceptual concerns.

The key idea in II languages is that some interfaces declare events, allowing one set of modules to contain code that dynamically and explictly announces events, while a second set of modules dynamically registers methods, called handlers, to receive calls (the implicit invocations) when events are announced. The two sets of modules are independent of each other and need only share the event interface declarations.

An example of Implicit Invocation

As an example, consider a drawing editor which consists of objects such as Points, Lines, etc. Each element is part of the overall figure and extends the FElement class. Other classes may be interested in knowing when such figure elements change. For example, there may be an Update class that updates the figure on the screen when any element changes.

The class FElement contains a list of all registered observers. It contains a method for observers to register with instances of the FElement class and a method for FElement objects to announce the change event, which notifies all registered observers.

	public abstract class FElement extends Object {
		private List changeObservers;
		protected void announceChangeEvent(FElement changedFE) {
			for(ChangeObserver o : changeObservers) {
				o.notify(changedFE);
			}
		}
		public void registerWithChangeEvent(ChangeObserver o) {
			changeObservers.add(o);
		}
	}

The class Point is an example of an FElement. Points have an x and a y location and setter methods setX and setY. Points also have a method makeEqual, which will set the x and y location of its argument to that of the current instance.

All three methods modify an instance of class Point and thus they all announce the change event. The first two methods announce the event for the current instance while the makeEqual method (since it modifies the other instance) announces the event for the other instance.

	public class Point extends FElement {
		int x;
		int y;
		public void setX(int x) {
			this.x = x;
			announceChangeEvent(this);
		}
		public void setY(int y) {
			this.y = y;
			announceChangeEvent(this);
		}
		public void makeEqual(Point other) {
			other.x = this.x;
			other.y = this.y;
			announceChangeEvent(other);
		}
	}

Finally consider the Update class, which is responsible for updating the figure elements on the screen. Update contains a method for registering as an observer to an FElement instance. It also contains a method notify to update the display, which is called each time the change event is triggered by a subject.

	public class Update implements IChangeObserver {
		FElement last;
		void registerWith(FElement fe) {
			fe.registerWithChangeEvent(this);
		}
		public void notify(FElement changedFE) {
			this.last = changedFE;
			Display.update();
		}
	}

What are the limitations of implicit invocation languages?

II Languages have following three limitations.

  • They require complex event declaration, announcement, and registration code scattered across the system.
  • The ability to replace the code for an event (what aspect-oriented techniques calls "around advice") is not available, without unnecessarily complex emulation code (to simulate closures in languages such as Java and C#).
  • Quantification (selecting a number of related events using one succint name) is not easy, since no abstraction like PCDs is available. Instead, a non-trivial strategy, such as a subscription registry, is needed.

In II languages, observers are coupled to subjects. Consider the example above, the Update class is coupled to the FElement class:

	void registerWith(FElement fe) {
		fe.registerWithChangeEvent(this);
	}

If the registration method changes names in the FElement class, all observer classes must also be updated.

Page last modified on $Date: 2011/07/29 10:39:12 $