Guides Misusing Dynamic Binding When Static Binding Would Do, Part 1

Misusing Dynamic Binding When Static Binding Would Do, Part 1

HTML-based languages treat Web applications as collections
of files linked to one another via <a href> and <form>
commands coded inside the files. This is one example of an anti-pattern that
pervades the Web application frameworks and libraries I’ve used to date:
misusing dynamic binding when static binding could do the job better.

In this example, the JSP page hard wires a dynamically bound link
to the target page in its <a href> command rather than calling a
statically bound, type-checkable method of the target page. None of the
Web app environments I’ve seen support the latter option. Pages
reference other pages by filename, not as objects, because browsers
use HTML, which does it this way.

But although HTML’s way of doing things does apply to browsers, it
does not apply to the server side of a Web application. Web apps should be
object-oriented programs just like any other except that they emit
HTML text to a browser. Pages should be first-class Java objects, not
file names as in HTML,
ASP,
PHP,
JSP
WebMacro,
Velocity
or Perl.

Java Web Application Architecture provides statically bound type-checkable substitutes for each example of this anti-pattern I’ve encountered in my work.
JWAA’s statically bound solutions can and should be used to replace
and/or supplement other Java Web application environments, such as JSP.

This does not mean that static binding should replace dynamic binding
throughout an application, only in those places that could be handled better
at compile time. A designer that uses dynamic binding for everything is like
an automobile engineer that uses screwing, bolting, or riveting for everything
when casting, forging, and welding would be much better for fabricating the
parts of the car.

Web Applications Are Not Files

But HTML-based languages treat them as such. For example, you write
<a href=”filename.jsp”> to link to another page in JSP. Regardless of
what goes on thereafter (for example, when JSP pages are compiled into
servlet objects), the objects identify each other as members of a collection
of files and not as a network of first-class objects. If filename.jsp does
not exist, the error won’t be noticed until it causes an Error 404. Maybe you
catch it during testing, but often it goes unnoticed until it’s reported by
the end-user.

For example, this figure represents the top-level objects of the
JWAA Demo Application. This
simplest imaginable demo’s state machine has six distinct states and
eleven legal transitions, and the figure doesn’t even show the error
transitions. Scale the demo up to hundreds of states and (potentially)
thousands of transitions, and the problem cries out for a way to manage
the states and transitions as references between first-class Java objects.
Keeping track of JSP file names as applications are refactored and
renamed becomes far too hard.

The solution is so obvious and the advantages so large that it is
surprising that it is not provided by the Web application environments
I’ve examined to date. JWAA provides an AbstractPage class
that applications subclass to define pages (the ovals in the figure).
The servlet for the application publishes a public final static
SomeClass instance
variable via which other pages reference
the singleton instance of each page of the application. When a page needs
to emit an <a href> link to another page (the arrows in the figure),
it calls SomeClass. instance. emitLink(ctx).
To emit a <form> command, it calls SomeClass. instance. emitForm(ctx) instead.

Presto, invalid links will be reported at compile-time. If the
application compiles, all links to dynamic pages are guaranteed to be
valid. JWAA also provides an AbstractLink class that applications
can subclass to specify links to legacy HTML files, graphic files, external
servers, and so forth. The subclass can provide warnings of files that
don’t exist when the application is starting up. Presto, another common
source of server errors is gone.

A JWAA application consists of one Java class per dynamic Web page. For example, the demonstration application consists of AddressPage, AdminPage, HomePage, LoginPage, LogoutPage, RefusePage, and RegisterPage. Each of these subclass another application-specific class, Page, which provides a consistent look and feel for the demo as a whole. Each application also provides a servlet class, named Demo in this case, which parses incoming URLs and dispatches them to the requested page’s controller.

The pattern demonstrated here is followed throughout JWAA.
JWAA simply provides a statically bound and type-checked alternative
to inappropriate use of dynamic binding. The dynamically bound construct,
<a href=”filename.jsp”> is available too. But this is deprecated, replaced by the statically bound equivalent, OtherPage.instance.emitLink(ctx), which has exactly the same result except that invalid links will now be detected at compile time.

This trades the ability to revise HTML files
underneath a running application for the ability to check
links at compile time. You will need to run make to change the
running image and restart the server if you haven’t configured Tomcat to auto-reload
changed classes. With Jikes, this is nearly instantaneous. Since everything
happens at compile time, there is no need for a Java SDK inside the running image
nor even to have the Java SDK on the deployment machine. This brings
significant savings in space, speed and security. For example, the JWAA
distribution is only about 70K whereas the Tomcat/JSP distribution is more than
ten times larger (about 1000K).

