Tuesday, 13 October 2015

Old tech never dies

I still have my first ever computer - a magnificent ZX81, with a 16K RAM pack. The tape deck permanent storage seems to have gone missing years ago. I'm pretty sure the whole lot still works, although I've not tried. All my truly obsolete hardware has pride of place above my PC in my home office. It only gets promoted to the top shelf if it is sure to get a look of puzzlement from those who might visit. I like to hear people say "Ooh, I remember when I had a Sony Discman - it cost me a fortune in batteries!", or "What are those little flat things in the box up there?" to which I reply "They're floppy discs".

My first Computer

I saved hard for that little ZX81 and I'm forever grateful that my Dad stumped up for the balance. I'm still a little surprised at that; even today he has no clue about technology. When I got that little box in my hand I didn't really know what to do with it. Sure you could write some for loops and print out messages - but what to really do with it? It soon turned out that what people really wanted to do with these machines was play games!

As the ZX81 only had 1K of memory (yes you read that correctly, 1K!) it took some real skill to write anything useful. Then came along the expansion pack to add a whopping 16K of memory and suddenly the sky was the limit. The local library came to the rescue with magazines dedicated to Sinclair computers. Every magazine issue had numerous games in which they would publish the full source code. The source was generally simple: a single REM (comment) statement followed by hundreds of ASCII symbols. This was followed by a loop that poked these symbols into memory as raw instruction code. If you typed one single character wrong it was toast! Luckily I had a tape deck onto which I could save a memory dump. This required loading an audio cassette, then pressing the record and play buttons. The little machine would then squeak and squeal like a fax machine and after a while you hoped that you had a copy.

I wonder how many people who cut their first lines of code on a ZX81 are still doing the same now?

All this old technology reminds me that nothing much has changed. Sure we've refined and improved, but there has been no major leap forward. We still store information on revolving platters of plastic or aluminium; computers still have a CPU, bus and memory made from silicon; we still carry digital music with us, only its become a little more compact.

Software development has changed, its become more sophisticated, collaborative and reaches far more into our lives than when the ZX81 was for sale. But in so many other ways it hasn't changed at all. So old tech never dies, it just gets improved.

Blast from the past with MVC

By chance I met an ex-colleague the other day. I had spent a few months at the beginning of the century consulting with his company creating a framework for a Health and Safety system. He reminded me that the company was still going strong but that every developer after me had raised an eyebrow or made a few remarks about that framework. I'm not surprised really.

You have to remember that this was the era of the dot com bubble and bust. Technology to deliver the product vision of many founders was in its infancy, costly and immature. What stands out for me thinking back, was that I was probably ahead of my time without really knowing it!

Leading each technology in the early 2000's was Visual Basic, ADO and ASP. Oh, and don't forget liberal use of COM and ActiveX objects. What I proposed back then was a little revolutionary. The idea was simply to use XSLT to render the display rather than the ASP page. We would create a data access layer (DAL) which retrieved all the necessary model information as XML. This XML was passed to the compiled XSLT which rendered HTML. The ASP page now became the controller. Gone was the horrible ASP syntax embedded with for loops and global variables. Form post back was also handled by the ASP page which validated and passed it on to the DAL.

If you'd come from a traditional ASP development environment you would wonder what was going on. If you had one of today's developers read the code, they would probably understand many of the constructs. Today we would probably call this framework MVC, back at the beginning of the century that acronym didn't exist - well not that I can remember.

I read widely, I synthesised ideas, I put some together and it kind of worked. It was like that back then. Nobody was really definitive about best practice - it was the dom com boom and bust. I'm happy it didn't bust.

Monday, 12 October 2015

Lambda expressions, events and weak references

What happens when you store a Java lambda expression in a weak reference? If this lambda expression is an instance method in an object that is still referenced then you might assume that it will be accessible until your object is out of scope. Your assumption may be wrong.

For some languages functions and methods are pointers in memory that can be passed around just like any other pointer. However, Java does not have pointers; so how does it allow us to pass a method to another method? In brief, a lambda expression is an anonymous class implementing a functional interface (with only one abstract method). Your lambda expression is no more than the instantiation of a compiler generated class.

Event driven example

