I'm curious to developers' opinions/practices on where should class interfaces, ideally, be placed in a .NET class library. Should they be contained within their own dedicated library within the solution e.g MyCompany.AccountPackage.Interfaces?
Should they have their own namespace e.g. MyCompany.AccountPackage.MasterAccounts.Interfaces?
Any other thoughts/opinions appreciated?
Is there any good guide demonstrating how to structure a .Net library(or even better, the solution), showing in general, what classes/interfaces should typically be exposed in the standard library.
Thanks, d.
Short answer:
Interfaces should be close to where they are implemented.
At least some of the BCL does this - IEnumerable<T>
lives in the System.Collections.Generic
namespace, for example.
Slightly longer answer:
It depends on what the purpose of the interfaces is.
Is it to provide a plug-in interface (a-la the provider model or MEF) for third parties?
If so, a separate assembly can make sense, so all that needs to be imported by the third party is this assembly.
Is it internal, for testing and IoC purposes?
I would argue that keeping it close to the implementation makes sense, organizationally and to help with keeping the code in sync with the interfaces.
I think the answer is rather contextual in that it depends what the interfaces are for and how they fit into the architecture of your library.
Object Model
In my opinion, if you are creating some form of object model, you should put the interfaces that represent the object model in one project within an assembly. This way, the references to the interfaces can be re-distributed and coded against without having to worry about the actual implementation, which could vary. It also allows for you to provide an initial implementation of the object model, while leaving it open to re-implementation by someone else (perhaps to support a new platform or related software).
Generic Use
If you are intended on creating an interface similar to those found in .NET's System.Collections.Generic
namespace, which are going to be re-used in many places; then I would suggest placing it low down enough so that multiple project can access and implement the interface. However, this does not mean you cannot implement the interface yourself within the same project. In that case, it all depends what your intending to be within that assembly.
Other Use
Another use may be some database interaction system, where you have an interface that defines some database interactor, but you may have two or more implementations of it. For example, you may have one that interacts specifically with Microsoft Access databases, and one that interacts with Sql Databases. In this case, it would be feasible to provide your interface(s) and implementation(s) in the same assembly.
All that being said, it does all depend on the situation and intended use. Best way that I have found to determine what that is, is to create a prototype version of the assembly and see how you may need to use it.
As in most situations: it depends.
But in 99% of all cases I put interfaces into their own assemblies, grouped into logical units to prevent tight interface dependencies. In former days I just put it where the first implementation was. This grew into a tightly coupled mess that was impossible to split up later.
If you practice/strive for loose coupling, I suggest moving interfaces to seperate assemblies. I prefer to only include:
into "interface assemblies" and to only reference:
This doesn't apply to internally used interfaces only used in one assembly (which will be the 1% of interfaces).
The only implementation that can be included in the same assembly as the interface itself is one, that:
The "implementation assemblies" should only be referenced in the main assembly, other assemblies only include the interface assembly. This also ensures that you don't use the implementation directly or test if the interface is of this special implementation.
Why? This way your assemblies only rely on stable assemblies and are not tightly coupled. This is also the preferred way if you plan to use dependency injection.
You should put the implementations in a sub-namespace of the interface. So, to pick up your example, I'd suggest:
MyCompany.AccountPackage.MasterAccounts
MyCompany.AccountPackage.MasterAccounts
MyCompany.AccountPackage.MasterAccounts.SQLMasterAccounts
or just MyCompany.AccountPackage.MasterAccounts.Implementation
.Why?
From the implementations side this means, you get all interfaces and extension stuff without having to use using MyCompany.AccountPackage.MasterAccounts.Interfaces
.
From the clients side this means that you will be shielded from too much options from intellisense in the implementations assemblies (which shouldn't include the other implementation assemblies anyway), yet have easily access to the implementations in the main assembly, where you choose the concrete implementation to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With