April 2010 Status Report

In early April, 2010 the Fiz team discussed the status of the project and evaluated our success so far in trying to create a component framework for Web applications. The participants in the discussion were Katsushi Fukui, Sameer Madan, John Ousterhout, and Eric Stratmann. This page contains a summary of our conclusions. Here is a short executive summary:

  • We've had more success with components for the front-ends of Web applications (managing the user interface) than components for the back-ends (managing the application data).
  • The value provided by Datasets appears to be increasing as we use them more and extend their features.
  • It's too hard to build simple things with Fiz.
  • The system still needs lots more work and we need more experience with applications.
  • If we were doing this again, we probably would not use the Java language.

Project Status

  • It's been about 2 years since work first began on Fiz.
  • The framework now contains about 25,000 lines of Java code, including comments. It has enough functionality to create functioning Web sites.
  • We have created one simple Web application using Fiz, which is a community Web site that allows people to download Fiz and share Fiz extensions. It contains about a dozen pages. The site has received relatively little traffic.
  • We made an open source release of Fiz (version 0.5) in the Summer of 2009; it has been downloaded and tried by a few people, but we don't know of any significant Web sites created with it. As you can guess from the version number, this is still a fairly immature release.
  • We have modified Fiz so that it can be run under Google AppEngine framework. This consisted mostly of creating a data manager for the AppEngine Datastore, plus providing mechanisms to turn off features that aren't supported by AppEngine, such as multiple threads.
  • Based on our own experiences creating the community Web site, plus initial reactions from a few people who downloaded Fiz 0.5, we think that the framework is probably not yet ready for usage in production Web sites, either in terms of functionality or convenience. Thus, we haven't been encouraging a lot of external usage.
  • Since the release of Fiz 0.5 we have focused on smaller internal projects to evaluate various features of Fiz and explore alternative approaches in areas where Fiz is currently weak.

Things that appear to be working

Sections

The basic mechanism of dividing a page up into Sections seems to be working pretty well. There isn't a lot of functionality in this mechanism, but it seems to provide a pretty good framework for hiding details such as HTML complexities, CSS, and Javascript-driven components.
We've been able to build several sections that encapsulate interesting functionality, such as FormSection, TreeSection, and ChartSection.

Forms

The form mechanism appears to be working quite well. We have been able to implement a number of nice features as part of the form mechanism, such as:

  • Built-in support for a variety of form elements (text entries, radio buttons, menu-based selection etc).
  • The ability to create custom form elements that use Javascript-based interfaces, and to mix and match them in forms with the standard elements. For example, we have added a calendar form element and an autocomplete form element.
  • A validation mechanism that allows validation to be performed on the fly as users modify forms (using Ajax) as well as when forms are submitted.
  • A mechanism for displaying error messages (such as those related to validation) next to form elements.
  • A mechanism for displaying help text for form elements.
  • Several mechanisms for customizing the appearance of forms including the use of a new general-purpose layout mechanism in Fiz.
  • Fiz forms use an Ajax-like mechanism for form submission, which simplifies the interactions between the browser and the server and makes it easy for the server to retain the current page when returning error information.

Fiz forms do a pretty good job of hiding the complex interactions between all of these features; they are reasonably easy to use for simple things, and can be customized to do fancier things. In general, forms seem to be a good match to a framework based on components.

Ajax support

We built Fiz under the assumption that Ajax would be used extensively in Web pages, so Fiz contains several facilities that make it relatively easy to use Ajax:

  • We chose an approach to Ajax where "the server is in charge": the browser initiates Ajax requests, but the browser does not control the handling of Ajax responses. The server controls what happens in response to Ajax requests, generate a response consisting of Javascript code. The browser simply executes the code returned to it. This simplifies the code that runs on the browser and gives the server a lot of flexibility.
  • Many of the Fiz controls contain built-in support for Ajax. For example, TabSection, which displays a collection of notebook tabs, allows an action to be specified for each tab, which is invoked when the tab is clicked. The action can either change pages to a new URL, invoke an Ajax request without changing the page, or invoke a Javascript script. The Link section, which generates clickable links, also offers the same three options when the link is clicked.
  • Ajax requests typically must be handled differently than normal HTTP requests (for example, the response is not an HTML page, and errors must be reported differently). Fiz hides this distinction as much as possible, so that developers can write code that works in either Ajax or normal requests without being aware of which request is in process. For example, Fiz provides a method evalJavascript which will arrange for Javascript to be executed in the browser; if the current request is a normal HTTP request then the Javascript is encapsulated in a <script> tag as part of the HTML page; if the current request is an Ajax request then the Javascript is just included verbatim in the Ajax response (which consists of nothing but Javascript). Fiz also provides error reporting functions that work differently for Ajax and normal requests.
  • Fiz provides facilities (based on Datasets) that make it easy to pass complex data structures between the server and the browser.
  • Fiz provides a nice mechanism for reporting errors that occur in Ajax requests (a message will be displayed in a "bulletin" area at the top of the current Web page).
  • The PageProperty mechanism provides a safe and convenient way of tracking the state of an Ajax-driven page across a series of Ajax interactions. This is described in an upcoming paper in the WebApps '10 conference.
  • One negative: the Ajax.invoke mechanism for inserting Ajax requests in a page is a bit clunky.

