Monday, February 15, 2010

Parent-Child Relationship in Java Business Logic Beans

There must be good tips and info out there on the net about best practices for designing Java beans business objects, etc. I don't mean basic stuff like getters/setters, but much more subtle questions like when to hide constructors, how to deal with parent-child objects and what sort of methods to expose for that, etc.
Somehow I never found good info on that (not that I tried too hard), and my classes didn't cover it.

Here's my take on the parent-child relationship between Java objects. Say there are two classes: Customer and Contact (a typical sales-app situation). Each customer has multiple contacts - a simple one-to-many relationship. The customer object keeps track of the child contacts with a collection, and the contact maintains a parent customer reference.

Question: how to handle creating new contact objects?

In contact class:
// package-private constructor
Contact(Customer c, parameters...) {
  this.customer = c; // keep parent reference
  // deal with other parameters
In customer class:
public Contact createContact(parameters...) {
  Contact c = new Contact(this, parameters...);
  this.contacts.add(c); // update children collection
  return c;
Why not expose the contact constructor directly and have it update the customer contacts collection? Adding to the children collection is altering object state - it is best to keep that inside the customer class.

Even in terms of readability this makes more sense. When humans say "customer", the meaning includes all the relevant contacts, etc. When we create a contact we change customer state, first and foremost. So it makes sense to initiate that change with the customer object.

Wednesday, February 10, 2010

Two-column Form Layout Without Floats

As part of my job, I work with HTML forms almost daily, and styling them is an ever-evolving challenge.

Clients like it when labels are horizontally aligned with inputs. It's the standard look, and it works well.

One of the big requirements is avoiding floats. Float behaviour is complicated and buggy, even outside of IE. Normally that's not a big issue, but in apps one can't predict where a given form will end up, what kind of custom widgets (that use their own funky float layout) will need to be part of it, etc. Basically, form CSS has to be rock-solid.

Markup has to be simple and valid XHTML. So no tricks like placing the input inside the label. And it sucks to litter markup with spans and whatnot.

There has to be allowance for error messages, help tips, overflowing label text, etc. Basically, no reliance on hand-tweaking content.

A good method that does not use floats is described in this A List Apart article:

It uses inline-block for labels - not great, because it's hard to put properly aligned help text after it. Same with error text.

The answer? Negative margins. Check this example (forgive the programmer art):

First, we keep label content to the left of everything else by assigning a width to it (as a block), and applying a left margin to other content in the form.

Next, we apply a negative bottom margin to every label. Any content that follows a label is "pulled up" vertically to appear as though they are on the same horizontal line.

For consistency across fonts and browsers, we assign a generous fixed height to the label, and make the negative margin match it. In theory, the fixed height can be anything, even zero - but IE6's overflow bug puts an end to that theory.

This brings up a big caveat with this method. If the label contains several lines of text, the browser will not auto-magically shift remaining content down, as it would with normal cleared floats. In the particular case of HTML forms, this is not an issue, given enough vertical spacing between inputs.