Should I have a separate assembly for interfaces?

Currently, we have quite a few classes in the project, and each of these classes implements an interface, mainly for DI reasons.

Now my personal opinion is that these interfaces should be placed in a separate namespace inside the same assembly (therefore, we have the assembly MyCompany.CoolApp.DataAccess and inside it there is the Interfaces namespace giving MyCompany.CoolApp.DataAccess.Interfaces ).

However, someone suggested that these interfaces should actually be in their own assembly. And my question is: are they right? I see that there are some advantages (for example, other projects will only need to consume the interface assembly), but at the end of this day all these assemblies will be loaded. It also seems to me that there might be a slightly more complicated deployment problem, since Visual Studio will not automatically pull the implementation assembly into the target bin folder.

Are there any recommendations for this practice?

EDIT:

To make my question a little clearer: we already split UI, DataAccess, DataModel and other things into different assemblies. Currently, we can also replace our implementation with another implementation without any pain, as we map the implementing class to the interface using Unity (IOC framework). I should note that we never write two implementations of the same interface, except for the causes of polymorphism and the creation of layouts for unit testing. Thus, we currently do not “replace” the implementation, except for unit tests.

The only drawback that I see is that the interface in the same assembly as the implementation is that the entire assembly (including the unused implementation) will be loaded.

However, I can see that having them in another assembly means that developers will not accidentally be the "new" implementation class, but will not be created using IOC covers.

One question that I did not understand from the answers is the deployment problem. If I'm just dependent on front-end assemblies, I will have something like the following structure:

 MyCompany.MyApplication.WebUI References: MyCompany.MyApplication.Controllers.Interfaces MyCompany.MyApplication.Bindings.Interfaces etc... 

When I create this, assemblies that are automatically placed in the bin folder are just these interface assemblies. However, my type mappings in unity display different interfaces with their actual implementations. How do assemblies containing my implementations get into the bin folder?

+41
namespaces assemblies
Jul 29 '10 at 2:06 p.m.
source share
5 answers

So far, the answers seem to suggest that introducing interfaces into their own assembly is common practice. I do not agree with the placement of unrelated interfaces in one "common" common assembly, so this would mean that I would need to have 1 interface assembly for each assembly of the "implementation".

However, thinking about this further, I cannot come up with many real-life examples of this practice (for example, log4net or NUnit provide public interface assemblies so that users can then solve different implementations? If so, what other nunit implementation can I use?). While spending time browsing Google, I found several resources.

+11
Aug 01 '10 at 16:01
source share
— -

A common traditional practice is to place them in your own assembly, because then a given project using these interfaces does not require a hard link to implement these interfaces. Theoretically, this means that you can replace the implementation with little or no pain.

However, I can’t remember the last time I did this to @ David_001 point, this is not necessarily “normal”. We usually have our interfaces in accordance with the implementation most commonly used for the tested interfaces.

I think that depending on what you do, there are different positions. I tend to create LOB applications that need to interact internally with other applications and teams, so there are some stakeholders in the public API of any application. However, it is not as extreme as creating a library or structure for many unknown clients, where a public API suddenly becomes more important.

In a deployment scenario, if you changed the implementation, you could theoretically just deploy this single DLL, leaving, say, interfaces and DLLs. If you compiled your interfaces and implementation together, you may need to redeploy the UI library ...

Another advantage is the pure segregation of your code - the presence of an interface library (or shared library) is explicitly indicated in any development team, where to place new types, etc. I no longer consider this an advantage, since we did not have any problems not doing it this way, the public contract is still easy to find regardless of where the interfaces are located.

I don’t know if there are better methods for or against, it is important that this is important in the code, you always consume interfaces and never skip any code to use the implementation.

+25
Jul 29 '10 at 14:12
source share

The sample that I follow what I call generic types (and I also use DI) should have a separate assembly that contains the following application-level concepts (and not the general concepts that are included in general assemblies):

  • Common interfaces
  • DTOS.
  • Exceptions

Thus, it is possible to manage dependencies between clients and libraries of the main applications, since clients cannot depend on a specific implementation either directly or as an unintended consequence of adding a link to a direct assembly, and then access to any old public type.

Then I have a runtime type project when I install my DI container at application startup or at the beginning of a set of unit tests. Thus, there is a clear separation between implementations and how I can change them through DI. My client modules never have a direct link to the actual core libraries, but only to the SharedTypes library.

The key to my design is the general concept of runtime for clients (be it a WPF or NUnit application), which sets up the necessary dependencies, that is, specific implementations or some kind of mocks \ stubs.

