Saturday, May 20, 2006

JavaOne Day 3 - The Rampdown Begins

Day 3 began with Erich Gamma taking centrestage with mission Eclipse. In the presentation titled "Java in the Trenches - Reflections Along the Eclipse Way", Gamma and John Wiegand took us through the development cycle of the Eclipse platform, which has delivered quality software with impeccable precision on delivery dates. The visuals which they demonstrated for the Eclipse version of agile methodologies reflected upon the enormous experience and process maturity that the team has imbibed over the years.

Gilad - The Saint

Gilad Bracha has a unique way of presenting things. He does not have the aggression of Josh Bloch, rather a very saintly way of taking the hall through the journey. His session entitled "Dynamic Languages on the Java Platform" had a full house. Though there was nothing very new from the content point of view apart from what he has already blogged on this subject, it was a fairly informative session. Typical responses expected as Q&A like tail call support in the JVM were dealt with in a saintly way (of course in the negative) by Gilad. Later after the talk, he has blogged his disappointment at the crowd not asking for Continuations support in the JVM - he had the response ready though. Support of continuations in the JVM has been discussed in many forums and Gilad has categorically turned all of them down citing reasons like cost of implementation and incompatibility with the current Java SE security model. Hence, I guess, people have given up all hope of finding continuation support in a JVM in the near future. This is what Gilad has to say in his blog on this issue
... continuation based web servers are very nice. Seaside is the nicest one I've seen. But ultimately they are just a phase, and we can already see how we will outgrow that phase. Since continuation-based servers won't be all that significant in the long term, and given the huge lead times and costs of adding continuations to the JVM, it makes little sense to support them.

Web servers aside, continuations, though admittedly difficult to implement, has many other uses. The comments section of Gilad's blog entry has ample testimony towards that.

Ajax Ajax

In day 3, also there were lots of sessions on Ajax, RIA, Dojo and Web 2.0. Not all of them were of high quality, but, while the lights are on, go follow the bandwagon. The new kid on the Ajax and SOA combo, JackBe, had Deepak Alur and Dan Malks (both of J2EE patterns fame) moderate a session on "Java Technology, Ajax, Web 2.0 and SOA", which had Craig McClanahan and Rod Johnson (among others) on the panel. I attended the session, which I felt was quite crappy, since none of Craig or Rod ever found the space to get going. And when Ajax is there in the panel discussion topic and u have a full house, nothing, but chaos can only reign!

In another session titled "Using the DOJO Toolkit to Develop AJAX enabled Java EE Web Applications", the speakers did a fairly good job of taking the (once again) full house through the process of using frameworks in an Ajax application. And DOJO seems like a leader in this space.


Apart from the above, I attended some of the other sessions where the main themes were once again GlassFish, NetBeans and how a combination can give us an easier programming model. Motorola, in their general session once again emphasized how they are transforming the mobile world with Java technology. The evening sessions on Day 3 saw a remarkable fall in attendance, since the sessions had to compete with free beer available in the After Dark Bash - no wonder we had some more crappy stuff scheduled during these hours.

Tomorrow I plan to attend a couple of sessions on EJB 3.0, which has been released after it passed the community process. If u consider the pre-Spring era, EJB 3.0 looks to be a solid progress from its demon predecessor towards a scalable component model. But hey, we have been through Spring and the best practices sermons of Rod Johnson - compared to that EJB 3.0 falls far below expectations. However, that's for another day, folks .. for now it is DG signing off from Moscone Center, San Francisco.

Friday, May 19, 2006

JavaOne Day 2 - Josh Rocks, But It's Ajax All the Way

Every year, JavaOne throws up the theme of the show. This year it's Ajax all the way. Every tech session on Ajax is booked, the most notable among them being the flagship session on "An Introduction to AJAX" by the founders of Ajaxian.com, Ben Galbraith and Dion Almaer. As has been mentioned in the conference report by John O' Conner
Using simple but effective examples, the two made a compelling argument for using Asynchronous JavaScript with XML (AJAX) to create dynamic, responsive applications that are easy to deploy and that require nothing more than a common web browser.

Besides this flagship from the creators, there were many other sessions which focussed on Ajax, RIA, SWT and the likes which promise to bring heaven on the client browser.

Josh Rocks!

I attended three sessions by Joshua Bloch, one of them the famous Puzzlers Session with Neal Grafter. Their book "Java Puzzlers - Traps, Pitfalls and Corner Cases" has been doing great in this year's JavaOne, but in their tech session the two wizards set the floor on fire with new additions to the puzzlers collection. Great show and I enjoyed every bit of it. This was preceded by a solo from Josh where he discussed some of the advanced Java patterns and idioms, which he promised to load in the next edition of Effective Java. Cool stuff! The icing on the cake was the BOF on "Collection Connection", which happened to be the eleventh edition of the show. Eleven long years - yet the Collections Framework is evolving, a definite sign of a living language (or perhaps Dynamic Language, as Gilad would like to mention it). The BOF was brightened up by the lumious anecdotes which Josh mentioned while recollecting his struggle with Binary Search in his CMU days. Overall the BOF was extremely enlightening with good indications of what to expect from the Collections Framework in Mustang and Dolphin.

Don't Ignore the Scripters

Two very interesting sessions which I attended on the second day of the conference included the ones on Groovy and JRuby. The Groovy session, led by Rod Cope had entertainments written all over. Some of the crazy things which he demonstrated included opening up new excel worksheets, filling up with data, formatting stuff, generating charts and ultimately putting the entire control within a Swing panel with buttons and callbacks - all with 20 lines of Groovy code! This is developer's productivity, at its best.

In the session on JRuby, the creators, Charles Nutter and Thomas Enebo, were there discussing passionately their experience trying to bring up the most powerful scripting language on planet into the Java Virtual Machine.

Can Java Studio Creator Eclipse the IDE World ?

Sun has come out strong with the message to use the Sun Java Studio Creator. Based on its much hyped NetBeans development environment, the creator has lots to offer as a rapid web application visual development tool. The Creator comes bundled with the Application Server, a database named Derby, data binding facilities through drag and drop, Ajax enabled JSF components, portlets as a project type, bunch of goodies for writing Web Services, themes and what not!. It will be really interesting to find out how the Big Blue responds with all the happenings in its Eclipse world. Tomorrow, I will find out what IBM has to say in the General Session to be addressed by none other than Erich Gamma.

In today's general sessions, both Oracle and BEA, led with their efforts towards contributing stuff to the Java space. BEA mentioned about their "blended strategy" of fusing commercial software and open source software towards development of enterpise tools that will make programming an enjoyable developer experience. The director of developer relations at BEA reiterated that BEA has been a key player in the open-source space. The company is a board member of the Eclipse Foundation and sponsored such projects as Apache Beehive, Apache XMLBeans, Eclipse AspectJ, Eclipse WTP, and more, besides being the first application server to provide certified support for the Spring framework.

Overall, day 2 at JavaOne had the all pervasive theme of Rich Internet Experience with Ajax leading all the way. Amidst all the industry frantics and open source hullahs, Gilad Bracha's session on "Superpackages: Development Modules in Dolphin" went almost unnoticed, with half of the hall empty. It had some important points though, which promise to make modular developments much easier in Java. But, at least for today, Ajax rules !

