Making the most of code  
Author Message
jstorta





PostPosted: 2008-5-28 5:10:00 Top

java-programmer, Making the most of code I have a web site that uses JSP and some back end classes to manage
data in a MySQL database. It does okay and has run well for about 3
years. It has, however, grown to the point where I need to redesign
some of it to be more dynamic. I've recently started incorporating
Hibernate and JavaServer Faces to ease the development now and make it
easier for me to make changes later on. Or at least that was my plan.

Each database table maps to a Java class. I will easily have 25-30
tables before I am done. I am okay with 25-30 classes to represent
the data, but my concern is when it comes to the associated classes
needed to manage the data connections and such. I find that I am
cutting and pasting way too much similar code into these separate
classes.

For example.
I have a HibernateDAO class that manages the Hibernate session.

Each class then has its own DAO class that extends the HibernateDAO
class and the code within the extended DAO classes is virtually
identical.

Here is one method from my clientDAO class.
public Client add( Client client) {
try {
begin();
getSession().save(client);
commit();
return get(client.getClientId()); //not every class
will have a clientId member
} catch (HibernateException e) {
rollback();
System.out.println( "Could not add client: " +
client.getClientId() + " : " + e); //message hard coded for client
class
return new Client();
}
}


And then in my ContactDAO class I have this.
public Contact add(Contact contact) {
try {
begin();
getSession().save(contact);
commit();
return get(contact.getId()); //not every class will have
an Id member
} catch (HibernateException e) {
rollback();
System.out.println( "Could not add contact: " +
contact.getId() + " : " + e); //Message hard-coded for contact class
return new Contact();
}
}


Note that the code is virtually identical.

The begin(), getSession(), rollback(), and commit() methods are all
from the HibernateDAO superclass.

I tried using Generics to make the return type and parameter <T>, but
this only gets me so far. I cannot declare a new instance of <T>, or
at least I don't know how to. And the method uses values that are
specific to the class in question. I.E. not every data class will
have a getId() method.

I am not sure if any of that made sense, but the crux of the issue is
I am trying to avoid cutting and pasting code and then having to
remember to update it in 25 different places when I make a change. I
feel like there is a way to do what I want, but I just don't have the
experience to see it.

If anyone can point me toward some documentation that might help set
me straight, I would appreciate it.

Thanks.
 
Roedy Green





PostPosted: 2008-5-28 5:21:00 Top

java-programmer >> Making the most of code On Tue, 27 May 2008 14:10:10 -0700 (PDT), jstorta <email***@***.com>
wrote, quoted or indirectly quoted someone who said :

>
>Note that the code is virtually identical.
>
>The begin(), getSession(), rollback(), and commit() methods are all
>from the HibernateDAO superclass.

A technique you might consider is the Stomper.

You write a Java method that takes N parameters and stomps out Java
source code. It can be considerably cleverer than a traditional macro.
Your code can do checks, computation, variable expansions etc.

You might find Quoter helpful to turn the basic code skeletion into a
giant set of Java strings.

You can also write stompers than do regex searches or indexOf searches
to do fancy search-replace-insert-delete on finished code. You embed
magic comments to make it simpler. I use one like this to change the
picture and text in http://mindprod.com/jgloss/index.html
and http://mindprod.com/jgloss/artcom.html
each day.


You periodically rerun your stompers when you find a better way to
expand the code.

http://mindprod.com/applet/quoter.html

use the "to Java String literal" option.


--

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
Mark Space





PostPosted: 2008-5-28 6:14:00 Top

java-programmer >> Making the most of code jstorta wrote:

