Comparison of Number Guess Implementations

Chris W. Johnson
Information Technology Services
The University of Texas at Austin
December 27, 2005

The Qwicap Introduction uses a simple number guess application to illustrate the similarities and differences between implementing a conventional command-line-interface application, and a Qwicap web application. This document, and its associated exhibits, provides other implementations of the number guess application, along with samples of the output they generate, in order to expand on that compare-and-contrast exercise.

Exhibits

Implementations

The conventional (command-line) implementation of the application is unquestionably the simplest and most straightforward of the four. It has only one source file, and it contains only one method. There are no other files. Flow control is fully expressed in the source code, as is the point-of-origin of the input data. It would be tough to come up with any implementation that was simpler, or more straightforward. For those reasons it is the ideal by which all other implementations are judged.

The Qwicap implementation is conceptually very similar to the conventional implementation, is roughly the same length, and also consists of just one source file, containing a single method. Flow control is fully expressed in the source code, as is the point-of-origin of the input data. It does, however, depend on a separate web page, and two associated style sheets. The creation of a web page for a web application is inevitable, of course. Understanding how the application and the web page interact requires some examination of the web page, and an understanding of Cascading Style Sheet level 2 (CSS2) selectors, but web application developers will already be familiar with those.

The JSP & Java Bean implementation bears no similarity to any of the other implementations. The program logic is split across two source files (the JSP and the Java Bean), and each has a different syntax. Flow control is obscure; there is no loop to request guesses from the user until the correct value is supplied (an effect of the standard hit-run-exit model of web applications). Program logic is fragmented; some is in the JSP and some in the bean, so both must be examined and understood in order to grasp program structure and control flow. The point-of-origin of the input data isn't directly present, nor readily apparent; the input is automatically fed to the bean by the Bean environment based on information in the JSP page's "form" elements, and the JSP page acquires it through the bean. Persistence of data between hits is supplied by the bean, but it is the JSP that makes the bean persistent. Finally, the web page needed by this web application is not a separate file, but an integral part of the application, because JSP pages intermingle source code with document markup, so both must be maintained concurrently.

The JSP-only implementation also bears no similarity to the conventional implementation. While it largely mimics the functionality of the Qwicap version, its implementation is, of necessity, entirely different. Unlike the JSP & Bean implementation, the program logic is present in a single file, and employs only one syntax (JSP). The point-of-origin of the input data is evident, though manual input validation is required. Flow control is clearer, but remains obscured by the standard web application hit-run-exit model, which means that the outer loop of the conventional (and the Qwicap) implementation—the one which keeps the guessing going until the user has guessed correctly—is implicit rather than explicit. Session state is employed to retain data from one hit to another, so an understanding of the ways in which that state changes as the user plays the game is required to reconstruct the flow of the program. As with any JSP, the code and document markup are intimately mixed, which complicates reading or editing either of them.

The JSP Tag Library implementation, not surprisingly, bears no similarity to the conventional implementation, and no similarity even to the JSP implementation, whose functionality it mimics precisely. While the tag library has removed the Java source code from the web page markup, thus making the web page relatively readable (unlike the JSP-only web page), the page markup remains contaminated by foreign material (the tag invocations) that prevents validation of the markup. The source code has not gotten-off lightly, either; it is now split across thirteen class files. Unfortunately, those classes don't fully express the program's logic, because the relationships between the classes and the elements of the web page are determined by the locations of the tag invocations within the page. The point-of-origin of the input data is not evident (a search of the classes is required to find it in the "InputSection" class), and manual input validation is required (along with three classes to implement the tags that represent its results in the page). Flow control is obscure since it is divided between the source code of the classes and the tag references in the page markup. Because the tags that represent logic, flow-control, and content-insertion functions all look the same, their syntax offers no indication of their purpose, and they thereby add to the challenge of untangling the flow-control, the problem of identifying the flow-control. (Tag naming conventions could help, but, as conventions, they'd never be as consistent or effective as the non-negotiable, automatically-enforced rules of a programming language's syntax.) Session state is employed to retain data from one hit to another, but its immediate effects are encapsulated in a single class (NumberGuessGame), which aids comprehension of its role in the program. Finally, 104 lines of meta data are required to setup mappings between the classes and the tags in the page markup that represent them. Creating and maintaining such meta data is tedious, and debugging it can be nightmarish.

Code Disposition

A comparison of the number of lines of code each sample implementation devotes to common tasks is problematic due to considerations such as the very different ways in which they work, what counts as a line of code, some lines counting in multiple categories, and the fact that the JSP & Bean implementation lacks some features of the others, most notably a history display, which makes its numbers look better than they should. Nonetheless, a rough comparison is possible, and can be suggestive of some of the strengths and weaknesses of the various approaches.

Implementation Lines of Code (Approximate)
Total Input & Validation Maintaining State Displaying History Document Manipulation
Conventional 28 10 0 0 n/a
Qwicap 30 1 0 3 5
JSP & Bean 51 (8 & 43) 8 1 n/a 4
JSP Only 49 17 14 15 9
JSP Tag Library >188 63 15 79 25

Skills Summary

Implementation Required Skills
Java Web Page Authoring Web App. Setup Hit-Run-Exit Model XSS Attacks & Page Corruption Session State JSP Tag Libs Java Beans Qwicap
Conventional X
Qwicap X X X X
JSP & Bean X X X X X X X X
JSP Only X X X X X X X
JSP Tag Library X X X X X X X X