Thursday, May 18, 2006

JavaOne Rumblings - Day 1

More community partcipation, more Open Source, crying for more compatibility - these sum up the clairvoyance of the chief Java evangelists of Sun Microsystems, as the first General Session of JavaOne 2006 unfolded to a live band playing below the multiplex of gigantic screens in Moscone Center of San Francisco. I am here for the first time to attend the pinnacle of all Java summits and celebrate the technology that Jonathan Schwartz says has become the key ingredient of the digital experience for hundreds of millions of people across the planet. Thank you Anshinsoft for sponsoring me for this trip.

I attended one of the Java University courses titled "How Java EE Patterns Help in Architecting and Designing Robust Java EE Applications". The instructor was very energetic and covered lots of material within the stipulated time frame. But at the end of the day, it was all same old stuff regarding Session Facade, Business Delegate and Transfer Objects. I expected something new related to the upcoming EJB 3.0 stuff, patterns for designing generic frameworks using EJB 3.0 interceptor technology, patterns for exploiting Java 5 annotations etc. With those old patterns which Deepak Alur had documented 5 years ago, the course was a run down of yet another UML based development, the old way, when people used to develop tons of models (read diagrams) only to discover that they have become outdated before the programmers could start writing a single line of code. Give me a break! The waterfall model of producing use-cases, refining use-cases, generating class diagrams, generating sequence diagrams etc. always work in demos and tutorials with a handful of classes, but they never scale in real life applications.

Open Source! Open Source!

All projects in java.net has been open sourced and this was repeated in almost all of the sessions by all leading Java evangelists. Jeff Jackson, SVP, Java Enterprise Platforms and Developer Products, emphasized on more community involvement to support all Java EE initiatives. He called for the following Calls to Action for the audience:

  • Join JCP

  • Download NetBeans and join the NetBeans community

  • Join java.net, and join the projects now open sourced, such as Sun Java Studio Creator 2, GlassFish, Mustang, WSIT (whiz-it)

  • Get the free GlassFish Open Source App Server

  • Visit The Aquarium, a Virtual water cooler for WSIT and GlassFish

  • Contribute to the BPEL Engine into Open ESB

  • Use the Beta of Java SE 6


What does the above imply ? As a developer, do I really care whether Java becomes open source from tomorrow - I have access to all source codes of the Java platform, except the JVM. And 99% of all developers worldwide do not care about the inner workings of the Java Virtual Machine. I fully agree with Cedric, that the one thing that Sun needs to figure out is the licensing and redistribution policies of Java. There are companies like BEA, IBM and Oracle, with bigger stake in Java's success waiting ringside to drive forward with developments in the core platform. It cannot be denied that much of the progress that we have seen on the Java front has been due to community participation - the progress on the core side (i.e. JVM and JRE) has been impeded by Sun itself. Compare it with Microsoft's progress with the .NET platform - there has been a flurry of developments in the recent past with all sorts of creative features being incorporated within the core platform.

Showcasing NetBeans

The first day at JavaOne was dominated by the showcasing of NetBeans - at least three sessions demonstrated how a sample Java EE application can be developed using NetBeans 5.5 in less than 15 minutes. Boy, if application development was really this easy! However, on the whole, Sun has been able to make its presence felt in the IDE space with ample demonstrations of the capabilities of NetBeans and its integration with the entire GlassFish suite.

Back to the POJOs

EJB 3.0 is here! In the technical session on EJB 3.0, it was obvious that the creators admitted the cumbersome programming model of earlier versions of EJB and brought out the POJO based architecture of EJB 3.0. The Java Persistence API of EJB 3.0 has been contributed by BEA through its KODO implementation, which will also form the backbone of the next Weblogic Application Server.

On the whole the main theme of Java EE 5 as evident from the first day's session in JavaOne is to come out with a more user-friendly programming model focussing on the ease of development. I think with all collaborations and community building exercises, this will make life easier for programmers at large and architects in general.

Tomorrow, the second day of JavaOne promises great stuff from Joshua Bloch. I will be back with some more news and fresh perspectives in the next edition of this blog. Till then .. Peace.

Monday, May 08, 2006

Don't Generate Code - Generate Model Implementations Instead

There has been lots of confusions regarding my views on automated code generation, since I wrote my last post. I guess it is the following rumbling that spread across the bad word and insinuated me as one of the crusadors of tool based code generation:
I have never been a fan of automatic code generators, which always tend to produce tons of boilerplates, which could otherwise be refactored much more elegantly using OO frameworks.

To some extent, the lack of expressiveness of my intent has been responsible for this - possibly my ardent readers have missed out the last segment of the above statement which qualifies my disliking to only those code generators which produce tons of boilerplate codes violating the ageold principles of abstraction and encapsulation. That was exactly my point in the last post, where the DAO generator generated lots of Java code which could otherwise be abstracted in an OO framework.

In today's world code generators have a significant role to play in the areas of Model Driven Architecture (MDA). Until recent times, UML had acquired the ignominy of being the unfriendly companion to the project manager - to the extent that we had started talking about Death by UML Fever, where designers produced tons of model documents which became obsolete even before the developers could install the proper plugins of Eclipse. UML 2.0 promises support for MDA - the new MDA-based features allow creation of various architectural modeling styles supporting reusable design patterns.

EMF, the Eclipse Modeling Framework offers MDA capabilities with UML as one of the importers of the model. The model which you design using UML can be directly imported into EMF and Java code for the implementation can be generated directly out of it. The model can be as rich with all sorts of relationships like aggregation, composition, inheritance and association - the EMF code generation module takes care of every iota of the richness and generates Java code as the implementation. Apart from UML, EMF also supports XMI documents, XML Schema and annotated Java as source of model artifact. e.g. We can define an annotated Java interface as follows:

/**
 * @model
 */
public interface Book {
  /**
   * @model
   */
  String getTitle();

  /**
   * @model
   */
  int getPages();
}


EMF code generator will spit out the following as implementation of the above model, a Java interface along with the corresponding implementation class:

public interface Book extends EObject {
  String getTitle();
  void setTitle(String value);

  int getPages();
  void setPages(int value);
}

public class BookImpl extends EObjectImpl implements Book {
  ...
  protected static final int PAGES_EDEFAULT = 0;
  protected int pages = PAGES_EDEFAULT;

  public int getPages() {
    return pages;
  }

  public void setPages(int newPages) {
    int oldPages = pages;
    pages = newPages;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET, ..., oldPages, pages));
  }

  ...
}

In the above code fragment (adopted from this series in developerWorks), the generator takes care of complicated semantics like enabling the observer pattern for the set method by notifying any observers of the abstraction through the eNotify() method. Also note the optimization guards implemented by the call to eNotificationRequired(), which, in the degenerate case (no observers) amounts to nothing more than an efficient null pointer check, which is inlined when using a JIT compiler.

The code generator component of EMF, called EMF Codegen, also supports customizable code generation through JSP like templates, JET(Java Emitter Templates) and easy regeneration and merging.

How is the code generator of EMF different from the run of the mill ones which generate boilerplates ?

The heart of the EMF is the ECore Metamodel, which has mapping for every UML construct. Hence when the UML model is translated into Java code, we have a lossless translation which preserves all the richness of the original artifact. An excellent illustration of these capabilities has recently been discussed in a TSS article by Patrik Nordwall. Hence EMF Codegen generates model implementations, as opposed to boilerplates.

