November 06, 2011

Observer: Part III - Java EventListenerList

This is continuation from Observer: Part II - Degenerated Observer.

In the previous parts, I have shown you how you may break your code by using Observer Pattern implementation that comes along in Java. I have also shown you how you can use a degenerated form of Observer Pattern.

Today I am going to show you yet another way to implement this pattern. I hope you are not getting tired of koalas, since we are about to implement our Koala Zoo example again. This time we are about to use javax.swing.event.EventListenerList.


Do it better - Use EventListenerList

Even though EventListenerList is located in javax.swing.event package, it is in no way restricted to user interface usage. Unlike the Java Observable/Observer, using the EventListenerList does not lead to fragile code either. You can find the EventListenerList usage instructions in the header of it's API documentation. It's almost as old as the Observable/Observer, but still useful today. So go ahead and use it!

Let's implement our Koala again:
    public class Koala {
        private final EventListenerList observers = new EventListenerList();

        public void addKoalaListener(final KoalaObserver observer) {
            observers.add(KoalaObserver.class, observer);
        }

        public void removeKoalaListener(final KoalaObserver observer) {
            observers.remove(KoalaObserver.class, observer);
        }

        public void setHungry(final boolean isHungry) {
            final KoalaEvent event = new KoalaEvent(isHungry);
            fireKoalaChanged(event);
        }

        private void fireKoalaChanged(final KoalaEvent event) {
            // Guaranteed to return a non-null array
            final Object[] listeners = observers.getListenerList();
            // Process the listeners last to first, notifying
            // those that are interested in this event
            for (int i = listeners.length - 2; i >= 0; i -= 2) {
                if (listeners[i] == KoalaObserver.class) {

                    ((KoalaObserver) listeners[i + 1]).koalaUpdate(this, event);
                }
            }
        }

        @Override
        public String toString() {
            return "koala";
        }
    }

Now the Koala keeps it's observers stored in the EventListenerList. Whenever changes happen, it notifies the observers.

But what is up with the funny backwards loop that skips every other element? 

Well, that is taken directly from the usage instructions in the API. The getListenerList returns an array that contains ListenerType-Listener pairs. So the first element in the list will be the type of the listener, e.g. KoalaObserver.class, and the second element will be the actual listener.

There only reason that I know for backwards looping is that this thingy was originally written for the Swing Events. The event handling has some rules and one of them is that the last registered listener should be notified first. That way the newly added listeners have possibility to consume events, too. Thus, the list must be processed from the back to the start.

There are some suggestions about other reasons in this StackOverflow thread: Why is EventListenerList traversed backwards in fireFooXXX(), but I am not buying most of those. The listener array is not going to break or anything if you loop it forwards.

But let's get back to Koala Zoo.

The KoalaObserver now uses a new KoalaEvent, but otherwise is has stayed the same:
    public interface KoalaObserver extends EventListener {
        void koalaUpdate(Koala koala, KoalaEvent change);
    }

I kept the KoalaObserver interface name the same as in previous implementation, so you can compare these easily. But normally I would have called it the KoalaListener.

The KoalaEvent looks like this:
    public class KoalaEvent {

        private final boolean hungry;

        public KoalaEvent(final boolean isHungry) {
            this.hungry = isHungry;
        }

        public boolean isHungry() {
            return hungry;
        }

    }

Note how the KoalaEvent hungry field is defined final. It should be up to the Koala to decide whether it is hungry or not, so we do not want anyone to change that field value later. Always, if possible, try to make your classes immutable. For non-english-speakers, immutable means not modifiable, something that you cannot change after it has been created.

I added the KoalaEvent just to demonstrate how you can deliver complex change information. Using event class is not mandatory. We could have just passed a boolean parameter in the koalaUpdate method.

