A Simple Example
Imagine a simple data structure from a CRM system that we need to convert back and forth to XML using JDOM. The structure might look like this:
public class Customer { public String name; public String address; public String email; public String phone; public String fax; public String cellPhone; }
OO purists might turn up their noses at the public fields. Indeed, if we start adding lots of behavior to the class, we probably ought to make the fields private. For the moment, however, this class is nothing more than a data structure, and it would be a shame to pollute it with a lot of getters and setters.
We'll use JDOM to convert this to the following XML:
<customer> <name>John M. Smith</name> <address>555 East Warwick Ave. Tulane, NJ 50101</address> <email>smith@tulane.nj</email> <phones> <business> 111-222-3333 </business> <fax> 111-222-3333 </fax> <cell> 111-222-3333 </cell> </phones> </customer>
Now we create the method that uses JDOM to get that XML. If we aren't using Agile methods, then we might simply write the method like this:
public Element toXML() { Element customer = new Element("customer"); customer.addContent(new Element("name").setText(name)); customer.addContent(new Element("address").setText(address)); customer.addContent(new Element("email").setText(email)); Element phones = new Element("phones"); phones.addContent(new Element("business").setText(phone)); phones.addContent(new Element("fax").setText(fax)); phones.addContent(new Element("cell").setText(cellPhone)); customer.addContent(phones); return customer; }
This looks like it will work, but are we sure? Let's write a JUnit test to make sure:
public class CustomerTest extends TestCase { public void testToXML() throws Exception { Customer c = new Customer(); c.name = "John Smith"; c.address = "55 Somewhere, City, State Zip"; c.email = "jsmith@somewhere.com"; c.phone = "111-222-3333"; c.fax = "444-555-6666"; c.cellPhone = "777-888-9999"; Element customer = c.toXML(); assertEquals("John Smith", customer.getChild("name").getTextTrim()); assertEquals("55 Somewhere, City, State Zip", customer.getChild("address").getTextTrim()); assertEquals("jsmith@somewhere.com", customer.getChild("email").getTextTrim()); Element phones = customer.getChild("phones"); assertEquals("111-222-3333", phones.getChild("business").getTextTrim()); assertEquals("444-555-6666", phones.getChild("fax").getTextTrim()); assertEquals("777-888-9999", phones.getChild("cell").getTextTrim()); } }
Okay, this test passes. Looks like we're done.
This code is a mess. It works fine, but it's filled with duplication and structures that are hard to parse. An error in this code could be quite difficult to find. If we had thousands of lines of code like this, we'd be in trouble.
The XP approach to this problem would have been to write the test and module together, while continuously refactoring. Let's see what that would look like. Wipe the slate clean and start over.