The dreaded DefaultAbstractHelperImpl


A while ago, we have published this fun game we like to call Spring API Bingo. It is a tribute and flattery to Spring’s immense creativeness when forming meaningful class names like

  • FactoryAdvisorAdapterHandlerLoader
  • ContainerPreTranslatorInfoDisposable
  • BeanFactoryDestinationResolver
  • LocalPersistenceManagerFactoryBean

Two of the above classes actually exist. Can you spot them? If no, play Spring API Bingo!

Clearly, the Spring API suffers from having…

To name things

There are only two hard problems in computer science. Cache invalidation, naming things, and off-by-one errors

– Tim Bray quoting Phil Karlton

There are a couple of these prefixes or suffixes that are just hard to get rid of in Java software. Consider this recent discussion on Twitter, that inevitably lead to an (very) interesting discussion:

Yes, the Impl suffix is an interesting topic. Why do we have it, and why do we keep naming things that way?

Specification vs. body

Java is a quirky language. At the time it was invented, object orientation was a hot topic. But procedural languages had interesting features as well. One very interesting language at the time was Ada (and also PL/SQL, which was largely derived from Ada). Ada (like PL/SQL) reasonably organises procedures and functions in packages, which come in two flavours: specification and body. From the wikipedia example:

-- Specification
package Example is
  procedure Print_and_Increment (j: in out Number);
end Example;

-- Body
package body Example is
 
  procedure Print_and_Increment (j: in out Number) is
  begin
    -- [...]
  end Print_and_Increment;
 
begin
  -- [...]
end Example;

You always have to do this, and the two things are named exactly the same: Example. And they’re stored in two different files called Example.ads (ad for Ada and s for specification) and Example.adb (b for body). PL/SQL followed suit and names package files Example.pks and Example.pkb with pk for Package.

Java went a different way mainly because of polymorphism and because of the way classes work:

  • Classes are both specification AND body in one
  • Interfaces cannot be named the same as their implementing classes (mostly, because there are many implementations, of course)

In particular, classes can be a hybrid of spec-only, with a partial body (when they’re abstract), and full spec and body (when they’re concrete).

How this translates to naming in Java

Not everyone appreciates clean separation of specs and body, and this can certainly be debated. But when you’re in that Ada-esque mind set, then you probably want one interface for every class, at least wherever API is exposed. We’re doing the same for jOOQ, where we have established the following policy to name things:

*Impl

All implementations (bodies) that are in a 1:1 relationship with a corresponding interface are suffixed Impl. If ever possible, we try to keep those implementations package-private and thus sealed in the org.jooq.impl package. Examples are:

This strict naming scheme makes it immediately clear, which one is the interface (and thus public API), and which one is the implementation. We wish Java were more like Ada with this respect, but we have polymorphism, which is great, and…

Abstract*

… and it leads to reusing code in base classes. As we all know, common base classes should (almost) always be abstract. Simply because they’re most often incomplete implementations (bodies) of their corresponding specification. Thus, we have a lot of partial implementations that are also in a 1:1 relationship with a corresponding interface, and we prefix them with Abstract. Most often, these partial implementations are also package-private and sealed in the org.jooq.impl package. Examples are:

In particular, ResultQuery is an interface that extends Query, and thus AbstractResultQuery is a partial implementation that extends the AbstractQuery, which is also a partial implementation.

Having partial implementations makes perfect sense in our API, because our API is an internal DSL (Domain-Specific Language) and thus has thousands of methods that are always the same, no matter what the concrete Field really does – e.g. Substring

Default*

We do everything API related with interfaces. This has proven highly effective already in popular Java SE APIs, such as:

  • Collections
  • Streams
  • JDBC
  • DOM

We also do everything SPI (Service Provider Interface) related with interfaces. There is one essential difference between APIs and SPIs in terms of API evolution:

  • APIs are consumed by users, hardly implemented
  • SPIs are implemented by users, hardly consumed

If you’re not developing the JDK (and thus don’t have completely mad backwards-compatibility rules), you’re probably mostly safe adding new methods to API interfaces. In fact, we do so in every minor release as we do not expect anyone to implement our DSL (who’d want to implement Field‘s 286 methods, or DSL‘s 677 methods. That’s mad!)

But SPIs are different. Whenever you provide your user with SPIs, such as anything suffixed *Listener or *Provider, you can’t just simply add new methods to them – at least not prior to Java 8, as that would break implementations, and there are many of them.

Well. We still do it, because we don’t have those JDK backwards-compatibility rules. We have more relaxed ones. But we suggest our users do not implement the interfaces directly themselves, but extend a Default implementation instead, which is empty. For instance ExecuteListener and the corresponding DefaultExecuteListener:

public interface ExecuteListener {
    void start(ExecuteContext ctx);
    void renderStart(ExecuteContext ctx);
    // [...]
}

public class DefaultExecuteListener
implements ExecuteListener {

    @Override
    public void start(ExecuteContext ctx) {}

    @Override
    public void renderStart(ExecuteContext ctx) {}

    // [...]
}

So, Default* is a prefix that is commonly used to provide a single public implementation that API consumers can use and instantiate, or SPI implementors can extend – without risking backwards-compatibility issues. It’s pretty much a workaround for Java 6 / 7’s lack of interface default methods, which is why the prefix naming is even more appropriate.

Java 8 Version of this rule

In fact, this practice makes it evident that a “good” rule to specify Java-8 compatible SPIs is to use interfaces and to make all methods default with an empty body. If jOOQ didn’t support Java 6, we’d probably specify our ExecuteListener like this:

public interface ExecuteListener {
    default void start(ExecuteContext ctx) {}
    default void renderStart(ExecuteContext ctx) {}
    // [...]
}