Here is our ZooKeeper:
    public class ZooKeeper implements KoalaObserver {

        @Override
        public void koalaUpdate(final Koala koala, final KoalaEvent change) {
            if (change.isHungry()) {
                LOGGER.info("Oh, the " + koala
                        + " is hungry. It needs some eucalyptus.");
            }
        }

    }

While handling the events, keep in mind that you do not know who else is going to get them after you are done. So never make any changes to the events that you handle. Exception to this rule is "consuming" the events, like key presses, so that the listeners that come next know that application has already acted based on user input. Most of the events should be immutable, so you can not change them even if you wanted.

And here we test that the notification is sent:
    public void testKoalaGetsFood() {
        final LogMsgCaptor logMsgCaptor = new LogMsgCaptor(LOGGER);
        final Koala koala = new Koala();
        final ZooKeeper zooKeeper = new ZooKeeper();

        koala.addKoalaListener(zooKeeper);
        koala.setHungry(true);
        assertEquals("The zookeeper should get notification",
                "Oh, the koala is hungry. It needs some eucalyptus.",
                logMsgCaptor.getMsg());
    }
LogMsgCaptor is a Mockito-based helper class that I wrote to collect logged messages so that I can test what was logged. Assert.assertEquals comes from JUnit and it makes our test case fail if the message logged does not match to what we expected.


What is the difference between Java Observable/Observer and EventListenerList?

Functionally, they have only minor differences.

The EventListenerList is designed to hold several different types of listener in it. If you would be implementing an user interface class, you could stuff all your MouseListeners, KeyListeners, ActionListeners and what have you, to this same EventListenerList. When the notification time comes, you can easily define which listeners should receive which event. While Observable happily stores any type of Observers, it always notifies all of them using the same argument.

But Observable has an inbuilt change-detection system, and that is something EvenListenerList does not have. The Observable sends notifications only if it has changed, and after the notifications have been sent, it does not send more notifications unless it is marked changed again.

Stylewise, EventListenerList is more elegant of the two. You should always favor composition over inheritance.

When you use composition, like we did here, you can hide the parts of the functionality that are not needed at the moment. If we wanted, we could easily remove the removeKoalaListener method from our Koala. But when you extend the Observable, you cannot hide or remove anything.

You can also restrict the visibility of the methods that should not be accessed from outside the class. Take a look at the fireKoalaChanged method of our Koala. It is private, so no-one can force the Koala to send notifications from outside. The respective methods in the Observable are all public or protected.

Also, as the EventListenerList does not come with predefined notification interface, you probably end up defining interfaces that suit your purposes better.

If you really need to implement a full-fledged Observer Pattern, EventListenerList is an good way to do that.

In the next part we are going to revisit the Java Observer/Observable using Generics.

October 30, 2011

Observer: Part II - Degenerated Observer


This is continuation from Observer: Part I - How to mess up your code with it.

In the previous part, I demonstrated some problems caused by a poor implementation of the Observer Pattern. In this and the next parts I am going to use the same Koala Zoo example to demonstrate how to implement it better.

Today we will be lazy and try to avoid implementing the pattern altogether.


Do it better - Degenerate the pattern

Often what we see is not a need for the full-fledged Observer Pattern, but a possible future need for it. In those cases, just save yourself some time and trouble and do not implement the pattern yet. Prepare for the need, but leave the implementation for the future.

Let's see how the Koala would be implemented using that mindset:
    public class Koala {
        private KoalaObserver keeper;

        public void setHungry(final boolean isHungry) {
            if (keeper != null) {
                keeper.koalaUpdate(this, isHungry);
            }
        }

        public void setObserver(final KoalaObserver keeper) {
            this.keeper = keeper;
        }

        @Override
        public String toString() {
            return "koala";
        }
    }

Instead of inheriting from the java.util.Observable, we now implement a very degenerated version of Observable ourselves.

As we need only one Observer we implement method setObserver, instead of addObserver. We do not provide method for deleting the Observer, unless we really need that. There is no change detection either. Just implement the bare minimum.