Buffered page rendering

In Fiz the HTML output for a page is not flushed to the browser immediately. Instead it is buffered in memory on the server until the page is complete. The contents of the page are collected in several different categories (header, Javascript, HTML), which means that additional header content can be created at any point during the page generation process. This makes it easier to create components, since any individual component may need to add content to the page header. Without buffering, the page header will have been flushed by the time the first component is rendered, making it impossible for later components to add to the header.

Things that aren't working very well

Data managers

The greatest weakness of the current Fiz implementation is probably the data manager mechanism, which is used for managing back-end data. Right now data managers provide a very thin abstraction; they are simply classes that move information between Datasets and back-end storage. We have built a few simple data managers for accessing files, SQL data, and the AppEngine Datastore, but these don't provide much more than a thin wrapper around the underlying storage systems. They don't appear to be particularly easy to use. We have used the existing data managers for a few simple applications, but we suspect they would be difficult to use for more complex things.

We are not yet sure what is the right solution to this problem, but here are few miscellaneous thoughts:

  • A model mechanism like the once in Rails or Django would probably be an improvement. However, the Rails model mechanism requires a level of metaprogramming that is not available in Java.
  • We probably need a mechanism for composing data managers, for example building a higher-level data manager that uses a lower-level data manager that provides additional features on top of it. One potential use for this is for data transformations, but the data transformation issue may be just a reflection of Fiz's weak templating mechanism (see below).

In the original version of Fiz we used an asynchronous approach to data management along with a 2-pass mechanism for page rendering. Each page was rendered by making 2 passes over all of its components. In the first pass, each component could initiate one or more data requests from data managers (without waiting for any of them to complete). In the second pass, each component rendered its portion of the final page, waiting if necessary for its data requests to complete. This approach was chosen in order to allow more efficient handling of data requests, e.g. by executing requests concurrently and/or batching requests for the same data manager.

However, in practice we found that this was not a convenient style for application developers. They had trouble "getting" the 2 pass approach and tended not to use it in the right way; typically they would render one component at a time, invoking each component twice in a row, once to initiate its data requests and once to render the component. This made the application more complicated and limited the benefits of the asynchronous approach to data management. In addition, there are many situations where the data requests cannot be executed in parallel, since some requests depend on the results of others. We eventually decided that the performance benefits of the asynchronous approach were dubious, while the complexity disadvantages were quite clear, so we switched to a simpler single-pass approach without asynchronous data requests. (However, with the new lazy dataset mechanism it will become possible to implement asynchronous requests again, for applications that want them.)

Maybe templates are a good idea after all

One of the original hypotheses for Fiz was that templates are a bad idea: they encourage developers to work at too low a level (HTML) and the mixture of code and HTML doesn't scale very well (there ends up being too much code to understand the HTML and too much HTML to understand the code); we thought that templates would interfere with the development and use of components.

However, we are gradually coming to appreciate the benefits of templates. We ended up implementing a simple template package fairly early in the Fiz development, intended primarily for use by component developers. Over time we have been gradually adding to the template mechanism; developers seem to use it quite a bit when generating any real pages. Here are some examples of why templates are still useful, even in a world where we are trying to encourage people to use higher-level components as much as possible:

  • Templates provide a simple and natural way to get started building a Web application; templates make simple things simple. Components help a lot with big complicated things, but they are more difficult to use for simple things than templates; without templates the learning curve for getting started is much higher.
  • There are many cases in applications where the easiest way to specify something is with a small snippet of HTML with values substituted; this is what templates do well.

