• Home
  • About
  • Sample Apps
  • Hierarchies

    February 26th, 2008

    Canoo’s CTO Bruno Schäffer is speaking at SD West 08 on “Design Patterns for Rich Internet Applications”.

    SD West 08

    The following blog post outlines some of the concepts that he will cover in his talk. This is part four of a series of blog posts:

    As we have seen in the previous posts of this blog post series, the presentation model clearly assigns responsibilities within the presentation layer. For simple user interfaces this approach is more than good enough. However, simple user interfaces are not really the domain of Rich Internet Applications (RIA). How can we tackle complex user interfaces using the presentation model approach? Let’s have a look at a non-trivial user interface:

    Screenshot

    It shows a typical master-detail view, further enhanced by a tree navigation on the left-hand side. The user can select different aspects of a person in the tree which brings up the corresponding form on the right hand side.
    A naïve approach would be to create a single presentation model for the entire view. While implementing the presentation model you will soon realize that there is just too much state and behaviour to be captured in a single presentation model.

    If a view is too complex, we have to split it up into manageable sub-views, each with a presentation model of its own. The combination of sub-view with its presentation model is called “application component”. An application component communicates with its environment only via the presentation model, i.e. the presentation model acts as an observer to other application components (resp. their presentation models).

    A complex user interface can now be decomposed into a number of fairly independent application components. Independence means, that these application components can be employed or reused in different contexts. Independence is facilitated by relying on the observer pattern for communication with other application components.
    How do you build a complex user interface from a set of application components. You simply arrange the application components in a hierarchy. Each application component is responsible for the creation of all directly known application components. Views and presentation models have to be aware of this hierarchy. An abstract base class for view resp. presentation model can factorize this.

    The component hierarchy for our example user interface shown above looks like this:

    Component hierarchy

    Views are marked red and presentation models are blue.

    As you can see not every view needs to come with a presentation model of its own. In this case the form view hooks up to the presentation model of the navigation view. A change in the tree selection will be broadcasted by the navigation presentation model. The form view updates itself accordingly by bringing the corresponding view to the front.

    In addition, application components are perfect candidates for testing. Each application component can be tested independently (as described in part three). Testing a user interface made up from a hierarchy of application components can be considered as integration testing. It still focuses on the behaviour of the presentation models, though. An integration test case first creates the presentation model hierarchy and then tests the behaviour of the model hierarchy. The view code in this hierarchy is still trivial and therefore rarely need dedicated test cases.

    Application components have another advantage. They are perfect candidates to be assigned as an independent task to a developer.

    There are still some challenges left, such as clean initialization for presentation models and views when creating a hierarchy of application components or distribution of update events in this hierarchy without ending up in infinite update cycles.

    In the next bog post, we will have a look at a simple framework which supports building user interfaces with application components. We will also see how easy it is to generically add undo/redo to an application.

    Part 1: MVC and the Brave New World of RIA
    Part 2: The World Needs More Models
    Part 3: A simple view on complex stuff


    A simple view on complex stuff

    February 11th, 2008

    Canoo’s CTO Bruno Schäffer is speaking at SD West 08 on “Design Patterns for Rich Internet Applications”.

    SD West 08

     

    The following blog post outlines some of the concepts that he will cover in his talk. This is part three of a series of blog posts:

    So far we discussed the deficiencies of plain MVC for complex user interfaces and how the presentation model approach can remedy this situation. The presentation model assumes most of the former responsibilities of the view/controller pair. What remains for the view/controller pair? Frankly spoken, not much:

    • The view is responsible to create the user interface components and arrange them in a layout.
    • All relevant events triggered by the user interface components are redirected to the appropriate methods of the presentation model
    • The view is an observer of the presentation model. It has to react to the relevant changes to the presentation model and update the user interface accordingly.

    Creating the user interface (besides design and ergonomical aspects) is trivial but cumbersome to code. However, we have the opportunity to employ some markup language for specifiying the UI. Markup language are not really suited to specify presentation logic, but since this is coded in the presentation model, views can easily be built this way. Examples for UI markup languages are SwiXml , ULC XML or XUL.

    Redirecting events to the presentation model and reacting to changes of the presentation model is also pretty straightforward in most cases. The standard scenarios can be covered by generic infrastructure known as binding. I will discuss some aspects of binding in a later blog post.

    Now let us have a look at a simple example to illustrate the concepts discussed so far.The example is based on the ULC component library, but the basic concepts can easily be transfered to most common component libraries. Here is a screenshot of the application to show what it looks like:

    Screenshot showing a simple view

    The application allows a user to load a record into the form, edit it and save it. There are two business objects involved, pertaining to the person and university. The presentation logic is simple: first name and last name must not be empty and the university id must relate to an existing university record. Validation is immediate, e.g. if the user enters the university id the university name field will be updated immediately. The presentation model captures the necessary state and logic. Below you can see the implementation stripped down to the properties personName and personFirstName (the observer infrastructure is left out too). It is fairly simple: since the presentation model is a Java Bean, we need to provide setters and getters which map to the person object referenced by the presentation model. The property personName has only a getter since it is a read only property. The setter validates the property and updates the errorList property accordingly.


    public class SimpleFormPresentationModel {
        private Person fPerson;
        private ErrorList fErrorList;
     
        public final static String PERSON_NAME = "personName";
        public final static String PERSON_FIRST_NAME = "personFirstName";
        public final static String ERROR_LIST = "errorList";
     
        public SimpleFormPresentationModel() {
            fireAllPropertiesChanged();
        }
     
        public String getPersonFirstName() {
            return getPerson().getFirstName();
        }
     
        public void setPersonFirstName(String firstName) {
            getPerson().setFirstName(firstName);
            validate(PERSON_FIRST_NAME);
            firePropertyChanged(PERSON_NAME, getPersonName(getPerson()));
        }
     
        public String getPersonName(Person person) {
            return person != null ? person.getFirstName() + " " + person.getLastName() : "";
        }
    }

    The view class is pretty straightforward. Basically, it creates the UI, hooks up the UI components to the presentation model and reacts to the changes of the presentation model. The implementation uses the UltraLightClient component library. The stripped down view class (incl. some convenience methods) looks like this:

    public class SimpleFormPane implements IPropertyChangeListener {
        private ULCBoxPane fFormPane;
        private ULCTextField fName;
        private ULCTextField fFirstName;
        private SimpleFormPresentationModel fFormPresentationModel;
        private Color fErrorColor = new Color(255, 0, 0, 192);
     
        private static final String[] UI_FIELDS = new String[]{"firstName"};
     
        public SimpleFormPane(SimpleFormPresentationModel formPresentationModel) {
            fFormPresentationModel = formPresentationModel;
        }
     
        public ULCComponent getPane() {
            if (fFormPane == null) {
                fFormPane = createForm();
                fFormPresentationModel.addPropertyChangeListener(PERSON_NAME, this);
                fFormPresentationModel.addPropertyChangeListener(PERSON_FIRST_NAME, this);
                addValueChangedListener(PERSON_FIRST_NAME, fFirstName);
            }
            return fFormPane;
        }
     
        private void addValueChangedListener(final String property, final ULCTextComponent textComponent) {
            textComponent.addValueChangedListener(new IValueChangedListener() {
                public void valueChanged(ValueChangedEvent event) {
                    if (textComponent instanceof ULCTextField && ((ULCTextField)textComponent).getDataType() != null)  {
                        fFormPresentationModel.setProperty(property, ((ULCTextField)textComponent).getValue());
                    } else {
                        fFormPresentationModel.setProperty(property, textComponent.getText());
                    }
                }
            });
        }
     
        private ULCBoxPane createForm() {
            ULCBoxPane boxPane = new ULCBoxPane(2, 1, 5, 5);
            boxPane.add(2, "cc", new ULCLabel(HTMLUtilities.convertToHtml("<strong>Person Data</strong>")));
     
            boxPane.add("rc", new ULCLabel("Name:"));
            fName = new ULCTextField();
            fName.setEnabled(false);
            boxPane.add("ec", fName);
     
            boxPane.add("rc", new ULCLabel("First Name:"));
            fFirstName = new ULCTextField();
            boxPane.add("ec", fFirstName);
     
            boxPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
            return boxPane;
        }
     
        public void update(String property, Object oldValue, Object newValue) {
            if (property.equals(PERSON_NAME)) {
                fName.setText((String)newValue);
            } else if (property.equals(PERSON_FIRST_NAME)) {
                fFirstName.setText(((String)newValue));
            } else if (property.equals(ERROR_LIST)) {
                ErrorList errorList = (ErrorList)newValue;
                    for (at.diefaehre.argo.pm.util.Error error : errorList) {
                    ULCComponent component = getComponent(error.getProperty());
                    if (component != null) {
                        if (error.isError()) {
                            component.setBackground(fErrorColor);
                        } else {
                            component.setBackground(Color.white);
                        }
                    }
                }
                setFocusToFirstError(errorList);
            }
        }
     
        private void setFocusToFirstError(ErrorList errorList) {
            for (String field : UI_FIELDS) {
                if (errorList.containsError(field)) {
                    ULCComponent component = getComponent(field);
                    if (component != null) {
                        component.requestFocus();
                        break;
                    }
                }
            }
        }
     
        private ULCComponent getComponent(String name) {
            ULCComponent component = null;
            try {
                component = (ULCComponent)PropertyUtils.getProperty(this, name);
            } catch (Exception e) {
            }
            return component;
        }
     
        public ULCTextField getName() {
            return fName;
        }
     
        public ULCTextField getFirstName() {
            return fFirstName;
        }
    }

    What would test cases for this simple scenario look like? The view contains no real logic and therefore we do not need to write any test cases. However, we should make sure that the presentation model updates its properties correctly (incl. validation) and triggers the appropriate update events. Tests for our presentation model could look like this:


    @Test
    public void testValidFirstName() {
        attachPropertyChangeRecorder(fPresentationModel);
        fPresentationModel.setPerson(Service.getService().getPersonById(1));
        fPresentationModel.setProperty(PERSON_FIRST_NAME, "Bruno");
        assertFalse(fErrorList.hasErrors());
        testPropertyChangeMap(PERSON_NAME, PERSON_FIRST_NAME, ERROR_LIST);
    }
     
    @Test
    public void testInvalidFirstName() {
        attachPropertyChangeRecorder(fPresentationModel);
        fPresentationModel.setPerson(Service.getService().getPersonById(1));
        fPresentationModel.setProperty(PERSON_FIRST_NAME, "");
        assertTrue(fErrorList.hasErrors());
        assertEquals("firstName", fErrorList.getError().getProperty());
        assertEquals(1, fErrorList.getError().getErrorNr());
        testPropertyChangeMap(PERSON_NAME, PERSON_FIRST_NAME, ERROR_LIST);
    }

    The first test case starts with attaching a person to the presentation model and then sets the personFirstName property. There are two checks: one whether no errors have been produced and the other checks whether all expected update events have been triggered. For this an event recorder is attached (attachPropertyChangeRecorder()) and testPropertyChangeMap verifies the expected update events.

    As shown above, this blog post looked at simple views and how they are implemented with a presentation model running underneath. The above example demonstrated the concepts introduced so far. Obviously, there are still some drawbacks to this simple approach. It will not easily scale to more complex user interfaces (e.g. a master detail view with tabbed forms) and contains quite a lot of repetitive code. In the next blog post, we will investigate how more complex user interfaces can be tackled.

    See also:

    Part 2: The world needs more models

    Part 1: MVC and the Brave New World of RIA


    The World Needs More Models

    February 1st, 2008

    Canoo’s CTO Bruno Schäffer is speaking at SD West 08 on “Design Patterns for Rich Internet Applications”.

    SD West 08

    The following blog post outlines some of the concepts that he will cover in his talk. This is part two of a series of blog posts:

    In part one we discussed why plain MVC is not suited for Rich Internet Applications. The presentation model extends MVC to better fit the needs of applications with complex presentation logic. Martin Fowler first described the basic idea of this approach. The presentation model inserts an additional model between the business model (i.e. business object) and the view-controller duo. It captures the state of the user interface and handles the presentation logic. The business object is not directly accessible to the view anymore. The presentation model offers only those business object properties to the view that are relevant to rendering the user interface. The presentation model may map the properties of several business objects. If the business object does not serve as the model in MVC, it does not need to provide any observer infrastructure and can stay a real POJO.
    In traditional MVC you have either equip the business object with some observer infrastructure, employ some kind of decorator for the business object which handles view notifications (e.g. a dynamic proxy) or define an aspect.

    illustration.jpg

    What state must be captured by the presentation model? Basically, it is the entire mutable state of the user interface. For example, the mutable state of a checkbox is whether it is

    • selected/not selected,
    • and enabled/not enabled

    (visibility might be another relevant state). The background color of a checkbox is not relevant to most UIs and hence not a mutable property which needs to be captured by the presentation model. Complex state such as a table model or tree model can easily be delegated to a sub-presentation model. Common UI toolkits provide default implementations for these models so there is no need to re-implement them in the presentation model.
    Now, how does the view react to changes in the presentation model? It is pretty simple: the presentation model is fully observable and the view gets notified of the changes by the observer pattern. This approach can even cover non-trivial scenarios, such as the following one:

    Screenshot

    The user just selected a different row in the table and the user interface has now ask the user whether any modifications should be saved. Changing the selection state is a responsibility of the presentation model. However, the presentation model is not supposed to directly pop up a dialog, but it can trigger an update event and the responsible view will react to that by displaying the dialog. The action buttons in the dialog will then call the appropriate methods in the presentation model.

    The observer pattern not only provides broadcast communication among classes but it also helps to decouple classes. On the other hand, one has to be aware of its drawbacks. In languages with static type checking it may circumvent the type checking by relying on a generic update method. Debugging also tends to be harder since one has to step through the observer infrastructure. In addition, trying to understand code with nested listeners (i.e. update listeners which themselves trigger update events again) is not really fun. At least try to avoid updating properties within a bean by means of the observer pattern.
    At start-up time the view needs to get the entire presentation state in order to render the initial state of the user interface. For this, the presentation model can trigger update events for all its properties.

    With the presentation model it is now clear to developers where to put all the presentation logic and therefore the implementation is more straightforward and uniform. Another big advantage is improved testability. As I mentioned in take one, automatic testing of user interfaces is expensive both at development and run-time. The presentation model substantially improves this situation. Most UI testing can be accomplished by just developing and executing unit tests on the presentation model without the need to run the user interface. These tests are way easier to implement since they only change properties of the presentation model and test properties resp. update events.

    Since the presentation model covers most of the former responsibilities - what remains to be done for the view? Part three “A Simple View on Complex Stuff” will discuss this. We will also look at a simple example. Stay tuned!


    MVC and the Brave New World of RIA

    January 28th, 2008

    Canoo’s CTO Bruno Schäffer is speaking at SD West 08 on “Design Patterns for Rich Internet Applications”.

    SD West 08

    The following blog post outlines some of the concepts that he will cover in his talk. This is part one of a series of blog posts:

    Rich Internet Applications pick up the ball where plain Web applications dropped it: they promise to bring the power of desktop applications to the Web. Desktop applications almost went out of fashion with the advent of Web applications. But most people still prefer the rich user interface (UI) and interactivity of desktop applications such as Outlook compared to their Web-based siblings such as GMail and Yahoo! Mail. In many cases the convenience of ubiquity compensates for the inferior or cumbersome user interface.

    MVC diagram

    Client-server applications with rich user interfaces first emerged at the beginning of the nineties. Usually implemented in C++ or Smalltalk, they followed a fat-client approach, the predominant client-server architecture at this time. The principal way to organize the presentation layer of such applications was the MVC model. The concept was first proposed by Trygve Reenskaug (see http://heim.ifi.uio.no/~trygver/2007/MVC_Originals.pdf) for the Smalltalk environment. As with any proven object-oriented design, MVC splits up the responsibilities of a user interface component into domain data (Model), rendering (View), and event handling (Controller). Quite often, view and controller are merged together, though.

    Today’s GUI component libraries still make use of MVC. For example, most non-trivial UI components in Swing employ some sort of MVC. However, if one tries to apply MVC to complex (form-based) applications, which is typical for desktop or Rich Internet Applications, experience shows that criteria such as clean design, maintainability, or reusability cannot be met. There are several reasons:

    1. What is the model of a form based application with a rich UI? Most developers point to the business object to be rendered in the form as the model. A form-based RIA has more model states than just the business object, though. This additional state is usually kept in the view class and increases the complexity of the view.
    2. The presentation logic of a Rich Internet Application is vastly more complex compared to a traditional Web application. The presentation logic has to deal with more events caused by extended interactivity. Another feature of RIAs is an up-to-date rendering of the presentation state. For example, UI components may be enabled/disabled or visible/invisible depending on the state of the application. This is also part of the additional model state as mentioned above. On top of that, RIAs feature instant validation (without interrupting a user’s flow of work by throwing a modal dialog into their face). This “silent” validation has to be handled (at least partly) by the presentation logic as well. Naïve design puts all of these aspects into the view class. As a result, the view class becomes overly complex, hardly reusable, and difficult to maintain.
    3. Automated testing of such view classes can only be accomplished by running the user interface. Tests are executed by triggering user events through a test tool or accessing the components through a library (e.g. Jemmy for Swing component library). This way of testing is slow and fragile: running hundreds or thousands of UI tests takes quite some time and changes to the user interface are likely to break the tests resulting in false negatives.

    As a company specializing in RIA, we have witnessed quite a few transitions from plain ugly Web applications to the brave new world of RIA. Some of our observations:

    • Typical Web developers have not heard of MVC and try to design RIAs like they would design a typical HTML application.
    • Seasoned developers who may have had some experience with fat client-server applications try to apply MVC concepts in the same way that they did in the nineties, without adapting to the new scenario.

    Both approaches have their weaknesses and lead to poor results. In part two of this blog post series - “The world needs more models” - we will discuss possible remedies to this situation.