Single Responsibility Principle

The SRP states, that every class/module/unit of work/component should only implement functionality for a single responsibility. Examples: Persistence, Logic, View rendering.

Why is this so important? Why bloating your code, by creating more classes/../components than necessary?

Advantages can be found in: Testing, Collaboration, Deployment

Testing: The more functionality you have in one component the more complex your tests get. Code coverage for a function with one if clause requires 2 tests. Make that 2 and you already need 4 tests. The complexity multiplies and soon you will not be able to cover all paths of your code. When having small units, you can control the complexity and test them easily, with less effort.

Collaboration: Of course it’s also easier to work on a single code basis with several developers, if you have different components. Even in the time of git.

Deployment: More separation means more stability. Having a bug in a component? Fix it and deploy only that component. No need to test the whole system again. This idea stretches from single classes, to microservices.

The consequences of SRP are layered architecture, MVC and even microservices. The implications of this principle are huge and widely overlooked.

An Anti-Pattern for SRP is for example the Active Record Pattern. There persistence logic is build into the domain objects, so you have functions like this:

obj.setProperty();
obj.merge(); // merges the object changes into the database

This makes it very hard to test the persistence layer. In DI Frameworks like Spring you can use reflection to mock the persistence layer, but this is more complicated than necessary and needs lots of insight and time.

Read for more explanations: http://moleseyhill.com/blog/2009/07/13/active-record-verses-repository/

Punchline: SRP has many benefits and implications. Most of my design/architectural problems with legacy code are a result from not following SRP.

JPA Persistence (and why not to bind entities to view data directly)

Consider the following setup:

CarEntityManagerProblem

(The association from ManagedBean to CarDAOBean is actually a dependency injection, but I think one could still call it an association)

Assume now the myCar Entity is used in a JSF based view like this:

<p:inputText id="cartype" value="#{managedBean.myCar.type}" />
<p:inputText id="carcolor" value="#{managedBean.myCar.color}" />
<p:commandButton value="send" action="#{managedBean.save()}" />

So far we don´t have a problem. The save() method of the ManagedBean will call

carDAOBean.create(myCar);

which then will execute

em.persist(car);

Now lets assume we want to delete that entity again and call the managedBean.delete(), which then executes:

carDAOBean.delete(myCar);

Oh wait… Transaction Rollback? Yeah!

Why? Because our myCar Entity is not managed by the persistence context anymore. Every Entity you want to remove has to be managed by the persistence context. An Entity is managed when you use EntityManager.persist() on it, BUT only as long, as the persistence context exists.
See http://www.objectdb.com/java/jpa/persistence/managed for further information.
So why does our example crash? Because our CarDAOBean is stateless and since our EntityManager is also stateless the persistence context will only manage our Entity as long as the EntityManager exists after we call persist() which is … not very long!

So at this point google is your friend and after a few pages you will know that you can declare your CarDAOBean as stateful and change the EntityManager declaration as follows:


@Stateful
public class CarDAOBean{

@PersistenceContext(unitName = "myPU", type = PersistenceContextType.EXTENDED)
 private EntityManager entityManager;

...

So your CarDAOBean will be stateful and you EntityManager will have an extended persistence context, which will be available longer. Great right?

I’ve been there and fortunatelly I found the following artifact before refactoring my whole application:

If you’re using a view technology that binds POJOs (e.g., SpringMVC) and you’re planning to bind web form data directly onto your Entities, you’ll get in trouble quick. Changes to an attached entity will become persistent on the next flush/commit, regardless of whether they were done in a transaction or not. Common error is, web form comes in and binds some invalid data onto an entity, validation fails and trys to return a screen to inform user. Building error screen involves running a query. Query triggers flush/commit of persistence context. Changes bound to attached entity get flushed to database, hopefully causing SQL exception, but maybe just persisting corrupt data.

http://stackoverflow.com/a/6432309

In fact this is worse, because now that you entity is bound permanently, you’ll have a lot of trouble to get corrupt data our of your database! So beware of the antipattern!

The „how to do it right“ might follow later.