So, next time when you think about rolling out your code generator, double check if you are producing code that can be better abstracted through an OO framework. And use your framework model and a lightweight DSL to generate model implementations, rather than boilerplates.

Friday, April 28, 2006

Code Generation, Boilerplates and OO

Of late, I have been playing around with DAOs a little bit and have also been blogging extensively on the implementation aspects of them (e.g. see here and here). Of all the leading vendors that offer DAO implementation, CodeFutures' Firestorm/DAO offers automatic code generation for DAOs from the relational schema. Andy Grove, the CTO of CodeFutures claims in his weblog that the code which FireStorm generates is as efficient and maintenable as hand-written code. In fact he also has a separate blog entry on the debate of frameworks versus code generators, where he mentions about the complexity of maintaining the framework as one of the driving reasons for going to the code generator approach. As an example he mentions that
the real benefit of Code Automation is that if the underlying framework changes substantially (for example going from EJB 1.1 to EJB 2.0) then the code can be re-generated for the new framework.


I have never been a fan of automatic code generators, which always tend to produce tons of boilerplates, which could otherwise be refactored much more elegantly using OO frameworks. Here is what Rod Johnson has to say about automatic generation of DAOs
There shouldn't be vast amounts of boilerplate code in DAOs. ... Using JDBC abstraction layer is better than generating JDBC code from a maintenability perspective. If we see requirement for boring repetitive code, we should apply an OO solution and abstract it into a framework, rather than generate it and live with the resulting duplication.


In one of my earlier posts, I expressed the same concern regarding the level of abstraction that Firestorm generated DAOs provide - I still feel that the code could have been better reengineered had we employed an OO framework based solution. At Anshinsoft we have been working on generic DAOs and adopting a mixed strategy for DAO code generation. All repetitive codes are part of an OO framework, which offers base level abstractions for DAO operations. The generated code only contains the specifics for the particular tables as specializations of the base abstractions.

After going through Andy's weblogs, recently I downloaded a copy of the evaluation version of FireStorm/DAO and started playing with it. I generated some DAO code against a schema and came up with the following implementation of AuthorDao, which I replicate below. The generated DAO implementation class consists of 586 lines of code for a table having 3 columns! Multiply this with the number of tables that can be there in a typical enterprise application, and all jars begin to explode.



/*
 * This source file was generated by FireStorm/DAO 3.0.1
 * on 07-Apr-2006 at 10:13:32
 *
 * If you purchase a full license for FireStorm/DAO you can customize this file header.
 *
 * For more information please visit http://www.codefutures.com/products/firestorm
 */

package com.mycompany.myapp.jdbc;

import com.mycompany.myapp.dao.*;
import com.mycompany.myapp.factory.*;
import com.mycompany.myapp.dto.*;
import com.mycompany.myapp.exceptions.*;
import java.sql.Connection;
import java.sql.Types;
import java.util.Collection;
import org.apache.log4j.Logger;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;

public class AuthorDaoImpl extends AbstractDataAccessObject implements AuthorDao
{
  /**
   * The factory class for this DAO has two versions of the create() method - one that
takes no arguments and one that takes a Connection argument. If the Connection version
is chosen then the connection will be stored in this attribute and will be used by all
calls to this DAO, otherwise a new Connection will be allocated for each operation.
   */
  protected java.sql.Connection userConn;

  protected static final Logger logger = Logger.getLogger( AuthorDaoImpl.class );

  /**
   * All finder methods in this class use this SELECT constant to build their queries
   */
  protected final String SQL_SELECT = "SELECT ID, NAME, PASSWORD FROM " + getTableName() + "";

  /**
   * Finder methods will pass this value to the JDBC setMaxRows method
   */
  private int maxRows;

  /**
   * SQL INSERT statement for this table
   */
  protected final String SQL_INSERT = "INSERT INTO " + getTableName() + " ( ID, NAME, PASSWORD ) VALUES ( ?, ?, ? )";

  /**
   * SQL UPDATE statement for this table
   */
  protected final String SQL_UPDATE = "UPDATE " + getTableName() + " SET ID = ?, NAME = ?, PASSWORD = ? WHERE ID = ?";

  /**
   * SQL DELETE statement for this table
   */
  protected final String SQL_DELETE = "DELETE FROM " + getTableName() + " WHERE ID = ?";

  /**
   * Index of column ID
   */
  protected static final int COLUMN_ID = 1;

  /**
   * Index of column NAME
   */
  protected static final int COLUMN_NAME = 2;

  /**
   * Index of column PASSWORD
   */
  protected static final int COLUMN_PASSWORD = 3;

  /**
   * Number of columns
   */
  protected static final int NUMBER_OF_COLUMNS = 3;

  /**
   * Index of primary-key column ID
   */
  protected static final int PK_COLUMN_ID = 1;