But we do need the interface for the KoalaObserver:
    public interface KoalaObserver {
        void koalaUpdate(Koala koala, boolean isHungry);
    }

Note that we are now able to pass on the information with correct types. Instead of two Objects, we are passing the Koala and a boolean telling whether the Koala is hungry. If you would need to pass more information, a good rule of thumb is to have maximum of four parameters in a method. So you might add two more parameters, like isAngry and isSick, but after that you should really refactor your code and implement a KoalaChangeEvent that would contain the parameters that need to be passed.

Now we are ready to implement the actual Observer:
    public class ZooKeeper implements KoalaObserver, WaterPipeObserver {

        @Override
        public void koalaUpdate(final Koala koala, final boolean isHungry) {
            if (isHungry) {
                LOGGER.info("Oh, the "
                        + koala
                        + " is hungry. I'll go into the cage and give" 
                        + " some eucalyptus to the little fella!");
            }
        }

        @Override
        public void pipeFixingNeeded() {
            LOGGER.info("Gonna fix the pipe now!");
        }
    }
Now the class declaration nicely tells us what entities the ZooKeeper is observing. I added the WaterPipe from the previous posting to demonstrate how all the different updates no longer go to a common update method. We are free to invent method names that really describe what is happening.

Last, here is how you would use the classes:
    public void testKoalaGetsFood() {
        final LogMsgCaptor logMsgCaptor = new LogMsgCaptor(LOGGER);
        final Koala koala = new Koala();
        final ZooKeeper zooKeeper = new ZooKeeper();

        koala.setObserver(zooKeeper);
        koala.setHungry(true);
        assertEquals(
                "The koala should get food",
                "Oh, the koala is hungry. I'll go into the cage and give" 
              + "some eucalyptus to the little fella!",
                logMsgCaptor.getMsg());
    }

If you now tried to do similar mistakes that we did in part I you would get compilation errors.
As you can see, methods are more descriptive and it is easier to see what each of the classes do just by looking at the classes themselves.

Overall, this degenerated pattern offers several advantages compared to using java.util.Observable and java.util.Observer. We have less functionality to maintain. Code is easier to read and debug. We get compilation errors if we break the pattern.


Pitfalls

There are two pitfalls here.

1. Skipping the interface

If you are a beginner, you might be tempted to skip the interface and just implement setKeeper(ZooKeeper keeper) method in the Koala. Do not do that - do not trust the Koala

The Koala or any Observable is not supposed to have full access to its Observer. Eventually someone is going to add some methods to the ZooKeeper that are too tempting for the Koala, like tieYourShoeLacesTogether. No Koala would miss that one. Even if you can keep yourself from calling those methods, the future maintenance person will not hesitate. If he can do something, he will.

2. Forgetting to synchronize when refactoring the code

Sometimes you do need to refactor the code later and add a list of Observers. You might be tempted to just add a List to hold the Observers and be done with it. Do not do that! The full-fledged Observer Pattern implementation needs synchronization.


Can you really do that? You'll have to implement the Observer Pattern sooner or later!

Well, it depends on the case. I have been using this deprecated pattern for over 5 years. I can still count with my one hand fingers the times that I needed to refactor the code to use a real Observer Pattern. Usually people have great plans for the future, but they never get implemented. You should prepare for the future, but never implement things that are not really needed now.

In most cases the Observable does just fine with one Observer. Sometimes there are cases where more Observers are needed, but this degenerated pattern is easily updated by storing the observers in a list and adding addObserver method. That will work as long as the Observers are added during initialization and synchronization is not needed. And with the Collections.synchronizedList(List list) you will add the synchronization in a minute, if needed.

Sometimes you will have a case where the Observers are added and removed on the fly from different threads and you need to make conditional notifications and/or store different types of Observers. Those cases are rare, but sometimes do happen. For those ones, you need a more complete implementations of the pattern. Let's take a look at those in the next parts.

