Technical Articles by Sony Mathew, Software Architect, Twin Cities, MN


Wednesday, December 3, 2008


Fluent DSL for Rich-UI

User Interface (UI) Layouts are generally defined using declarative forms such as HTML or XML. One of the primary reasons for this is to separate roles of UI designers and programmers - whether they are separate individuals or the same person. However, this separation is going to reach its practical limits as user experience requirements get richer and more demanding - what I mean is - an XML or HTML template is just NOT going to be a valid representation of the view that the user sees because at the end of the day its just a static view. A richer experience by definition means the view is changing constantly with each user action - sometimes drastically - this means the code behind the template will become the center of focus as it re-shapes the view in response to user actions. As for XML or HTML templates - well they can continue to have a place subordinate to the UI code, loaded on demand perhaps for small fixed layout sections and like its cousin "the image" banished to the static content-managed realm. Additionally, code close to the UI will be managing more data, state transitions and controller logic for quicker user responses. People who demand a "staticky" template-first approach for UI design will end up with an increasingly complex soup of code mixed inside an increasingly irrelevant and inaccurate template - creating something that neither the UI designers nor programmers can consume easily with their minds or their tools. It will become more practical in the future for programmers to develop the UI using a programming language from a set of mock-ups created by the UI designers - to fully deliver the dynamic user experience desired. However, building UI in programming languages can be verbose and cumbersome with little clarity and virtually no visual clues to the layout structure in the code. This needs to be fixed - and it can be fixed by heavily leveraging Object-Oriented features - in fact with the right approach OO languages like Java can provide a truly great experience for laying out complex UI for Rich Internet Apps (RIA) (not to mention for Desktop Apps or even today's old-fashioned static HTML generating web apps). UI Building in an OO language can be made fluent and succinct such that it can out-do any equivalent HTML/XML format in simplicity, clarity and functionality. Unlike external DSLs that exist today - I would prefer a DSL internal to my native programming language for building my UI. A DSL internal to your native language simplifies the transition you undoubtedly must make between your UI and its supporting data models, controls and services written in your native language - not to mention being able to use your favorite language tools like code-refactoring. Now I am not suggesting that all UI frameworks in the future should support a single Fluent API (or be written only in Java) but if enough DSLs start looking similar - a standard should be considered for your favorite programming language and adopted by the web frameworks supporting that language.
The terms Fluent and DSL are in reference to Martin Fowler's writings. I won't go into detail regarding them. Checkout Martin Fowler's entries DomainSpecificLanguage (DSL) and FluentInterface.

AxisPanel: An example

Lets look at an example of a fluent layout panel I created in Java called AxisPanel. I created this primarily for GWT but I've also created a sample panel for Swing, and conceivably such a Fluent API could also be created for generating old-fashioned static HTML on the server-side (imagine NOT having to deal with untyped ${expression} anymore). The AxisPanel API attempts to follow the elegant principle of self-similarity (a property of Fractals) such that complex layouts are created with a few simple constructs applied recursively. AxisPanel lays your widgets out in the X axis (horizontal) or Y axis (vertical), you can nest as deep as you like and set properties for any panel at any depth, and the important part is: you can modify your layout at any nesting depth simply by adding/removing x or y panels - you don't need to create new wrapper panels, find suitable variable names for each of them, or refactor insertion points of old panels every-time you change your mind as to where widgets are positioned. This combination of horizontal and vertical layouts along with the fluent interface creates a very effective and powerful DSL in Java for laying out UI of almost any complexity. Here is an example of using AxisPanel to emulate a simple Border Layout i.e. laying out widgets in a North, South, East and West fashion.
AxisPanel p = new AxisPanel()
.y().width("100%")
    .x(myNorthContentPanel).css("north").q()
    .x().width("100%")
        .y(myWestContentPanel).css("west").q()
        .y(myCenterContentPanel).css("center")
            .width("100%").align(0,0).q()
        .y(myEastContentPanel).css("east")
            .width("100%").align(1,0).q()
        .q()
    .x(mySouthContentPanel).css("south").q()
    .q();
Where: x(...) - Add widgets horizontally. y(...) - Add widgets vertically. q() - Quit building the current panel and revert to building the parent panel. css(..), width(..), etc. - various properties that can be set on any panel. Note: The various content panels (e.g. myNorthContentPanel) could have been created in-line recursively as well, but to emphasize the Border Layout they are shown as created earlier (perhaps as other AxisPanels).

AxisPanel: Another example

The following example lays out a series of search options on the top half of the page followed by a dynamic bottom section that changes based on the search performed i.e. results section. The results section has a results table and a cart - and users can move items between the results and the cart real-time. This example shows the layout only - the interactive widgets like buttons, links, text-boxes along with their action listeners were created prior to their layout (as I layout and find I need a button or a text-box, I create them just above the layout or in another dedicated method).
AxisPanel p = new AxisPanel()
.y().css("search").border(1)
    .y().css("options").space(5)
        .x("Search Options").css("header").space(5).q()
        .x(searchByNameOption,searchByNameBox).css("byName").space(5)
            .x(alphaLinks).css("alpha-links").space(5).q()
            .q()
        .x(searchTop10Option, searchTop10Box).css("top10").space(5).q()
        .x(searchButton).space(5).q()
        .q()
    .y().css("results").width("100%").space(5)
        .y().css("info").space(5)
            .x("Search Results").css("header").q()
            .x("Click Cart+ to move items to cart")
                .css("howto").q()
            .q()
        .x().space(20).width("80%").align(0,0)
            .y().css("detail")
                .x("Your Results").css("header").q()
                .x(searchResultsTable).css("table").border(1).q()
                .x(pagePrevLink, new Label("page"), pageNextLink)
                    .space(5).width("100%").align(0,0).q()
                .q()
            .x(new Image("/path/to/arrow/image")).q()
            .y().css("cart")
                .x("Your Cart").css("header").q()
                .x(itemCartTable).css("table").border(1).q()
                .x(itemCartRemoveAllLink).space(5).width("100%")
                    .align(0,0).q()
                .q()
            .q()
        .x(checkOutButton).width("80%").q()
        .q()
    .q();
Here is the result of the above sample layout:

In conclusion:

Hopefully, the AxisPanel example demonstrates that you can create a Fluent Object-Oriented DSL within your native language that is simpler yet more powerful than its declarative XML/HTML cousins for coding Rich Internet Apps (RIA) (in addition to Desktop Apps or even old-fashioned static HTML generating apps). Without a Fluent API, complex layouts in your native language can be verbose with unclear layout structures and cumbersome modifications. AxisPanel is a good start but I would like to see more Fluent APIs in Java and other OO languages coming out of the wood-work and supported by more web-frameworks directly. See sample AxisPanel code: http://code.google.com/p/xsonymathew/wiki/AxisPanel