  /**
   * Inserts a new row in the AUTHOR table.
   */
  public AuthorPk insert(Author dto) throws AuthorDaoException
  {
    long t1 = System.currentTimeMillis();
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      StringBuffer sql = new StringBuffer();
      sql.append( "INSERT INTO " + getTableName() + " (" );
      int modifiedCount = 0;
      if (dto.isIdModified()) {
        if (modifiedCount > 0) {
          sql.append( ", " );
        }
    
        sql.append( "ID" );
        modifiedCount++;
      }
    
      if (dto.isNameModified()) {
        if (modifiedCount > 0) {
          sql.append( ", " );
        }
    
        sql.append( "NAME" );
        modifiedCount++;
      }
    
      if (dto.isPasswordModified()) {
        if (modifiedCount > 0) {
          sql.append( ", " );
        }
    
        sql.append( "PASSWORD" );
        modifiedCount++;
      }
    
      if (modifiedCount==0) {
        // nothing to insert
        throw new IllegalStateException( "Nothing to insert" );
      }
    
      sql.append( ") VALUES (" );
      for (int i=0; i < modifiedCount; i++ ) {
        if (i>0) {
          sql.append( "," );
        }
    
        sql.append( "?" );
      }
    
      sql.append( ")" );
      stmt = conn.prepareStatement( sql.toString() );
      int index = 1;
      if (dto.isIdModified()) {
        stmt.setInt( index++, dto.getId() );
      }
    
      if (dto.isNameModified()) {
        stmt.setString( index++, dto.getName() );
      }
    
      if (dto.isPasswordModified()) {
        stmt.setString( index++, dto.getPassword() );
      }
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + sql.toString() + " with values: " + dto);
      }
    
      int rows = stmt.executeUpdate();
      long t2 = System.currentTimeMillis();
      if (logger.isDebugEnabled()) {
        logger.debug( rows + " rows affected (" + (t2-t1) + " ms)");
      }
    
      return dto.createPk();
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Updates a single row in the AUTHOR table.
   */
  public void update(AuthorPk pk, Author dto) throws AuthorDaoException
  {
    long t1 = System.currentTimeMillis();
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      StringBuffer sql = new StringBuffer();
      sql.append( "UPDATE " + getTableName() + " SET " );
      boolean modified = false;
      if (dto.isIdModified()) {
        if (modified) {
          sql.append( ", " );
        }
    
        sql.append( "ID=?" );
        modified=true;
      }
    
      if (dto.isNameModified()) {
        if (modified) {
          sql.append( ", " );
        }
    
        sql.append( "NAME=?" );
        modified=true;
      }
    
      if (dto.isPasswordModified()) {
        if (modified) {
          sql.append( ", " );
        }
    
        sql.append( "PASSWORD=?" );
        modified=true;
      }
    
      if (!modified) {
        // nothing to update
        return;
      }
    
      sql.append( " WHERE ID=?" );
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + sql.toString() + " with values: " + dto);
      }
    
      stmt = conn.prepareStatement( sql.toString() );
      int index = 1;
      if (dto.isIdModified()) {
        stmt.setInt( index++, dto.getId() );
      }
    
      if (dto.isNameModified()) {
        stmt.setString( index++, dto.getName() );
      }
    
      if (dto.isPasswordModified()) {
        stmt.setString( index++, dto.getPassword() );
      }
    
      stmt.setInt( index++, pk.getId() );
      int rows = stmt.executeUpdate();
      long t2 = System.currentTimeMillis();
      if (logger.isDebugEnabled()) {
        logger.debug( rows + " rows affected (" + (t2-t1) + " ms)");
      }
    
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Deletes a single row in the AUTHOR table.
   */
  public void delete(AuthorPk pk) throws AuthorDaoException
  {
    long t1 = System.currentTimeMillis();
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + SQL_DELETE + " with PK: " + pk);
      }
    
      stmt = conn.prepareStatement( SQL_DELETE );
      stmt.setInt( 1, pk.getId() );
      int rows = stmt.executeUpdate();
      long t2 = System.currentTimeMillis();
      if (logger.isDebugEnabled()) {
        logger.debug( rows + " rows affected (" + (t2-t1) + " ms)");
      }
    
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Returns the rows from the AUTHOR table that matches the specified primary-key value.
   */
  public Author findByPrimaryKey(AuthorPk pk) throws AuthorDaoException
  {
    return findByPrimaryKey( pk.getId() );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'ID = :id'.
   */
  public Author findByPrimaryKey(int id) throws AuthorDaoException
  {
    Author ret[] = findByDynamicSelect( SQL_SELECT + " WHERE ID = ?", new Object[] { new Integer(id) } );
    return ret.length==0 ? null : ret[0];
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria ''.
   */
  public Author[] findAll() throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " ORDER BY ID", null );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'ID = :id'.
   */
  public Author[] findWhereIdEquals(int id) throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " WHERE ID = ? ORDER BY ID", new Object[] { new Integer(id) } );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'NAME = :name'.
   */
  public Author[] findWhereNameEquals(String name) throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " WHERE NAME = ? ORDER BY NAME", new Object[] { name } );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'PASSWORD = :password'.
   */
  public Author[] findWherePasswordEquals(String password) throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " WHERE PASSWORD = ? ORDER BY PASSWORD", new Object[] { password } );
  }

  /**
   * Method 'AuthorDaoImpl'
   *
   */
  public AuthorDaoImpl()
  {
  }

  /**
   * Method 'AuthorDaoImpl'
   *
   * @param userConn
   */
  public AuthorDaoImpl(final java.sql.Connection userConn)
  {
    this.userConn = userConn;
  }

  /**
   * Sets the value of maxRows
   */
  public void setMaxRows(int maxRows)
  {
    this.maxRows = maxRows;
  }

  /**
   * Gets the value of maxRows
   */
  public int getMaxRows()
  {
    return maxRows;
  }

  /**
   * Method 'getTableName'
   *
   * @return String
   */
  public String getTableName()
  {
    return "AUTHOR";
  }

  /**
   * Fetches a single row from the result set
   */
  protected Author fetchSingleResult(ResultSet rs) throws SQLException
  {
    if (rs.next()) {
      Author dto = new Author();
      populateDto( dto, rs);
      return dto;
    } else {
      return null;
    }
    
  }

  /**
   * Fetches multiple rows from the result set
   */
  protected Author[] fetchMultiResults(ResultSet rs) throws SQLException
  {
    Collection resultList = new ArrayList();
    while (rs.next()) {
      Author dto = new Author();
      populateDto( dto, rs);
      resultList.add( dto );
    }
    
    Author ret[] = new Author[ resultList.size() ];
    resultList.toArray( ret );
    return ret;
  }

  /**
   * Populates a DTO with data from a ResultSet
   */
  protected void populateDto(Author dto, ResultSet rs) throws SQLException
  {
    dto.setId( rs.getInt( COLUMN_ID ) );
    dto.setName( rs.getString( COLUMN_NAME ) );
    dto.setPassword( rs.getString( COLUMN_PASSWORD ) );
  }

  /**
   * Returns all rows from the AUTHOR table that match the specified arbitrary SQL statement
   */
  public Author[] findByDynamicSelect(String sql, Object[] sqlParams) throws AuthorDaoException
  {
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      // construct the SQL statement
      final String SQL = sql;
    
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + SQL);
      }
    
      // prepare statement
      stmt = conn.prepareStatement( SQL );
      stmt.setMaxRows( maxRows );
    
      // bind parameters
      for (int i=0; sqlParams!=null && i < sqlParams.length; i++ ) {
        stmt.setObject( i+1, sqlParams[i] );
      }
    
    
      rs = stmt.executeQuery();
    
      // fetch the results
      return fetchMultiResults(rs);
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(rs);
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Returns all rows from the AUTHOR table that match the specified arbitrary SQL statement
   */
  public Author[] findByDynamicWhere(String sql, Object[] sqlParams) throws AuthorDaoException
  {
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      // construct the SQL statement
      final String SQL = SQL_SELECT + " WHERE " + sql;
    
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + SQL);
      }
    
      // prepare statement
      stmt = conn.prepareStatement( SQL );
      stmt.setMaxRows( maxRows );
    
      // bind parameters
      for (int i=0; sqlParams!=null && i < sqlParams.length; i++ ) {
        stmt.setObject( i+1, sqlParams[i] );
      }
    
    
      rs = stmt.executeQuery();
    
      // fetch the results
      return fetchMultiResults(rs);
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(rs);
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

}


To me, this is reams of boilerplate code with hardly any abstraction for the common SQL operations. Have a look at the method Author[] findByDynamicSelect(...), which gets duplicated for every DAO you generate. Apart from the return type and the exception class, everything is identical across all DAOs! This, I think, is a design smell. As Andy has mentioned in his blog, Code Generators don’t mind writing repetitive code, but all these repetitive stuff goes to swell the bottomline of my application. I have been working on a financials project which has 600 database tables - the amount of boilerplate code that will be generated with the above approach will be enough to stretch the existing jar size by at least 30%. I simply could not afford the decision.

Bye Bye Code Generators - Enter OO

In my earlier post, I had discussed about how generic DAOs have helped us shrinkwrap the core data access functionalities into generic base abstractions - every specific DAO implementation only contains the details of that particular database table. Have a look at the following code generated for a table Employee using our code generator and OO framework concoction :


package com.anshinsoft.pi.dao.app.dao;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;

