Thursday, October 22, 2009

Item 54: Keep style separate from content











 < Day Day Up > 





Item 54: Keep style separate from content



At first, this item may seem like a repeat of Item 53. While they share some similar ideas, the items are somewhat different. Whereas in Item 53 we seek to separate presentation logic from processing logic, here we seek to differentiate and separate style from content. Before we can dive too deeply into this, though, we need to define the difference between the two.



Content is the actual data being returned by a particular request. This is the data without any sort of display mechanics or markup associated with it. For example, when conducting a search on a Web site, the content will be the various items returned by the search (or the text "No items found").



Style, on the other hand, relates to the aesthetic elements we put around content to make it visually appealing to end users. Font sizes, background and/or foreground colors, layout, and so on fall under the general heading of style. As a basic rule of thumb, we can remove style from a page without affecting its basic usability; we cannot remove content, however, without fundamentally damaging the response. A plaintext, comma-separated list of search results is still usable; a nicely formatted page that contains no results (not even "No items returned") is pretty useless.



The value of this particular item becomes obvious to anybody who has ever heard those dreaded words right before the Web application is scheduled to ship: "We've decided to change the entire look-and-feel of our Web site, so all your pages are going to have to conform to the new look. That shouldn't take very long, right?" If the style of the page is somehow embedded into the output of the application, every single JSP page in the Web application has to be modified to reflect the new look-and-feel. Once again, I can't think of a bigger waste of my time as a programmer. Fortunately, two technologies come to the rescue here, at least for HTML-based applications.



The first is Cascading Style Sheets, known more popularly by its acronym, CSS. CSS provides the ability to control the style and layout of elements on an HTML page from another file, typically centrally defined for the entire site. Colors, fonts, sizes, even exact locations and layout can all be controlled by CSS elements. CSS also supports hierarchical styles, such that it can define styles for all paragraph (P) elements on a page as well as provide a different style for paragraph elements defined with a style attribute by name. CSS also has the benefit of being a World Wide Web Consortium standard, meaning it enjoys widespread support from most HTML browsers.



Unfortunately, the level of CSS support varies across different browser implementations and versions; a site that relies heavily on CSS for style may render correctly in one browser version but look entirely differently in another or older browser version. For enterprise applications deployed within a corporate intranet, where browser versions are typically centrally managed, this can be a manageable problem; for applications deployed to the public Internet, however, where users are still using browsers like Internet Explorer 1.0 and Netscape Navigator 2.0, this can be disastrous.



The logical successor of CSS for XML, XSL:Transformations, or XSLT for short, offers another possible solution. XSLT provides the capability to transform any XML source into just about any kind of output, including HTML. This means that if the output of a given JSP is a well-formed XML Infoset, we can run it through an XSLT to turn it into any kind of HTML imaginable.



The XSLT approach has a number of positive points about it. For starters, thanks to the widely varying HTML support among different browsers, it can be difficult to write HTML output that renders nicely in all browsers. Instead, in front of all JSP pages you can place a filter that examines the User-Agent header of an HTTP request to determine the browser sending the request and uses one of several different XSLT pages to transform the JSP output into HTML specific to that particular browser version. This helps avoid having to encode those differences directly within the JSP page. Plus, the style of the rendered HTML can be captured directly in those XSLT files, thus keeping all stylistic decisions in one logical place.



Regardless of which approach you select, the goal is still the same: keep all stylistic decisions localized to a single place, once again to obey the Once-and-Only-Once Rule (see Item 53). This way, when the VP of Marketing stops by your cubicle to tell you about the corporate-wide change to the look-and-feel of the site, updating the Web application to reflect the new changes takes a matter of days or hours rather than weeks or months. In fact, if the site makes use of CSS itself, you can just reuse the new CSS page directly.



Not only that, but now the actual generated output from the JSP (or servlet) can be kept to a minimum, focusing entirely on serving back only the content and leaving all style to be inserted by either the CSS or XSLT process. This means that now the JSP or servlet generating the response will be simpler, making debugging easier, making modifications to the output easier, and, in the case of CSS (which is rendered on the end-user's browser), keeping the bandwidth consumption required to send back the response smaller, thus not only reducing the concurrent load on the server and the network but also reducing the latency of the page as a whole.



We reap an unexpected benefit out of this as well. By taking stylistic decisions away from the generated JSP/servlet output, we effectively remove the developer from the awkward position of having to decide what looks good on the page. Programmers are, unfortunately, notorious for making some hideous UI decisions[2]�mostly because programmers view the world and how we interact with it in a very different fashion than the average computer user. By removing decisions regarding colors, fonts, backgrounds, and even in some cases layout itself, programmers can focus on generating the data responses and leave the stylistic decisions to those who are better trained for them.

[2] I am, of course, making a generalization here�some programmers do have at least passing awareness of good human interface design. But unless you've been trained in it, it's far better to assume that you're in the category of "hideous UI designer"�simply relying on our intuition here typically generates hideous results. Check out Alan Cooper's The Inmates Are Running the Asylum [Cooper99] for more information on the subject if you're not convinced.



If the stylistic elements of the page are generated from a data-only content response from the servlet or JSP, using XSLT to generate the necessary HTML, another benefit accrues�if and when the application needs to interoperate with other, non-Java systems such as .NET, the transition to making the site support Web Services is suddenly much simpler. Now, instead of having to write two separate servlets, one to generate HTML output and the other to generate SOAP response output, the servlet that generates the generic response can be used, and different XSLT stylesheets invoked to create HTML or SOAP output on demand. This transformation can be done from within a filter, and different URL patterns can be established pointing to the same servlet, thus providing two separate endpoints that call into one servlet. The web-app deployment descriptor would look something like it:










<web-app>

<servlet>

<servlet-name>ProcessRequest</servlet-name>

<servlet-class>

com.javageeks.webapp.ProcessRequestServlet

</servlet-class>

</servlet>



<servlet-mapping>

<servlet-name>ProcessRequest</servlet-name>

<url-pattern>/ProcessRequest</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>ProcessRequest</servlet-name>

<url-pattern>/WebService/ProcessRequest</url-pattern>

</servlet-mapping>



. . .



</web-app>




Now, any changes to the generated output only need to be made once�if the changes are structural in nature (more or different data needs to be returned), the one servlet can be modified, and if the changes are visual in nature (changing HTML stylistic surroundings or adopting a later version of SOAP), the change can be made to the filter and/or the XSLT file used to run the transformation. In both cases, the relevant code is localized to a single place, making maintenance on both much simpler.



Note that nothing comes for free, however, and the same is true of the XSLT-based approach. In this particular case, we're increasing the latency of the request, since the transformation process requires time to execute. For CPU-strapped sites, it may be more desirable to pregenerate the XSLT-rendered output (see Item 55) into different JSP pages (one per browser version) and select between them when forwarding from the controller servlet. This will greatly bloat the number of JSP pages on the site, however, potentially making it cumbersome to change and/or debug. This would be a last-resort approach used only if the latency is entirely unacceptable and other performance-enhancing techniques fail to address the problem.













     < Day Day Up > 



    No comments:

    Post a Comment