> Here is one method from my clientDAO class.
> public Client add( Client client) {
> try {
> begin();
> getSession().save(client);
> commit();
> return get(client.getClientId()); //not every class

I'm not using your packages (Hibernate, etc.) so I really can't talk
about best practice, but the first thing that occurs to me is to push
the work of saving onto the object being saved.

So if Client and Contact both have some interface "SessionSavable" with
a save() method which takes a session as a parameter,

public Object add( SessionSavable s ) {
try {
begin();
s.save( getSession() );
commit();
//....

Then in Client

@Override
public void save( Session x ) {
x.save( this );
}

and the same in Contact. You'd have to do the return method the same
way. Have both Client and Contact implement a method which returns
Object, but really returns the specific class/ID that is needed for that
type of object.

This could muck up your Client and Contact classes a little, but maybe
the decrease in boilerplate would be worth it.


Alternately, if session is just a Map or something, you could just save
all your objects as some base class, e.g., Object or something else you
create. You'd still need return method to over ride, so I think Object
may not be the best choice here.
 
 
Abhijat Vatsyayan





PostPosted: 2008-5-28 11:21:00 Top

java-programmer >> Making the most of code jstorta wrote:
> I have a web site that uses JSP and some back end classes to manage
> data in a MySQL database. It does okay and has run well for about 3
> years. It has, however, grown to the point where I need to redesign
> some of it to be more dynamic. I've recently started incorporating
> Hibernate and JavaServer Faces to ease the development now and make it
> easier for me to make changes later on. Or at least that was my plan.
>
> Each database table maps to a Java class. I will easily have 25-30
> tables before I am done. I am okay with 25-30 classes to represent
> the data, but my concern is when it comes to the associated classes
> needed to manage the data connections and such. I find that I am
> cutting and pasting way too much similar code into these separate
> classes.
>
> For example.
> I have a HibernateDAO class that manages the Hibernate session.
>
> Each class then has its own DAO class that extends the HibernateDAO
> class and the code within the extended DAO classes is virtually
> identical.
>
> Here is one method from my clientDAO class.
> public Client add( Client client) {
> try {
> begin();
> getSession().save(client);
> commit();
> return get(client.getClientId()); //not every class
> will have a clientId member
> } catch (HibernateException e) {
> rollback();
> System.out.println( "Could not add client: " +
> client.getClientId() + " : " + e); //message hard coded for client
> class
> return new Client();
> }
> }
>
>
> And then in my ContactDAO class I have this.
> public Contact add(Contact contact) {
> try {
> begin();
> getSession().save(contact);
> commit();
> return get(contact.getId()); //not every class will have
> an Id member
> } catch (HibernateException e) {
> rollback();
> System.out.println( "Could not add contact: " +
> contact.getId() + " : " + e); //Message hard-coded for contact class
> return new Contact();
> }
> }
>
>
> Note that the code is virtually identical.
>
> The begin(), getSession(), rollback(), and commit() methods are all
> from the HibernateDAO superclass.
>
> I tried using Generics to make the return type and parameter <T>, but
> this only gets me so far. I cannot declare a new instance of <T>, or
> at least I don't know how to. And the method uses values that are
> specific to the class in question. I.E. not every data class will
> have a getId() method.
>
> I am not sure if any of that made sense, but the crux of the issue is
> I am trying to avoid cutting and pasting code and then having to
> remember to update it in 25 different places when I make a change. I
> feel like there is a way to do what I want, but I just don't have the
> experience to see it.
>
> If anyone can point me toward some documentation that might help set
> me straight, I would appreciate it.
>
> Thanks.
You should think along separating your domain representation from
details of persistence technology. Sure, every class that corresponds to
a table needs to be saved but if you have a one-to-one correspondence
between database tables and classes, your (mapped) classes are pure data
with no behaviour (except the ability to persist).

As far are you code is concerned, it should be pretty easy to provide a
common implementation for the two methods you have provided as example.
Let us, for the time, concentrate on the add method and the two classes
Client and Contact (and stick to pre 1.5 syntax) . Both of these classes
should implement an interface "Identifiable" which should be
serializable and contain at least one method - "Long getID()". Move your
add method out of each class and into a class say "IdentifiableDAO"
where you should provide a common implementation of add which will look
something like this (not showing all the details here).

Identifiable add(Identifiable obj2save)
{
.....
Long objID = session.save(obj2save) ;
return get(objID);
}

Looking at your code, I would say using spring's HibernateDAO might also
be a good idea for you.

Note: The idea of moving the hibernate code out of the domain objects is
not really central to your problem but it will help (if implementation
details of persistence are separate from your domain representation) if
you want to later change your persistence mechanism or change the way
you manage transactions etc.

Hope this helps.

Abhijat

 
 
Lew Bloch





PostPosted: 2008-5-28 12:06:00 Top

java-programmer >> Making the most of code jstorta wrote:
>> I have a web site that uses JSP and some back end classes to manage
>> data in a MySQL database. It does okay and has run well for about 3
>> years. It has, however, grown to the point where I need to redesign
>> some of it to be more dynamic. I've recently started incorporating
>> Hibernate and JavaServer Faces to ease the development now and make it
>> easier for me to make changes later on. Or at least that was my plan.
...
>> If anyone can point me toward some documentation that might help set
>> me straight, I would appreciate it.

<http://java.sun.com/javaee/5/docs/tutorial/doc/bnbpy.html>
Hibernate implements the Java Persistence API (JPA). Although the referenced
link is a tutorial, I find it a bit opaque, especially trying to convert it to
running code. I deem patience a virtue with this one.

O'Reilly has a Hibernate book out with a good reputation. I don't know if
it's any clearer than the documentation at or through hibernate.org, though.

That same tutorial link leads to chapters on JSF, also. "Persistence", the
part linked, is Part V. "The Web Tier" is Part II. The overall link is
<http://java.sun.com/javaee/5/docs/tutorial/doc/>

Abhijat Vatsyayan wrote:
> You should think along [the lines of] separating your domain representation from
> details of persistence technology. Sure, every class that corresponds to
> a table needs to be saved but if you have a one-to-one correspondence
> between database tables and classes, your (mapped) classes are pure data
> with no behaviour (except the ability to persist).

JPA frameworks, and the other object-relational mapping (ORM) frameworks I've
seen for Java, use pure value objects to represent entities. This may seem
strange to O-O programmers accustomed to objects that manage their own
behaviors, but it's valid. Persistence actions use entity objects, but their
concerns are not those of an entity. An entity just is, in its own mind, and
it takes its values as gifts. Any behaviors it does have will not relate to
persistence, but to its own concerns, trusting persistence matters to the
layer that handles them.

The closest a JPA-annotated class has to knowing its persistence
responsibilities is a declarative set of hints and assertions that do not
constrain the mechanism used to achieve their purpose. Sure, '@Entity' tells
a class that it is an entity, perhaps revealing the associated database table
and such things, but nothing at all about how that is accomplished.

--
Lew
 
 
jstorta





PostPosted: 2008-5-28 21:05:00 Top

java-programmer >> Making the most of code > Looking at your code, I would say using spring's HibernateDAO might also
> be a good idea for you.


I had heard of Spring, but never really looked into it. I did some
reading this morning and I think it is exactly what I am looking for.

Hibernate to wrap around the complexity of database access.
Spring to wrap around the complexity of Hibernate.

One more framework to learn. :-)

Thanks.
 
 
Are Nybakk





PostPosted: 2008-5-28 21:58:00 Top

java-programmer >> Making the most of code jstorta wrote:
> I have a web site that uses JSP and some back end classes to manage
*snip*
> Each database table maps to a Java class. I will easily have 25-30
> tables before I am done. I am okay with 25-30 classes to represent
> the data, but my concern is when it comes to the associated classes
> needed to manage the data connections and such. I find that I am
> cutting and pasting way too much similar code into these separate
> classes.
*snip*

On a side note; did you consider using Java Persistence API (JPA)?

*snip*
> I tried using Generics to make the return type and parameter <T>, but
> this only gets me so far. I cannot declare a new instance of <T>, or
> at least I don't know how to. And the method uses values that are
> specific to the class in question. I.E. not every data class will
> have a getId() method.

I don't know Hibernate, but how about this?


public interface DAO<T> {

public T add(T obj);

}

public class DAOTasks {

public static <T> T add1(T obj) {
//...
}

public static <T> T add2(T obj) {
//...
}

}

public class ContactDAO implements DAO<Contact> {

public Contact add(Contact obj) {
DAOTasks.add1(obj);
//Or DAOTasks.add2(obj);
}

}

*snip*

Are
 
 
RedGrittyBrick





PostPosted: 2008-5-28 22:51:00 Top

java-programmer >> Making the most of code Lew Bloch wrote:
>
> JPA frameworks, and the other object-relational mapping (ORM) frameworks
> I've seen for Java, use pure value objects to represent entities. This
> may seem strange to O-O programmers accustomed to objects that manage
> their own behaviors, but it's valid. Persistence actions use entity
> objects, but their concerns are not those of an entity. An entity just
> is, in its own mind, and it takes its values as gifts. Any behaviors it
> does have will not relate to persistence, but to its own concerns,
> trusting persistence matters to the layer that handles them.
>

"Rabbit's clever," said Pooh thoughtfully.
"Yes,"said Piglet, "Rabbit's clever."
"And he has Brain."
"Yes," said Piglet, "Rabbit has Brain."
There was a long silence.
"I suppose," said Pooh, "that that's why he never understands anything."

;-)

--
RGB