Tuesday, June 9, 2009

Updating the User Interface

As a java developer, I’ve found the best way to actually create software is to create functionality from the software point of view.  Too often, I see software that has been built from the User Interface perspective which creates a dependency on the UI for the software.  Dependency on the UI is generally a bad thing because it makes it hard to test, hard to change and generally hard to understand.

I’ve made it a rule of mine to build software that does not depend on whether it is a web application, swing application, javafx application or any other environment specific application.  I also try to even limit my software’s dependency on where the model is stored.  I do this generally by creating an interface and more than likely a factory class to hide the implementation.  This way, I can code my software to utilize the interface through the controller, rather than starting with a specific implementation that will manipulate my software component and inevitably lock me into using the implementation forevermore.

Lets say for example that I have a software component that has a counter in it.  I know that I want the counter displayed to the user, but I’m not sure how yet.  I also want to stick to my rule about not depending on any specific display implementation.  If I follow the herd on this one, its likely that I would get a handle on my HttpServletRequest object, get the count and set it as an attribute and then create a tag to show it as an HTML element.  Personally, I’ve done this hundreds of times…the struts action get the count from the counter and puts it in the request or session.

But then what happens if I want to run my software in JavaFX?  I have to change the way my software works, which means that if I want to stay compatible with my current solution, I need to add a bunch of logic that says “If we are running in JavaFX do this…otherwise, do that.”  This idea is really fragile and likely to be riddled with defects.  Worse than that, I may re-implement the logic to run on another platform…this creates serious maintenance issues.

In another approach, lets say that I want my software to just update an appropriate display.  My software doesn’t need to know about what kind of display it is, so I just add a bit of abstraction to my code that allows me to decide later how I want my display updated and then carry on writing my counter code.  To do that, I create an interface:

  1: public interface CounterDisplay
  2: {
  3:    void updateDisplay(int value);
  4: }

OK.  That was easy, now I may use a factory to give this Little piece to my counter software, or I may just hard code it depending on how flexible I need to be.  The main thing is, that my software just knows that there is a counter display to deal with…it might be a JOptionPane message box, a JSF page or a JavaFX Scene.  How we update the display isn’t important to the software component.

  1: public void incrementCounter(CounterDisplay display)
  2: {
  3:   counter++;
  4:   display.updateDisplay(counter);
  5: }

In a struts application, I may have my CounterDisplay as an action form.  In this case, I could simply implement my CounterDisplay interface on the action form and then allow struts to do its thing:

  1: public class MyForm extends ActionForm implements CounterDisplay
  2: {
  3:    private int counter;
  4:    ...
  5:    public int getCounter()
  6:    {
  7:       return counter;
  8:    }
 10:    public void updateDisplay(int value)
 11:    {
 12:       counter = value;
 13:    }
 14: }

This way, we separate the UI from the software and we can implement it anywhere.