Thursday, June 22, 2006

JPA and caveats

Patrick Lindksey is giving his talk "The good bad and the ugly" related to EJB 3.0 persistence. Interesting to get a more detailed picture of the JPA specification. I really find it more interesting today compared to last year. One of the reasons is that we have more or less nothing else but runtime dependencies and some wrapper code around a generic repository implementation in my current project. This may make it feasible to actually swich persistence providers as long as we have several good open source ones available already. The only thing that will require some work is getting rid of the implementations we have related to searching that uses the Hibernate Criteria API. Maybe JQL will do the job? I don't know I have never been using this part of the API.

One thing Patrick went into depths explaining related to POJO based persistence is really interesting. It really hides some subtleties related to designing API's and access to fields and properties. This applies to most mapping frameworks including Hibernate and is relevant when it comes to discussing domain models and where to put the actual business logic.

Consider the following code fragment representing the setter for the age property in the Customer class:

public void setAge(int age) {
    if (age < 18) {
       throw new JuvenileException("We dont accept young customers");
    }
    this.age = age;
}



This might seem like a business rule to implement in the Customer class, why? Because principles of cohesion should be the rule and the business logic should for reasons of clarity be placed in the Customer class implementation. But what if this is a new Rule that did not previously exist? You have provided this rule such that the API will prevent you from entering Illegal data. But that also means that the persistence framework that will use the setter for populating objects from a search will get the same ,exception as a side effect on data that was valid last year. Hence using setters as a mechanism for managing state in persistent entities is dead wrong. It is a good way to enforce integrity for new (transient entities) but not for dealing with persistence lifecycle. After all APIS and business rules tend to evolve, but historic data tends to stay the same!
The Irony is that you will probably be pretty happy with the first release of the system but after the system is going into maintenance errors will start coming in after the first upgrade. Consultants will probably not even notice, they are on the way implementing setX and setY with heaps of business logic in new domain objects for new customers and by habit use property (instead of field) based access in entities :-)

No comments: