To Javascript or not to Javascript: Kaleidoscope ’09 Report I

This is an (obviously) late post in a series of posts about ODTUG Kaleidoscope 2009. Monday was the least busy day for me at Kaleidoscope–I only attended two presentations, “That’s Rich! Putting a smile on ADF Faces,” by Lucas Jellema, and “Fusion Design Fundamentals,” by Duncan Mills. But it was perhaps the most thought-provoking of my days there. In fact, I have a full three posts worth of stuff to say about just these two talks. Today, I’m going to talk about a dramatic contrast: the two talks, among other things, represented opposite ends of a debate I consider quite important: the advisability, or lack thereof, of using ADF Faces RC client-side components.

Lucas’ Talk

Lucas’ talk was a treasury of features that are new in ADF Faces RC (part of ADF 11g):

  • The new layout containers, including the extremely important popup component and a preview of the planned panelDashboard component (a layout component like a lightweight portal, with movable cells displaying different content)
  • Out-of-the-box asynchronous data fetching for components like ADF tables and data visualization components
  • How to create and use client side components for Javascript manipulation
  • How to send your own AJAX events from within client-side Javascript
  • The setPropertyListener component, which allows you to set values on a managed bean not just based on the “default action” of a component (click on a button, change value on a text field, and so on), as the older setActionListener did, but on almost any Javascript-recognizable event (rollover, mousedown, keypress, drag, etc.) and several ADF-specific events (detail disclosure, table row selection, column sort, etc.)
  • The entirely redone skinning system for 11g (more skinnable components, ability to extend the standard Oracle skin)
  • Pushing active data from the server to the client

Because it’s an area that I’m into right now, I was especially interested in Lucas’ take on client-side programming. I’ll write about this more later in the post, but I want to note that Lucas is very fond of client-side programming. He spent much of the talk on it, and called it “very useful.”

Duncan’s Talk

Duncan’s talk was about the principles the Oracle Applications team used to design and develop Oracle Fusion Applications–a massive rewrite of Oracle’s business applications based on ADF with the Fusion Stack (that is, ADF all the way from bottom to top: business components, model, task flows, Faces RC). It was very informative and interesting, but I’m not going to talk about it here–I’ll save it for next week.

But at the end of his talk, Duncan went through his “Five Laws to Live By,” practices he personally recommends for developing Fusion-stack applications. This was by far the most controversial part of his talk, and it drew some quibbles from me, too.

Law 1: Thou Shalt not write Javascript

This is, of course, the location of the big debate with the position taken in Lucas’ talk. I’ll talk about this more in the next section. Duncan did agree with Lucas (and myself, by the way) about one thing–if you’re going to break this law, use client components and the ADF Faces RC client-side API. Don’t try to read the morass of HTML generated by ADF faces and code directly to the generated page’s DOM. That’s an insanely non-productive way to go about it, and what’s worse, the exact HTML of the generated page is subject to change, even in point releases or patches. You can very, very easily write code that will break. And coding directly to the DOM means you have to be very careful about accessibility and cross-browser functionality; it’s easy to write something that will work in one browser but will drive another browser, or a screen reader, crazy.

Law 2: Thou Shalt not Write HTML

Or JSP tags, or scriptlets, or JSTL, or anything else that makes your page, in whole or in part, look like an HTML page or old fashioned JSP page. The whole point of the JSF view layer (and a Fusion web application is always, at bottom, a JSF application) is that it’s component-based development, with core components and rendering kept separate. You’ll lose this if you throw in fragments of non-component stuff. In particular, your application will lose some of its ability to go into accessibility mode (where everything is nicely tailored for screen readers and non-visual input), and you may lose the option of making it available to agents other than standard HTML browsers (such as mobile browsers). You’ll also be tied to the JSP engine, which is OK for now, but there are some plans (Duncan mentioned them, so I assume I can mention them too) for the Oracle Application Server to provide an alternative and more optimized engine for rendering JSF.

I agree with Duncan’s general rule here 99.9%. The only exception I can think of is truly static pages, that are not databound at all. The (pretty significant) performance improvement you get from simply making these HTML pages (that is, with a .html extension, represented on the task flow as a URL View activity, and not managed by the JSF engine at all) may be worth giving up the extra flexibility provided by using a JSF page. And many of the flexibility concerns aren’t as serious for static HTML: It’s not too hard to write it accessibly, it’s not even that hard to make a separate copy for wireless devices, and if it’s static HTML, it’s not using the JSP engine anyway. But other than that, I wholeheartedly agree that there’s really never an excuse for writing HTML, or JSP constructs, in a Fusion application (or any application that uses ADF Faces RC).

Law 3: Minimize Use of Inline Styles

And, for that matter, CSS other than the skin. Inline styles are generally horrible anywhere in web development–they’re a pain to maintain, for one thing: if you ever want to change the way a particular component of your look-and-feel looks, you have to find every place you’ve used the inline style and change it. This particular thing isn’t a problem for regular CSS attachments, as long as you remember to attach them to every page. But Duncan said, and I agree, that it’s much better to use the skinning technology ADF Faces provides, unless (maybe) you have a particular component that you want to style in a way you’re sure you’ll never use again–or, at least, if you use it somewhere else, you don’t want to keep the style of the various uses synchronized.

Law 4: Thou Shalt not Write SQL

As you might imagine, the room found this one pretty shocking, and Duncan immediately amended it to “Thou shalt not write SQL, usually.” But he had a really good point: Declarative view object definitions can implement most of the queries you need (though not certain fancy things like unions, queries involving multi-row functions, or subqueries), they’re portable between DBs, they optionally auto-optimize their SELECT clause based on what data the client really needs, and–hey–it’s one less language for your developers to worry about. Of course, most developers in your average Fusion shop know SQL like the backs of their hands, but the ability to use (at least some) developers who don’t means you’re that much more flexible. In fact, I’d go even a step further than Duncan. Go to Tools | Preferences, select the Business Components\View Objects node, and select “Enable declarative SQL mode for new objects.” You can always change it back for particular view object definitions if if you need to.

Law 5: Thou Shalt Communicate

Yes! Yes yes! You can’t possibly hope to implement any methodology that involves significant component or code reuse without great communication. Document your APIs (including things like the inputs and outputs for reusable applications), document your patterns, don’t be afraid to ask other people on your team for help (and don’t do or say anything to make them afraid to ask you for help, either), talk to each other. This is the key to good team-based development.

To Javascript or not to Javascript?

So, you can probably guess where I stand on the writing Javascript issue. I definitely agree more with Lucas than with Duncan; the client-side Javascript APIs are a good thing, and you shouldn’t shy away from using them when appropriate.

Duncan had some good points about this. He pointed out a number of potential problems with writing Javascript: It’s an extra thing to maintain, it’s annoying to debug (since it runs in the browser, not on the server, JDeveloper can’t help you debug it, and Javascript debugging tools are still light years behind serious Java process debuggers like JDeveloper’s), Javascript validation can always be bypassed (with some, but not a huge amount, of effort) by a malicious user who knows the language, and you have to pay attention to accessibility and cross-browser compatibility issues. He also pointed out that in most cases it’s unnecessary–ADF Faces RC components are already very rich, and a lot of stuff you might think of writing in Javascript is already done for you (in generated Javascript that you don’t have to worry about, that is fully supported on any certified browser, etc).

But the fact is, there really are times–I’d say a lot of times, though far from the majority–when doing some stuff client-side is useful. It will save a server hit, and although Oracle has done a great job limiting the bandwidth used by partial requests, but there is still such a thing as connection latency, and it can be an issue if you’re doing it all the time, or have some users in remote places. And there are ways to minimize many of the problems Duncan mentioned:

  • Maintenance is a lot less of a headache if you maintain good principles of reusability. Consider creating your own “libraries” (JS files that can be attached to multiple pages, often cross-application) of Javascript functions thathave general applicability, and let these functions do most of the Javascript work for you, even if you need to wrap them in component-specific clientListeners (JS functions called directly by components).
  • Debugging Javascript can be a pain, but there are an increasing number of browser plug-ins that will help you do it. And neither Lucas nor I were saying you should be using Javascript all the time, just in what will probably be a handful of legitimate cases. For most purposes,  you’re going to be debugging Javascript that numbers in the tens of lines, not the thousands.
  • Javascript validation can indeed always be bypassed, but consider two things: First, a lot of validation (not a majority, but a lot)  is really intended for the convenience and safety of the user, not of your system. Take, for example, validation on a shipping address. If a user makes a mistake, client-side validation will stop them. And if a malicious user really so badly wants their package to be mis-delivered that they’ll take the time to hack the Javascript, well, that’s their problem. If a user calls up and says, “I deliberately bypassed the security of your application, and as a result I never got my shipment!” I think your customer service reps will be quite justified in hanging up on them. Second, you can always duplicate validation you’ve implemented in Javascript on the server. Why would you do this? Well, the Javascript will save you server round-trips in the 99.99% of validation errors that are legitimate mistakes, and you have the server as the backup in the remaining 0.01% that are deliberate attempts to break the application.
  • Most of the accessability issues, and all the cross-browser issues (among supported browsers, of course), that you might run into by coding Javascript that directly manipulates the browser DOM can be avoided by, well, not directly manipulating the browser DOM. We’ve already agreed that coding only to the ADF Faces RC API is a vastly superior option.

And it is true that the framework provides the large majority of the Javascript you’ll need. You certainly shouldn’t do something in custom Javascript unless you’ve thoroughly checked that there’s no declarative way to configure a component that provides exactly the behavior you want. But, as I’ve said before, there are always bits of functionality that a large application will need which are not provided by the out-of-the-box components of any framework. ADF Faces RC is no exception.

Duncan advised against worrying too much about server round-trips, repeating the saying, “Premature optimization is the root of all evil.” And I agree. You shouldn’t worry too much about server round-trips, and you shouldn’t optimize prematurely. But you should be ready to take server round-trips into consideration, and to optimize when it’s appropriate.

For this reason, I think the one problem with the ADF Faces RC API is a very sad one: Its level of documentation and exposure  is terrible. Actually, I just looked at the doc, and it’s gotten a lot better than last I saw, but still the large majority of functions in the large majority of classes have no documentation beyond the function and parameter names. This in itself will probably let you muddle through coding, because the class, function, and parameter names tend to be pretty intuitive, but truly proper documentation would make things a lot easier. Oracle has actually made a deliberate choice not to broadly expose the availablility of the API or to document it extensively, because Duncan’s Law 1 is Oracle’s general recommendation. But for reasons I’ve outlined above, I hope they rethink this. The API is extensive and powerful, and it shouldn’t be made too hard for people to figure out.

I’m going to talk about Lucas’ tips for using it, but not for a couple of weeks. Next week, as I said above, I’ll talk more about the methodology that Duncan explained, the methodology used by the Oracle Fusion Applications team.