The Database Guy…you, the developer, & you, the organization, should really start doing your bit for the open source community

I am not an expert on design pattern histories, but I do believe that this style of abstracting out the persistence layer, a DAO class per type in your application, was used for a very long time.  Things were pretty much stagnant on this side.

If you peek into the current state of your code in the DAO classes, assuming that you have refactored all DAOs to use the SQLExecutor, you should notice a pattern of repetition across the methods.

@Override
public void record(LedgerEntry theEntry) throws SQLException {

   String insertLedgerEntrySQL = "insert into ledger "
           + "(amount, description, txntime, txntype) "
           + "values (?, ?, ?, ?)";

   sqlExecutor.executeUpdate(
           insertLedgerEntrySQL,
           theEntry.getAmount(),
           theEntry.getDescription(),
           theEntry.getDate().getTime(),
           theEntry.getCreditOrDebit().name());
}

@Override
public double fetchBalance(
       @NotNull final String stashId)
       throws SQLException {

   return sqlExecutor.executeQuery(
           "select balance from mystash where id = ?",
           new BalanceInterpreter(),
           stashId);
}

@Override
public void saveBalance(
       @NotNull final String stashId,
       final double balance)
       throws SQLException {

   sqlExecutor.executeUpdate(
           "update mystash set balance = ?",
           balance);
}

Basically, the methods are experts on setting up the right query for the domain data they deal with.  In case of a fetch use-case, they would build up a select query and interpret the results & in case of an update use-case, an insert or an update SQL query.  

The easiest way to understand the next step in the evolution of the architecture of the persistence layer in an application would be – to ask the much too familiar question again.  Take any of the methods and pose the question.  What do you think is the answer?

If this was an in person discussion, I would have posed this question…and then said…oh, you want to know what the question to be posed is?  Come on…you know it already!

Hmmmm…what could be the reasons for these methods to change? It’s the same question as always.  

…and the answer is quite simple and pretty much self evident when you do pose the question.  Let’s take an example, as always, of one of our methods – record(LedgerEntry):

@Override
public void record(LedgerEntry theEntry) throws SQLException {

   String insertLedgerEntrySQL = "insert into ledger "
           + "(amount, description, txntime, txntype) "
           + "values (?, ?, ?, ?)";

   sqlExecutor.executeUpdate(
           insertLedgerEntrySQL,
           theEntry.getAmount(),
           theEntry.getDescription(),
           theEntry.getDate().getTime(),
           theEntry.getCreditOrDebit().name());
}

What could be the reasons for this to change?

  • Any change to the nomenclature in the ledger table.  Rename of the table, rename of any of its columns, a new column, a deletion of an existing column, etc.
  • Any change to the nomenclature of the incoming LedgerEntry class.  Rename of the class, rename of any of its fields, addition of an additional attribute to it, deprecation/deletion of any of its attributes, etc.

Take a closer look of the two bullets above.  The changes seem coupled.  If I decided to call LedgerEntry something else, I would most likely rename the table legder as well.  If I add a new attribute to LedgerEntry, I would want to add a new column to the table as well.  So on and so forth.  You get the idea.  

…and if you now recognize the above stated similarity in the bullets, you may be ready to accept that there is indeed a coupling of the classes and the database design.  You could make the data model (database structure) the main driving force & derive your object model (classes) based on it or vice-versa, i.e.  make your object model the main driving force and create the required data model based on it.  The schools of thought, professed to me by various people, prefer coming from an object model point of view (think abstraction). The golden answer is to derive the right synergy between them.  For example, you may create an object model & equivalent data model for LedgerEntry like the following:

ORM-1

Or like this:

ORM-2

Each design has its pros & cons and you should be debating on whether it is correct to store all entries into a single table or create a separate table for credits, a separate table for debits and a common table Ledger for the common data between them.  For example, if the data is NOT widely varying in terms of structure, except for the type & they are typically always queried together, it may make sense to store both of them in a single table.

…but at the end of the day, you need to account for each data element in the object model in the data model.  Kind of a mapping between the objects and its data model needs to be formalized and defined.  To put it in more common jargon, a mapping between the objects and their mapping in a relational database (RDBMS).

…take a break & google “Object to RDBMS mapping”.  Hehehe…a lot of kind, passionate, benevolent folk have already done the work for you ages ago and taken care of all the heavy lifting involved.  So much so that now we have a JEE specification out there in the form of Java Persistence API (JPA).  Isn’t that just awesome?  Open source guys just rock. Special mention in my books to the Hibernate folk.  I feel guilty, almost everyday, of not doing my bit.  Hopefully, these blogs count in some shape and form towards that.  There is no real point in furthering our design efforts on the persistence layer.  We should rather spend energies on understanding these valiant efforts and make contributions to further the cause together.  In summary, please start using OR Mapping frameworks for your needs of persistence to a relational database.  You will notice that the Session interface in hibernate is an evolved mature equivalent of our current SQLExecutor.  You will notice that you no longer need redundant DAO classes, you get to focus on abstraction and good object model design in the form of entities (think LedgerEntry).

I just love this story of the evolution of the persistence architecture – at least the one that plays out in my mind.  Once you get familiar with this world you may feel the same.  I believe many expert programmers would have asked the question about the DAO(s) written by them.  What would cause the DAO to change?  And what I find fascinating is that they would have actually answered the question (the bullets laid out above, when we posed the same question), but would have done nothing about it.  And I don’t exclude myself from this list of programmers who didn’t do anything about it.   All of them would have had pragmatic reasons why the investment was not made.  The beauty of open source shines here in delivering that investment and people who didn’t do anything about it in their designs, reaping benefits from it.

Leave a comment