import com.anshinsoft.pi.core.StringBufferSize;
import com.anshinsoft.pi.dao.DAOBase;
import com.anshinsoft.pi.dao.DAOImplBase;
import com.anshinsoft.pi.dao.DTOBase;
import com.anshinsoft.pi.pix.orm.DbUtils;
import com.anshinsoft.pi.pix.orm.ICriteria;
import com.anshinsoft.pi.pix.orm.NullCriteria;
import com.anshinsoft.pi.pix.orm.SimpleCriteria;


/**
 * The DAO implementation for {@link Employee} class.
 *


 *
 */
public class EmployeeDAO
    extends DAOBase {


  /**
   * Enum for column names.
   */
  public enum ColumnNames {

    PK,
    ID,
    NAME,
    BIRTH_DATE,
    JOINING_DATE,
    DESIGNATION,
    ADDRESS_PK,
    PASSPORT_NO,
    EXPERTISE;

    /**
     * Constructor.
     */
    ColumnNames() {
    }
  }


  /**
   * Constructor.
   *
   * @param impl the concrete implementation of {@link DAOImplBase}
   */
  public EmployeeDAO(DAOImplBase impl) {
    super(impl);
  }

  /**
   * Returns a list of the column names.
   * @return list of column names.
   */
  protected List getColumnNames() {
    ColumnNames[] names = ColumnNames.values();
    List l = new ArrayList(names.length);
    for (ColumnNames name : names) {
      l.add(name.name());
    }
    return l;
  }


  /**
   * Subclasses must override and provide the TABLE_NAME
   * that the bean is associated with.
   *
   * @return the table name.
   */
  public String getTableName() {
    return "EMPLOYEE";
  }


  /**
   * {@inheritDoc}.
   */
  protected ICriteria getPrimaryKeyWhereClause(T employee) {
    try {
      String str =
      BeanUtils.getProperty(employee,
        DbUtils.dbColumn2PropertyName(
        ColumnNames.PK.name()));
      return new SimpleCriteria(
        new StringBuilder(StringBufferSize.SMALL.size())
        .append(ColumnNames.PK.name())
        .append(" = ")
        .append(str).toString());
    } catch (Exception ex) {
      return NullCriteria.getInstance();
    }
  }
}



All mundane SQL operations are wrapped inside DAOBase<T>, all base level functionalities of transfer objects are encapsulated within DTOBase. In case the user wants to add additional behavior to the transfer objects, he can extend one out of DTOBase :

class MyDTOBase extends DTOBase {
// added behavior
}

And this way they can add global behaviors like state management functionalities to all DTOs that they use.

Monday, April 24, 2006

Scala Hosts a Friendly Visitor

GOF tells us that the intent of the Visitor design pattern is to
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

The focus is on defining new operations, and not on allowing a flexible hierarchy of the elements themselves. In fact, the Consequences section of the Visitor pattern mentions that Visitor makes adding new operations easy and Adding new ConcreteElement classes is hard, since adding every new ConcreteElement forces a change in the Visitor interface and hence in all Visitor implementations. Thus the vanilla Visitor implementation in today's mostly used object oriented languages like Java and C++ violates the Open Closed Principle.

What's special in Scala ?

Scala offers three features which enable a Visitor implementation to have piecemeal growth. Both the visitor and the visited hierarchy can be enhanced incrementally resulting in flexible inheritance hierarchies for both of them.

The nuances of the Visitor implementation in Scala is part of the more general Expression Problem, which has been dscribed in the Scala context by Zenger and Odersky.

Let us review the above claim using an example. The following snippet illustrates a sample combination of the Visited and Visitor hierarchy. Here we have only one level of specialization for the Visited and the Visitor abstractions, along with the base contracts for each of them.

trait Base {

  trait Node { // Element base of the hierarchy
    def accept(v: visitor): unit;
  }

  // ConcreteElement specialization
  class File(name: String) extends Node {
    def accept(v: visitor): unit = v.visitFile(name);
  }

  type visitor <: Visitor;
  trait Visitor { // Visitor base of the hierarchy
    def visitFile(name: String): unit;
  }

  // ConcreteVisitor specialization
  trait PrintingVisitor requires visitor extends Visitor {
    def visitFile(name: String): unit =
    Console.println("printing file: " + name);
  }
}

Figure 1 - The Base

Let us see how the above implementation differs from the standard Java Visitor boilerplate. The main problem with the Java/C++ implementation is the fact that the visitor interface has to change with the addition of a ConcreteElement (the visited). This is where we violate the Open Closed Principle - we need to make invasive changes at the contract level, which forces a recursive change down the inheritance hierarchy for all concrete visitor implementations. The Scala implementation above addresses this problem by allowing us to abstract over the concrete visitor type. In order to keep the set of Visited classes open, the Abstract Type visitor is used. Every concrete implementation of Visitor interface such as PrintingVisitor above, implements its bound Visitor. And every Visited element uses the same abstract type visitor for the accept() methods. It is this magic combination of abstract type and mixin composition which allows us to enrich the dual hierarchies incrementally.

In the following sections we will look at how the Scala implementation allows a seamless adding of concrete members to the Visited as well as Visitor hierarchies.


Adding a ConcreteElement (the Visited hierarchy)

// data extension : add Link
trait BaseLink extends Base {

  type visitor <: Visitor;

  trait Visitor extends super.Visitor {
    def visitLink(subject: Node): unit;
  }

  class Link(subject: Node) extends Node {
    def accept(v: visitor): unit = v.visitLink(subject);
  }

  trait PrintingVisitor requires visitor
      extends super.PrintingVisitor
      with Visitor {
    def visitLink(subject: Node): unit =
      subject.accept(this);
  }
}

Figure 2 - Adding a ConcreteElement

Override the abstract type visitor with the extended Visitor trait and include the new visitLink() method - completely non-invasive, yet extensible! The concrete implementation of the new PrintingVisitor extends the trait from the superclass and compose with the extended Visitor trait using Scala mixin composition.

In the above, we claimed that the abstract type visitor allows us to abstract over the concrete visitor types. In the above method visitLink() of PrintingVisitor, the call to accept() has the argument this. But the type PrintingVisitor is not a subtype of the abstract visitor type visitor. The above implementation handles this by the statement requires visitor in the definition of the trait PrintingVisitor. This is called Self Type Annotation, which provides an alternative way of associating a class with an abstract type. The self type specified above is taken as the type of this within the class. Without this feature, the type of this is the usual type of the class itself. In the above implementation, the usage of the self type annotation ensures that the type of this, specified in the argument of accept() is of the abstract type visitor as demanded by the declaration of the Node trait.

Combining Independent Element Extensions

Similar to BaseLink extension above, we can have similar independent extensions in the Visited hierarchy. e.g. we can have a BaseDirectory trait which extends Base with Directory as another Node. I do not go into the details of this implementation, but it will be exactly along the same lines as BaseLink. The important part is the ability to combine independent Element extensions through composition. Scala's powerful modular mixin composition is the answer to all these as the following example demonstrates:

// compose all
trait BaseAll extends BaseDirectory with BaseLink {

  type visitor <: Visitor;
  trait Visitor extends super[BaseDirectory].Visitor
      with super[BaseLink].Visitor;

  trait PrintingVisitor requires visitor
      extends super[BaseDirectory].PrintingVisitor
      with super[BaseLink].PrintingVisitor
      with Visitor;
}