Lets take an example of event driven architecture to illustrate this in action. The following uses an event emitter to notify observers of a change of state in a game of chess. The EventEmitter class has a set (implemented as a WeakHashMap) of callback functions that are executed with an event payload.

public class EventEmitter<E extends AbstractEvent> {
     private final WeakHashMap<EventObserver<E>, Object> observers=new WeakHashMap<>();

     public EventEmitter() {
          super();
     }

     public void add(EventObserver<E> observer) {
          observers.put(observer, null);
     }

     public void remove(EventObserver<E> observer) {
           observers.remove(observer);
     }

     public void fireEvent(E payload) {
          observers
          .keySet()
          .stream()
          .forEach(o -> o.callback(payload));
     }

     public int size() {
          return observers.size();
     }
}

The event payload

An event payload must extend AbstractEvent, which is no more than a marker class. A concrete example of this event is a SquareChangedEvent which signals to the graphical board that a square must be re-drawn. The logic for the chess game, including the computer player, are separated from the display logic. When the computer player makes a move it is signalled to the display for update. The event contains a payload of the square changed:

public class AbstractEvent {

}

public final class SquareChangedEvent extends AbstractEvent {
     private Square<ChessPiece> square;
 
     public SquareChangedEvent(Square<ChessPiece> square) {
          this.square = square;
     }

     public Square<ChessPiece> getSquare() {
          return square;
     }
}

The Observer

One or more objects may listen to emitted events. To receive the event, the class must implement a method with the correct signature. In this case, any method which takes as a single parameter a class extending AbstractEvent.

@FunctionalInterface
public interface EventObserver<E extends AbstractEvent> {
     void callback(E event);
}

// A MVC style controller that is a bridge between the chess engine and the display.
public class GameController {
     private final BoardPanel board;
     private final ChessGame game;

     public GameController(ChessGame game) {
          this.game=game;
          game.setOnSquareChanged(this::onSquareChanged);
     }

     // Have the board redraw the square 
     public void onSquareChanged(SquareChangedEvent event) {
          board.draw(event.getSquare());
     }
}

The Emitter

The event source keeps a track of observers that wish to receive the event using an EventEmitter for each event type. When the chess engine generates a move, the game signals the change by firing an event for the source and destination square affected.

public class ChessGame {
     private final EventEmitter<SquareChangedEvent> squareChangedObservers = new EventEmitter<>();

     public void setOnSquareChanged(EventObserver<SquareChangedEvent> observer) {
          squareChangedObservers.add(observer);
     } 
 
     public void move(String algebraic) {
               .
               .
               .
          squareChangedObservers.fireEvent(new SquareChangedEvent(from));
          squareChangedObservers.fireEvent(new SquareChangedEvent(to));
               .
               .
               .
     }
}

What is wrong?

On the surface, that all looks perfectly acceptable; it has a certain simplicity, even elegance. The trouble is that the events are never received by the Observer. The reason may not be obvious, but it is simple to understand. When game.setOnSquareChanged(this::onSquareChanged) is called passing the object method onSquareChanged the compiler is creating an anonymous class which delegates to this method. The object is only referenced in one place - the WeakReference held by a map. This makes it immediately available for garbage collection. The WeakHashMap has a ReferenceQueue that it polls and removes any dereferenced objects before returning a KeySet or other entries. It is as if it was never registered!

How to fix this?

The fix is easy. Either stop using Weak references or store at least one reference to the anonymous class before passing it to the event source. The first option is trivial, so let's look at the second option.

// A MVC style controller that is a bridge between the chess game and the display.
public class GameController {
     private final BoardPanel board;
     private final ChessGame game;
     // Keep a permanent reference to the event handler so it is not garbage collected
     private final EventObserver<SquareChangedEvent> onSquareChangedHandler = this::onSquareChanged;

     public GameController(ChessGame game) {
          this.game=game;
          game.setOnSquareChanged(onSquareChangedHandler);
     }

     // Have the board redraw the square 
     public void onSquareChanged(SquareChangedEvent event) {
          board.draw(event.getSquare());
     }
}

We now have a durable reference to this method which will last the lifetime of our object. When our object is dereferenced, so will the reference to the event handler in the WeakReferenceMap.

For many, using a weak reference in this manner is overkill. You could simply use a Set rather than a WeakHashMap if you do not have observers created and de-referenced on a regular basis.