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.

Exception handling

This article tackles a lot of issues. Thowing/re-throwing errors , adding useful information in the meantime, prevent 100 different specific exception classes, shortening code using fluent pattern.

https://northconcepts.com/blog/2013/01/18/6-tips-to-improve-your-exception-handling/

Automated integration tests with Spring

Integration tests test the interactions of a component with other components. Thus, the test setup requires a test environment not only for the component under test, but also the components it interacts with. E.g.: you want to test a function of a component that embeds a 3rd party service API. This requires you to set up a test environment for your component as well as the 3rd party service.

There are two possibilities:
1. You mock the 3rd party service, if you cannot set up a test environment for it
2. You can and use the real service and are able to clean up after your test.

This article focuses on automated integration tests with Spring using MockMVC and SpringJUnit4 as a test runner. We use use MockMVC to perform REST calls to Spring controllers. The tests are not executed in the Spring environment, but from the SpringJUnit4ClassRunner, so we need to give the test runner the path to the ApplicationContext.xml which contains the information about the JPA Connection, so the persistence context can be injected (EntityManager).

To recognize which function is mapped to which URI, the test runner needs to know the dispatcher servlet, so we also hand over the „webmvc-config.xml“ file. The webmvc-config.xml is usually found under

src/main/webapp/WEB-INF/spring

The problem is, that this path cannot be referenced inside the deployed war file (see: http://stackoverflow.com/a/14946430 for information about the structure of a war file).
Thus we need to move the webmvc-config.xml to

src/main/resources/META-INF/spring

and

src/test/resources/META-INF/spring.

A test setup looks like this:


@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations ={"classpath:META-INF/spring/applicationContext.xml", 

"classpath:META-INF/spring/webmvc-config.xml"})
@TransactionConfiguration(transactionManager = "transactionManager")
@DirtiesContext
public class TrackerStatsControllerTest {

@Autowired
WebApplicationContext wac;
private MockMvc mockMvc;

@PersistenceContext
EntityManager entityManager;

@Before
public void setup() throws Exception {
 this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}

The DirtiesContext annotation ensures, that the context is loaded again for each test class!