Figure 3 - Composing all Extensions

The abstraction above combines the two independent extensions through mixin composition. In case of such mixin composition, the Scala type system requires that abstract types have to be refined covariantly. Hence BaseAll has to redefine the bounds of the the abstract type visitor through explicit overriding, such that the bound of the new visitor is a subtype of both old bounds.

This is not all - we will see how adding new visitors in the hierarchy combines with the extensibility of the BaseAll trait, resulting in a complete implementation of the Visitor Design Pattern.


Adding a New Visitor to the Hierarchy

Adding new visitors is easy, as the pattern claims - every new operation added simply adds up to the Visitor hierarchy, implementing all the visitor interfaces.

// function extension
trait BaseExt extends BaseAll {
  class RemoveVisitor requires visitor extends Visitor {
    def visitFile(name: String): unit =
    Console.println("removing file: " + name);

  def visitDirectory(name: String): unit =
    Console.println("cannot remove directory: " + name);

  def visitLink(subject: Node): unit =
    subject.accept(this);
  }
}

Figure 4 - Extending the Visitor Interface


Compose Them All - The Grand Visitor

We now have the grand Visitor in place where we can add to Visited and Visitor hierarchies seamlessly ensuring piecemeal growth. The abstractions are open for extension but closed for invasive changes.

Here goes the final usage ..

object VisitorTest extends BaseExt with Application {
  type visitor = Visitor;

  val f = new File("foo.txt");
  val nodes = List(
    f,
    new Directory("bar"),
    new Link(f)
  );

  class PrintingVisitor extends super.PrintingVisitor;
  nodes.elements foreach { x => x.accept(new PrintingVisitor()); }

  class RemoveVisitor extends super.RemoveVisitor;
  nodes.elements foreach { x => x.accept(new RemoveVisitor()); }
}

Friday, April 21, 2006

Project Geometry

How do you ensure that the current Java project that you have been working on uses the correct exception hierarchy for the DAOs ? How do you identify the stamp of your organization when you look at the SVN check outs of a project ? How do you prevent reinventing the wheels of the maven script when you plan the build architecture of the project that you are supposed to manage ?

The answer to all of the above is to have a uniform Project Geometry for your organization. When I talk about the geometry, I mean only the software aspect of the project, the code that gets churned out by the software development team, the documentation artifacts that get generated in the process and the machinery that builds the code and deploys the binary to the desired target platform. The geometry ensures a uniformity not only in the look and feel of the project (the directory hierarchy, package structure, archetypes, build engine etc.), but also the innards of implementation which include the whole gamut from the design of the exception hierarchy down to the details of how the application interfaces with the external services layer. The following rumblings are some of my thoughts on what I mean when I talk about Project Geometry.

Software Reuse

In the article Four Dynamics for Bringing Use Back Into Software Reuse published in the Communications of the ACM, January 2006, Kevin C Desouza, Yukika Awazu and Amrit Tiwana identify three salient dynamics associated with the knowledge consumption lifecycle of a project - reuse, redesign and recode. They define
Reuse is the application of existing software artifacts as is; redesign is the act of altering existing software artifacts; and recoding is the discovery of new software artifacts through construction of software code or system designs.

In each of the above dynamics, there is an implicit assumption of pre-existence of software artifacts which finds place in the current lifecycle through a discovery process - either as-is or in a derived manifestation.

The question is : where from do we get these artifacts that can be reused ?

The Project Container

Every modern day IT organization who delivers software can have a Project Container, a meta-project which helps individual project teams to incubate new projects. The project container evangelizes the best practices for development, deployment and documentation and provides plug-ins and archetypes to kick-start a new project for the organization.

It should be as simple as 1-2-3 .. Let us consider a case study ..

For my organization, the build platform of choice for a Java based project is maven 2 and I should be able to generate a standard project skeleton structure from an archetype which is part of my project container. Here they go ..

  1. Download plugin for bootstrap from the project container repository

  2. Run maven install (mvn install ...)

  3. Setup project home

  4. Create archetype (mvn archetype:create -D... ...)


Boom .. we go .. my entire project hierarchy skeleton is ready with the corporate standard directory hierarchy, package naming conventions, documentation folders and (most importantly) a skeleton Project Object Model (POM) for my project. When I open up my IDE, I can find my prject already installed in the workspace! I can straightway start adding external dependencies to the pom.xml. Maven has really done wonders to the project engineering aspect through its concepts of archetypes, plugins and POMs. I can start defining my own project specific package hierarchy and write my own business logic.

My Project Structure

Any Java based project bootstrapped using the above project container of my organization bears the stamp of its identity. With its families of plug-ins and artifacts, the project container ensures a uniform geometry of all projects delivered from this place. It's really geometry in action - promoting reuse and uniformity of structure, thereby making life easier for all team members joining the project later in the lifecycle. Joel Spolsky talks about the Development Abstraction Layer as an illusion created by the management with its associated services which makes the programmer feel that a software company can be run only by writing code. In this context, the project container takes care of the engineering aspects of the project environment and presents to the programmer a feeling that the software that he delivers is only about writing the business logic. The other machineries like coding conventions (comes integrated with the IDE through container based checkstyles), build engine (again comes with the incubation process), documentation (maven based, comes free with the project container) and project portal (maven generated with container based customization) gets plugged in automatically as part of the bootstrapping process. The best thing is that the process is repeatable - every project based on a specific platform gets bootstrapped the same way with the same conventions replicated, resulting in a uniform project geometry.

Is This All ?

Actually project geometry is extensible to the limits you take it to. I can consider a standard infrastructure layer to be part of my project container for Java based projects. The exception hierarchy, standard utilities, a generic database layer, a generic messaging layer can all be part of the container.

But, what if I don't need'em all ?

You pay only for what you take. The project container repository gives you all options that it has to provide - pick and choose only the ones you need and set up dependencies in your POM. Remember, Maven 2 can handle transitive dependencies, one feature that we all have been crying for months.

The Sky is the Limit!

Taking it to the extremes - the project container can offer you options of implementation of some features if you base your code based on the container's contracts. This implies that the project container is not a mere engineering vehicle - it acts as a framework as well. Suppose in your Java application you need to have an Application Context for obvious reasons. You can design your application's context based upon the contracts exposed by your project container. And you can choose to select one of the many possible implementations during deployment - you can choose to use Spring's IoC container based context implementation or you can select the vanilla flat namespace based default implementation provided by the container itself. Whatever you do, you always honor the basic guideline, that of discovering from the project container and making it suitable for your use, and in the process maintaining the uniform geometry within your project.

Friday, April 14, 2006

Functional Programming for the Masses - Are We Ready For It ?

I have been talking a lot about Scala of late. Scala is a multiparadigm language offering both OO and functional programming features. This post is not about Scala though. It is about the latest trend in modern language design - the return of the functional programming in the mainstream. We have Ruby, Python, Scala all of them enriched with higher order functions, type inference, initializers, lambdas, meta-programming with expression trees and many other features which have their roots in functional programming languages like Lisp and Haskell.

