96

I'm new to a team working on a rather large project, with lots of components and dependencies. For every component, there's an interfaces package where the exposed interfaces for that component are placed. Is this a good practice?

My usual practice has always been interfaces and implementations go in the same package.

Levi
  • 175
  • 2
  • 11
kctang
  • 10,894
  • 8
  • 44
  • 63
  • 5
    Why is this tagged [language-agnostic]? – finnw May 22 '11 at 09:45
  • Another situation where this might be preferred if the module is to be communicated over some rpc rather than direct invocation - then interface comes in handy to generate proxies for the client ?? – redzedi Oct 13 '20 at 05:28

14 Answers14

117

Placing both the interface and the implementation is common place, and doesn't seem to be a problem.

Take for example the Java API -- most classes have both interfaces and their implementations included in the same package.

Take for example the java.util package:

It contains the interfaces such as Set, Map, List, while also having the implementations such as HashSet, HashMap and ArrayList.

Furthermore, the Javadocs are designed to work well in those conditions, as it separates the documentation into the Interfaces and Classes views when displaying the contents of the package.

Having packages only for interfaces may actually be a little bit excessive, unless there are enormous numbers of interfaces. But separating the interfaces into their own packages just for the sake of doing so sounds like bad practice.

If differentiating the name of a interface from an implementation is necessary, one could have a naming convention to make interfaces easier to identify:

  • Prefix the interface name with an I. This approach is taken with the interfaces in the .NET framework. It would be fairly easy to tell that IList is an interface for a list.

  • Use the -able suffix. This approach is seen often in the Java API, such as Comparable, Iterable, and Serializable to name a few.

coobird
  • 159,216
  • 35
  • 211
  • 226
  • 47
    +1 although I wouldn't recommend the I* naming convention unless you're in the .NETverse, and even then only for consistency – CurtainDog Jun 17 '09 at 05:31
  • 8
    I've used this convention in java code and I've found it useful .... YMMV – hhafez Jun 17 '09 at 06:14
  • It also seems to be used a lot in the Eclipse ecosystem. – Simon Nickerson Jun 17 '09 at 07:17
  • 5
    I know this is kind of old, but what I have found to be suggested now is to name the interface clearly, and name the implementation something strager. e.g. Interface = Store Implementation = StoreImpl Mainly to highlight that the interface should be used over the implementation. – frostymarvelous May 06 '15 at 15:47
  • I have an app that chooses between two packages at build time (build variants for supporting different hardware) that each provide different classes which implement the same interface. This means that each package and the app need to be able to reference that same interface. I like this answer and train of thought, but I'm looking for a way to apply this take to my situation. Anyone have any comments on this? – ThePartyTurtle Mar 13 '18 at 19:17
  • 1
    I this that this approach, even if it looks right, brings to architectural problems. For example, there's no way to define libraries that use just the interfaces and then have them implemented in a common library, that is the infrastructure layer. – Luca Masera May 18 '18 at 09:48
  • 2
    I agree with the comment about not using the "I" prefix for interfaces in the same way I wouldn't recommend using the "impl" suffix for implementations, this is a nice article reflecting on those cases: https://octoperf.com/blog/2016/10/27/impl-classes-are-evil/ – raspacorp Apr 16 '19 at 22:23
22

For any language, putting them together in the same package is fine. The important thing is what's exposed to the outside world, and how it looks from outside. Nobody's going to know or care if the implementation is in that same package or not.

Let's look at this particular instance.

If you have all public things in one package, and private things in another package that is not publicly exposed, the client of the library sees one package. If you move the private things to the package with the publicly exposed things, but do not expose them from within the package, the client sees exactly the same thing.

Thus, this has the smell of a rule with no good reason: it's making a decision based on something being publicly visible without that decision having any effect on what's publicly visible.

That said, if in any particular instance it seems like a good idea to split the interface and implementation in to separate packages, go right ahead and do that. Reasons for doing this that come to mind are that the package is huge, or you have an alternate implementation you might want to link in instead of the standard one.

