'Twas WYSIWYG, unsightly code
Did file and frumble by the way;
All grinsy were the morrow-knows,
And the dumb sooths outlaid.
Beware the GUI Builder, son!
The drag that drops, the cut that pastes!
Beware the graphic god, and shun
The nerdious interface!
He took his QWERTY keys in hand,
Long time the dialog he fought-
So rested he by the Widget tree,
And sat awhile in thought.
And, as in WIMPish thought he sat,
The GUI Builder, icons lame,
Came blitting through the worldly web,
And googled as it came!
Grid bag! Grid bag! And layout do
The QWERTY keys went clicker-clack!
With one last call, he uninstalled
And went compiling back.
And hast thou slain the GUI Builder?
Come to my arms, my beanish boy!
O wizard real! Just look and feel!
He buffered in his joy.
'Twas WYSIWYG, unsightly code
Did file and frumble by the way;
All grinsy were the morrow-knows,
And the dumb sooths outlaid.
With apologies to Lewis Carroll
Ever since the advent of GUI toolkits there have been GUI builders - graphic applications that allow the developer to build an interface in a WYSIWYG fashion. Ostensibly, they offer the following advantages over the hand coding of interfaces:
GUI builders often appeal to managers and novice GUI developers, who believe that a combination of the above attributes will increase programmer productivity and reduce development costs. Had they greater experience of interface development, they would likely appreciate the manyfold disadvantages of using these tools. For the benefit of those who risk falling for the superficial appeal of GUI builder tools, this article will outline the major failings of this application genre.
The impressive demos and tutorials that accompany many GUI builders invariably describe the same scenario; the construction of a panel or dialog containing components whose position, visibility and configuration do not change at runtime. The choice is a deliberate one, designed to avoid confronting a limitation of GUI builders - their reliance upon static code analysis. By "static code analysis", I refer to those aspects of the code's behavior that can be determined from consideration of it's structure alone, without regard to it's runtime behavior.
Now consider the following panel from the interface of an "Address Book" application:
The Gender field is static, in that it always has two options (hermaphrodites not withstanding). But the radio buttons in the Salutation field change dynamically, depending upon the currently selected Gender. For males, three salutations are possible. As shown below, for females five different salutations are possible:
But there are further complications. This interface is also internationalizable. In France, it has to present the options for males like this:
How would you go about implementing such a panel using a GUI builder? Enter any one of the above configurations and press the "Generate Code" button, and you will certainly not get code that captures any of the above dynamic requirements. You'll have to go into the generated code and add in that functionality yourself, which rather obviates the use of the GUI builder to begin with. If you have a particularly capable GUI builder, you might find that it can resolve references to external resource bundles (thereby predicting a simple piece of runtime behavior), but many will not even do that.
Such shortcomings weren't apparent when you saw the simple, forms-based demo that convinced you to purchase the GUI builder to begin with, were they?
One attraction to GUI builders is that a superficial consideration suggests that they simplify the GUI construction process. That simplification is particularly attractive to managers, who can see and understand the process of dragging and dropping components onto a panel, but who cannot so readily appreciate or visualize the programmatic production of the same result.
However the simplification, apparent or real, comes at a price. As demonstrated by the example above, there is only so much you can do within the limitations of static code analysis. Beyond that, you have to venture into the code anyway; at which point you will need to work with the detail and complexity of the GUI toolkit's API, which is exactly what the GUI builder is meant to spare you from, isn't it? So not only can you not avoid dealing with the intrinsic complexities of interface development, you must also learn to use the GUI builder itself.
This may be a non-trivial addition to the learning curve. As a developer, you have enough on your plate in coming to terms with the essential technologies of your application, without adopting additional overhead in learning to use a GUI builder. And some of the mechanisms that a GUI builder presents you with will be necessarily awkward to deal with, for the simple reason that they are aiming to present visually concepts which do not lend themselves well to such a presentation. For instance, layout managers.
A layout manager is an invisible attribute of a container component that determines how the contained components are positioned within it, and how they respond to resizing operations. The constraints they impose upon the positioning of the components they lay out are many and varied. They may force all components to have the same height and width, to have their centers equidistant around the perimeter of a circle, to have the same height but attain widths that are a fixed percentage of the parent component's width, and so on. How do you visually represent these infinitely variable sets of constraints amongst components, and in such a way that they can be configured with mouse clicks and keyboard operations? The answer is "With great difficulty". You need to introduce an artificial mechanism that make otherwise implicit constraints explicit so that they can be manipulated. This mechanism will be unique to the GUI builder, and your knowledge of how to use it of no use in any other context. It is part of the unnecessary addition to your learning curve that has been introduced through use of the GUI builder. But remember, the GUI builder is meant to be saving you time and shortening the learning curve, isn't it?
If a GUI builder provides you with nothing more than an alternative way to assemble a component hierarchy, how much work can it save you, anyway? The lion's share of the effort involved in learning a new GUI toolkit is coming to an understanding of what the 1,001 attributes of the components do. If a GUI builder does nothing but provide an alternative way of supplying values for those attributes, then what has been saved? You still need to understand what attribute to change to what value in order to get a desired effect. Rather than entering a line of code to set the attributes value, you now select it from a drop-down list. Big saving, that.
When designing and coding an interface by hand, one is naturally on the lookout for opportunities to save time by creating GUI components that can be reused elsewhere within the application. In general, you are on the lookout for instances of repetition in the interface that might be exploited to reduce code volume. Consider the following panel that contains a series of checkboxes, each checkbox representing a color:
If this interface were constructed with an SWT-based GUI builder and the "Generate Code" button pressed, something like the following code would result (the code below was generated by SWT Designer [http:www.swt-designer.com], but any GUI builder would likely produce a similar result):
setLayout(new RowLayout(SWT.VERTICAL)); final Button redButton = new Button(this, SWT.CHECK); redButton.setText("Red"); final Button orangeButton = new Button(this, SWT.CHECK); orangeButton.setText("Orange"); final Button yellowButton = new Button(this, SWT.CHECK); yellowButton.setText("Yellow"); final Button greenButton = new Button(this, SWT.CHECK); greenButton.setText("Green"); final Button blueButton = new Button(this, SWT.CHECK); blueButton.setText("Blue"); final Button indigoButton = new Button(this, SWT.CHECK); indigoButton.setText("Indigo"); final Button violetButton = new Button(this, SWT.CHECK); violetButton.setText("Violet");
But if we set out to code this panel manually, we could exploit the obvious repetition of checkboxes:
setLayout(new RowLayout(SWT.VERTICAL)); String[] colors = { "Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet" }; Button[] buttons = new Button[colors.length]; for (int i = 0; i < colors.length; i++) { buttons[i] = new Button(this, SWT.CHECK); }
Clearly, this is a trivial example that saves only a few lines of code. But the GUI Builder's inability to recognize repetitive structures in the GUI (opportunities for reusing a custom component) has the potential to create a great deal of unnecessary code, should the scope of duplication involve a larger number of components.
Consider the following interface panel:
Looking at the above, it is immediately obvious that the "Home" and "Work" groups are so similar that they could be different instances of a custom component, with labels and callbacks parameterized differently. Will a GUI builder spot this? No. Press the "Generate Code" button and the GUI builder will happily generate two near-identical blocks of code, probably within the same class body, probably within the same class method.
The formulaic approach that invariably accompanies automatic code generation actually discourages component development or reuse.
The better GUI builders will import almost any piece of code, regardless of whether the tool originally generated it or not. A great many GUI builders are not that capable, and need the code to conform to some builder-specific pattern in order to import it for further modification. In these cases, you are forcing future developers to make an either/or choice. They either continue to use the same GUI builder to modify and extend the generated code, or make manual changes to the generated code in the absence of the GUI builder, which entertains the risk of unintentionally modifying the code so as to render subsequent import into the same GUI builder impossible. On the one hand, you tie future development to the GUI builder (and its vendor) and on the other, you risk rendering the tool you've invested in obsolete, together with the money you've invested in it, and learning how to use it.
There may also be versioning problems, depending upon what GUI toolkit you're using. If you are unfortunate enough to be using a GUI builder in combination with SWT (such as SWT Designer), the reliance upon native code and absence of a "bean box" approach to component integration means that the GUI builder tool itself must be upgraded every time a new release of SWT appears. A perpetual upgrade cycle in the making.
When you inherit legacy GUI code, it is generally not hard to tell that the original programmers used a GUI builder. Look out for any of the following symptoms of GUI builder usage, and take their presence as an indication that you are in for a rough time maintaining this code:
So, are GUI builders good for anything at all? Perhaps. They have some utility for mocking up interfaces. You can create static "snapshots" of your interface and show them to users, perhaps employing printouts of them as paper prototypes. In other words, you ignore the code generation functionality and use the GUI builder as a shape-based drawing tool. I believe this is one of the few useful applications of GUI builders.
Attempting to use them in the prescribed manner is generally a bad idea. They shield the programmer from coding details that they must eventually conquer anyway, introduce an unnecessary tool dependency into the development cycle, and discourage re-use. Of course, as long as there are uninformed managers with access to the company purse, GUI builders will continue to be sold on the basis of their novelty and unsubstantiated claims to productivity improvement.