October 29, 2011

Who is my Koala keeper?



This post contains answers to the puzzler presented in my previous post Observer Pattern: Part I - How to mess up your code with it.


All the code presented in the previous post is here:



What was wrong with the code?

There were 3 things wrong with the code:
  1. The WaterPipe is not getting fixed
  2. The Boss is observing the Koalas, but when they are hungry, all he does is complain
  3. Whenever the ZooKeeper feeds a Koala, the Boss is notified twice


Was the Boss supposed to observe the Koala?

Well, we have no way of knowing for sure just by looking at the code. I try to avoid puzzles with no clear answer in the future, but there was no going around for this one. When you do not type strictly, you just miss the information in the code if something goes wrong.

The initial though you probably had is that it probably is a mistake to add the Boss as the observer for the Koala, because he does not have the Koala-feeding code in his update method. But you cannot know for sure.

It is also possible (though not probable) that, for example, the Boss was supposed to feed the Koalas while the ZooKeeper is on vacation, but the implementation was never completed. We would need to search through the code and try to find if ZooKeeper ceases to observe the Koalas at some point. If we find such a code, we must fix the Boss so that he can feed the Koalas. If the ZooKeeper is available all the time, we can assume that the Boss should probably not be observing the Koalas. 



Could something like this really happen? Why would someone code something like this?

Yes, and no. 

The broken pipe was my own addition. As we do not have a complex subject and 10.000-50.000 lines of code here, I needed some distraction for you. I do not think it is a common mistake to totally mix up the observers like that. That type of mistake is possible, but as the pipe-fixing functionality would stop working altogether, it would be caught in the testing quite fast and thus the error would not survive long. 

But what happened with the Boss is real. I have fixed a similar bug. One of the nasty things about this pattern implementation is that the only reference to update method is in the java.util.Observable. The codebase had about 10 different Observers and I had to check through them all while I tried to find out who should observe who. Only after that was clear, was I able to concentrate on trying to find out what is wrong. The update method having and argument of Object array with four unknown Boolean and Integer parameters did not help either. 

Finally I came into conclusion that probably the Boss and the ZooKeeper had originally both been observing the Koala. At some point someone had thought that it is better that the ZooKeeper keeps the Boss informed. And while he remembered to remove the Koala-feeding code from the Boss, he did not remember that the Boss was still added as Observer for Koalas. We were getting quite a lot of extra notifications! 

While the similar situation could have occurred with better implementation of the Observer Pattern, it could not have happened by mistake. If strict types would have been used, the programmer would have gotten a compilation failure for trying to add the Boss as an observer for Koala.

In the next part of this series, I'll show you better ways to implement the Observer Pattern.





October 22, 2011

Observer: Part I - How to mess up your code with it


The Observer pattern is one of the patterns published in the Design Patterns book by the Gang of Four. It is needed when you have an object that changes it's state and you want other objects to notice the change.

If you are programming Java user interfaces you cannot really avoid this pattern. The whole Java event handling is based on it. So whenever you are writing event listeners for Swing components, you are actually using this pattern.

But Java also offers an implementation of the Observer interface and an Observable class to go with the interface. The problem with the Java Observer and Observable is that they were written before the Generics and so they use plain Objects to pass information. While that is not a problem in small hobby projects, it may lead to disasters in larger applications.


If you want to create easily maintainable code, you need to enforce the strong type checking that Java offers.

I guess most of you have heard that before. But maybe some of you have not seen what may happen when that rule is broken. And that is what I am about to demonstrate today. This is a beginner-level article. If you have already messed up your code by violating the rule and always try to avoid casting objects in your code, you might want to just quickly browse through the code and read the puzzler at the end of the post.


How to mess up your code with Java Observer

I am going to demonstrate the problem with a simple example from the Koala Zoo. In the very first version of the Koala Zoo we have just a Koala and a ZooKeeper, who gives food to the Koala when it is hungry.

