This weblog is a little bit different than the ones I wrote before. I don’t give you a working example (don’t worry you will get all the code you need) and I use UML to show you the general ideas. Furthermore I try to explain in simple steps how I came up with the solution instead of just presenting the final product.
It all began when…
one of my colleagues pointed out that we need specific error messages in one of our bsp applications. I already had created the setter methods for the modelbinding in my model class which checked if the input made by the user was valid or not (for example materialnumbers which don’t exist in the system) but I was not sure how I can inform my controller about invalid input. Normally returning parameters or exceptions can be used to inform the invoker of a method that something went wrong. The problem is that the setter methods for modelbinding are called automatically by the MVC framework so it is not possible to use this approach to report errors to the controller.
Be aware of the dark side of the force…
The easiest solution would be this one:
Just give the model class a reference to the controller class and when something bad happens it access the controller and tells him what went wrong. Now, why is this solution not useful? Simple, take a look at the UML diagram and you will see that it creates a bidirectional association which means that both classes know and depend on each other, now. Moreover the model layer is not clearly separated from the GUI layer anymore!
The Observer Pattern
The pattern was written down by the famous Gang of Four group and can be found in every programming environment (just search for *observer* in the SE80 or if you are a java fan take a look at the official javadoc). For a detailed description of the pattern click here. The idea is that you use an interface to get rid of the dependancy between the object which are interested in events like updates or errors (called observers) and the object which is observed. Furthermore the implementation of the registration of the observers and the event dispatching is separated in another class.
Adopting the Pattern
At first I identified how my classes relate to the pattern and what role they have:
Now we need the classes to the corresponding roles:
The observable class is abstract because I don’t want that it is used as a “standalone” class. The observer was created as an interface because the actual implementation of the error handling is not known yet and has to be done by the programmer who uses the interface.
Don’t forget we want to observe our model class:
Since ABAP OO doesn’t support multiple inheritances the observable class has to inherit from cl_bsp_model
There are many observers who want to observe our model:
As you can see our observable class has a private attribute with the name tab_observer, now. It is an internal table which will be used to store the observers. Due to the new attribute there is an association between the class and the interface, now. This is logical because the observable class will store the observers. Here is the code for the type definition of the table:
Put the code in the types definition of the observable class:
Methods for adding and deleting observer:
Observer are able to register or deregister themself for certain errortypes. This makes sense because sometimes a controller is only interested in one error event. The classic observer pattern uses a different approach and always notifies every observer. Below is the coding for these two methods:
A method for contacting the observer:
We need a way to tell the observer that an error has happenend. Therefore the interface gets a new method called error. It has only one parameters which is the eventtype (errortype) which occured.
“Houston we have a problem” or how to notify our observers:
When something went wrong the observers have to be notified. This is done by invoking the method notifyObserverError. The method loops over the observer-table and calls the error method of the observers which registered for the particular errorevent:
It is time to put everything together…
Ok now you can see how everything fits together. The actual model class inherits from the observable class and the controller implements the observer interface. We have succesfully removed the evil bidirectional association and also created a simple, easy to use and highly reuseable event framework.
A little example how to setup the whole thing…
Below is a little code snippet which should give a general idea how to register and notify observer.
This blog showed how easy it is to use design pattern for your daily development tasks. For more information about design pattern read the blogs from Igor.