cjs
  • 25,752
  • 9
  • 89
  • 101
  • Given the 'Java' tag on the question - what is the meaning of a '_publicly_ exposed package', in Java? Or is your answer not Java-specific? I thought only package members (such as classes, interfaces and their members), not packages themselves, had access control specifiers like 'public', 'private' etc. (This is discussed further @ question http://stackoverflow.com/questions/4388715/java-expose-only-a-single-package-in-a-jar-file) – bacar Mar 07 '12 at 22:12
  • I just clarified the wording; by "publicly exposed package" I really meant, "the package with the publicly exposed things." – cjs Jul 06 '12 at 06:39
  • Surely all the packages should have public things; if not, how can you use the package? – bacar Jul 06 '12 at 07:59
  • 1
    In this particular case, there were packages with nothing public, but which were used by packages that made things public. So the former cannot be used directly, but only indirectly through the latter. – cjs Dec 07 '14 at 07:40
  • 1
    But the same question applies. How can the packages that made things public use the packages that did not make anything public? I know of no way in Java to enforce "the former cannot be used directly, but only indirectly through the latter." If your implementation package has only private members, it is just as inaccessible by your interface package as it is by the client. & similarly for other access scopes. There's no equivalent of `friend` (C++) or `internal` (C#) in Java. – bacar Dec 09 '14 at 09:25
  • Following @bacar's comments- it's really horrible that there's no notion of internal or similar in Java. If you want to extract your classes e.g. to a separate library they still have to be made `public` to be accessible to other packages in the library which makes them accessible also outside of the library! – User May 11 '17 at 12:06
  • One of the best examples might be this. If you're the sole implementation provider for your interfaces, it's perfectly normal publish implementation updates fully isolated from your interfaces. By that way, you don't get your interfaces involved into such updates which seems a bit more safer, right? Similar logic is being followed by Google (for play services and the corresponding client library that update over SDK manager) – stdout Jun 16 '17 at 14:35
10

In many frameworks, such as OSGi, you almost have to. I think this promotes looser coupling, at the package instead of the jar level.

javamonkey79
  • 17,443
  • 36
  • 114
  • 172
9

The book Practical Software Engineering: A Case-Study Approach advocates for putting interfaces in seperate projects/packages.

The PCMEF+ architecture which the book talks about has the following principles:

  1. Downward Dependency Principle (DDP)
  2. Upward Notification Principle (UNP)
  3. Neighbor Communication Principle (NCP)
  4. Explicit Association Principle (EAP)
  5. Cycle Elimination Principle (CEP)
  6. Class Naming Principle (CNP)
  7. Acquaintance Package Principle (APP)

The description of principle #3 and #7 explain why it is a good idea:

The Neighbor Communication Principle demands that a package can only communicate directly with its neighbor package. This principle ensures that the system does not disintegrate to an incompressible network of intercommunicating objects. To enforce this principle, message passing between non-neighboring objects uses delegation (Section 9.1.5.1). In more complex scenarios, acquaintance package (Section 9.1.8.2) can be used to group interfaces to assist in collaboration that engages distant packages.

The Acquaintance Package Principle is the consequence of the Neighbor Communication Principle. The acquaintance package consists of interfaces that an object passes, instead of concrete objects, in arguments to method calls. The interfaces can be implemented in any PCMEF package. This effectively allows communication between non-neighboring packages while centralizing dependency management to a single acquaintance package. The need for acquaintance package was explained in Section 9.1.8.2 and is discussed again next in PCMEF context.

See this link: http://comp.mq.edu.au/books/pse/about_book/Ch9.pdf

Community
  • 1
  • 1
Kenci
  • 4,794
  • 15
  • 64
  • 108
7

One argument for putting interfaces in different packages is that it is easier to create 'api' jars that can be distributed to consumers of your product or service. It's perfectly possible to do this with interfaces and implementations together, but simpler to script if they are in different packages.

Cameron Pope
  • 7,565
  • 2
  • 26
  • 24
  • 8
    You can have the API project separate (being a separate distributable) and that still does not stop interfaces and implementation being in the same package. A bit like you have unit tests in the same package as tested classes but still in a separate build artifact. Jars and packages are pretty much orthogonal in Java. – George Jun 17 '09 at 09:49
  • what do you mean? How can I create a jar that only contains the interfaces when thr package contains also the implementations? – cobby Nov 16 '22 at 10:45
5

Yes, it's a very good practice, because it allows you to publish the interface without publishing your specific implementation. That said, if you have no need to publish external interfaces, there's no problem with putting the interface definitions in the same package as the implementation.

Paul Sonier
  • 38,903
  • 3
  • 77
  • 117
  • 2
    Maybe if you are defining interfaces for the JCP or something this makes good sense, but if you are producing multiple concrete implementations of these interfaces for your project then it seems like an unnecessary burden to package the interfaces separately. – Brian Reiter Jun 17 '09 at 03:47
  • 2
    It's not much of a burden, in any event... – Paul Sonier Jun 17 '09 at 03:50
  • 4
    -1 Yes, it is. It makes it unnecessarily hard to find the implementations and separates things that belong together. – Michael Borgwardt Jun 17 '09 at 05:58
  • 5
    And not publishing the implementations is a completely different matter that can be done by making them package-private - and can NOT be done by placing them in a separate package. There is no such thing as a non-public package. – Michael Borgwardt Jun 17 '09 at 06:01
  • 1
    Moreover, it sounds like making all the interfaces unnecessarily public. – Adeel Ansari Jun 17 '09 at 14:05
  • 1
    So what's with all the downvotes on this accepted answer? – Paul Sonier Jun 18 '09 at 15:24
  • @Michael, not sure why I am replying but some packages like `sun.` may not be access under security restrictions making it virtually 'non-public'. – bestsss May 22 '11 at 09:56
  • If you extend "publish" to the notion of a layered architecture then I think it is good practice even within an application. The higher layer should depend on an abstraction only, i.e. the interface published by the lower layer. But it should not depend on the implementation of the lower layer. Say your service layer needs a repository. If you only have to add a dependeny to an interface JAR I find this is better than winding up with a transitive dependency on an implementation-specific library (JDBC driver for Oracle, MySQL, ...) because you depend on a JAR that includes the implementation. – StaticNoiseLog Apr 05 '19 at 13:16
4

We do this where I work (ie: put interface in one package and implementation in another) and the main advantage we get out of this is we can easily swap between implementations.

hhafez
  • 38,949
  • 39
  • 113
  • 143
3

I haven't much Java experience, but I like to do this as a good practice in C#/.NET because it allows for future expansion where the assemblies with the concrete classes which implement the interfaces may not be distributed all the way down to the client because they are proxied by a middleman factory or across the wire in a web service scenario.

Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
2

I'm doing this on a project and it is working well for me because of these reasons:

  • Separately packaged interfaces and implementations are for a different use case than for the various types of Map or Set. There is no reason to have a package just for trees (java.util.tree.Map, java.util.tree.Set). It is just a standard datastructure, so put it together with the other datastructures. However, if you are dealing with a puzzle game that has a really simple debug interface and a pretty production interface, as part of its front-end you might have a com.your.app.skin.debug and a com.your.app.skin.pretty. I would not put these in the same package, because they do different things and I know I would resort to some SmurfNamingConvention (DebugAttackSurface, DebugDefenceSurface, PrettyAttackSurface etc) to create some informal namespace for the two if they were in the same package.

  • My workaround for the problem of finding related interfaces and implementations that are in separate packages is to adopt a naming configuration for my packages. E.g. I can have all my interfaces in com.your.app.skin.framework, and know that other packages on the same level of the package tree are implementations. The disadvantage is that this is an unconventional convention. Honestly, I will see how good this convention is in 6 months time :)

  • I do not use this technique religiously. There are interfaces which only make sense in a particular implementation. I don't stick them in the framework package. There are some packages where it doesn't look like I'm going to create 40 different implementation classes, so I don't bother.

  • My application uses guice and has very many interfaces.

