Question

I’m currently working on an open source project that requires me to refactor a lot of old code and make use of hibernate for my database access & spring to tie it all together. The code as it is now makes use of “God” objects where the database queries, business logic, database row & all getters and setters are implemented into a single object.

What I want to do is refactor these objects into the following layers:

  1. A management layer containing business logic contains a reference to a Database Acces Object for its database access (DAO)
  2. A DAO layer that will query the database and return DatabaseObjects (DO’s)
  3. A database object (DO) with just getters & setters containing no logic what so ever

So far so good, but now a requirement comes in where I don’t want end users to use any of the DO getters & setters. So I made them package protected and added getters and setters to my management layer. The management class getters/setters will add the business logic side of things and then call the DO’s setters/getters.

So I now have something like this (there are interfaces for all the management/DAO classes but for simplicity reasons I left these out):

public class PersonManager{


    @Autowired(required = true)
    protected PersonDAO personDAO;

    public List<PersonDO> findAll(){
        return personDAO.findAll();
    }

    public void setPersonName(PersonDO person, String name)
    {
        ...Business logic authentication checks...
        person.setName(name);
    }
}

Again this approach is working well, but now every time a developer want to use the backend the management object is required alongside the database object. Since this is an open source project I fear that the temptation might be a little to much to just make a DO method public & skip past the manager (and add business logic code to the DO again).

So what I had in mind now is to create an additional layer that encapsulates the manager and DO into a single object, something like this:

public class Person()
{
    protected PersonManager personManager;
    protected PersonDO personDO;


    public List<Person> findAll(){
         return personManager.findAll();
    }

    public void setPersonName(String name)
    {
         ...Business logic authentication checks...
         person.setName(name);
    }
}

This would encapsulate the backend into the old “God Object” that used to exist but with the benefit that is completely hollow and just calls on the “layered backend API”. So the other open source contributors can still make use of old code while the backend has been cleaned up.

But there is one small problem in my setup and that is that the “findAll()” method would return a list of “PersonDO” objects when we actually want Person objects ! (This is because this is how hibernate returns my objects) So I’m at a los at how best to solve this.

Is there no other way but to use the manager for everything ? Or am I missing some other way I could encapsulate the manager & the DO into an object.

Was it helpful?

Solution

Commonly used pattern in this situation is separation of the value objects (VO) and the service classes. Individual public methods of the service classes usually follow the transaction script pattern. Some call this approach "anemic object model", but for better or worth it seemed to be a good fit with the modern approaches to testing (the TDD, mocking, etc.) and to dependency injection and database transaction management.

If you follow this project, you API would return simple VOs that are safe to use upstream. The database transaction boundary should be at the level of your individual API methods, so VOs returned from the API calls would be disconnected from the database and changes to their values would not make it back to the database, unless VOs are passed back to the API methods explicitly designed for that purpose.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top