3

I'm working on a base library intended to provide common interfaces to a large application which is intended to support several DBMS (Oracle, SQLServer, MySQL, PostgreSQL, etc). Additionaly a concrete class may use JDBC or JPA to interact with the DBMS.

I want to provide a contract with basic persistence operations involving domain (model) classes so I've made this interface using generics:

public interface IDomainDAO<T> {

    public int insert(T domainObject);

    public int update(T domainObject);

    public int delete(T domainObject);

    public List<T> getList(IQueryFilter queryFilter);
}

Note: IQueryFilter is not relevant to my problem.

I'm trying to decide if I should provide more specialized interfaces so concrete classes can implement those ones instead of IDomainDAO, or doing so is just a waste of time. For instance:

public interface IUserDAO extends IDomainDAO<User>{}

This is an example of how a concrete implementation will look like:

public class UserDAOJDBC implements IUserDAO {

    public int insert(User domainObject){...};

    public int update(User domainObject){...};

    public int delete(User domainObject){...};

    public List<User> getList(IQueryFilter queryFilter){...};
}

On the other hand an implementation could simply be as shown below (and I don't have to spend some time providing specialized interfaces):

public class UserDAOJDBC implements IDomainDAO<User> {

    public int insert(User domainObject){...};

    public int update(User domainObject){...};

    public int delete(User domainObject){...};

    public List<User> getList(IQueryFilter queryFilter){...};
}
dic19
  • 17,821
  • 6
  • 40
  • 69
  • Which would be the use of the extra interface? Because as far as I can tell, if somewhere you need an `UserDaoJdbc`, you could replace it with `IDomainDao extends User>` – SJuan76 Feb 11 '14 at 20:48
  • 1
    Also, I have "inherited" a project that uses the first approach. More important than this design issue, do not limit yourself to these methods for the implementation, add specific methods (like `addUserRole` in `UserDao`). Otherwise, you will end with your bussiness logic scattered and copy-pasted all over the place (one of the last bugs fixed required replacing the same code 30 times). – SJuan76 Feb 11 '14 at 20:51
  • @SJuan76 thanks for your comment, I'll keep it in mind. In the past (2 years ago) I had to add a new functionality to an application which was entirely designed in this way. I had to modify at least 10 interfaces/classes to add a trivial feature. I hated the guy who made all those interfaces but now I'm in the same situation and I'm trying to avoid shooting myself in the foot. – dic19 Feb 11 '14 at 21:10

2 Answers2

2

This comes down to a design issue. It depends on whether you think that you will -- at any time -- add anything to the IUserDAO interface that doesn't belong in the IDomainDAO interface.

If you considered creating IUserDAO merely to allow you to say implements IUserDAO as an abbreviation for implements IDomainDAO<User>, then it's useless and it is actually more verbose with the extra interface.

If you consider an IUserDAO as a specialized form of an IDomainDAO<User>, then keep the interface; that keeps open the possibility of adding functionality to IUserDAO that doesn't exist in -- and shouldn't be in -- IDomainDAO<User>, e.g. a method such as List<User> getActiveUserList().

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • This is the answer I was looking for. Since this is my first time in this kind of project I was trying to avoid shooting myself in the foot. Your 3rd paragraph gave me a good reason to keep that interface because I'll probably need to add some functionality in the short time. Thanks! – dic19 Feb 11 '14 at 20:57
0

I recommend to avoid any DAO and to use plain Command design pattern instead. If you use JPA then you do not need to worry about JDBC because it supports native queries of any type and JPA is smart enough to avoid stale object in JPA query after update via native query.
JPA query API is already the Command design pattern but you can define wrapper commands to hide EntityManager API for convenience, it can also help to upgrade to newer JPA version later. Commands can help to demarcate transactions and reuse query result processing code.

If it does not convince and you decided to use DAO anyways then you can use Spring DAO wrappers, they might be useful for transactions but command design pattern helps to avoid it.

You can find links to DAO framework implementations in this answer DAO implementations

Community
  • 1
  • 1
jbaliuka
  • 249
  • 1
  • 10