*Utils or *Helper

OK, so here’s one for the mock/testing/coverage experts and aficionados out there.

It’s TOTALLY OK to have a “dump” for all sorts of static utility methods. I mean, of course you could be a member of the object-orientation police. But…

Please. Don’t be “that guy”! 🙂

So, there are various techniques of identifying utility classes. Ideally, you take a naming convention and then stick to it. E.g. *Utils.

From our perspective, ideally you’d even just dump all utility methods that are not stricly bound to a very specific domain in a single class, because frankly, when did you last appreciate having to go through millions of classes to find that utility method? Never. We have org.jooq.impl.Utils. Why? Because it’ll allow you to do:

import static org.jooq.impl.Utils.*;

This then almost feels as if you had something like “top-level functions” throughout your application. “global” functions. Which we think is a nice thing. And we totally don’t buy the “we can’t mock this” argument, so don’t even try starting a discussion

Discussion

… or, in fact, let’s do start a discussion. What are your techniques, and why? Here are a couple of reactions to Tom Bujok’s original Tweet, to help get you started:

Let’s go 😉

4 thoughts on “The dreaded DefaultAbstractHelperImpl

  1. I do not agree with the Util/Helper class as a “dump” for anything.

    I am currently refactoring a very messy legacy codebase that has helpers, advisors, managers, brokers, addins, utils, helperadvisorbrokerutilsadinfinitum.

    Classes, regardless of what they are named, should be concise and coherent. They shouldn’t be a dumping ground for static methods or they stand a strong chance of winding up a very messy incoherent jumbled dump of crap – just like in any other trash dump.

    As for naming – the name of a class should be as close to what it does as possible. What is a helper? Helps do what? Devs tend to just throw anything and everything into these classes. Few have the discipline and patience to create something like Apache StringUtils with a coherent and concise interface.

    And no – I don’t like *****Impl at all. I used to use it, and then decided it was redundant. I still use Abstract and sometimes Default, but sparingly.

    Anymore an IDE along with a quick glance at the code, will tell you whether something is an interface or not. Ditto for Abstract classes too really. Default implementations – those are worth noting in the name.

    • I essentially agree with you on the criticism on helper dumps. The goal should be something like StringUtils. Two things should be considered:

      1. Java doesn’t support top-level functions. We have to put them in some class (my point)
      2. … for this reason, that class must be named in a way that makes it easy to find those “top-level” functions (your point)

      I don’t like ****Impl either, but when specs and implementation are in a 1:1 relationship, I haven’t found a better solution, so far.

  2. I agree with most of your post, except the first paragraph. In my opinion Spring is far away from having a naming problem. I can see that many class names might sound like a black magic mix of general terms (adapter, factory, resolver, delegate, etc.). But if you are familiar with the concepts in Spring many of the class names become very self explaining.

    Here are some examples that make some of the longest class names in Spring:

    ***HandlerMethodArgumentResolver:
    In Spring’s web framework classes that handle web requests are called Handlers. Such an Handler typically has one or more methods that take incoming requests and generate some kind of response (=HandlerMethod).
    Handler methods can have many different arguments which are passed by Spring once such a handler method is invoked. For example: If a handler methods defines a parameter of type Locale, Spring automatically passes the request locale. (see this for a full list of possible arguments: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html)
    These arguments are resolved by an HandlerMethodArgumentResolver (pretty clear name, right?).
    HandlerMethodArgumentResolver is an interface with a lot of different implementations. For example:
    PathVariableMethodArgumentResolver – resolves path variables from the requested url
    MatrixVariableMapMethodArgumentResolver – resolves matrix variables
    ServletCookieValueMethodArgumentResolver – resolves cookie arguments

    ***BeanPostProcessor
    A BeanPostProcessor can be used to implement custom modifications after a bean is created. This is used a lot by Spring itself to implement various features. Again, I think BeanPostProcessor is not the worst name for such an interface.
    Implementation names are also very descriptive:
    RequiredAnnotationBeanPostProcessor – processes @Required annotations in newly created beans
    InitDestroyAnnotationBeanPostProcessor – responsible for calling init/destroy methods on created beans
    PersistenceExceptionTranslationPostProcessor – translates exceptions of various persistence solutions into Springs DataAccessException.

    More long names:

    BufferedImageHttpMessageConverter:
    An implementation of an HttpMessageConverter that can be used to read/write BufferedImage objects

    QualifierAnnotationAutowireCandidateResolver:
    An AutowireCanditateResolver that resolves canditates eligible for autowiring based on @Qualifier annotations.

    JodaDateTimeFormatAnnotationFormatterFactory:
    An AnnotationFormatterFactory for handling DateTimeFormat annotations using Joda-Time.

    Jsr310DateTimeFormatAnnotationFormatterFactory:
    An AnnotationFormatterFactory for handling DateTimeFormat annotations using JSR-310 Date/Time API

    I have never heard of BeanFactoryDestinationResolver (your example). But I know for what Spring’s DestinationResolver interface is used. So it becomes very obvious what a BeanFactoryDestinationResolver might do.

    While some names might be very long, you can often do a pretty good guess what a class does just by reading the class name. For a framework with >3K classes I think this is quite an accomplishment.

    • Two points (apart from the fact that that part was more of a “funny” rant than anything else):

      1. I doubt that 2/3 of those types need to be part of any public API. I really doubt it
      2. Subtype polymorphism is completely overused in Spring, where generic polymorphism would have been much better.
      3. I personally doubt that 2/3 of Spring is really needed in general. I really don’t see the point of anything like a JodaDateTimeFormatAnnotationFormatterFactory. I’m sure, this can be written with a one-liner and String.format() or so. But that might just be me, trying to KISS 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s