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.
An answer to such a question can only reflect the tastes of the person who answers... So these are my tastes:
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.Impl
suffix is good enough. But on the other hand, it sounds weird.I'd suggest two alternate proposals for a given interface
Foo
:Impl
suffix; find a more "appealing" name. For instance,TheOnlyOneFoo
;s
:Foos
. Then, aFoo
instance would be aFoos.newInstance(whatever, args)
.I prefer the second solution, for two reasons:
@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:
And as a final note... Have you considered the builder pattern?
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.
Calling your single implementations "defaults".
Calling your base implementations (if, sometimes extended) as "support".
I come across these naming conventions a lot when using the Spring Framework.
Edit : In response to user
nyxz
's comment about the-Base
orBase-
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: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.
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 markedabstract
, which is in line with the 1st point.Here's the
Adapter
hierarchy from the Android framework as an example:Interface hierarchy.
The
abstract
Base
class that factors out the common behaviour and interface implementations.Peripheral classes that are mostly instantiated but sometimes extended by an Android application.