As a result we are gradually rethinking the role of templates in Fiz. One example is a new general-purpose Layout mechanism that uses a template-like approach to separate layout and content. We are also considering ways of making the existing template mechanism more general and powerful; it's clunkier to use templates in Fiz than in other frameworks such as Rails or Django.

We are still concerned that templates are not the right mechanism to use for creating reusable components, but they do seem to serve an important role for smaller non-reusable parts of applications.

Customization

In order for components to be used successfully they must be easy to customize; otherwise developers will be forced to abandon the components and build new ones if they need features not currently supported. We have tried to make the Fiz components as customizable as possible, but we aren't yet sure that they are customizable enough. Also, the customization mechanisms add complexity to the components, which makes them harder to use; there appears to be a trade-off between ease of use and customizability.

Simple sites are too hard

It still feels too hard to build simple Web sites with Fiz: there is too much to learn, too much stuff has to be set up, and Fiz does not provide much structure for how to organize a Web site. If we don't make it easier to build simple sites, people may never get to the point of appreciating Fiz's benefits for larger sites.

Datasets

Fiz contains a mechanism called Datasets, which is a general-purpose facility for passing around structured data. Datasets are something like a combination of arrays and hashes in languages such as Javascript, and they integrate cleanly with the Fiz template mechanism. Initially there was some concern that datasets are too thin and abstraction to be interesting: are they just a compensation for the lack of good arrays and hashes in the Java language? This may still be true, but we have been gradually adding more and more features to Datasets, which are making them more interesting:

  • CompoundDatasets allow datasets to be combined in interesting ways.
  • A new mechanism called LazyDatasets allows Dataset values to be generated on demand.
  • Fiz makes it easy to move complex collections of data between Datasets on the server and Javascript objects in the browser.

The weak typing is one of the biggest advantages of datasets (it makes them more flexible than Java HashMaps, for example), but it can also be a disadvantage since certain kinds of errors cannot be detected at compile time.

Overall, we're feeling more and more like Datasets provide interesting and useful containers for data in Web applications.

Java

The choice of Java as implementation language for Fiz was an experiment that John Ousterhouts decided to try at the beginning of the project. Most modern frameworks are implemented in scripting languages, and John wanted to see how well a more strongly typed language might work in this context. There were two primary motivations for choosing Java:

  • Performance: scripting languages already have a reputation for being somewhat slow for Web applications (especially Ruby). John hypothesized that a component-driven framework would introduce significant overheads (lots of layer crossings between components) and that a scripting language might result in performance too poor for interactive page generation.
  • Strong typing: in prior experience building Web applications with PHP, John found that the lack of typing made code harder to read and maintain. For example, without type declarations for function arguments it was hard to remember what were the actual types of arguments, particularly when returning to old code.

On the other hand, strongly typed languages are notorious for being verbose and inflexible; one of the goals for Fiz was to see if we can compensate enough for the potential disadvantages of a strongly typed language to make it a viable platform for modern Web framework.

Although the experience with Java has not been horrible, our conclusion is that we would probably have been better off using a more scripting-oriented language. Here are some comments on our Java experiences:

  • Java is definitely syntaxy and verbose.
  • Java doesn't have very powerful features for metaprogramming. It does allow introspection, but it is difficult to create new classes on-the-fly and impossible to extend existing ones. These facilities are quite useful when creating a Web framework.
  • With Java it's hard to create little chunks of code and intermix those with data in a dynamic and flexible fashion, such as in templates. For example, the smallest chunk of code is a simple class that has a lot of boilerplate; if all that's needed is an expression to add 10 to a value before inserting into a Web page, it's clunky to implement that in Java and trivial in most scripting languages.
  • We are pretty sure that Java's performance is much better than scripting languages, but we haven't yet built any applications large enough for this to matter. It's possible that the performance will ultimately be important, but we can't prove that yet.
  • At least some of us like some of the strong typing facilities in Java, though we would also like the option of doing things in a more weakly typed fashion in places. If Java had more weakly typed arrays and hashes, the Fiz Dataset mechanism might not have been necessary.
  • Java has an enormous collection of useful libraries, which simplifies the creation of applications.

Next steps and future projects:

Here are a few ideas we discussed for things to do next in the Fiz project:

  • Redesign the mechanism for managing data.
  • Reimplement the form mechanism in another framework to see if it's possible to get all of their benefits without the rest of Fiz.
  • Improve the template mechanism, perhaps allowing arbitrary Java code snippets?
  • Build more applications in order to evaluate the existing facilities and identify the next round of problems and opportunities.