Questions of program design generally involve benefits and drawbacks and there is no one-size-fits all answer. Like why would you ever use this technique in a tiny 200-line program? It makes sense for me, given my other architectural choices, for my specific problem. :)

2

I normally put Interfaces with the implementation however I can sort of see why you may want to keep them separate. Say, for instance, someone wanted to reimplement classes based upon your interfaces, they would need a jar/lib/etc with your implementation rather than just the interfaces. With them separate you could just say "Here's my implementation of that interface" and be done with it. Like I said, not what I do but I can sort of see why some might want to.

Matt_JD
  • 566
  • 6
  • 16
1

I prefer them in the same package. Feels pointless to create a package specifically for interfaces. This is especially redundant for teams that simply love their interface prefixes and suffixes (e.g. the "I", and "Impl" for Java).

If there's a needs to publish a set of interfaces as public API, it makes more sense to keep them in an entirely separate project and create project dependencies instead. But it all boils down to preference and convenience of the situation I suppose.

aberrant80
  • 12,815
  • 8
  • 45
  • 68
1

I think it is important to note that for the OSGi framework, it is nicer that they are in different packages so that you can easily export a whole package while hiding the implementation packages.

jkabugu
  • 331
  • 3
  • 3
0

Put them in packages that reflect your projects. It is fine and common to put interfaces and implementations together if they're part of the same project, but if you're writing an API, then someone else would likely be choosing a package name relevant to their project.

In general, if it's for the same project, I don't see any benefit in keeping the interfaces in a separate package from their impls. If it's getting cluttered, there may be other package naming issues, irrespective of the interface arrangement.

Rog
  • 4,075
  • 2
  • 24
  • 35
0

There are a lot of good reasons for putting interfaces in a separate package from implementation. For example you may want to use container that supports Dependency Injection to wire up the necessary implementation(s) at run time, in which case only the interface needs to be present at build time and the implementation can be supplied at run time. Alternatively, you may want to provide multiple implementations (for example using mock implementations for testing) or multiple versions of a particular implementation at run time (for example for A/B testing, etc). For these kinds of use cases it's more convenient to package interface and implementation separately.

Tyson
  • 1,685
  • 15
  • 36
  • You don't need to put the implementation in a different package to do either of the things you listed – Crowie Jul 08 '13 at 15:05
  • That's fair, but I still think that the "being present at build time vs run time" difference in requirements is a compelling case for packaging separately. I updated the text to try to reflect that more clearly. – Tyson Jul 08 '13 at 21:08