If the above common types are not taken into account, but instead clients add a reference to the assembly with a specific implementation, then it is very easy for customers to use specific implementations, rather than interfaces, as in obvious, obvious ways. It is very easy to gradually end excessive traction over time, which is almost impossible to understand without much effort and, more importantly, time.

Update

To illustrate an example of using dependencies in the target application.

In my situation, I have a WPF client application. I use Prism and Unity (for DI), where it is important, Prism is used to compose an application.

With Prism, your application assembly is just a shell, the actual implementations of the functionality are in the module assemblies (you can have a separate assembly for each concept module, but this is not a requirement, I have one module assembly ATM). The responsibility for loading the modules lies with the shell - the composition of these modules is an application. Modules use the SharedTypes assembly, but the shell references specific assemblies. The type of execution script I developed is responsible for initializing dependencies, and this is done in the shell.

Thus, module assemblies that have all the functionality are independent of specific implementations. They are loaded by a shell that sorts the dependencies. The shell refers to specific assemblies, and that is how they get into the bin directory.

Dependency Sketch:

 Shell.dll <-- Application --ModuleA.dll --ModuleB.dll --SharedTypes.dll --Core.dll --Common.dll + Unity.dll <-- RuntimeDI ModuleA.dll --SharedTypes.dll --Common.dll + Unity.dll <-- RuntimeDI ModuleB.dll --SharedTypes.dll --Common.dll + Unity.dll <-- RuntimeDI SharedTypes.dll --... 
+8
Jul 29 '10 at 14:17
source share

I agree with the ticking answer. Good for you, David. In fact, I was relieved to see the answer, I thought I was crazy.

I see this interesting pen-in-pen pattern in C # corporate jobs all the time, where people follow the crowd agreement and the team needs to meet, and doesn't meet the requirements.

Another crazy thing is one namespace for every meaningless assembly. Thus, you get the SomeBank.SomeApp.Interfaces namespace and everything in it.

For me, this means that types are scattered across namespaces and assemblies containing a whole bunch of things that I care about, you need to reference everywhere.

As for interfaces, I don’t even use interfaces in my personal applications; DI works on types specific to virtual, base classes, or interfaces. I select accordingly and place the types in the DLL according to what they do.

I never had a problem with DI logic or swap later.

• .NET assemblies are a security unit, application and deployment area of ​​the API and are not dependent on namespaces.

• If two assemblies are dependent on each other, they cannot be deployed and versioned separately and must be combined.

• Having a large number of DLLs often means creating a lot of public materials, so it's hard to tell the actual public API from type members who were supposed to be published because they were arbitrarily placed in their own assembly.

• Should code outside my DLL use my type?

• Start conservative; Usually I can easily move the type of layer, it's a bit more complicated in the opposite direction.

• Can I neatly pack my area or framework into a NuGet package so that it is fully optional and version accessible, like any other package?

• Are my types consistent with the delivery of the function and can they fit into the function namespace?

• Many real libraries and frameworks are branded, which simplifies their discussion, and they do not burn namespace names that suggest its use or are ambiguous, can I reinforce the components of my application using "code names" such as Steelcore, and not generic clichéd and confusing terms, errm 'Services'?

Edit

This is one of the incomprehensible things that I see in development today. This is so bad.

You have an API, so put all its types in one API project. Only push them when you need to use / reuse them. When you move them, move them directly to the NuGet package with a clear name that bears the intention and focus of the package. If you are fighting for a name and consider "Common", perhaps because you are creating a landfill.

You must include your NuGet package in a family of related packages. Your "main" package should have minimal dependencies on other packages. The types inside are associated with use and are dependent on each other.

Then you create a new package for more specialized types and subtypes that require additional sets of dependencies; more clearly: you break down the library according to its external dependencies, and not according to type of type, as well as about its interface or exception.

Library Factoring

Thus, you can use all your types in one large library, but some more specialized types (color spots) depend on some external libraries, so now your library needs to use all these dependencies. This is optional; you must break these types down into additional specialized libraries that require the necessary dependencies.

Types in packages A and B can belong to the same namespace. Link A includes one set of types, and then, optionally, link B complements the namespace with even more connectives.

What is it.

Luke

+6
Jun 05 '15 at 7:55
source share

I look at System.Data.dll (4.0) in the object browser, and I see that it is autonomous in itself, not only with interfaces, but also with tool classes such as DataSet, DataTable, DataRow, DataColumn, etc. Moreover, by looking at a list of namespaces such as System.Data, System.Data.Common, System.Configuration and System.Xml, it first offers the interfaces contained in their own assemblies, with all the relevant and necessary codes stored together and second and more importantly, reuse the same namespaces in a common application (or framework) to also sort classes.

0
Jan 09 '13 at 17:18
source share



All Articles