My Interpretation of the Signals and Slots Pattern

BasicWiring

What happens

An ObservableClass ‘emitssignals when something interesting happens.

Examples of interesting things:

a property change in a bean;

a new db connection up;

a window closes

Emitting a signal is something that has to be done manually by the programmer after they’ve done the interested thing

Example

setProperty(Object newValue) {

this.property = newValue;

emit(newValue);

}

It means tell all the InterestedClasses to check out the signal and optional newValues passed and do something with it in a slot method

To let the ObservableClass know which InterestedClass methods to call (slots) when we emit the signal, we must connect them to each other.

We could also connect multiple slots to signals

Once connected however, the connection is quite loose.

The slot method is usually referred to as a string (though we could use closures in future). Thus slot or slots to execute when a signal is emitted is determined at runtime, by looking at the parameters in the emit and matching them to the parameters of the connected slots (methods).

Implementation Use Case:

  1. We are interested in one or more discrete events that happens in the lifetime of the Observable Class.
  2. We create Signal objects to represent each of these events that could ever be emitted by the ObservableClass. We usually do this in the constructor of the ObservableClass
  3. We update our methods to emit signals (call the emit method straight after the interesting thing has occured)
  4. If we want to send some event context data to any interested listeners (slots), we can pass parameters to the emit to pass on when the Signal is fired.
  5. In another class (or maybe even same one?) we write a method to execute when the interesting thing happens. This is called a slot
  6. We connect the signal to the slot via a connect method
  7. When the interesting thing happens, the emit method on the Signal object is called. emit is responsible for letting all the connected slot methods to know to fire.

    Other Notes (extentions)

  • A signal can be connected to multiple slots (methods) in any number of different classes
  • You can chain signals together
  • Communication is one way from the Signal event to the InterestedClass.
  • The params in emited in the Signal can be more than the slot method (but not the other way around)

Comparison to the usual way done in Java Swing (Observer Pattern)

In Java, an Observable Event occurs. InterestedClasses must register their interest with the observable class.

The ObservableClass must keep track of who is listening and notify each of them when the event occurs.

The InterestedClasses must all implement the same notification method (and full method signature) in order to use the event. Potentially less runtime mistakes because the IDE will pick up at compile time

Remember the Signals and Slots pattern doesn’t care about the method signatures of who is listening and effectively can fire updates to different methods of different types.

Design your own DSL with Groovy

http://www.infoq.com/presentations/Design-Your-Own-DSL-with-Groovy

This presentation is by Guillaume Laforge, one of the Groovy founders, who does quite an interesting presentation about how Groovy supports Domain Specific Languages.

In short he starts with a simple example of how the Groovyisms in the language such as method calls without the need for parenthesis, named params and maps and list param injection into method arguments make for readable DSLs, all without touching any of the fancy meta-programming functions provided.  Very impressive. Other Groovy features that we sometimes forget about are ranges and operator overloading which were demonstrated here and  improve readability.

Then he scratches the surface a little deeper showing an example of how to add methods to existing classes using the metaClass property.  He takes the Number class and dynamically adds a method that constructs an object representing a measure – 6.pills or 6.euros which call a method Dosage getPills() that you inject into Number. 

   1: Number.metaClass.getPills = {

   2:     return new Dosage( numOfPills: delegate );

   3: }

When combined with the previous readability of maps representing method args and parenthesis less method calls, it can lead to some readable code

   1:  take  1.pills

   2:   of: SomeDrug,

   3: after: 6.hours // Number.metaClass.getHours = { … }

take is defined as

   1: def take(Map m, Dosage d)

This is a great intro to metaClass object protocol for those who haven’t come across it in Groovy.

The last part of the presentation talks about Abstract Syntax Tree transformations and how you can inject syntax into the Groovy language using annotations.  He uses the example of the Spock testing framework and how the @Speck annotation injects behaviours that wouldn’t normally be allowed in Groovy or Java, such as method names which are “strings with spaces and question marks?” and other neat stuff.  He also talks about how its important to limit what your DSLs can do in the JVM if you are giving them off to

I think in summary Groovy is a great language for supporting DSLs and the presentation gives a valuable insight into some of the more advanced groovy features, a worthwhile watch.