Jeff's Blog

Musings about software development, Java, OO, agile, life, whatever.


Tuesday, October 11, 2005 
Database TDD Part 3

Time to refactor. I took about 10 minutes and ran through about three different refactoring passes, running JUnit each time to ensure I maintained a green bar.

First pass: move responsibilities into a separate class, JdbcAccess. It's actually a move that will stave off duplication at some future point, once I have another domain class with persistence needs. But right now I'm following the single responsibility principle as my primary refactoring driver.

Second pass: eliminate common code duplication. Example: extraction of the createStatement method.

I made a couple other minor refactorings, including inlining the loadDriver method into createConnection (it wasn't pulling its own weight, violating simple design rule #4). The bigger move was divorcing the ResultSet from the need to populate the user object.

The code still has lots of problems, of course. There's still the presumption that there's a single row of data, and worse now, the JdbcAccess class presumes there are always two string columns.

Also: The User class still has to import java.sql (because of SQLException). And there's more duplication in the SQL strings that we've not touched on yet. And worse, we now have a class (JdbcAccess) with no unit test coverage.

Code from User.java:
public void save() throws SQLException {
   new JdbcAccess().execute(
      String.format("insert into userdata (name, password) values ('%s', '%s')", name, password));
}

public static User find(String nameKey) throws SQLException {
   JdbcAccess access = new JdbcAccess();
   List row =
      access.executeQuery(String.format("select name, password from userdata where name = '%s'", nameKey));
   return new User(row.get(0), row.get(1));
}
JdbcAccess.java:
import java.util.*;
import java.sql.*;

import com.mysql.jdbc.Driver;

public class JdbcAccess {
   private Connection connection;
   private Statement statement;

   public void execute(String sql) throws SQLException {
      createStatement();
      statement.execute(sql);
      closeConnection();
   }

   public List<String> executeQuery(String sql) throws SQLException {
      createStatement();

      ResultSet results = statement.executeQuery(sql);
      results.next();
      List<String> row = getRow(results);
      results.close();

      connection.close();
      return row;
   }

   private List<String> getRow(ResultSet results) throws SQLException {
      List<String> row = new ArrayList<String>();
      row.add(results.getString(1));
      row.add(results.getString(2));
      return row;
   }

   private void createStatement() throws SQLException {
      createConnection();
      statement = connection.createStatement();
   }

   private void createConnection() throws SQLException {
      new Driver();
      connection = DriverManager.getConnection("jdbc:mysql://localhost/test?user=root&password=xxx");
   }

   private void closeConnection() throws SQLException {
      connection.close();
   }
}

Comments: Post a Comment

Links to this post:

Create a Link



<< Home

RSS Feed (XML)

Archives

February 2004   March 2004   May 2004   September 2004   October 2004   January 2005   February 2005   September 2005   October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   June 2006   August 2006   January 2007   February 2007   March 2007   April 2007   September 2007   October 2007   November 2007   December 2007   January 2008  

This page is powered by Blogger. Isn't yours?