Let's start by implementing the Koala using the Java Observable:
    public class Koala extends Observable {

        public void setHungry(final boolean isHungry) {
            setChanged();
            notifyObservers(isHungry);
        }

        @Override
        public String toString() {
            return "koala";
        }
    }

There we go! In real life the Koala class would probably be a bit more complex, but this is enough for our purposes. As you notice, Observable is a class and needs to be extended by our Koala.

Let's continue and create our Observer, the ZooKeeperObserver is an interface with a single method for getting updates from the Observable:
    public class ZooKeeper implements Observer {

        @Override
        public void update(final Observable animal, final Object arg) {
            if (arg instanceof Boolean) {
                final boolean isHungry = (Boolean) arg;
                if (isHungry) {
                    LOGGER.info("Oh, the " + animal
                            + " is hungry. I'll go into the cage and "
                            + "give some eucalyptus to the little fella!");
                }

            }
        }
    }

Our Observable and Observer are ready to go, let's test how they work:
    public void testKoalaGetsFood() {
        final LogMsgCaptor logMsgCaptor = new LogMsgCaptor(LOGGER);
        final Koala koala = new Koala();
        final ZooKeeper zooKeeper = new ZooKeeper();

        koala.addObserver(zooKeeper);
        koala.setHungry(true);
        assertEquals("The zookeeper should get notified",
                "Oh, the koala is hungry. I'll go into the cage and "
                        + "give some eucalyptus to the little fella!",
                logMsgCaptor.getMessage());
    }

LogMsgCaptor is a Mockito-based helper class that I wrote to collect logged messages so that I can test what was logged. Assert.assertEquals comes from JUnit and it makes our test case fail if the message logged does not match to what we expected.

As we can see, the code works nicely and ZooKeeper is able to keep the Koala stuffed with eucalyptus. But things are going to change when the code evolves.

The Zoo is growing and getting new animals. Introduce the Tiger!
    public class Tiger extends Observable {

        public void setHungry(final boolean isHungry) {
            setChanged();
            notifyObservers(isHungry);
        }

        @Override
        public String toString() {
            return "tiger";
        }
    }

At this point I might spare a thought on whether I could use a common superclass called Animal. But as it's easy to refactor later and pull the methods up, I am not going to do that now.

The Tiger observable is ready to use, but we have not made any changes to our Observer, the ZooKeeperThe nasty thing is that we can actually add the ZooKeeper as an observer for Tiger already and we get no compilation errors when we compile the code. Huh? The ZooKeeper is an observer for Koala, and as the update method is passing Objects as arguments, compiler have no way to know that the method is not implemented properly.

That means we need to REMEMBER to update the ZooKeeper's update method, so that he knows how the Tiger needs to be feed. But hey, that's no problem at all. I have great memory! If I sometimes forget my keys or the dinner or my pants or something it is just because I am thinking something else. But enough blabbering, let's have a coffee break. I suggest you to have a cup too!

Are you back yet? Where were we? Yeah, the Tiger. Let's continue and implement our new test case, the one where the ZooKeeper is feeding the Tiger:
    public void testTiggerGetsFood() {
        final LogMsgCaptor logMsgCaptor = new LogMsgCaptor(LOGGER);
        final Tiger tigger = new Tiger();
        final ZooKeeper zooKeeper = new ZooKeeper();

        tigger.addObserver(zooKeeper);
        tigger.setHungry(true);
        // As this test goes through OK, we forgot to update the ZooKeeper 
        assertEquals("Hmmm. Should the zookeeper go into the cage?",
                "Oh, the tiger is hungry. I'll go into the cage and "
                        + "give some eucalyptus to the little fella!",
                logMsgCaptor.getMessage());
    };
Oh well, what do you know... I'll fix the code in a minute...

