Java Interface Naming Conventions [closed]
Asked Answered
O

2

27

I work on a Java web-app that uses Spring for dependency injection and JMock for mocking out these dependencies in our unit tests.

Currently our team is at a point were we have a few different opinions in terms of how to name certain interfaces that we use. We have no issue with naming the interfaces in our domain that have multiple implementations, that is simple. However, when it comes to interfaces for which we only have one implementation and intend on only having one implementation in the future, we have hit a snag.

The reason that we have such interfaces is purely for mocking, for example, we have services and repositories that we mock out in our unit tests and these services will be named "DocumentMappingService" or for repositories "EmployeeRepository". At the moment some of the guys just prefix the associated interface name with an "I", i.e. "IDocumentMappingService" and "IEmployeeRepository". Others name the interface as I have above and then append an "Impl" after the interface name for the implementing class.

The third "faction" feels that both of these options are poor. Looking at literature such as the well-known "Growing object-oriented software, guided by tests" would lead one to believe that both of the before-mentioned options are poor and that the interface name should clearly define the contract and the implementing classes name should clearly specify how that contract has been implemented. We have found this quite difficult to do in the case I have mentioned above though.

I was hoping that someone out there has had a similar issue before and has some suggestions ito which option is the best and why. Also, if you think that the "I" and "Impl" options are both poor, then please suggest a specific alternative convention.

Odelsting answered 24/6, 2013 at 12:20 Comment(5)
This might be better on Programmers ... but I doubt it. There is simply no objectively correct Answer possible. And SO is not a discussion forum.Haleyhalf
The general criticism of "Impl" is that it isn't meaningful to bung the same thing on all of your classes. The name of the implementation class should reflect the implementation. For instance, the "array" in ArrayList and likewise "linked" in LinkedList. I don't think "Impl"/"Default" will particularly cause a problem (until the second implementation), but it's not the best.Pitanga
If your interfaces are purely for mocking, perhaps use a better mocking framework? I guess you are using JMock - ditch all those interfaces and try an alternative like Mockito or EasyMock?Kalgan
despite this question being closed, I got the answer I wanted and the number of upvotes and favourites show that at least some other members also found this to be useful.Odelsting
interface and class naming anti-patternsAleksandr
G
37

There's no "one" correct answer here. Naming is quite subjective but what matters the most is that it should be consistent throughout the code base. I would just like to add (to @fge's answer) some more options for you:

  • Making the Interfaces more generic.

    EmployeeRepository implements Repository
    DocumentMappingService implements MappingService
    
  • Calling your single implementations "defaults".

    DefaultEmployeeRepository implements EmployeeRepository
    DefaultDocumentMappingService implements DocumentMappingService
    
  • Calling your base implementations (if, sometimes extended) as "support".

    EmployeeRepositorySupport implements EmployeeRepository
    DocumentMappingServiceSupport implements DocumentMappingService
    

I come across these naming conventions a lot when using the Spring Framework.


Edit : In response to user nyxz's comment about the -Base or Base- convention.

Like I said before, naming is subjective and there's nothing wrong with using the Base nomenclature as such. But, personally, I don't prefer using it. Here's why:

  1. If your implementations would mostly be used directly, then the code instantiating the classes leaves an impression of breaking the OOP hierarchy. That perhaps a specific derived class should have been instantiated.

  2. If your implementations would mostly be extended from, then the word Base becomes redundant in a way. You're extending from it so, of course, it's a base class. Duh!

The 2nd point mostly applies to peripheral classes in your project. Extension points that you provide when you're publishing a framework or library to be used and extended in other projects.

On the other hand, a good use case for using the Base terminology would be for classes internal to your framework that factor common functionality out of other peripheral classes. Since, these classes aren't supposed to be instantiated directly, they are marked abstract, which is in line with the 1st point.

Here's the Adapter hierarchy from the Android framework as an example:

  • Interface hierarchy.

    public interface Adapter
    public interface ListAdapter extends Adapter
    public interface SpinnerAdapter extends Adapter
    
  • The abstract Base class that factors out the common behaviour and interface implementations.

    public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter
    
  • Peripheral classes that are mostly instantiated but sometimes extended by an Android application.

    public class SimpleAdapter extends BaseAdapter implements Filterable
    public class ArrayAdapter<T> extends BaseAdapter implements Filterable
    