Nonetheless, this trade-off is not acceptable in shops that divide responsibilities
between software developers (Java programmers) and information architects (HTML
developers). Therefore, JWAA’s traditional support for using MLS to code HTML
as strings within private view methods has recently been extended so that MLS
supports the ability to maintain Java code and HTML templates in separate files.
Unlike other template languages which bind at run time, binding occurs entirely at pre compile time and imposes no run time overhead at all.

Fields Are Not Strings

Yet servlet engines treat them as such. For example, the servlet engine’s
request.getParameter(“name”) method returns
the String value of the named parameter if it exists or null under various
error conditions. Template engines exhibit the same anti-pattern by
using a Hashtable to pass named values between Java code and the
template (presentation) layer.

String is a final class in Java, so an application cannot
define application-specific methods by defining application-specific String
subclasses that do input validation. So input validation logic winds up
scattered through the application instead of being encapsulated into
application-specific field classes.

Fields are not Strings. In an application that manages addresses,
they should be application-specific objects like Street, USState, Zipcode, and Country. Fields are not used only during input validation and converted back to Strings for use in the application. They displace Strings and their evil consort, the Java null, from the application. Fields are the lowest-level atoms from which an application is composed:
fields are to beans as atoms are to molecules. Strings and nulls are only used as
lowest-level building blocks and rarely if ever appear in the application itself.

The solution is again straightforward and easily added to any environment.
The servlet passes each JWAA application a servlet context object (named Ctx
for brevity) that contains the request-specific state information applications
use to communicate with their environment. The Ctx object provides a getField
method that generates validated instances of application-specific objects like
this:

Email email = (Email)ctx.getField("email", addressBean.getEmail());

The first argument is the request parameter name. The second is the
default value which getField will clone (copy) and return if the requested
parameter is empty (“”) or null. In this example, the default value is
obtained from the addressBean. In an application where the default should
be empty, the application would specify Email.Null as the second argument.
By convention all field classes provide a Null instance initialized with
an empty string (“”).

The getField method is defined in terms of the Validatable interface
in the JWAA package. JWAA also provides an abstract class, AbstractField,
to serve as the abstract superclass of application-specific field classes.

Briefly, it works like this. The email.ok() call returns true
if the email address the user provided complies with the syntactic
validity requirements of the Email class, and email.getMessage() returns a
string that explains the reason for the non-compliance in the user’s frame
of reference. When the Email field is assigned a value via its setValue(Object
aValue)
method, it uses a regular expression to set the boolean returned by
email.ok() and the message string that will be returned by getMessage() (too long, too short, not in [email protected] format). The logic for editing an email address with input validation is then as simple as this:

ctx.send({{
{{ ctx.emitForm(this) }}
Email Address: {{ email.asField("email", 32) }} {{ fontRed(email.getMessage()) }}
<input type=submit name="op" value="OK"> prompt(op, new Validatable[] { email });
</form>
}});

[The above uses multi-line string’s {{aString}} syntax, which is roughly equivalent to Java’s “aString” with enhancements. It will be discussed in Part 2. Also see the author’s site for more information on this topic.]

This code uses application-specific methods provided by the application’s
Page class to display the getMessage() text in a red font and to return a standard prompt alongside the submit button (either “Click OK to proceed” or “Correct the errors marked with red text”). Notice that Strings and nulls no longer appear
in the application and that the need to check for null field values is eliminated.

Beans Are Made of Fields, Not Strings

Fields are to beans as atoms are to molecules. But JDBC provides
only get and set methods that encourage applications to declare bean
fields as Strings and other generic Java types like int or long.

JWAA’s solution is the same as the above. A bean’s API to the
application should be defined to accept application-specific field
data types like Email instead of generic data types like String. The bean’s
load and save methods simply use AbstractField
methods to convert between the generic data types used by JDBC and the
field data types used by the application.

In Part 2, we’ll discuss multi-line strings, choice of configuration language, appropriate dynamic binding, and bringing everything together.

Resources

About the Author

Brad Cox’s background and interests are in software engineering and object-oriented software development. The connection with social and organizational learning is discussed in his collection of articles on the social construction of reality. Also see the book, Superdistribution: Objects as Property on the Electronic Frontier. He maintains the Middle of Nowhere Web as a vehicle for the distance education courses he teaches and to experience first-hand the bewildering phenomena that society has not yet mastered the taming of the electronic frontier.

Latest Posts

Related Stories