But guess who is the leader ? The big daddy, of course. Microsoft has unleashed the LINQ framework which will be supported by upcoming versions of C# 3.0 and Visual Basic 9. Erik Meijer has hit it right on the nail in LtU - Functional Programming Has Reached The Masses - It's Called Visual Basic. In his confessions, Erik notes
After a long journey through theoretical computer science, database theory, functional programming, and scripting, abstract concepts such a monoids, lambda-expression, and comprehensions have finally reached the day to day world of ordinary programmers. The LINQ framework effectively introduces monad comprehensions into the upcoming versions of C# 3.0 and Visual Basic 9.


LINQ defines query operators for declarative traversal, filter, projection operations over abstract collections (based on IEnumerable<T>). The query interface extends seamlessly over both XML and SQL data as this overview document from Microsoft states
The query operators over XML (XLinq) use an efficient, easy-to-use in-memory XML facility to provide XPath/XQuery functionality in the host programming language. The query operators over relational data (DLinq) build on the integration of SQL-based schema definitions into the CLR type system. This integration provides strong typing over relational data while retaining the expressive power of the relational model and the performance of query evaluation directly in the underlying store.


In today's application development environment, we use Relational databases for persistence, Objects for implementing business logic and XML in the presentation tier - the infamous ROX triangle of Erik. By offering all of the three paradigms within the same framework, LINQ promises to unify all the three data models for the application developer. Under the hood its all monads and comprehensions, however, the application programmer uses his favourite SQL like syntax

Dim expr As IEnumerable(Of String) = _
    Select s.ToUpper() _
    From s in names _
    Where s.Length = 5 _
    Order By s


Along with .NET providing seamless functional programming capabilities uniformly over C# 3.0 and Visual Basic 9, modern languages like Ruby, Python and Scala also have lots to offer in the game. Programmers at large are getting to see the daylight of the elegance of functional programming through the monads, closures, meta programming and comprehensions. Despite the fact that each of these have been around for years, locked up in the functional programming community and discussed by a handful in LtU, they are expected to be part of mainstream programming very shortly. The question, however, is that, is the programming community ready for this ? In one of my earlier posts, I had expressed the concern over the lack of knowledge on the basic principles of functional languages like recursion, higher order functions, function currying, closures amongst the myriads of programmers coming out of CS schools. I think it's time the grad schools shell themselves out of their Java clothing and go back to the first principles that SICP has preached for ages.

Wednesday, April 12, 2006

Generics in Scala - Part 1

How big should a programming language be ? Well, that depends on what you would like to do with it. Common Lisp started out as a small elegant functional language, but with the proliferation of multiple dialects, the addition of object-oriented components (CLOS), generalized iteration construct (LOOP), full blown condition system etc., the current ANSI Common Lisp's specification is about 1,300 pages long and has 1,000 defined symbols [source: Patterns of Software - Gabriel].

Scala is a rich language targetted towards component based development - it offers a fusion of object oriented as well as the functional paradigms. The advanced type system of Scala backed by rich features like type inferencing and type annotations place Scala far ahead of its contemporaries. Scala's support of generics is the most advanced amongst all modern languages - it is possibly the only modern language that supports both parameterized types (originating from functional languages) and virtual types (from the OO paradigm).

Scala Parameterized Types Implemented through Erasure

This is similar to Java implementation where the generic type info gets erased after program compilation. Some efforts are on amongst the Scala designers towards reification of generics in Scala and have added an experimental support for interoperability with Java generics since Scala 2. Here is a simple example of a generic class in Scala :

object GenericsTest extends Application {

  abstract class Sum[t] {
    def add(x: t, y: t): t;
  }

  object intSum extends Sum[Int] {
    def add(x: Int, y: Int): Int = x + y;
  }

  class ListSum[a] extends Sum[List[a]] {
    def add(x : List[a], y : List[a]) : List[a] = x ::: y;
  }

  val s = new ListSum().add(List("a", "b"), List("c", "d"));
  val t = new ListSum().add(List(1, 2), List(3, 4));
  Console.println(s);
  Console.println(t);
}


Scala Parameterized Types Allow Variance Annotations

There is a strong relation between parameterized types and (co|contra|in)variance in type declarations / expressions. Java class declarations do not support any covariance annotations - List<Derived> is never a subtype of List<Base> in Java, even though Derived is a subtype of Base. However, Java allows covariance of generic types to be expressed by annotating every occurrence of List type to match the form List<? extends Base>. This implements a form of family polymorphism within all List types where the type argument is an arbitrary subtype of Base.

Scala allows variance annotations at class declaration (unlike Java). Consider the following declaration of an immutable Stack (adopted from Scala By Example) :

abstract class Stack[+a] {
  def push[b >: a](x: b): Stack[b] = new NonEmptyStack(x, this)
  def isEmpty: boolean
  def top: a
  def pop: Stack[a]
}

object EmptyStack extends Stack[Nothing] {
  def isEmpty = true
  def top = throw new Error("EmptyStack.top")
  def pop = throw new Error("EmptyStack.pop")
}

class NonEmptyStack[+a](elem: a, rest: Stack[a]) extends Stack[a] {
  def isEmpty = false
  def top = elem
  def pop = rest
}


The + in type argument for the class definition indicates that subtyping is covariant on that type parameter. A - in the same place changes the relationship to contravariance. The default (without any prefix) declaration indicates invariance of subtyping.

Along with variance annotations at class declarations, Scala's type checker verifies its soundness as well. Though safe for immutable data types, covariant subtyping is never safe for mutable data types, and the typechecker is quick to disallow such unsafe declarations. e.g. in the following declaration of a mutable Stack

class Stack[+T] {
  var elems: List[T] = Nil
  def push(x: T): Unit = elems = x :: elems
  def top: T = elems.head
  def pop: Unit = elems = elems.tail
}

The covariant argument for push() appears in a contravariant position - the Scala compiler will flag this as an error. Compare this approach with Java's covariant subtyping for arrays where we need to depend on runtime checks to ensure type safety of the underlying structure.

The question is how do we avoid a similar situation of push() method in the immutable version of the Stack definition. Immutable data structures are always candidates for covariant subtyping and Scala achieves this through specification of lower bounds for type parameters. Observe the contract def push[b >: a](x: b): Stack[b] in the functional version of the Stack definition above. In this contract the type parameter a does not appear in the contra variant position (parameter type of push()). The type parameter has been moved as a lower bound for another type parameter of a method, which is a covariant position. This lower bound of the type parameter makes it completely typesafe to implement covariant subtyping.


Subtyping with Generic Types - Scala, Java and C#

As I mentioned above, Scala supports covariant typing using annotations at class declaration, as opposed to Java, which allows annotations at type expressions. Thus Scala restricts annotations to the class designer, while Java leaves it to the users. The Scala designers found it difficult for users to maintain consistency of usage-site annotations as Odersky observes in his OOPSLA 05 paper on abstractions
In an earlier version of Scala we also experimented with usage-site variance annotations similar to wildcards. At first-sight, this scheme is attractive because of its extensibility. A single class might have covariant as well as non-variant fragments; the user chooses between the two by placing or omitting wildcards. However, this increased extensibility comes at price, since it is now the user of a class instead of its designer who has to make sure that variance annotations are used consistently.


