Code Formatting
One of the things that bothers me most about working with other programmers is dealing with code formatting other than my own, and I have never had the patience to sit down and write all of the rules to format code just the way I want it. In normal Java or C/C++ source, I can deal with varying levels of whitespace and curly brace placement, but code formatting moves from minor annoyance to productivity killer when dealing with markup languages like HTML, JSP, or XML.
When working with markup involving open and close tags, the best method I've found to keep track of opening and closing tags is to consistently indent. This means that any enclosed tag is indented from its enclosing tags. We're all used to this in XML where indenting is usually fairly consistent, but let's look at a few examples where indenting can help prevent you from making mistakes.
Most programmers I've worked with enter the basic structure of a document as follows:
<html> <head> <title>Title</title> </head> <body> </body> </html>
More often than not, these same programmers frequently leave out the closing html or body tag. With a little indenting, it becomes much easier to spot problems:
<html>
<head>
<title>
Title
</title>
</head>
<body>
</body>
</html>
With this form, you immediately spot the problem when you have a gap in your closing indent sequence. Of course, I know there are tools that help you with this, but do you want to spend your time learning tools or coding? I prefer to code so I try to use a form that will let me spot problems with or without a tool.
Taking this a step further, you can see where this kind of code formatting really pays off:
<html>
<head>
<title>
Title
</title>
</head>
<body>
<table>
<c:forEach items="${list}" var="item">
<tr>
<td>
${item.a}
</td>
<td>
${item.b}
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
Note how easy it is to see that any code printed in the forEach loop will be part of the table tag. I have yet to see a programmer indent their JSP/JSTL this way yet it makes it so much easier to read and maintain.
Here's another approach I use in the case of long code lines, especially when there is no closing tag:
<input type="submit" name="submit" value="Text of the Submit Button" onClick="return confirm( 'Are you absolutely sure?' )" />
When you write code, you have to keep in mind that all programmers are different. Some use GUI editors, some text mode. Some run at uber-geek, high resolution while others still run at 800x600 because it's easier to read. Keeping your code within a 78 character width often works best for everyone involved so finding ways to format to that width is important to productivity.
You can also take this approach into normal code:
return functionWithLotsOfParameters( param1, param2, param3, param4, param5 );
These are just a few of my methods of making code more readable while at the same time increasing productivity by reducing compiler errors, whether browser, JSP, or compiler. It may feel like it takes longer to format everything this way, but it pays off in the long run.
Posted at 04:16PM Jun 19, 2007 by Jason Koeninger in General |
Google's Guice
One of the blogs I read occasionally is written by Bob Lee, a Java programmer who works for Google. Recently, he announced the release of Google's Guice 1.0, a dependency injection framework built around annotations with support for generics. Why is this significant? To me, it's significant because I've grown to appreciate the productivity benefits of solutions built on annotations (Stripes, for instance) versus their XML alternatives (Struts, etc.). In this case, Guice is going up against Spring, or at least some of Spring.
At this point, I have little to add because I haven't used Guice. If you've read my article on Spring, though, you know I use it as more than a dependency injection framework, and I can envision Guice having a tough time pulling me away from Spring because of it. Nevertheless, it will be on my mind as I dig into new projects as a possible time-saver.
Posted at 03:41PM Mar 13, 2007 by Jason Koeninger in Java | Comments[0]
Our Java Stack: Hibernate
JDBC held its place as our primary data access technology far too long. Having grown up in C/C++ programming, JDBC felt like the natural replacement for ODBC. Unlike ODBC, we didn't wrap JDBC up in our own class library which seems odd in hindsight, and it led to some problems in production applications. As soon as you experience a few traffic spikes in an application with connection leaks, it becomes obvious why you should have wrapped JDBC in a library. We waited long enough, though, that a great number of competent libraries already existed.
The two tools we reviewed were iBatis and Hibernate. As a bit of a SQL jockey, I really liked the level of control offered by iBatis, but the potential productivity benefits of Hibernate (no SQL coding of CRUD operations) won out in my evaluation.
In November 2005, I dove into a new project with Hibernate 2.x as the data access layer. After spending a few months with Hibernate, I hated it. Yes, you read that right. I hated Hibernate. To be honest, I think some of my problems with it were of my own making and not necessarily the fault of Hibernate itself, but I could never see using it again. In March 2006 on the doorstep of switching to iBatis, I found Hibernate Annotations and decided to give Hibernate sans-XML configuration another shot.
Even though some of my issues with Hibernate remain (and remember, they're probably my own ignorance), Hibernate Annotations earned Hibernate a semi-permanent spot in our Java stack. I know there are arguments for and against code-based configuration, but the simple fact of the matter is that I am more productive using annotations.
Posted at 05:29PM Mar 06, 2007 by Jason Koeninger in Java | Comments[2]
Our Java Stack: Swing User Interface
With most of JJCC's work dominated by web applications, it's a rare opportunity to step away and work on a rich client. Health Occupation Students of America provided just such an opportunity a little over a year ago. The design for the HOSA Conference Management System called for a thick client capable of running stand-alone while staff worked on-site at the conference. The interface did not have to be pretty so much as it needed to be user-friendly and functional, and as usual, time was short.
In past graphical user interface projects, I have used Java AWT, Java Swing, OS/2 Presentation Manager APIs, and the Microsoft Foundation Class Library. I even went so far as to write a cross-platform GUI class library with support for both 16-bit Windows APIs and OS/2. Not looking to reinvent the wheel this time around, I needed to find a tool to build screens and connect them to data much more quickly.
As leery of GUI programming tools as ever, I set out to investigate some of the XUL (XML User Interface) options available. Initially, Mozilla caught my eye with its XULRunner. Being new and somewhat unstable handicapped Mozilla's offering as did requiring Javascript for coding actions. Javascript would have been fine, but there would have been a learning curve.
Having been exposed to XUL by Mozilla, I then started reviewing some of the Java XUL frameworks. Some were too big and cumbersome, others were incomplete or poorly documented, and still others were just too simple. It wasn't until I stumbled onto SwiXAT that I found something that I thought might work.
SwiXAT is not so much an independent project as it is a coming together of several useful parts into a more efficient whole. The basic XUL displays are written using SwiXml, but with SwiXml, you can do little more than mock up the screens. You still have to write code to load and display the screens and process events and actions. This is where SwiXAT shines. It allows you to wire user interface actions and events to BeanShell scripts. It also allows you to populate controls using JavaBeans accessed through JXPath. The end result is a stable, functional application written with a minimum of compiled code.
As long as you are not a GUI design fan, the only downside of SwiXAT is that it isn't all that popular and has not reached a stable version yet. Nevertheless the original architect, Paolo Marrone, remains active and helpful on the mailing list, and I have yet to see an application failure attributable to SwiXAT or its components.
If you're considering a XUL framework, download SwiXAT and give it a shot. You won't be disappointed.
Posted at 12:06AM Feb 03, 2007 by Jason Koeninger in Java | Comments[0]
Effective Java Exceptions at Dev2Dev
Barry Ruzek has written a great article on Java exception handling at Dev2Dev.
Posted at 05:45PM Jan 25, 2007 by Jason Koeninger in Java | Comments[0]
Our Java Stack: Swiss Army Knife (Spring)
Spring is a lot larger than a Web Application Framework. Swiss Army Knife is the best analogy I can come up with for how we use Spring.
Most importantly, we use it for Dependency Injection. Specifically, we program all data access to interfaces and have Spring inject the actual implementation classes at runtime. Early on in our work with ORM tools, we weren't sure which tool we would end up choosing. Having an easy way to keep our service objects independent from the underlying data access was very important to us so that we could switch data access methods if we changed our minds. Programming to interfaces provides endless flexibility, and Spring makes it simple.
As mentioned in the Web Application Framework article, we also use it to annotate transactions. Having experienced problems in older JDBC projects from leaking resources, Spring helped our application stability immensely by taking away an opportunity for programmer error to cause systems to become unavailable.
Other helpful Spring tools are its wrappers for several of the major data access technologies. Right now, we're using Hibernate v3.x, but it also supports other popular tools like iBatis, JDBC, and EJB.
Beyond some of those basics, we also had a few problems pop up in one project which were solved less painfully than normal using AoP (Aspect Oriented Programming). Spring's built-in AoP support meant we could implement some aspects without adding any dependencies to the project, and they saved us the trouble of major architecture changes to get the right information info the right piece of code.
There's little doubt we'll find further use for Spring as the years go by. The nice thing about it is that even if you don't want to use one piece of it, you can still easily use the rest of it.
Links:
Posted at 07:00AM Dec 17, 2006 by Jason Koeninger in Java | Comments[0]
Our Java Stack: Web Application Framework
The last 3 years have been an interesting time for JJCC as we have been working to find a web application framework we can live with. Our home-grown framework was written for a year-long project and was not encapsulated in a way that the code could be used in other projects. Struts was also gaining popularity, and in reviewing it, we found that many of the concepts we used in our framework were provided in Struts. It also provided tag libraries, file-based configuration (as opposed to code-based like ours), and a variety of other useful features like filters on top of what our framework offered. With its popularity on the rise, it seemed like the obvious choice of frameworks available at the time.
Unfortunately, in practice, we found Struts to be cumbersome and error prone. Don't get me wrong...Struts itself was very solid. The problem was that development using it was error prone. Additionally, we often ended up with views that couldn't be re-used in different contexts. The blame for this does not entirely rest with Struts. Indeed, we were part of the problem, but it seemed like we were constantly chasing configuration files. To help with that, we enlisted XDoclet, but it all seemed to turn into a bigger and bigger mess. I don't recall all of the problems we encountered, but we were spending more time on build systems, configuration files, library versions, and troubleshooting the framework than we were on coding.
After most of our projects stabilized, we decided to look at alternatives to Struts. This time, Spring was the new kid on the block with rising popularity. Granted, more of the buzz about Spring dealt with Inversion of Control, but it also came with its own web framework. Our experience with SpringMVC didn't even last through the completion of our first project. It felt like the same maze of configuration files that we had with Struts, and there was no other significant added benefit for the kinds of projects we typically undertake. In truth, we didn't even stick with it long enough to see how well it could have worked. We fought a little with its form handling interfaces with little success and ended up using it as little more than a thin servlet wrapper.
Our experience with Spring did expose us to something we did like, though...Annotations. We had used the Spring Transactional annotation to control transactions in our data layer, and it made life a lot simpler than coding a bunch of garbage into an XML configuration file. While there are some good arguments for external configuration, they just don't apply in our typical project scenario.
By some accident, we stumbled onto the Stripes project before finishing the first SpringMVC project. Stripes is a drastically simplified framework which relies primarily on annotations for configuration. However, simplification shouldn't be confused with lacking power. Stripes allows you to write a form using a small tag library which draws data from JavaBeans defined in your Action. When the user submits the form, Stripes intercepts it, finds the action associated with the URL, automatically converts and binds the form field values to the JavaBeans in the action, runs annotated validations on the values as they are bound, and then executes the handler method in the action.
To a lot of programmers, it's confusing because it seems like magic. Grabbing parameters through the request, converting data types, catching exceptions, handing off to error handlers, etc...all things of the past. Stripes does all of this work for you so you can focus on the application and not trivia. It even adds in goodies like FlashScope which allows you to retain data in the session for a short response/request cycle as you would get when sending a redirect at the end of a form submission to prevent reload/resubmit problems.
Since switching to Stripes, we have cut our estimates for building web-based forms/database applications in half. Try it out and see if you have the same it-just-feels-right reaction to it.
Links:
Posted at 03:22PM Dec 16, 2006 by Jason Koeninger in Java | Comments[0]
The JDB Library
Over the years, I've written a lot of code, but no piece of code has kept my interest like the B-tree implementation I first wrote for a college file structures course. At Oklahoma State University, building a working B-tree was a bit of a rite of passage for all Computer Science students. Sad as it may be, few were able to accomplish the feat. But me? I was hooked. It seems like I coded solid for a couple of days to build the initial B-tree without delete support and spent another day implementing delete. As it turned out, I messed up one rotation in delete, but it just meant the tree was in an underflow condition on a page, not out of order.
During the initial R&D phase for Shepherd while trying to build a data store for the directory, I experimented with Sybase SQL Anywhere, DB2, and even OpenLDAP. Unfortunately, none of them measured up to the combination of speed, ease of installation, and porability I wanted. Sybase was easy to install and came with royalty free runtime licenses, but for directory data, it was slow. DB2, speed demon that it is, was just too expensive and too painful to install in this situation. OpenLDAP worked okay, but it forced Shepherd users into running some kind of Unix box since it wasn't portable to OS/2. At the time, the primary target platform was OS/2 so OpenLDAP wasn't an option. With no other viable alternatives, I set out to write my own data store.
Creative in naming as always, the JDB library was born. The initial version drew on features I liked from Sybase SQL Anywhere and disliked with xBase databases. All data was stored in a single file. The goal with this approach was simplicity. Having supported xBase databases in past projects, getting someone to zip up a set of 30 .dbf and .cdx files was a serious pain. Even though Shepherd users would be more technically adept, it still would be easier to ask for just one file. While this early version of JDB worked, it suffered from its lack of support for transactions and logging. Power outages and software crashes frequently destroyed the database requiring a rebuild from an LDIF import file.
So, a major rewrite took place to add transactions and logging and clean up the code. The end result was a faster JDB library with a more professional disposition. Over the past few years, I've been slowly debugging the code so that I can talk about uptime in months instead of weeks. As of last month and with the help of Mac OS X and its development tools, I was able to find two bugs which were capable of corrupting portions of the B+Trees within the data file. Now, I am cautiously optimistic that our uptime will soon be measured in years.
How does JDB work, you ask? Glad you did. It may not be as elegant as some would like, but it gets the job done.
JDB does not work with a row or column metaphor. Instead, it works on data as a whole. As such, it might be more appropriately called an object database. Instead of rows, it includes an interface with a simple set of read/write functions not unlike Java's Serializable interface. Applications wishing to use JDB as a data store implement these two methods for any class they wish to store in JDB and then use the API to create the database, create tables, store data, commit, rollback, etc. There is no SQL interface, but one could easily be added by creating a "row" data type with the appropriate supporting SQL language tools.
So here I sit with a transactional storage engine with commit, rollback, and crash recovery capabilities. The question I keep asking myself is what should I do with it, if anything? Should I implement a MySQL storage engine and go up against InnoDB? Given the recent uncertainty, it doesn't seem like a bad idea. Should I open source it as a general library and see if anyone has any interest in it? Unfortunately, either of those options carries with it the weight of time required to comb through source for release and potentially remove lower-level libraries we don't wish to open. It's not a competitive or licensing issue in those cases but more of a code quality issue. Some of our core library dates back to my first few years of programming. As such, the design of the code is very poor and would reflect badly on the company if open sourced.
If you have any ideas, please let us know.
Posted at 12:54AM Dec 14, 2006 by Jason Koeninger in General | Comments[1]
Our Java Stack: Introduction
It's amazing how things have changed since I entered the programming field back in 1993. In our first database project, my business partner at the time wrote a hierarchical set of index and flat files. Everytime I pulled up DOS Edit and fixed an indexing problem in the production database, he cringed and sometimes with good reason. The fixes often made the problem worse, not better. When the limitations of our first database caught up to us, we moved into real database territory by consulting the Programmer's Paradise catalog and finding CodeBase by Sequiter Software. Back then, before many software companies even had web sites, companies working in PC software often took that approach. There were several catalog sites selling 3rd party SDKs and APIs in addition to those available through the major operating system vendors. When you found what you needed, you ordered it, consulted the documentation, and wrote the code.
Now, the game is much different. Orphaned operating systems caused us to pull away from platform-specific code...orphaned SDKs/APIs caused us to pull away from commercial solutions. Our only gamble would be the survival of Sun and Java.
When we first made the leap to Java, we did not use any 3rd party tools. At the time, not many were available, and those that were available weren't on our radar. In our first Java web application, we used servlets to a fault making a huge, tangled mess of Java classes. In fact, that was before a lot of the servers on the market supported JSP so the servlets were full of out.println( "..." ) statements.
On the next project, we learned a bit from past mistakes and implemented what could best be described as Struts 0.01. We had never seen Struts, but we ended up creating an architecture with some similarities to Struts Actions but lacking the other pieces of Struts like tag libraries, configuration, and filters. As luck would have it, it has served us well and still runs today. However, it's impossible to look at the code without seeing its shortcomings.
Beyond the web application architecture, we were also reinventing the wheel in other areas. As a result, applicatons were taking too long to design, develop, test, and debug so we set out to find a set of tools to improve our productivity, increase application stability, and simplify code. This series of articles will review the tools we have chosen and discuss a few of the tools we rejected along the way.
Posted at 04:25PM Dec 13, 2006 by Jason Koeninger in Java | Comments[0]
Launch of JJCC Blog
JJCC is finally launching a blog to replace the archaic, manual html writing we had been doing to create news, articles, tips, and other information. Hopefully someone will find some use for the information presented here. Posts prior to this post are reposts of content already published on our site.
Posted at 02:41PM Dec 06, 2006 by Jason Koeninger in General | Comments[0]
Mac OS X Form Field Tabbing
In December 2003, I finally took the plunge and started using a dual G5 Macintosh running OS X for my home machine. This machine primarily serves as a video and audio editing workstation, but being a full blown Unix OS under the hood, it comes in handy for evening and weekend software development and system administration work.
As a video editing workstation, the Mac has been a dream. Final Cut Express, even at a paltry 512 Mb of RAM, flies through moderately complex video projects. DVD Studio Pro's MPEG encoding embarasses my earlier Linux-based attempts in both speed and quality. Add to that the fact that I can produce Dolby 5.1 digital audio, and you have an unbeatable platform for amateur DVD production.
In the general use and software development arena, however, I haven't been quite as happy. My biggest frustration has been the fact that web page forms, necessities for web application development, do not support tab stops for all form elements. Or, so I thought...
After installing Firefox to get around what I thought was a problem in Safari, I ran into the same problem again. Select elements and others were skipped in the form tab order. At this point, I suspected either a bug or an oversight and started searching the Internet for others commenting on the same problem.
As it turns out, OS X has a setting in the Keyboard Shortcuts section of the Keyboard and Mouse preferences panel that turns on additional keyboard access. Once checked, Safari allows tabbing to all form fields.
While I'm pleased to have the additional keyboard support, it concerns me that the default does not correspond to the standards. According to the W3C, platforms shouldn't differentiate between different kinds of form elements.
In the mid-1990's, we ran tests to see which style of form completion was faster, keyboard or combination keyboard/mouse. The form in question included a wide variety of text fields, radio controls, check boxes, and combo boxes. The results of the tests showed that the keyboard user could enter anywhere between 2-3 times as much data as the mouse user.
As a result of those tests, we do everything we can to fully enable keyboard use of all of our applications. Right now, we likely have several new OS X users wasting a good deal of time clicking on select boxes when tab doesn't work. While we will definitely get the word out to them on how to fix it, Apple still would be well served to make the default behavior standards compliant.
Posted at 12:00PM Feb 12, 2005 by Jason Koeninger in OS X | Comments[0]
Linksys Network Everywhere NR041 Broadband Router
Shortly after installing broadband, most people usually find the need to connect more than one device to their Internet connection. To do that, they need a device called a router with the ability to do Network Address Translation (NAT). With the popularity of broadband, the price of these devices has gone down while the number of features available has skyrocketed. Unfortunately, some manufacturers have sacrificed quality.
Such is the case with the Linksys NR041 Broadband Router. At an attractive price with a full slate of features and the backing of a company like Cisco (now Linksys' parent company), why not try out the Network Everywhere brand? In fact, most any user on most any operating system will find it very easy to jump in and configure Cable or DSL access with this device.
Unfortunately, nothing else positive can be said about this router. The simple fact is that the hardware is poorly designed and prone to heat problems. When it does overheat, the device will simply drop the network connection. Power-cycling the router usually brings the connection back.
Linksys support has recommended changing MTU settings and upgrading the firmware, but the MTU they recommend is not retained by the router, and the firmware available on the website is older than the firmware on the router. Two requests for newer firmware they claim to have available have resulted in no return e-mails. Regardless, the real problem is heat, and in our test setting, we're talking about ambient room temperatures of only 72 degrees farenheit.
Please consider alternate brands like Netgear before purchasing this device. While it may have a nice price, it's not worth it. Given our experience with support, we would also recommend staying away from Linksys branded products even though they don't appear to have the same heat problems as the Network Everywhere NR041.
Posted at 12:00AM Nov 05, 2004 by Jason Koeninger in Hardware | Comments[1]