Gorges answered 24/6, 2013 at 12:37 Comment(7)
those are great suggestions Ravi, thanks. I have seen the second suggestion as well (i.e. Default). As for the first suggestion, that MappingService would work but I don't think the Repository one would work for us because not all of our repositories have the exact same contract so it is abstracted one level too far. The third option (i.e. Support) intrigues me, I have never seen it before. Where did you come across that and what is the reason for using the term "Support"?Odelsting
Spring Framework makes use of "support" classes a lot. For example, to write a custom property editor (to convert string representation of a custom objects in Spring.xml) we extend PropertyEditorSupport. When using Spring JDBC it's recommended for all DAOs to extend JdbcDaoSupport.Gorges
I really like that suggestion Ravi, thanks. I gave you a plus 1 already and if no one comes up with a better suggestion fairly soon then I will accept your answerOdelsting
I was wondering what do you think about the -Base or Base- convention? Ex. interface EmployeeRepository and BaseEmployeeRepository or EmployeeRepositoryBase. I saw this couple of times in ones code.Monomorphic
@Monomorphic I've added my thoughts on the Base class naming convention to my answer. I would actually prefer EmployeeRepository implements Repository over BaseEmployeeRepository implements EmployeeRepository. In cases where defining a very general Repository interface is not feasible, you could employ generics like EmployeeRepository<Employee> implements Repository<Employee>.Gorges
@Ravi Thapliyal Adding your thoughts on the Base naming convention in this particular moment was very helpful since I have to make some abstract classes renaming and started wondering on this topic again. Thanks.Monomorphic
@Monomorphic I'm so glad to know that. I was initially thinking that perhaps it's too late to answer this now but I added the update anyway. Little did I know, I was just in time :)Gorges
S
5

An answer to such a question can only reflect the tastes of the person who answers... So these are my tastes:

  • I hate the initial I. It brings nothing of value to the picture. It reminds me of the Hungarian notation where float variables were to be suffixed with _f or the like. No.
  • The Impl suffix is good enough. But on the other hand, it sounds weird.

I'd suggest two alternate proposals for a given interface Foo:

  • create a single implementation but not with the Impl suffix; find a more "appealing" name. For instance, TheOnlyOneFoo;
  • create a factory with an appended s: Foos. Then, a Foo instance would be a Foos.newInstance(whatever, args).

I prefer the second solution, for two reasons:

  • it can hide the fact that the real implementation has an ugly name;
  • it can be extended easily when you realize one day that "no, after all, there is more than one implementation for that": just add another static factory method; and if the only existing method in existence sounds too generic, you can just mark it as @Deprecated.

It could even be used in a manner so that all Foo implementations are package local, or even private to the factory. But stack traces would look worse...

No real solution there ;)

edit: as for mocking:

  • I'd recommend mockito. Really. It is very easy to use, and very powerful.
  • If those are "one-implementation classes" you are dealing with, maybe there is a better alternative in the JDK itself? What is it that you want to do exactly? The JDK has hidden treasures...

And as a final note... Have you considered the builder pattern?

Skidmore answered 24/6, 2013 at 12:25 Comment(10)
I am not keen to change from JMock, I am happy with it so far and having to create an interface is not a major issue, I would just like a consistent logical way of naming these interfaces. When you ask what I want to do exactly, it is just what I said in the question. I have services and repositories that are mocked out in unit tests and hence need to have an interface (due to JMock). I was asking if anyone has been in the same boat and what naming convention they recommend for these interfaces. The I/Impl may be sufficient in this case, just wanted to see if someone knew of a better approach.Odelsting
OK, but seriously: you should consider mockito. Jmock just can't catch up ;)Skidmore
we do use builders for building entities and the like in our tests, but I am not following what you mean in this context. Could you explain a bit more? Say I have a unit test testing a method on XYZService which has a dependency on ABCRepository (i.e. ABCRepository is autowired into XYZService) and hence I need to mock out ABCRepository in my test. How would you propose this be done with the builder pattern?Odelsting
Well, pass an ABCRepository mock to your builder... Or did I misunderstand the intent?Skidmore
But when you wire this repos into your service (i.e. in your "production" code) you will still be wiring it in using the "ugly" interface name. Or are you suggesting that the builder be used in production code as well and then you forgo autowiring the dependencies directly into the service completely? I apologise if I am completely missing what you are suggesting here.Odelsting
"are you suggesting that the builder be used in production code" <-- I thought this was already the case for you! I use them all the time. I see no reason to forego the builders' power (which is far greater than you can imagine). I use this all the time to great effect.Skidmore
when we use builders it has just not been for repositories and services. Am I then correct in saying that you don't autowire dependencies (repositories or services) directly into your services, etc?Odelsting
I don't know what you mean by "autowire" here. The typical use is: MyClass.byDefault().thaw().setX().setY().freeze() where .byDefault() returns a frozen instance with default values. I use this to modify. And it helps a lot.Skidmore
by autowire I just mean using the spring autowire annotation. The way we do it right now is in XYZService we have an instance variable for ABCRepository and a setter for that annotated with "Autowired". This dependency will automatically be injected in production since our application context exists and for unit tests (where it does not exist) we just create a mock of ABCRepository and set it on XYZService manually using the setter during our fixture setup step.Odelsting
Ah OK. I don't use Spring, so I can't help here...Skidmore

© 2022 - 2024 — McMap. All rights reserved.