I know that at this point some of you are thinking that this is not a big deal. But as time goes by and code gets filled up with little slips like the one I made above, results can be... interesting.

Let me show you an example with a little puzzler.


Puzzler: Koala Zoo after 2 years

The application has expanded and the Zoo now has new personnel. The ZooKeeper has been changed, and he has a Boss to report to:
    public class Boss implements Observer {

        @Override
        public void update(final Observable observable, final Object arg) {
            if (observable instanceof ZooKeeper) {
                ((ZooKeeper) observable).getStatusReport();
            }

            LOGGER.info("I hate being bugged with little things");
        }

    }

We can see that the ZooKeeper has become Observable too. Here is the new code for the ZooKeeper:
    public class ZooKeeper extends Observable implements Observer {

        public void getStatusReport() {
            LOGGER.info("Well, I have taken care of everything");
        }

        @Override
        public void update(final Observable observable, final Object arg) {
            final boolean argIsTrue = Boolean.TRUE.equals(arg);
            if (observable instanceof Koala && argIsTrue) {
                LOGGER.info("The lazy critter is hungry again, I cannot believe how much it eats");
            }
            else if (observable instanceof WaterPipe && argIsTrue) {
                LOGGER.info("I'll do what needs to be done");
            }

            if (argIsTrue) {
                setChanged();
                notifyObservers();
            }
        }
    }

Oh, it seems that the ZooKeeper now observers a WaterPipe too. But what is the argument? Lets check that out the WaterPipe to find out:
    public class WaterPipe extends Observable {

        public void setBroken(final boolean isBroken) {
            setChanged();
            notifyObservers(isBroken);
        }

        @Override
        public String toString() {
            return "watering system";
        }
    }

Oh, the argument is telling if the pipe is broken!
Let's see how all these classes are used:
        final List fifteenKoalas = initKoalas();
        final WaterPipe pipe = new WaterPipe();
        final ZooKeeper zooKeeper = new ZooKeeper();
        final Boss boss = new Boss();
        zooKeeper.addObserver(boss);
        pipe.addObserver(boss);

        for (final Koala koala : fifteenKoalas) {
            koala.addObserver(boss);
            koala.addObserver(zooKeeper);
        }

And as you might guess, this code is not working.

What is wrong and how would you fix it? Is the Boss supposed to observe the Koalas?

I'll tell you the answers in the next post.




October 15, 2011

Introduction and policy

This blog will contain little lessons about things that may cause problems in the context of larger code-bases. I will present you coding mistakes, bad practices and a way to implement the same thing in a better way. I will also present you some patterns that are widely promoted, but are often implemented badly by beginners. I will present stuff that is just fine in little home projects or school-work, but in the bigger projects cause a major headache in the future for the maintenance person. 

I am a Java specialist with over 10 years of experience in working with large code-bases. I have started some of those myself from the scratch, some I have just maintained. But in every case there has been so much to learn. 

The best way of learning is by mistake. Most of the stories told here are based on my own mistakes and bad practices. However, our own mistakes and bad habits are often invisible for us, at least for the first 1-2 years after the program has been made. Thus, I would never have learned so much without my dear colleagues. If you know me and see a mistake that was made by you, be proud. You have helped me to learn, and now you are helping others to learn.  

There is a companion code-base for this blog, called beyondhc. All the code snippets and classes presented in this blog can be found there. As most of the large code-bases are commercial, the code is published with Eclipse Public License 1.0 so that you may really use what you find. 

I respect my employer and do not use any project code in this blog. As the stories are based on what I have learned while working, the classes may have some resemblance to existing project code (dead or alive). But I assure that any such resemblance is purely coincidental. Each and every class presented here is written from the scratch - nothing is copied from existing projects.

And one last thing. I am not going to publish regularly, no-no. I'll just publish when I have something new to say. However, once I start a new series, you may expect the next parts to appear maybe once in a week (or two weeks) until the series is finished.