Notes of a (Java) developer

Software developers Programmers

Point of view: Packaging

Software developer Programmer

According to The Unified Modeling Language User Guide, object-oriented software elements belong to one of these four categories:

  • Structural things
  • Behavioral things
  • Grouping things
  • Notational things

Obviously, classes are structural elements. According to this same book, packaging is the act of grouping classes.

Something is bothering me about packaging. All programs I have been working on, and all courses I have been following, share a single vision of the way these groups should be considered.

In this single vision, classes are grouped on structural criteria. In a same package, we will find objects assuming a single role: DAOs with DAOs, entities with entities, controllers with controllers. To be honest, this helps designing interesting class diagrams. This has a real interest for building effective heritage hierarchies.

But in my point of view, we let apart behavioral criteria. One DAO object usually interacts only with a single entity class and a few services. This means, if we design sequence, activity or state diagrams, the involved objects will belong to different packages. This would be very helpful to help software maintenance: in a single set we have all the relevant elements.

Here is a summary:
  1. Usually, package elements grouping is based on classes roles to help software design
  2. Package elements grouping should also be based on classes interactions to help software maintenance

If we would like to design really modular applications, I think we should consider these two axes while packaging. On a pure design point of view, a class should belong to two packages : one structural (1) and one behavioral (2). This could be possible because one class usually has interactions with a few classes.

In Java, one solution to help set up this second kind of packages could be annotations. But the problem would be in class loading. This wouldn't be a real problem if we all time use to write APIs.

A pragmatic solution would be to change the packaging in the development process. Once the software has been designed building interesting heritage hierarchies based on roles, packaging should be modified to follow classes interactions in order to help software maintenance.

Heisenbug - Concurrency case

Software developer Programmer

Solving an Heisenbug can be really tricky. This kind of bug occurs when the program execution conditions are changing. In many cases, using a debugger or a log output doesn't help. Such tools can have an influence on the execution.

I once faced such a bug in a Swing application. The problem occurred in a quite long process (half an hour)  at various steps with constant input data. I lost time with that bug because I had no methodology. I have to admit the final solution was rather simple.

I designed an activity diagram of the main activities involved in the failing process. I paid attention to swimlanes because I suspected a concurrency problem. For each activity there was a single log output. A custom logging level was set up so that only activity logs could be written (an attempt with the debug log level was completely helpless). The logging framework was also configured to print the current thread name. There I got the activity which was not in the right place and the name of the criminal. The random occurrence of the problem was probably due to the variable system load and user interactions.

SPI

Software developer Programmer

What are the Service Provider Interfaces (SPI) ?

These are important elements of the Java platform. More documentation is available in the official tutorial. In a few words, you probably have noticed the Java APIs mainly consist in interfaces. The SPI is the mechanism setting up the appropriate implementation so that programs don't rely on the implementation at compile time.

When an implementation is provided, to associate it to the implemented interface, there is one (or more) entry point. For example, the JPA API has for single point the interface javax.persistence.spi.PersistenceProvider . All other interfaces are available via this one.

If you want to provide a JPA implementation, you first have to code a class implementing this interface. Then, a text file named after the fully qualified name of the interface should be available to the class loader setting up the environment in the META-INF/services directory.
This mean, if you are working with Eclipse IDE in a Java SE environment with an src source directory :
src/META-INF/services/javax.persistence.spi.PersistenceProvider

This text file just has to contain the available implementations. If I want my own implementation (the provider is org.test.jpaimpl.PersistenceProvider) to be available along with EclipseLink (the provider is org.eclipse.persistence.jpa.PersistenceProvider ) the file has to contain these two lines : 

org.eclipse.persistence.jpa.PersistenceProvider
org.test.jpaimpl.PersistenceProvider

For the specific case of JPA, when multiple implementations are found by the class loader, the implementation to use can be specified in the persistence.xml file, in the provider element of a persistence-unit :

<persistence version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/persistence" xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="COLLECTIONS" transaction-type="RESOURCE_LOCAL">
<provider>org.test.jpaimpl.PersistenceProvider</provider>
...
</persistence-unit>
</persistence>

JAVA SPI JPA IMPLEMENTATION