However, Java implementation of generics achieves flexibility in typing through use of wildcards along with type-capture technique as detailed out in this wonderful exposition by Torgerson et. al. This paper is a strong justification of adding wildcard support in generics implementation and discusses all related issues of subtyping in the object oriented environment. Wild cards have added flexibility in Java typing in the sense that the user can now declare the same List class as covariant (List<? extends Number>) or contravariant (List<? super Number>). The other player to this game, Microsoft .NET does not use erasure and does not support wild cards in generics implementation - instead they have chosen to make the runtime support the implementation. Designers of C# do not consider subtyping to be an issue with generic types and do not feel wild card support an important offering. In his weblog Puzzling through Erasure II, Eric Gunnerson mentions that it is more important to be able to have generics over value types and performant implementations than to support wildcards.

In this entry I have discussed only one aspect of Scala's generics implementation - the parameterized types. In the next post, I will discuss the OO of generics - The Abstract Member Type which implements virtual types in Scala.

Friday, April 07, 2006

Java Persistence - Fun with Generic DAOs

Handling Java persistence through DAOs have really picked up, particularly among small to mid-sized application development space, who cannot afford to have a full fledged ORM implementation. In my last post on the subject of Java persistence, I projected ORM and DAO as cooperating technologies (rather the competing ones) and suggested that mid sized applications should use both to ensure proper layering and separation of concerns.

Firestorm/DAO from CodeFutures is one of the very popular products in the market today that generates all DAOs and POJOs once you feed in your schema for the database. The code generator from Firestorm/DAO generates one DAO interface and one implementation class for each database table along with separate classes for the DTOs, factories and the exceptions. Looking at the generated code, I somehow have the feeling that they could have been better engineered through employing a higher level of abstraction. For every DAO, the basic functionalities provided are the same; e.g. findByPrimaryKey() locates a record from the table using the passed in primary key; findAll() fetches all records from the table - yet we do not find any base class abstracting the commonality of SQL processing!

In the meantime, I have been doing some work outs on generic DAOs, with the idea of making the generated code more compact and better engineered without sacrificing an iota of typesafety. My last posting on this subject has some information on what I thought could be the base of my design - a Bridge based implementation of generic DAOs -

  • the interface hierarchy providing the contracts to be extended by application DAOs

  • the implementation hierarchy, providing options to implement the DAOs using different engines like JDBC, Hibernate etc.


Here's a sample usage for a table Employee for executing a query with a dynamic criterion :

// make the DAO
EmployeeDAO<Employee> e =
    DAOFactory.getInstance().getEmployeeDAO();

// make the criteria
ICriteria cri = new SimpleCriteria("employee_id = 10");

// get 'em
List<Employee> es = e.read(cri, Employee.class);


Note that in the above snippet, EmployeeDAO is a generic class and takes a POJO as the actual parameter of instantiation. EmployeeDAO has been generated as :

public class EmployeeDAO<T extends DTOBase> extends DAOBase<T> {
    ....
}


An alternative could have been to have the EmployeeDAO as a concrete class with the POJO Employee hardwired :

public class EmployeeDAO extends DAOBase<Employee> {
    ....
}


Well, it really depends upon how much flexibility you would want to give to your users. With the former approach, the user is allowed to construct the EmployeeDAO with any other POJO, so long the POJO contains the properties that match the database column names. This is often useful when the user wants to work with database views in the application, which has different backing POJOs than the ones associated with the main tables.

The abstraction DTOBase provides a suitable container for dumping all stuff common to all DTOs, e.g. bean state management functionalities (whether it has been changed since its last fetch from database) are very powerful candidates for this placeholder. Incidentally these functionalities are scattered throughout all POJOs in Firestorm/DAO generated codes.


Projection on a Table is also a DAO!

With the above code snippet for query, we can read entire records from the Employee table to the List<Employee>. Now what about projections - I want to select a few columns of the table into my POJO. The point to note is that the end result of a Projection is no different than the above read(), except the fact that we now have a smaller list of columns to deal with. It's no different from an operation on a DAO, which transforms the end result to contain a subset of the column list.

Think Decorator! Decorate a DAO to get the Projection :

public class Projection<T extends DTOBase> extends DAOBase<T> {
    private DAOBase<T> base;
    ...
}


And now the usage :

// set up the Projection
Projection<Employee> ep =
  DAOFactory.getInstance()
    .getEmployeeProjection()
    .setColumn(EmployeeDAO.ColumnNames.EMPLOYEE_ID)
    .setColumn(EmployeeDAO.ColumnNames.EMPLOYEE_NAME);

// get 'em
List<Employee> es = ep.read(cri, Employee.class);


Cool stuff ! We have the encapsulation of the SQL married to the typesafety of operations. The user does not have to write SQL statements or use hardcoded column names that can be checked only during runtime. That was the promise of the DAO Design Pattern - right ?


How about Joins ?

Joins are nothing but compositions of multiple tables based on primary key / foreign relationship. The result of a Join is also a DAO!

public class Join<T extends DTOBase> extends DAOBase<R> {
  public Join<T> addJoinParticipant(DAOBase<? extends DTOBase> dao){
  ...
  }
}


Compose as you Wish

// make the DAO
EmployeeDAO<Employee> e =
DAOFactory.getInstance().getEmployeeDAO();

// make the DAO
EmpSalaryDAO<EmpSalary> s =
DAOFactory.getInstance().getEmpSalaryDAO();

// make the criteria
ICriteria cri = new SimpleCriteria(
new StringBuilder(128)
    .append(EmployeeDAO.ColumnNames.EMPLOYEE_ID.name())
    .append(" = 10").toString());

Join<EmpSalaryDetails> d =
    DAOFactory.getInstance()
      .getEmpSalaryDetailsDAO()
        .addJoinParticipant(e)
        .addJoinParticipant(s)
        .addLeftColumn(EmployeeDAO.ColumnNames.EMPLOYEE_ID)
        .addRightColumn(EmpSalaryDAO.ColumnNames.EMPLOYEE_ID);

Projection<EmpSalaryDetails> esd =
    new Projection<EmpSalaryDetails>(
        new DAOJDBCImpl<EmpSalaryDetails>(),
        d);

// get 'em
List<EmpSalaryDetails> es = esd.read(cri, EmpSalaryDetails.class);

Thursday, April 06, 2006

Conquest of the Arithmetic Progression

May June issue of The American Scientist contains an essay by Brian Hayes, where he takes us through a number of anecdotes and references describing all variations of the popular story of Carl Friedrich Gauss conquering the world of arithmetic progression as a little school kid. The essay begins with Brian's own version of the story
In the 1780s a provincial German schoolmaster gave his class the tedious assignment of summing the first 100 integers. The teacher's aim was to keep the kids quiet for half an hour, but one young pupil almost immediately produced an answer: 1 + 2 + 3 + ... + 98 + 99 + 100 = 5,050. The smart aleck was Carl Friedrich Gauss, who would go on to join the short list of candidates for greatest mathematician ever. Gauss was not a calculating prodigy who added up all those numbers in his head. He had a deeper insight: If you "fold" the series of numbers in the middle and add them in pairs—1 + 100, 2 + 99, 3 + 98, and so on—all the pairs sum to 101. There are 50 such pairs, and so the grand total is simply 50×101. The more general formula, for a list of consecutive numbers from 1 through n, is n(n + 1)/2.


And then he digs deep into the research that he did to collect all versions of the famous anecdote. A fascinating read ..