Java Champion / JavaOne Rockstar Adam Bien (adam-bien.com) is a self-employed consultant, lecturer, software architect, developer, and author in the enterprise Java sector. He is also the author of several books and articles on Java and Java EE technology, as well as distributed Java programming. adam has posted 59 posts at DZone. View Full User Profile

Service s = new ServiceImpl() - Why Are You Doing That?

09.12.2010
| 7335 views |
  • submit to reddit

I see the following "best practice" over and over again in projects and reviews :

Service service = new ServiceImpl();

Basically: for every interface there is an implementation with the "Impl" ending. That's not enough: sometimes both are configured in a XML-File (probably to emphasize the importance of this pattern :-)). That is not only bloat (and the opposite of "Convention Over Configuration" idea), but it causes real damage:

  1. Imagine you get another implementation (thats the whole point of an interface) - how would you name it?
  2. It doubles the amount of artifacts - and significantly increases the "complexity"
  3. It is really funny to read the javadocs on the interface and the impl - another redundancy
  4. The navigation in the IDE is less fluent


I asked why developers are writing such code, but I didn't get a reasonable answer, except "because of mocking".
For several years however, this is no longer true. Any ideas, why are you doing that?

From http://www.adam-bien.com/roller/abien/entry/service_s_new_serviceimpl_why

1.444445
Your rating: None Average: 1.4 (9 votes)
Published at DZone with permission of its author, adam bien.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Slava Lo replied on Sun, 2010/09/12 - 8:30am

Having an interface for your service is not only good for creating mocks when testing but also is handy when Spring creates proxy of service class when weaving the aspects (like @Transactional). 

Any mordern IDE know allows seemless navigation to the implemenation from the point where interface is refereced.

Henk De Boer replied on Sun, 2010/09/12 - 9:01am

I often used Jboss' AsyncUtils.mixinAsync() and this one only works with classes that have an interface. The power of many small asynchronous executions still seems to be rather undervalued in the Java enterprise world.

Neil Shannon replied on Sun, 2010/09/12 - 10:18am

If your complaint is about naming, I agree.  I name my interfaces as such:

Service service = new JPAService(); 

or

Service service = new JDBCService(); 

The interface should say what the generic service does/is, the concrete class name should give a little more information about the implementation.  Anticipating the obvious next question:  Yes, my projects often do use different implementations depending on configuration.

 

Eric Adamson replied on Sun, 2010/09/12 - 11:05am

Because by defining interface MyService on Day 1, it becomes possible for the MyClient team to have MyServiceMockImpl written by Day 3, allowing their component to be finished and tested by Day 9 -- and expect that when the more complex MyServiceImpl is finished on Day 15, switching over to collaborate with it will be painless. In the meantime, the MyClient team could be implementing another component.

Essentially, defining interfaces facilitates contract-first, component-based design. Without interfaces, building a system is like building a traditional house -- the house must be built in dependency order (drains, foundation, plumbing, wiring, drywall, etc.) Introducing interfaces and leveraging them using mocks makes building systems more like building modular homes, where the components can be built independently, and assembled onsite to form the final product.

Gervais Blaise replied on Sun, 2010/09/12 - 12:59pm

Like Neil Shannon, if you complain about the naming I fully agree. But in some case the name is stupid (like ServiceImpl) because the package is not. com.me.myapp.services.impls.rest.ServiceImpl can make sense and the reflection Api can be ysed here to load a custom implemntation from a custom configuration. I you complain because you have an interface and only one concrete class, read other comments and don't forget that many IDE also provide a "Extract interface" function.

Hauke Ingmar Schmidt replied on Sun, 2010/09/12 - 2:01pm

I agree with the naming complaint. Another bad candidate is DefaultService.

I don't agree it increases the complexity, in contrary. You only "know" the public interface that is specifically coded so you (or another developer jumping in as a holiday replacement) can't do weird things. Explicitly writing what you mean increases and not letting it deduced implicitly increases the number of lines or the types, but reduces complexity by plainly telling what is meant (Why should I write "var x='Hello'" when I know x should be a String? To save three characters?)

The Javadocs of the implementation should just inherit the interface's docs and only point out when a method does something weird.

Navigating is a problem? Hm... a good IDE is important for Java developing, I don't want the "text editing with shelling out console commands" days back. An IDE today should allow navigating between interface and implementation and understand semantics of the used frameworks, e.g. showing Spring declarations and allow navigating them; IDEs today are capable of that. (Ideally you wouldn't need to navigate between interface and implementation... but that is theory, sadly.)

Nim Lhûg replied on Sun, 2010/09/12 - 2:06pm

Wow. Are you seriously asking why people program against interfaces? Or are you just complaining about the Impl-name?

As for redundant Javadocs...why on earth would anyone duplicate comments on an implementation when they're already present on the interface?

Hauke Ingmar Schmidt replied on Sun, 2010/09/12 - 4:04pm

Just for clarification: I didn't mean to copy the doc but thought of the use of {@inheritDoc}.

Wujek Srujek replied on Sun, 2010/09/12 - 4:56pm in response to: Hauke Ingmar Schmidt

You don't need that {@inheritDoc}. If you leave the method commentless, it will automatically inherit the docs. This tag should be used whenever you want to override / add something, and it is very flexible in that if, for example, you only change the description, and don't change the parameters section, this part will only be inherited.

As for the naming part - I fully aggree, the XXXImpl is a bad name, MKay, cause it's baaad, MKay. But, I wouldn't go that far to say that even though you are using EJB 3.1 and local interface-less EJB are available, you shouldn't use them. For starters, you don't see into the future, and even though you can refarctor later, just think of all the places where you would have to do it. Ok, it's automatic, but then again, something can go wrong. The second part is that even thouhg it is EJB 3.1 environment today, it might be something else tomorrow - these are just POJOs, right? And tomorrow you need interfaces for it to work. C'mon, it's not that hard and more complex.

Liam Knox replied on Sun, 2010/09/12 - 5:51pm

So you have defined 4 pointless reasons in why not to define interfaces. Why? How can you ever sight an IDE limitation in this argument.

In a discussion about class vs. interface surely you should be quoting usage and context arguments and not this nonsense.

Liam Knox replied on Sun, 2010/09/12 - 9:28pm

Basically the Mocking argument also still applies here. By using Mockito you have to explicitly decide to make your implementations non final. This is often undesirable for lots of different reasons.

Grzegorz Grzybek replied on Mon, 2010/09/13 - 12:00am

First - Slava Lo is right - interfaces are good for creating proxies.

Second - in case someone argues about explicit using of "new" - look at org.slf4j.impl.StaticLoggerBinder - even if there is "new" keyword, the implementation depends on the JAR you place on your classpath - that's IMO great use of interface and good choice for SLF4J - choose your JAR and the implementation changes - and that doesn't change the test code of classes using the interface.

 

Alex(JAlexoid) ... replied on Tue, 2010/09/14 - 12:30pm

I have to agree, with one case. If you have the following line in a non-test code:

Service service = new ServiceImpl();

Then you are better off not having the Service interface. Because that implies that there is and will be only one implementation. And creating mocks can be done with classes, as well as interfaces.

The main point is as always, the person creating interface/implementation  duo has to ask himself - "Will there be any alternative implementations of this interface?". In case the answer is No, then there is no need for an interface.

adam bien replied on Sat, 2010/10/02 - 4:07pm in response to: Alex(JAlexoid) Panzin

@Alex, totally agreed with your comment - thanks!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.