User Experience, Developer Experience

The JSP & Java Bean implementation provides the worst user experience, by far. While its web page is the least elaborate of the web applications examined here, that is an incidental matter and not relevant to this evaluation of user experience. Its problems are that it provides the user with little or no feedback about bad input, and it provides no history of the user's guesses. The former was obviously an omission intended to keep the example code short and simple. The underlying problem is that input validation and the provision of associated feedback to the user is not a feature of Java Beans or the JSP system, so it always falls to the developer to provide it for each and every item of input data. Even in a case like this where there is only one such item, providing validation and feedback is tedious and time-consuming, so there's an unavoidable temptation on the part of the developer to implement them quickly and poorly, or, as in this case, not at all.

Since the JSP & Java Bean implementation wasn't created for the purposes of this comparison, as the other implementations were, the fact that it does not provide a history of the user's guesses in its web interface isn't significant by itself. It just wasn't something the author felt that his demonstration application needed, if it even occurred to him. What is interesting to consider is that even though the JSP & Bean implementation is significantly more complex, and required more time, skill, and knowledge to create than the conventional, command-line version, it is the command-line version that provides the superior user interface. The command-line implementation doesn't do the work of maintaining a history itself, of course, but through the automatic action of the console, its users nonetheless receive an equivalent benefit. So, at least in this simple case, the command-line environment is providing better service to its application than the vastly more sophisticated browser/HTML/HTTP/Java/Tomcat/Servlet/JSP/etc. environment is providing to its application. Consequently, developers work harder, but have less to show for their efforts, and even the end-user is short-changed.

We, the developers, deserve better environments. (And so do our users.)

The JSP-only implementation emulates the relatively high-quality user interface of the Qwicap implementation, but at the cost of having to write 63% more code. Specifically, 17 of its 49 lines of code are devoted to the acquisition, validation, and rejection of user input, and a further 15 are required to maintain its history display. The cost of the history display must also include a portion of the 14 lines required for maintaining session state in the application. There's some uncertainty and overlap in those line counts, but it is clear that this simple feature consumes more than a third of the application's code. This should serve to suggest how the limited services provided to developers by the JSP environment1 could discourage the addition of helpful extras to the interfaces of web applications.

The user input validation & rejection code represents a more concrete and immediate problem, however, because the problem will grow with each additional piece of input requested, and each page added to the application. The JSP environment provides no direct assistance with this, and offers no obvious approach to creating a library of common code for performing the validation & rejection task on all inputs and pages. This leaves the developer to supply that functionality over-and-over again throughout each web application, which drives-up the work load, increases maintenance problems, and creates the temptation to cut corners by settling for the sort of low quality user interfaces seen in the command-line and JSP & Bean examples, or even by omitting validation entirely.

And in spite of the effort invested in the user interface of this implementation, a subtle but crucial corner has been cut: When it quotes bad input in its error messages, and when it repopulates the input field so it can be corrected, it fails to HTML-encode the bad input, which allows the document sytnax to be corrupted if a character with significance to that syntax is present in the bad input, for example a single quote ('), or a left chevron (<) character. Worse, it enables cross-site scripting (XSS) attacks. The JSP environment provides the developer with no assistance in solving this fundamental problem.

Ideally, a trivial application would have a trivial implementation. Unfortunately, this implementation is both non-trivial, and seriously flawed.

We, the developers, deserve better environments. (And so do our users.)

The JSP Tab Library implementation creates the same user interface as the JSP-only implementation, but its implementation adds the problems of an enormous growth in code size, a substantial additional learning-curve, the necessity of meta data creation and maintenance, and the challenge of debugging the union of all those issues. While reusable tag libraries may offset some of those problems in practice (while probably aggravating others), the tag library API still leaves developers with most of the core problems of the JSP-only implementation, including no assistance with user input & validation, and no provision for the problems of web page integrity and XSS attacks.

We, the developers, deserve better environments. (And so do our users.)

The Qwicap implementation supplies some perspective on what an environment can do for its developers by providing services such as: automatically handling the HTML encoding (and decoding) problem; performing the work of user input validation, rejection and correction in a single statement; providing a powerful and convenient templating engine that allows the history display to be implemented in three lines of code (or just one, if you wish); and maintaining session state entirely transparently, while simultaneously greatly extending its power. To receive all these services, the developer need only become familiar with the methods of two classes2. There's no special markup employed in the XHTML pages, no scripts, and no meta-data, either. There's one pattern that should be employed when prompting the user for input, and that's about all there is to it.

To elaborate on those features:

Of course, there are more features than these under Qwicap's hood, but like those discussed above, they generally operate automatically to eliminate from your work the common, tedious elements of web application development, so that you can get on with doing the important stuff: writing the code that makes your application unique.

1. Fundamentally, the author regards Java Server Pages (JSP) as an anti-templating engine. To explain: If we accept that a templating engine is something that allows a body of code to manipulate a separate document by inserting values into it, etc., then something that intimately mixes code and markup, as JSP does, would seem to be the opposite of a templating engine. By themselves, Servlets are in the same boat, just at the other end; they insert the markup into the code. Tag Libraries appear to be a response to those problems, but they create problems of their own including: driving-up the learning curve; fragmenting code; requiring meta-data; and adopting a syntax that obscures, rather than emphasizes, the function of its elements.
2. Almost all of the public Qwicap API is supplied by two classes: Qwicap and Results.
Valid XHTML 1.0! Valid CSS!